From 8acf8f08855e18fa4c04a65609194df29ed1bcf4 Mon Sep 17 00:00:00 2001
From: Neil Gershenfeld <gersh@cba.mit.edu>
Date: Mon, 29 Oct 2018 21:48:32 -0400
Subject: [PATCH] wip

---
 input_devices/mag/hello.mag.45.js             |   42 +-
 .../mag/node_modules/.bin/detect-libc         |    1 +
 .../node_modules => }/.bin/mkdirp             |    0
 .../mag/node_modules/.bin/prebuild-install    |    1 +
 input_devices/mag/node_modules/.bin/prominode |    1 +
 input_devices/mag/node_modules/.bin/rc        |    1 +
 .../node_modules => }/.bin/semver             |    0
 .../mag/node_modules/.bin/serialport-list     |    1 +
 .../mag/node_modules/.bin/serialport-repl     |    1 +
 .../mag/node_modules/.bin/serialport-term     |    1 +
 .../mag/node_modules/.bin/serialportlist      |    1 -
 .../mag/node_modules/.bin/serialportterm      |    1 -
 .../mag/node_modules/.bin/window-size         |    1 +
 .../@serialport/binding-abstract/CHANGELOG.md |   18 +
 .../@serialport/binding-abstract/LICENSE      |   21 +
 .../@serialport/binding-abstract/README.md    |   14 +
 .../binding-abstract/binding-abstract.js      |  230 +
 .../@serialport/binding-abstract/package.json |   84 +
 .../@serialport/binding-mock/CHANGELOG.md     |   18 +
 .../@serialport/binding-mock/LICENSE          |   21 +
 .../@serialport/binding-mock/README.md        |   11 +
 .../@serialport/binding-mock/binding-mock.js  |  258 +
 .../@serialport/binding-mock/package.json     |   85 +
 .../@serialport/bindings/CHANGELOG.md         |   30 +
 .../node_modules/@serialport/bindings/LICENSE |   21 +
 .../@serialport/bindings/README.md            |   11 +
 .../@serialport/bindings/binding.gyp          |   57 +
 .../bindings/build/Release/bindings.node      |  Bin 0 -> 56320 bytes
 .../@serialport/bindings/lib/bindings-test.js |  650 ++
 .../lib/bindings-win32-sn-parser-test.js      |   38 +
 .../@serialport/bindings/lib/darwin.js        |  109 +
 .../@serialport/bindings/lib/index.js         |   15 +
 .../bindings/lib/linux-list-test.js           |  116 +
 .../@serialport/bindings/lib/linux-list.js    |   99 +
 .../@serialport/bindings/lib/linux.js         |  111 +
 .../@serialport/bindings/lib/poller.js        |  111 +
 .../@serialport/bindings/lib/unix-read.js     |   56 +
 .../@serialport/bindings/lib/unix-write.js    |   70 +
 .../@serialport/bindings/lib/util.js          |   20 +
 .../bindings/lib/win32-sn-parser.js           |   15 +
 .../@serialport/bindings/lib/win32.js         |  110 +
 .../@serialport/bindings/package.json         |  108 +
 .../@serialport/bindings/src/darwin_list.cpp  |  359 ++
 .../@serialport/bindings/src/darwin_list.h    |   45 +
 .../@serialport/bindings/src/poller.cpp       |  135 +
 .../@serialport/bindings/src/poller.h         |   33 +
 .../@serialport/bindings/src/serialport.cpp   |  485 ++
 .../@serialport/bindings/src/serialport.h     |  126 +
 .../bindings/src/serialport_linux.cpp         |   39 +
 .../bindings/src/serialport_linux.h           |    8 +
 .../bindings/src/serialport_unix.cpp          |  403 ++
 .../bindings/src/serialport_unix.h            |    7 +
 .../bindings/src/serialport_win.cpp           |  948 +++
 .../@serialport/bindings/src/serialport_win.h |   71 +
 .../parser-byte-length/CHANGELOG.md           |   18 +
 .../@serialport/parser-byte-length/LICENSE    |   21 +
 .../@serialport/parser-byte-length/README.md  |    1 +
 .../parser-byte-length/byte-length.js         |   55 +
 .../parser-byte-length/package.json           |   81 +
 .../@serialport/parser-cctalk/CHANGELOG.md    |   18 +
 .../@serialport/parser-cctalk/LICENSE         |   21 +
 .../@serialport/parser-cctalk/README.md       |    1 +
 .../@serialport/parser-cctalk/cctalk.js       |   41 +
 .../@serialport/parser-cctalk/package.json    |   81 +
 .../@serialport/parser-delimiter/CHANGELOG.md |   18 +
 .../@serialport/parser-delimiter/LICENSE      |   21 +
 .../@serialport/parser-delimiter/README.md    |    1 +
 .../@serialport/parser-delimiter/delimiter.js |   55 +
 .../@serialport/parser-delimiter/package.json |   82 +
 .../@serialport/parser-readline/CHANGELOG.md  |   18 +
 .../@serialport/parser-readline/LICENSE       |   21 +
 .../@serialport/parser-readline/README.md     |    1 +
 .../@serialport/parser-readline/package.json  |   84 +
 .../@serialport/parser-readline/readline.js   |   32 +
 .../@serialport/parser-ready/CHANGELOG.md     |   18 +
 .../@serialport/parser-ready/LICENSE          |   21 +
 .../@serialport/parser-ready/README.md        |    1 +
 .../@serialport/parser-ready/package.json     |   81 +
 .../@serialport/parser-ready/ready.js         |   63 +
 .../@serialport/parser-regex/CHANGELOG.md     |   18 +
 .../@serialport/parser-regex/LICENSE          |   21 +
 .../@serialport/parser-regex/README.md        |    1 +
 .../@serialport/parser-regex/package.json     |   81 +
 .../@serialport/parser-regex/regex.js         |   57 +
 .../@serialport/stream/CHANGELOG.md           |   18 +
 .../node_modules/@serialport/stream/LICENSE   |   21 +
 .../node_modules/@serialport/stream/README.md |   14 +
 .../@serialport/stream/package.json           |   84 +
 .../node_modules/@serialport/stream/stream.js |  676 +++
 .../mag/node_modules/ansi-bgblack/LICENSE     |   21 +
 .../mag/node_modules/ansi-bgblack/README.md   |   74 +
 .../mag/node_modules/ansi-bgblack/index.js    |   14 +
 .../node_modules/ansi-bgblack/package.json    |  108 +
 .../mag/node_modules/ansi-bgblue/LICENSE      |   21 +
 .../mag/node_modules/ansi-bgblue/index.js     |   14 +
 .../mag/node_modules/ansi-bgblue/package.json |  108 +
 .../mag/node_modules/ansi-bgblue/readme.md    |   74 +
 .../mag/node_modules/ansi-bgcyan/LICENSE      |   21 +
 .../mag/node_modules/ansi-bgcyan/index.js     |   14 +
 .../mag/node_modules/ansi-bgcyan/package.json |  108 +
 .../mag/node_modules/ansi-bgcyan/readme.md    |   74 +
 .../mag/node_modules/ansi-bggreen/LICENSE     |   21 +
 .../mag/node_modules/ansi-bggreen/index.js    |   14 +
 .../node_modules/ansi-bggreen/package.json    |  108 +
 .../mag/node_modules/ansi-bggreen/readme.md   |   74 +
 .../mag/node_modules/ansi-bgmagenta/LICENSE   |   21 +
 .../mag/node_modules/ansi-bgmagenta/index.js  |   14 +
 .../node_modules/ansi-bgmagenta/package.json  |  108 +
 .../mag/node_modules/ansi-bgmagenta/readme.md |   74 +
 .../mag/node_modules/ansi-bgred/LICENSE       |   21 +
 .../mag/node_modules/ansi-bgred/index.js      |   14 +
 .../mag/node_modules/ansi-bgred/package.json  |  108 +
 .../mag/node_modules/ansi-bgred/readme.md     |   74 +
 .../mag/node_modules/ansi-bgwhite/LICENSE     |   21 +
 .../mag/node_modules/ansi-bgwhite/index.js    |   14 +
 .../node_modules/ansi-bgwhite/package.json    |  108 +
 .../mag/node_modules/ansi-bgwhite/readme.md   |   74 +
 .../mag/node_modules/ansi-bgyellow/LICENSE    |   21 +
 .../mag/node_modules/ansi-bgyellow/index.js   |   14 +
 .../node_modules/ansi-bgyellow/package.json   |  108 +
 .../mag/node_modules/ansi-bgyellow/readme.md  |   74 +
 .../mag/node_modules/ansi-black/LICENSE       |   21 +
 .../mag/node_modules/ansi-black/index.js      |   14 +
 .../mag/node_modules/ansi-black/package.json  |  108 +
 .../mag/node_modules/ansi-black/readme.md     |   74 +
 .../mag/node_modules/ansi-blue/LICENSE        |   21 +
 .../mag/node_modules/ansi-blue/index.js       |   14 +
 .../mag/node_modules/ansi-blue/package.json   |  108 +
 .../mag/node_modules/ansi-blue/readme.md      |   74 +
 .../mag/node_modules/ansi-bold/LICENSE        |   21 +
 .../mag/node_modules/ansi-bold/index.js       |   14 +
 .../mag/node_modules/ansi-bold/package.json   |  108 +
 .../mag/node_modules/ansi-bold/readme.md      |   74 +
 .../mag/node_modules/ansi-colors/LICENSE      |   21 +
 .../mag/node_modules/ansi-colors/README.md    |   94 +
 .../mag/node_modules/ansi-colors/index.js     |  434 ++
 .../mag/node_modules/ansi-colors/package.json |  188 +
 .../mag/node_modules/ansi-cyan/LICENSE        |   21 +
 .../mag/node_modules/ansi-cyan/index.js       |   14 +
 .../mag/node_modules/ansi-cyan/package.json   |  110 +
 .../mag/node_modules/ansi-cyan/readme.md      |   74 +
 .../mag/node_modules/ansi-dim/LICENSE         |   21 +
 .../mag/node_modules/ansi-dim/index.js        |   14 +
 .../mag/node_modules/ansi-dim/package.json    |  110 +
 .../mag/node_modules/ansi-dim/readme.md       |   74 +
 .../mag/node_modules/ansi-gray/LICENSE        |   21 +
 .../mag/node_modules/ansi-gray/index.js       |   14 +
 .../mag/node_modules/ansi-gray/package.json   |  109 +
 .../mag/node_modules/ansi-gray/readme.md      |   74 +
 .../mag/node_modules/ansi-green/LICENSE       |   21 +
 .../mag/node_modules/ansi-green/index.js      |   14 +
 .../mag/node_modules/ansi-green/package.json  |  110 +
 .../mag/node_modules/ansi-green/readme.md     |   74 +
 .../mag/node_modules/ansi-grey/LICENSE        |   21 +
 .../mag/node_modules/ansi-grey/index.js       |   14 +
 .../mag/node_modules/ansi-grey/package.json   |  108 +
 .../mag/node_modules/ansi-grey/readme.md      |   74 +
 .../mag/node_modules/ansi-hidden/LICENSE      |   21 +
 .../mag/node_modules/ansi-hidden/index.js     |   14 +
 .../mag/node_modules/ansi-hidden/package.json |  108 +
 .../mag/node_modules/ansi-hidden/readme.md    |   74 +
 .../mag/node_modules/ansi-inverse/LICENSE     |   21 +
 .../mag/node_modules/ansi-inverse/index.js    |   14 +
 .../node_modules/ansi-inverse/package.json    |  108 +
 .../mag/node_modules/ansi-inverse/readme.md   |   74 +
 .../mag/node_modules/ansi-italic/LICENSE      |   21 +
 .../mag/node_modules/ansi-italic/index.js     |   14 +
 .../mag/node_modules/ansi-italic/package.json |  108 +
 .../mag/node_modules/ansi-italic/readme.md    |   74 +
 .../mag/node_modules/ansi-magenta/LICENSE     |   21 +
 .../mag/node_modules/ansi-magenta/index.js    |   14 +
 .../node_modules/ansi-magenta/package.json    |  108 +
 .../mag/node_modules/ansi-magenta/readme.md   |   74 +
 .../mag/node_modules/ansi-red/LICENSE         |   21 +
 .../mag/node_modules/ansi-red/index.js        |   14 +
 .../mag/node_modules/ansi-red/package.json    |  108 +
 .../mag/node_modules/ansi-red/readme.md       |   74 +
 .../mag/node_modules/ansi-regex/index.js      |    4 +
 .../mag/node_modules/ansi-regex/license       |   21 +
 .../mag/node_modules/ansi-regex/package.json  |  123 +
 .../mag/node_modules/ansi-regex/readme.md     |   39 +
 .../mag/node_modules/ansi-reset/LICENSE       |   21 +
 .../mag/node_modules/ansi-reset/index.js      |   14 +
 .../mag/node_modules/ansi-reset/package.json  |  108 +
 .../mag/node_modules/ansi-reset/readme.md     |   74 +
 .../node_modules/ansi-strikethrough/LICENSE   |   21 +
 .../node_modules/ansi-strikethrough/index.js  |   14 +
 .../ansi-strikethrough/package.json           |  108 +
 .../node_modules/ansi-strikethrough/readme.md |   74 +
 .../mag/node_modules/ansi-underline/LICENSE   |   21 +
 .../mag/node_modules/ansi-underline/index.js  |   14 +
 .../node_modules/ansi-underline/package.json  |  108 +
 .../mag/node_modules/ansi-underline/readme.md |   74 +
 .../mag/node_modules/ansi-white/LICENSE       |   21 +
 .../mag/node_modules/ansi-white/index.js      |   14 +
 .../mag/node_modules/ansi-white/package.json  |  108 +
 .../mag/node_modules/ansi-white/readme.md     |   74 +
 .../mag/node_modules/ansi-wrap/LICENSE        |   21 +
 .../mag/node_modules/ansi-wrap/README.md      |   89 +
 .../mag/node_modules/ansi-wrap/index.js       |    5 +
 .../mag/node_modules/ansi-wrap/package.json   |  106 +
 .../mag/node_modules/ansi-yellow/LICENSE      |   21 +
 .../mag/node_modules/ansi-yellow/index.js     |   14 +
 .../mag/node_modules/ansi-yellow/package.json |  108 +
 .../mag/node_modules/ansi-yellow/readme.md    |   74 +
 input_devices/mag/node_modules/aproba/LICENSE |   14 +
 .../mag/node_modules/aproba/README.md         |   94 +
 .../mag/node_modules/aproba/index.js          |  105 +
 .../mag/node_modules/aproba/package.json      |   89 +
 .../node_modules/are-we-there-yet/CHANGES.md  |   37 +
 .../mag/node_modules/are-we-there-yet/LICENSE |    5 +
 .../node_modules/are-we-there-yet/README.md   |  195 +
 .../node_modules/are-we-there-yet/index.js    |    4 +
 .../are-we-there-yet/package.json             |   94 +
 .../are-we-there-yet/tracker-base.js          |   11 +
 .../are-we-there-yet/tracker-group.js         |  107 +
 .../are-we-there-yet/tracker-stream.js        |   36 +
 .../node_modules/are-we-there-yet/tracker.js  |   30 +
 .../mag/node_modules/arr-flatten/LICENSE      |   21 +
 .../mag/node_modules/arr-flatten/README.md    |   86 +
 .../mag/node_modules/arr-flatten/index.js     |   22 +
 .../mag/node_modules/arr-flatten/package.json |  143 +
 .../mag/node_modules/arr-swap/LICENSE         |   21 +
 .../mag/node_modules/arr-swap/README.md       |   85 +
 .../mag/node_modules/arr-swap/index.js        |   17 +
 .../arr-swap/node_modules/is-number/LICENSE   |   21 +
 .../arr-swap/node_modules/is-number/README.md |  115 +
 .../arr-swap/node_modules/is-number/index.js  |   22 +
 .../node_modules/is-number/package.json       |  152 +
 .../mag/node_modules/arr-swap/package.json    |  114 +
 .../node_modules/async-limiter/.travis.yml    |    7 +
 .../mag/node_modules/async-limiter/LICENSE    |    8 +
 .../async-limiter/coverage/coverage.json      |    1 +
 .../lcov-report/async-throttle/index.html     |   73 +
 .../lcov-report/async-throttle/index.js.html  |  246 +
 .../coverage/lcov-report/base.css             |  182 +
 .../coverage/lcov-report/index.html           |   73 +
 .../coverage/lcov-report/prettify.css         |    1 +
 .../coverage/lcov-report/prettify.js          |    1 +
 .../lcov-report/sort-arrow-sprite.png         |  Bin 0 -> 209 bytes
 .../coverage/lcov-report/sorter.js            |  156 +
 .../async-limiter/coverage/lcov.info          |   74 +
 .../mag/node_modules/async-limiter/index.js   |   67 +
 .../node_modules/async-limiter/package.json   |   97 +
 .../mag/node_modules/async-limiter/readme.md  |  132 +
 .../mag/node_modules/bindings/README.md       |   98 +
 .../mag/node_modules/bindings/bindings.js     |  171 +
 .../mag/node_modules/bindings/package.json    |   84 +
 input_devices/mag/node_modules/bl/.jshintrc   |   59 +
 input_devices/mag/node_modules/bl/.travis.yml |   16 +
 input_devices/mag/node_modules/bl/LICENSE.md  |   13 +
 input_devices/mag/node_modules/bl/README.md   |  208 +
 input_devices/mag/node_modules/bl/bl.js       |  281 +
 .../mag/node_modules/bl/package.json          |   98 +
 .../mag/node_modules/bl/test/test.js          |  702 +++
 .../node_modules/buffer-alloc-unsafe/index.js |   17 +
 .../buffer-alloc-unsafe/package.json          |   89 +
 .../buffer-alloc-unsafe/readme.md             |   46 +
 .../mag/node_modules/buffer-alloc/index.js    |   32 +
 .../node_modules/buffer-alloc/package.json    |   90 +
 .../mag/node_modules/buffer-alloc/readme.md   |   43 +
 .../mag/node_modules/buffer-fill/index.js     |  113 +
 .../mag/node_modules/buffer-fill/package.json |   80 +
 .../mag/node_modules/buffer-fill/readme.md    |   54 +
 .../node_modules/choices-separator/LICENSE    |   21 +
 .../node_modules/choices-separator/README.md  |  147 +
 .../node_modules/choices-separator/index.js   |  101 +
 .../node_modules/debug/.coveralls.yml         |    1 +
 .../node_modules/debug/.eslintrc              |   11 +
 .../node_modules/debug/.npmignore             |    9 +
 .../node_modules/debug/.travis.yml            |   14 +
 .../node_modules/debug/CHANGELOG.md           |  362 ++
 .../node_modules/debug/LICENSE                |   19 +
 .../node_modules/debug/Makefile               |   50 +
 .../node_modules/debug/README.md              |  312 +
 .../node_modules/debug/component.json         |   19 +
 .../node_modules/debug/karma.conf.js          |   70 +
 .../node_modules/debug/node.js                |    1 +
 .../node_modules/debug/package.json           |  128 +
 .../node_modules/debug/src/browser.js         |  185 +
 .../node_modules/debug/src/debug.js           |  202 +
 .../node_modules/debug/src/index.js           |   10 +
 .../node_modules/debug/src/inspector-log.js   |   15 +
 .../node_modules/debug/src/node.js            |  248 +
 .../node_modules/ms/index.js                  |  152 +
 .../node_modules/ms/license.md                |   21 +
 .../node_modules/ms/package.json              |  101 +
 .../node_modules/ms/readme.md                 |   51 +
 .../choices-separator/package.json            |  136 +
 input_devices/mag/node_modules/chownr/LICENSE |   15 +
 .../mag/node_modules/chownr/README.md         |    3 +
 .../mag/node_modules/chownr/chownr.js         |   88 +
 .../mag/node_modules/chownr/package.json      |   89 +
 .../mag/node_modules/clone-deep/LICENSE       |   21 +
 .../mag/node_modules/clone-deep/README.md     |   84 +
 .../mag/node_modules/clone-deep/index.js      |   55 +
 .../clone-deep/node_modules/kind-of/LICENSE   |   21 +
 .../clone-deep/node_modules/kind-of/README.md |  342 ++
 .../clone-deep/node_modules/kind-of/index.js  |  147 +
 .../node_modules/kind-of/package.json         |  179 +
 .../mag/node_modules/clone-deep/package.json  |  137 +
 .../mag/node_modules/code-point-at/index.js   |   32 +
 .../mag/node_modules/code-point-at/license    |   21 +
 .../node_modules/code-point-at/package.json   |   98 +
 .../mag/node_modules/code-point-at/readme.md  |   32 +
 .../mag/node_modules/collection-visit/LICENSE |   21 +
 .../node_modules/collection-visit/README.md   |   89 +
 .../node_modules/collection-visit/index.js    |   30 +
 .../collection-visit/package.json             |  146 +
 .../mag/node_modules/commander/CHANGELOG.md   |  396 ++
 .../mag/node_modules/commander/LICENSE        |   22 +
 .../mag/node_modules/commander/Readme.md      |  417 ++
 .../mag/node_modules/commander/index.js       | 1227 ++++
 .../mag/node_modules/commander/package.json   |  114 +
 .../node_modules/commander/typings/index.d.ts |  309 +
 .../node_modules/component-emitter/History.md |   68 +
 .../node_modules/component-emitter/LICENSE    |   24 +
 .../node_modules/component-emitter/Readme.md  |   74 +
 .../node_modules/component-emitter/index.js   |  163 +
 .../component-emitter/package.json            |  209 +
 .../console-control-strings/LICENSE           |   13 +
 .../console-control-strings/README.md         |  145 +
 .../console-control-strings/README.md~        |  140 +
 .../console-control-strings/index.js          |  125 +
 .../console-control-strings/package.json      |   88 +
 .../mag/node_modules/copy-descriptor/LICENSE  |   21 +
 .../mag/node_modules/copy-descriptor/index.js |   81 +
 .../node_modules/copy-descriptor/package.json |  115 +
 .../mag/node_modules/core-util-is/LICENSE     |   19 +
 .../node_modules => }/core-util-is/README.md  |    0
 .../core-util-is/float.patch                  |    0
 .../mag/node_modules/core-util-is/lib/util.js |  107 +
 .../node_modules/core-util-is/package.json    |   86 +
 .../mag/node_modules/core-util-is/test.js     |   68 +
 .../mag/node_modules/debug/CHANGELOG.md       |  395 ++
 input_devices/mag/node_modules/debug/LICENSE  |   19 +
 .../mag/node_modules/debug/README.md          |  437 ++
 .../mag/node_modules/debug/dist/debug.js      |  886 +++
 input_devices/mag/node_modules/debug/node.js  |    1 +
 .../mag/node_modules/debug/package.json       |  142 +
 .../mag/node_modules/debug/src/browser.js     |  180 +
 .../mag/node_modules/debug/src/common.js      |  249 +
 .../mag/node_modules/debug/src/index.js       |   12 +
 .../mag/node_modules/debug/src/node.js        |  174 +
 .../node_modules/decompress-response/index.js |   29 +
 .../node_modules/decompress-response/license  |   21 +
 .../decompress-response/package.json          |  100 +
 .../decompress-response/readme.md             |   31 +
 .../mag/node_modules/deep-extend/CHANGELOG.md |   46 +
 .../mag/node_modules/deep-extend/LICENSE      |   20 +
 .../mag/node_modules/deep-extend/README.md    |   91 +
 .../mag/node_modules/deep-extend/index.js     |    1 +
 .../deep-extend/lib/deep-extend.js            |  150 +
 .../mag/node_modules/deep-extend/package.json |  124 +
 .../mag/node_modules/define-property/LICENSE  |   21 +
 .../node_modules/define-property/README.md    |   95 +
 .../mag/node_modules/define-property/index.js |   31 +
 .../node_modules/define-property/package.json |  121 +
 .../graceful-fs => delegates}/.npmignore      |    0
 .../mag/node_modules/delegates/History.md     |   22 +
 .../mag/node_modules/delegates/License        |   20 +
 .../mag/node_modules/delegates/Makefile       |    8 +
 .../mag/node_modules/delegates/Readme.md      |   94 +
 .../mag/node_modules/delegates/index.js       |  121 +
 .../mag/node_modules/delegates/package.json   |   76 +
 .../mag/node_modules/delegates/test/index.js  |   94 +
 .../mag/node_modules/detect-libc/.npmignore   |    7 +
 .../mag/node_modules/detect-libc/LICENSE      |  201 +
 .../mag/node_modules/detect-libc/README.md    |   78 +
 .../detect-libc/bin/detect-libc.js            |   18 +
 .../detect-libc/lib/detect-libc.js            |   92 +
 .../mag/node_modules/detect-libc/package.json |   98 +
 .../mag/node_modules/end-of-stream/LICENSE    |   21 +
 .../mag/node_modules/end-of-stream/README.md  |   52 +
 .../mag/node_modules/end-of-stream/index.js   |   87 +
 .../node_modules/end-of-stream/package.json   |   93 +
 .../mag/node_modules/error-symbol/LICENSE     |   21 +
 .../mag/node_modules/error-symbol/README.md   |   52 +
 .../mag/node_modules/error-symbol/index.js    |    1 +
 .../node_modules/error-symbol/package.json    |  106 +
 .../node_modules/expand-template/.travis.yml  |   10 +
 .../node_modules/expand-template/README.md    |   43 +
 .../mag/node_modules/expand-template/index.js |   25 +
 .../node_modules/expand-template/package.json |   88 +
 .../mag/node_modules/expand-template/test.js  |   47 +
 .../mag/node_modules/extend-shallow/LICENSE   |   21 +
 .../mag/node_modules/extend-shallow/README.md |   61 +
 .../mag/node_modules/extend-shallow/index.js  |   33 +
 .../node_modules/extend-shallow/package.json  |  111 +
 input_devices/mag/node_modules/for-in/LICENSE |   21 +
 .../mag/node_modules/for-in/README.md         |   85 +
 .../mag/node_modules/for-in/index.js          |   16 +
 .../mag/node_modules/for-in/package.json      |  138 +
 .../mag/node_modules/for-own/LICENSE          |   21 +
 .../mag/node_modules/for-own/README.md        |   85 +
 .../mag/node_modules/for-own/index.js         |   19 +
 .../mag/node_modules/for-own/package.json     |  140 +
 .../mag/node_modules/fs-constants/LICENSE     |   21 +
 .../mag/node_modules/fs-constants/README.md   |   26 +
 .../mag/node_modules/fs-constants/browser.js  |    1 +
 .../mag/node_modules/fs-constants/index.js    |    1 +
 .../node_modules/fs-constants/package.json    |   78 +
 .../mag/node_modules/gauge/CHANGELOG.md       |  160 +
 input_devices/mag/node_modules/gauge/LICENSE  |   13 +
 .../mag/node_modules/gauge/README.md          |  399 ++
 .../mag/node_modules/gauge/base-theme.js      |   14 +
 input_devices/mag/node_modules/gauge/error.js |   24 +
 .../mag/node_modules/gauge/has-color.js       |   12 +
 input_devices/mag/node_modules/gauge/index.js |  233 +
 .../mag/node_modules/gauge/package.json       |  118 +
 .../mag/node_modules/gauge/plumbing.js        |   48 +
 .../mag/node_modules/gauge/process.js         |    3 +
 .../mag/node_modules/gauge/progress-bar.js    |   35 +
 .../mag/node_modules/gauge/render-template.js |  181 +
 .../mag/node_modules/gauge/set-immediate.js   |    7 +
 .../mag/node_modules/gauge/set-interval.js    |    3 +
 input_devices/mag/node_modules/gauge/spin.js  |    5 +
 .../mag/node_modules/gauge/template-item.js   |   73 +
 .../mag/node_modules/gauge/theme-set.js       |  115 +
 .../mag/node_modules/gauge/themes.js          |   54 +
 .../mag/node_modules/gauge/wide-truncate.js   |   25 +
 .../github-from-package/.travis.yml           |    4 +
 .../minimist => github-from-package}/LICENSE  |    0
 .../github-from-package/example/package.json  |    8 +
 .../github-from-package/example/url.js        |    3 +
 .../node_modules/github-from-package/index.js |   17 +
 .../github-from-package/package.json          |   80 +
 .../github-from-package/readme.markdown       |   53 +
 .../github-from-package/test/a.json           |    8 +
 .../github-from-package/test/b.json           |    5 +
 .../github-from-package/test/c.json           |    5 +
 .../github-from-package/test/d.json           |    7 +
 .../github-from-package/test/e.json           |    5 +
 .../github-from-package/test/url.js           |   19 +
 .../mag/node_modules/has-unicode/LICENSE      |   14 +
 .../mag/node_modules/has-unicode/README.md    |   43 +
 .../mag/node_modules/has-unicode/index.js     |   16 +
 .../mag/node_modules/has-unicode/package.json |   86 +
 .../mag/node_modules/info-symbol/LICENSE      |   21 +
 .../mag/node_modules/info-symbol/README.md    |   52 +
 .../mag/node_modules/info-symbol/index.js     |    1 +
 .../mag/node_modules/info-symbol/package.json |  106 +
 .../node_modules => }/inherits/LICENSE        |    0
 .../node_modules => }/inherits/README.md      |    0
 .../mag/node_modules/inherits/inherits.js     |    7 +
 .../inherits/inherits_browser.js              |    0
 .../mag/node_modules/inherits/package.json    |   89 +
 input_devices/mag/node_modules/ini/LICENSE    |   15 +
 input_devices/mag/node_modules/ini/README.md  |  102 +
 input_devices/mag/node_modules/ini/ini.js     |  194 +
 .../mag/node_modules/ini/package.json         |   91 +
 .../is-accessor-descriptor/LICENSE            |   21 +
 .../is-accessor-descriptor/README.md          |  144 +
 .../is-accessor-descriptor/index.js           |   69 +
 .../node_modules/kind-of/CHANGELOG.md         |  157 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  365 ++
 .../node_modules/kind-of/index.js             |  129 +
 .../node_modules/kind-of/package.json         |  176 +
 .../is-accessor-descriptor/package.json       |  138 +
 .../mag/node_modules/is-buffer/LICENSE        |   21 +
 .../mag/node_modules/is-buffer/README.md      |   53 +
 .../mag/node_modules/is-buffer/index.js       |   21 +
 .../mag/node_modules/is-buffer/package.json   |  108 +
 .../mag/node_modules/is-buffer/test/basic.js  |   24 +
 .../node_modules/is-data-descriptor/LICENSE   |   21 +
 .../node_modules/is-data-descriptor/README.md |  161 +
 .../node_modules/is-data-descriptor/index.js  |   49 +
 .../node_modules/kind-of/CHANGELOG.md         |  157 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  365 ++
 .../node_modules/kind-of/index.js             |  129 +
 .../node_modules/kind-of/package.json         |  176 +
 .../is-data-descriptor/package.json           |  137 +
 .../mag/node_modules/is-descriptor/LICENSE    |   21 +
 .../mag/node_modules/is-descriptor/README.md  |  193 +
 .../mag/node_modules/is-descriptor/index.js   |   22 +
 .../node_modules/kind-of/CHANGELOG.md         |  157 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  365 ++
 .../node_modules/kind-of/index.js             |  129 +
 .../node_modules/kind-of/package.json         |  176 +
 .../node_modules/is-descriptor/package.json   |  143 +
 .../mag/node_modules/is-extendable/LICENSE    |   21 +
 .../mag/node_modules/is-extendable/README.md  |   72 +
 .../mag/node_modules/is-extendable/index.js   |   13 +
 .../node_modules/is-extendable/package.json   |  108 +
 .../is-fullwidth-code-point/index.js          |   46 +
 .../is-fullwidth-code-point/license           |   21 +
 .../is-fullwidth-code-point/package.json      |  100 +
 .../is-fullwidth-code-point/readme.md         |   39 +
 .../mag/node_modules/is-number/LICENSE        |   21 +
 .../mag/node_modules/is-number/README.md      |  152 +
 .../mag/node_modules/is-number/index.js       |   31 +
 .../mag/node_modules/is-number/package.json   |  154 +
 .../mag/node_modules/is-plain-object/LICENSE  |   21 +
 .../node_modules/is-plain-object/README.md    |  104 +
 .../node_modules/is-plain-object/index.d.ts   |    5 +
 .../mag/node_modules/is-plain-object/index.js |   37 +
 .../node_modules/is-plain-object/package.json |  154 +
 .../mag/node_modules/is-windows/LICENSE       |   21 +
 .../mag/node_modules/is-windows/README.md     |   95 +
 .../mag/node_modules/is-windows/index.js      |   27 +
 .../mag/node_modules/is-windows/package.json  |  147 +
 .../node_modules/nopt => isarray}/.npmignore  |    0
 .../minimist => isarray}/.travis.yml          |    0
 .../mag/node_modules/isarray/Makefile         |    6 +
 .../mag/node_modules/isarray/README.md        |   60 +
 .../node_modules => }/isarray/component.json  |    0
 .../mag/node_modules/isarray/index.js         |    5 +
 .../mag/node_modules/isarray/package.json     |   96 +
 .../mag/node_modules/isarray/test.js          |   20 +
 .../mag/node_modules/isobject/LICENSE         |   21 +
 .../mag/node_modules/isobject/README.md       |  122 +
 .../mag/node_modules/isobject/index.d.ts      |    5 +
 .../mag/node_modules/isobject/index.js        |   12 +
 .../mag/node_modules/isobject/package.json    |  154 +
 .../mag/node_modules/kind-of/LICENSE          |   21 +
 .../mag/node_modules/kind-of/README.md        |  261 +
 .../mag/node_modules/kind-of/index.js         |  116 +
 .../mag/node_modules/kind-of/package.json     |  176 +
 input_devices/mag/node_modules/koalas/LICENSE |   21 +
 .../mag/node_modules/koalas/README.md         |   91 +
 .../mag/node_modules/koalas/index.js          |   58 +
 .../mag/node_modules/koalas/package.json      |  133 +
 .../mag/node_modules/lazy-cache/LICENSE       |   21 +
 .../mag/node_modules/lazy-cache/README.md     |  195 +
 .../mag/node_modules/lazy-cache/index.js      |   73 +
 .../mag/node_modules/lazy-cache/package.json  |  139 +
 input_devices/mag/node_modules/log-ok/LICENSE |   21 +
 .../mag/node_modules/log-ok/index.js          |   20 +
 .../mag/node_modules/log-ok/package.json      |  115 +
 .../mag/node_modules/log-utils/LICENSE        |   21 +
 .../mag/node_modules/log-utils/index.js       |  224 +
 .../mag/node_modules/log-utils/package.json   |  153 +
 .../mag/node_modules/map-visit/LICENSE        |   21 +
 .../mag/node_modules/map-visit/README.md      |  155 +
 .../mag/node_modules/map-visit/index.js       |   37 +
 .../mag/node_modules/map-visit/package.json   |  144 +
 .../mag/node_modules/mimic-response/index.js  |   32 +
 .../mag/node_modules/mimic-response/license   |    9 +
 .../node_modules/mimic-response/package.json  |  101 +
 .../mag/node_modules/mimic-response/readme.md |   54 +
 .../mag/node_modules/minimist/.travis.yml     |    8 +
 .../rc/node_modules => }/minimist/LICENSE     |    0
 .../minimist/example/parse.js                 |    0
 .../mag/node_modules/minimist/index.js        |  236 +
 .../mag/node_modules/minimist/package.json    |   98 +
 .../mag/node_modules/minimist/readme.markdown |   91 +
 .../node_modules/minimist/test/all_bool.js    |   32 +
 .../mag/node_modules/minimist/test/bool.js    |  166 +
 .../mag/node_modules/minimist/test/dash.js    |   31 +
 .../minimist/test/default_bool.js             |   35 +
 .../node_modules => }/minimist/test/dotted.js |    0
 .../node_modules/minimist/test/kv_short.js    |   16 +
 .../node_modules => }/minimist/test/long.js   |    0
 .../rc/node_modules => }/minimist/test/num.js |    0
 .../node_modules => }/minimist/test/parse.js  |    0
 .../minimist/test/parse_modified.js           |    9 +
 .../node_modules => }/minimist/test/short.js  |    0
 .../node_modules/minimist/test/stop_early.js  |   15 +
 .../mag/node_modules/minimist/test/unknown.js |  102 +
 .../minimist/test/whitespace.js               |    0
 .../mag/node_modules/mixin-object/LICENSE     |   21 +
 .../mag/node_modules/mixin-object/README.md   |   75 +
 .../mag/node_modules/mixin-object/index.js    |   36 +
 .../mixin-object/node_modules/for-in/LICENSE  |   21 +
 .../node_modules/for-in/README.md             |   85 +
 .../mixin-object/node_modules/for-in/index.js |   16 +
 .../node_modules/for-in/package.json          |  135 +
 .../node_modules/mixin-object/package.json    |  115 +
 .../mag/node_modules/mkdirp/.travis.yml       |    8 +
 .../node_modules => }/mkdirp/LICENSE          |    0
 .../node_modules => }/mkdirp/bin/cmd.js       |    0
 .../node_modules => }/mkdirp/bin/usage.txt    |    0
 .../node_modules => }/mkdirp/examples/pow.js  |    0
 .../mag/node_modules/mkdirp/index.js          |   98 +
 .../node_modules/minimist/.travis.yml         |    0
 .../node_modules/minimist/LICENSE             |    0
 .../node_modules/minimist/example/parse.js    |    0
 .../mkdirp/node_modules/minimist/index.js     |    0
 .../mkdirp/node_modules/minimist/package.json |   93 +
 .../node_modules/minimist/readme.markdown     |    0
 .../mkdirp/node_modules/minimist/test/dash.js |    0
 .../minimist/test/default_bool.js             |    0
 .../node_modules/minimist/test/dotted.js      |    0
 .../node_modules/minimist/test/long.js        |    0
 .../node_modules/minimist/test/parse.js       |    0
 .../minimist/test/parse_modified.js           |    0
 .../node_modules/minimist/test/short.js       |    0
 .../node_modules/minimist/test/whitespace.js  |    0
 .../mag/node_modules/mkdirp/package.json      |   86 +
 .../node_modules => }/mkdirp/readme.markdown  |    0
 .../mag/node_modules/mkdirp/test/chmod.js     |   41 +
 .../mag/node_modules/mkdirp/test/clobber.js   |   38 +
 .../mag/node_modules/mkdirp/test/mkdirp.js    |   28 +
 .../node_modules => }/mkdirp/test/opts_fs.js  |    6 +-
 .../mkdirp/test/opts_fs_sync.js               |    6 +-
 .../mag/node_modules/mkdirp/test/perm.js      |   32 +
 .../mag/node_modules/mkdirp/test/perm_sync.js |   36 +
 .../mag/node_modules/mkdirp/test/race.js      |   37 +
 .../mag/node_modules/mkdirp/test/rel.js       |   32 +
 .../node_modules => }/mkdirp/test/return.js   |    0
 .../mkdirp/test/return_sync.js                |    0
 .../mag/node_modules/mkdirp/test/root.js      |   19 +
 .../mag/node_modules/mkdirp/test/sync.js      |   32 +
 .../mag/node_modules/mkdirp/test/umask.js     |   28 +
 .../node_modules/mkdirp/test/umask_sync.js    |   32 +
 input_devices/mag/node_modules/ms/index.js    |  162 +
 input_devices/mag/node_modules/ms/license.md  |   21 +
 .../mag/node_modules/ms/package.json          |  102 +
 input_devices/mag/node_modules/ms/readme.md   |   60 +
 .../mute-stream/.nyc_output/33508.json        |    1 +
 .../mute-stream/.nyc_output/33510.json        |    1 +
 .../mag/node_modules/mute-stream/.travis.yml  |    9 +
 .../mag/node_modules/mute-stream/LICENSE      |   15 +
 .../mag/node_modules/mute-stream/README.md    |   68 +
 .../coverage/lcov-report/__root__/index.html  |   93 +
 .../lcov-report/__root__/mute.js.html         |  500 ++
 .../mute-stream/coverage/lcov-report/base.css |  212 +
 .../coverage/lcov-report/index.html           |   93 +
 .../coverage/lcov-report/prettify.css         |    1 +
 .../coverage/lcov-report/prettify.js          |    1 +
 .../lcov-report/sort-arrow-sprite.png         |  Bin 0 -> 209 bytes
 .../coverage/lcov-report/sorter.js            |  158 +
 .../mute-stream/coverage/lcov.info            |  155 +
 .../mag/node_modules/mute-stream/mute.js      |  145 +
 .../mag/node_modules/mute-stream/package.json |   98 +
 .../node_modules/mute-stream/test/basic.js    |  207 +
 .../mag/node_modules/nan/CHANGELOG.md         |  503 ++
 input_devices/mag/node_modules/nan/LICENSE.md |   13 +
 input_devices/mag/node_modules/nan/README.md  |  456 ++
 .../mag/node_modules/nan/doc/asyncworker.md   |  146 +
 .../mag/node_modules/nan/doc/buffers.md       |   54 +
 .../mag/node_modules/nan/doc/callback.md      |   76 +
 .../mag/node_modules/nan/doc/converters.md    |   41 +
 .../mag/node_modules/nan/doc/errors.md        |  226 +
 .../mag/node_modules/nan/doc/json.md          |   62 +
 .../mag/node_modules/nan/doc/maybe_types.md   |  583 ++
 .../mag/node_modules/nan/doc/methods.md       |  661 +++
 input_devices/mag/node_modules/nan/doc/new.md |  147 +
 .../mag/node_modules/nan/doc/node_misc.md     |  123 +
 .../node_modules/nan/doc/object_wrappers.md   |  263 +
 .../mag/node_modules/nan/doc/persistent.md    |  296 +
 .../mag/node_modules/nan/doc/scopes.md        |   73 +
 .../mag/node_modules/nan/doc/script.md        |   38 +
 .../mag/node_modules/nan/doc/string_bytes.md  |   62 +
 .../mag/node_modules/nan/doc/v8_internals.md  |  199 +
 .../mag/node_modules/nan/doc/v8_misc.md       |   85 +
 .../node_modules => }/nan/include_dirs.js     |    0
 .../mag/node_modules/nan/nan-2.11.1.tgz       |  Bin 0 -> 74561 bytes
 input_devices/mag/node_modules/nan/nan.h      | 2802 +++++++++
 .../mag/node_modules/nan/nan_callbacks.h      |   88 +
 .../node_modules/nan/nan_callbacks_12_inl.h   |  514 ++
 .../nan/nan_callbacks_pre_12_inl.h            |  520 ++
 .../mag/node_modules/nan/nan_converters.h     |   72 +
 .../node_modules/nan/nan_converters_43_inl.h  |   48 +
 .../nan/nan_converters_pre_43_inl.h           |   42 +
 .../nan/nan_define_own_property_helper.h      |   29 +
 .../nan/nan_implementation_12_inl.h           |  403 ++
 .../nan/nan_implementation_pre_12_inl.h       |  263 +
 input_devices/mag/node_modules/nan/nan_json.h |  166 +
 .../mag/node_modules/nan/nan_maybe_43_inl.h   |  369 ++
 .../node_modules/nan/nan_maybe_pre_43_inl.h   |  316 +
 input_devices/mag/node_modules/nan/nan_new.h  |  340 ++
 .../mag/node_modules/nan/nan_object_wrap.h    |  155 +
 .../node_modules/nan/nan_persistent_12_inl.h  |  132 +
 .../nan/nan_persistent_pre_12_inl.h           |  242 +
 .../mag/node_modules/nan/nan_private.h        |   73 +
 .../mag/node_modules/nan/nan_string_bytes.h   |  305 +
 .../nan/nan_typedarray_contents.h             |   90 +
 input_devices/mag/node_modules/nan/nan_weak.h |  432 ++
 .../mag/node_modules/nan/package.json         |  135 +
 .../mag/node_modules/nan/tools/1to2.js        |  412 ++
 .../mag/node_modules/nan/tools/README.md      |   14 +
 .../mag/node_modules/nan/tools/package.json   |   19 +
 .../mag/node_modules/napi-build-utils/LICENSE |   21 +
 .../node_modules/napi-build-utils/README.md   |   48 +
 .../node_modules/napi-build-utils/index.js    |  213 +
 .../node_modules/napi-build-utils/index.md    |   81 +
 .../napi-build-utils-1.0.0.tgz                |  Bin 0 -> 26382 bytes
 .../napi-build-utils/package.json             |   99 +
 .../mag/node_modules/node-abi/.travis.yml     |   19 +
 .../node_modules/node-abi/CODE_OF_CONDUCT.md  |   73 +
 .../mag/node_modules/node-abi/CONTRIBUTING.md |   53 +
 .../mag/node_modules/node-abi/LICENSE         |   21 +
 .../mag/node_modules/node-abi/README.md       |   50 +
 .../mag/node_modules/node-abi/index.js        |  112 +
 .../mag/node_modules/node-abi/package.json    |  107 +
 .../mag/node_modules/node-abi/test/index.js   |  151 +
 .../mag/node_modules/noop-logger/.npmignore   |    1 +
 .../mag/node_modules/noop-logger/History.md   |   16 +
 .../mag/node_modules/noop-logger/Makefile     |    8 +
 .../mag/node_modules/noop-logger/Readme.md    |   27 +
 .../mag/node_modules/noop-logger/circle.yml   |    9 +
 .../mag/node_modules/noop-logger/lib/index.js |   25 +
 .../mag/node_modules/noop-logger/package.json |   78 +
 .../node_modules/noop-logger/test/index.js    |   18 +
 .../mag/node_modules/npmlog/CHANGELOG.md      |   49 +
 input_devices/mag/node_modules/npmlog/LICENSE |   15 +
 .../mag/node_modules/npmlog/README.md         |  216 +
 input_devices/mag/node_modules/npmlog/log.js  |  309 +
 .../mag/node_modules/npmlog/package.json      |  101 +
 .../mag/node_modules/number-is-nan/index.js   |    4 +
 .../mag/node_modules/number-is-nan/license    |   21 +
 .../node_modules/number-is-nan/package.json   |   95 +
 .../mag/node_modules/number-is-nan/readme.md  |   28 +
 .../mag/node_modules/object-assign/index.js   |   90 +
 .../mag/node_modules/object-assign/license    |   21 +
 .../node_modules/object-assign/package.json   |  110 +
 .../mag/node_modules/object-assign/readme.md  |   61 +
 .../mag/node_modules/object-copy/LICENSE      |   21 +
 .../mag/node_modules/object-copy/index.js     |  174 +
 .../node_modules/define-property/LICENSE      |   21 +
 .../node_modules/define-property/README.md    |   77 +
 .../node_modules/define-property/index.js     |   31 +
 .../node_modules/define-property/package.json |  105 +
 .../is-accessor-descriptor/LICENSE            |   21 +
 .../is-accessor-descriptor/README.md          |  123 +
 .../is-accessor-descriptor/index.js           |   69 +
 .../is-accessor-descriptor/package.json       |  115 +
 .../node_modules/is-data-descriptor/LICENSE   |   21 +
 .../node_modules/is-data-descriptor/README.md |  128 +
 .../node_modules/is-data-descriptor/index.js  |   55 +
 .../is-data-descriptor/package.json           |  114 +
 .../node_modules/is-descriptor/LICENSE        |   21 +
 .../node_modules/is-descriptor/README.md      |  193 +
 .../node_modules/is-descriptor/index.js       |   22 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  342 ++
 .../node_modules/kind-of/index.js             |  147 +
 .../node_modules/kind-of/package.json         |  179 +
 .../node_modules/is-descriptor/package.json   |  142 +
 .../mag/node_modules/object-copy/package.json |  107 +
 .../mag/node_modules/object-visit/LICENSE     |   21 +
 .../mag/node_modules/object-visit/README.md   |   83 +
 .../mag/node_modules/object-visit/index.js    |   33 +
 .../node_modules/object-visit/package.json    |  124 +
 input_devices/mag/node_modules/once/LICENSE   |   15 +
 input_devices/mag/node_modules/once/README.md |   79 +
 input_devices/mag/node_modules/once/once.js   |   42 +
 .../mag/node_modules/once/package.json        |   95 +
 .../mag/node_modules/os-homedir/index.js      |   24 +
 .../mag/node_modules/os-homedir/license       |   21 +
 .../mag/node_modules/os-homedir/package.json  |  101 +
 .../mag/node_modules/os-homedir/readme.md     |   31 +
 .../mag/node_modules/pointer-symbol/LICENSE   |   21 +
 .../mag/node_modules/pointer-symbol/README.md |   81 +
 .../mag/node_modules/pointer-symbol/index.js  |   20 +
 .../node_modules/pointer-symbol/package.json  |  102 +
 .../node_modules/prebuild-install/.travis.yml |   10 +
 .../prebuild-install/CONTRIBUTING.md          |    8 +
 .../mag/node_modules/prebuild-install/LICENSE |   21 +
 .../node_modules/prebuild-install/README.md   |  102 +
 .../prebuild-install/appveyor.yml             |   38 +
 .../node_modules/prebuild-install/asset.js    |   48 +
 .../mag/node_modules/prebuild-install/bin.js  |   79 +
 .../node_modules/prebuild-install/download.js |  130 +
 .../node_modules/prebuild-install/error.js    |   13 +
 .../node_modules/prebuild-install/help.txt    |   14 +
 .../node_modules/prebuild-install/index.js    |    1 +
 .../mag/node_modules/prebuild-install/log.js  |   13 +
 .../prebuild-install/package.json             |  178 +
 .../node_modules/prebuild-install/proxy.js    |   36 +
 .../mag/node_modules/prebuild-install/rc.js   |   79 +
 .../mag/node_modules/prebuild-install/util.js |   97 +
 .../process-nextick-args/index.js             |   44 +
 .../process-nextick-args/license.md           |   19 +
 .../process-nextick-args/package.json         |   79 +
 .../process-nextick-args/readme.md            |   18 +
 .../mag/node_modules/promirepl/.npmignore     |    3 +
 .../mag/node_modules/promirepl/LICENSE        |   22 +
 .../mag/node_modules/promirepl/README.md      |   78 +
 .../node_modules/promirepl/bin/prominode.js   |    8 +
 .../mag/node_modules/promirepl/index.js       |   73 +
 .../mag/node_modules/promirepl/package.json   |   77 +
 .../mag/node_modules/prompt-actions/LICENSE   |   21 +
 .../mag/node_modules/prompt-actions/README.md |   78 +
 .../mag/node_modules/prompt-actions/index.js  |  267 +
 .../node_modules/debug/.coveralls.yml         |    1 +
 .../node_modules/debug/.eslintrc              |   11 +
 .../node_modules/debug/.npmignore             |    9 +
 .../node_modules/debug/.travis.yml            |   14 +
 .../node_modules/debug/CHANGELOG.md           |  362 ++
 .../prompt-actions/node_modules/debug/LICENSE |   19 +
 .../node_modules/debug/Makefile               |   50 +
 .../node_modules/debug/README.md              |  312 +
 .../node_modules/debug/component.json         |   19 +
 .../node_modules/debug/karma.conf.js          |   70 +
 .../prompt-actions/node_modules/debug/node.js |    1 +
 .../node_modules/debug/package.json           |  128 +
 .../node_modules/debug/src/browser.js         |  185 +
 .../node_modules/debug/src/debug.js           |  202 +
 .../node_modules/debug/src/index.js           |   10 +
 .../node_modules/debug/src/inspector-log.js   |   15 +
 .../node_modules/debug/src/node.js            |  248 +
 .../prompt-actions/node_modules/ms/index.js   |  152 +
 .../prompt-actions/node_modules/ms/license.md |   21 +
 .../node_modules/ms/package.json              |  101 +
 .../prompt-actions/node_modules/ms/readme.md  |   51 +
 .../node_modules/prompt-actions/package.json  |  124 +
 .../mag/node_modules/prompt-base/LICENSE      |   21 +
 .../mag/node_modules/prompt-base/README.md    |  675 +++
 .../mag/node_modules/prompt-base/changelog.md |   55 +
 .../mag/node_modules/prompt-base/index.js     |  938 +++
 .../mag/node_modules/prompt-base/package.json |  192 +
 .../mag/node_modules/prompt-checkbox/LICENSE  |   21 +
 .../node_modules/prompt-checkbox/README.md    |  331 ++
 .../mag/node_modules/prompt-checkbox/index.js |   50 +
 .../node_modules/debug/.coveralls.yml         |    1 +
 .../node_modules/debug/.eslintrc              |   11 +
 .../node_modules/debug/.npmignore             |    9 +
 .../node_modules/debug/.travis.yml            |   14 +
 .../node_modules/debug/CHANGELOG.md           |  362 ++
 .../node_modules/debug/LICENSE                |   19 +
 .../node_modules/debug/Makefile               |   50 +
 .../node_modules/debug/README.md              |  312 +
 .../node_modules/debug/component.json         |   19 +
 .../node_modules/debug/karma.conf.js          |   70 +
 .../node_modules/debug/node.js                |    1 +
 .../node_modules/debug/package.json           |  128 +
 .../node_modules/debug/src/browser.js         |  185 +
 .../node_modules/debug/src/debug.js           |  202 +
 .../node_modules/debug/src/index.js           |   10 +
 .../node_modules/debug/src/inspector-log.js   |   15 +
 .../node_modules/debug/src/node.js            |  248 +
 .../prompt-checkbox/node_modules/ms/index.js  |  152 +
 .../node_modules/ms/license.md                |   21 +
 .../node_modules/ms/package.json              |  101 +
 .../prompt-checkbox/node_modules/ms/readme.md |   51 +
 .../node_modules/prompt-checkbox/package.json |  168 +
 .../mag/node_modules/prompt-choices/LICENSE   |   21 +
 .../mag/node_modules/prompt-choices/README.md |  523 ++
 .../mag/node_modules/prompt-choices/index.js  |  867 +++
 .../node_modules/prompt-choices/lib/choice.js |  258 +
 .../node_modules/prompt-choices/lib/utils.js  |   46 +
 .../node_modules/clone-deep/LICENSE           |   21 +
 .../node_modules/clone-deep/README.md         |   98 +
 .../node_modules/clone-deep/index.js          |   48 +
 .../node_modules/clone-deep/package.json      |  141 +
 .../node_modules/define-property/CHANGELOG.md |   82 +
 .../node_modules/define-property/LICENSE      |   21 +
 .../node_modules/define-property/README.md    |  117 +
 .../node_modules/define-property/index.js     |   38 +
 .../node_modules/define-property/package.json |  136 +
 .../node_modules/kind-of/CHANGELOG.md         |  157 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  365 ++
 .../node_modules/kind-of/index.js             |  129 +
 .../node_modules/kind-of/package.json         |  178 +
 .../node_modules/shallow-clone/LICENSE        |   21 +
 .../node_modules/shallow-clone/README.md      |  152 +
 .../node_modules/shallow-clone/index.js       |   82 +
 .../node_modules/shallow-clone/package.json   |  135 +
 .../node_modules/prompt-choices/package.json  |  165 +
 .../mag/node_modules/prompt-list/LICENSE      |   21 +
 .../mag/node_modules/prompt-list/README.md    |  173 +
 .../mag/node_modules/prompt-list/index.js     |   84 +
 .../mag/node_modules/prompt-list/package.json |  164 +
 .../mag/node_modules/prompt-question/LICENSE  |   21 +
 .../node_modules/prompt-question/README.md    |  301 +
 .../mag/node_modules/prompt-question/index.js |  326 +
 .../node_modules/prompt-question/lib/utils.js |   72 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  342 ++
 .../node_modules/kind-of/index.js             |  147 +
 .../node_modules/kind-of/package.json         |  179 +
 .../node_modules/prompt-question/package.json |  153 +
 .../mag/node_modules/prompt-radio/LICENSE     |   21 +
 .../mag/node_modules/prompt-radio/README.md   |  152 +
 .../mag/node_modules/prompt-radio/index.js    |   60 +
 .../node_modules/debug/.coveralls.yml         |    1 +
 .../prompt-radio/node_modules/debug/.eslintrc |   11 +
 .../node_modules/debug/.npmignore             |    9 +
 .../node_modules/debug/.travis.yml            |   14 +
 .../node_modules/debug/CHANGELOG.md           |  362 ++
 .../prompt-radio/node_modules/debug/LICENSE   |   19 +
 .../prompt-radio/node_modules/debug/Makefile  |   50 +
 .../prompt-radio/node_modules/debug/README.md |  312 +
 .../node_modules/debug/component.json         |   19 +
 .../node_modules/debug/karma.conf.js          |   70 +
 .../prompt-radio/node_modules/debug/node.js   |    1 +
 .../node_modules/debug/package.json           |  128 +
 .../node_modules/debug/src/browser.js         |  185 +
 .../node_modules/debug/src/debug.js           |  202 +
 .../node_modules/debug/src/index.js           |   10 +
 .../node_modules/debug/src/inspector-log.js   |   15 +
 .../node_modules/debug/src/node.js            |  248 +
 .../prompt-radio/node_modules/ms/index.js     |  152 +
 .../prompt-radio/node_modules/ms/license.md   |   21 +
 .../prompt-radio/node_modules/ms/package.json |  101 +
 .../prompt-radio/node_modules/ms/readme.md    |   51 +
 .../node_modules/prompt-radio/package.json    |  146 +
 .../mag/node_modules/pump/.travis.yml         |    5 +
 input_devices/mag/node_modules/pump/LICENSE   |   21 +
 input_devices/mag/node_modules/pump/README.md |   56 +
 input_devices/mag/node_modules/pump/index.js  |   82 +
 .../mag/node_modules/pump/package.json        |   88 +
 .../mag/node_modules/pump/test-browser.js     |   62 +
 .../mag/node_modules/pump/test-node.js        |   53 +
 .../mag/node_modules/radio-symbol/LICENSE     |   21 +
 .../mag/node_modules/radio-symbol/README.md   |  147 +
 .../mag/node_modules/radio-symbol/index.js    |   53 +
 .../node_modules/radio-symbol/package.json    |  119 +
 .../node_modules => }/rc/LICENSE.APACHE2      |    0
 .../node_modules => }/rc/LICENSE.BSD          |    0
 .../node_modules => }/rc/LICENSE.MIT          |    0
 input_devices/mag/node_modules/rc/README.md   |  227 +
 .../node_modules => }/rc/browser.js           |    0
 input_devices/mag/node_modules/rc/cli.js      |    4 +
 input_devices/mag/node_modules/rc/index.js    |   53 +
 .../mag/node_modules/rc/lib/utils.js          |  104 +
 .../mag/node_modules/rc/package.json          |   96 +
 .../node_modules => }/rc/test/ini.js          |    0
 .../node_modules/rc/test/nested-env-vars.js   |   50 +
 .../mag/node_modules/rc/test/test.js          |   59 +
 .../node_modules/readable-stream/.travis.yml  |   55 +
 .../readable-stream/CONTRIBUTING.md           |   38 +
 .../readable-stream/GOVERNANCE.md             |  136 +
 .../mag/node_modules/readable-stream/LICENSE  |   47 +
 .../node_modules/readable-stream/README.md    |   58 +
 .../doc/wg-meetings/2015-01-30.md             |   60 +
 .../readable-stream/duplex-browser.js         |    1 +
 .../node_modules/readable-stream/duplex.js    |    1 +
 .../readable-stream/lib/_stream_duplex.js     |  131 +
 .../lib/_stream_passthrough.js                |    9 +-
 .../readable-stream/lib/_stream_readable.js   | 1019 ++++
 .../readable-stream/lib/_stream_transform.js  |  214 +
 .../readable-stream/lib/_stream_writable.js   |  687 +++
 .../lib/internal/streams/BufferList.js        |   79 +
 .../lib/internal/streams/destroy.js           |   74 +
 .../lib/internal/streams/stream-browser.js    |    1 +
 .../lib/internal/streams/stream.js            |    1 +
 .../node_modules/readable-stream/package.json |  134 +
 .../readable-stream/passthrough.js            |    1 +
 .../readable-stream/readable-browser.js       |    7 +
 .../node_modules/readable-stream/readable.js  |   19 +
 .../node_modules/readable-stream/transform.js |    1 +
 .../readable-stream/writable-browser.js       |    1 +
 .../node_modules/readable-stream/writable.js  |    8 +
 .../mag/node_modules/readline-ui/LICENSE      |   21 +
 .../mag/node_modules/readline-ui/README.md    |  198 +
 .../mag/node_modules/readline-ui/index.js     |  301 +
 .../node_modules/ansi-regex/index.js          |   10 +
 .../node_modules/ansi-regex/license           |    9 +
 .../node_modules/ansi-regex/package.json      |  121 +
 .../node_modules/ansi-regex/readme.md         |   46 +
 .../node_modules/debug/.coveralls.yml         |    1 +
 .../readline-ui/node_modules/debug/.eslintrc  |   11 +
 .../readline-ui/node_modules/debug/.npmignore |    9 +
 .../node_modules/debug/.travis.yml            |   14 +
 .../node_modules/debug/CHANGELOG.md           |  362 ++
 .../readline-ui/node_modules/debug/LICENSE    |   19 +
 .../readline-ui/node_modules/debug/Makefile   |   50 +
 .../readline-ui/node_modules/debug/README.md  |  312 +
 .../node_modules/debug/component.json         |   19 +
 .../node_modules/debug/karma.conf.js          |   70 +
 .../readline-ui/node_modules/debug/node.js    |    1 +
 .../node_modules/debug/package.json           |  128 +
 .../node_modules/debug/src/browser.js         |  185 +
 .../node_modules/debug/src/debug.js           |  202 +
 .../node_modules/debug/src/index.js           |   10 +
 .../node_modules/debug/src/inspector-log.js   |   15 +
 .../node_modules/debug/src/node.js            |  248 +
 .../is-fullwidth-code-point/index.js          |   46 +
 .../is-fullwidth-code-point/license           |   21 +
 .../is-fullwidth-code-point/package.json      |  105 +
 .../is-fullwidth-code-point/readme.md         |   39 +
 .../readline-ui/node_modules/ms/index.js      |  152 +
 .../readline-ui/node_modules/ms/license.md    |   21 +
 .../readline-ui/node_modules/ms/package.json  |  101 +
 .../readline-ui/node_modules/ms/readme.md     |   51 +
 .../node_modules/string-width/index.js        |   36 +
 .../node_modules/string-width/license         |    9 +
 .../node_modules/string-width/package.json    |  115 +
 .../node_modules/string-width/readme.md       |   42 +
 .../node_modules/strip-ansi/index.js          |    4 +
 .../node_modules/strip-ansi/license           |    9 +
 .../node_modules/strip-ansi/package.json      |  119 +
 .../node_modules/strip-ansi/readme.md         |   39 +
 .../mag/node_modules/readline-ui/package.json |  139 +
 .../mag/node_modules/readline-utils/LICENSE   |   21 +
 .../mag/node_modules/readline-utils/README.md |  359 ++
 .../mag/node_modules/readline-utils/index.js  |  814 +++
 .../node_modules/is-number/LICENSE            |   21 +
 .../node_modules/is-number/README.md          |  115 +
 .../node_modules/is-number/index.js           |   22 +
 .../node_modules/is-number/package.json       |  152 +
 .../node_modules/readline-utils/package.json  |  137 +
 .../mag/node_modules/safe-buffer/LICENSE      |   21 +
 .../mag/node_modules/safe-buffer/README.md    |  584 ++
 .../mag/node_modules/safe-buffer/index.d.ts   |  187 +
 .../mag/node_modules/safe-buffer/index.js     |   62 +
 .../mag/node_modules/safe-buffer/package.json |  101 +
 input_devices/mag/node_modules/semver/LICENSE |   15 +
 .../mag/node_modules/semver/README.md         |  399 ++
 .../mag/node_modules/semver/bin/semver        |  153 +
 .../mag/node_modules/semver/package.json      |   86 +
 .../mag/node_modules/semver/range.bnf         |   16 +
 .../mag/node_modules/semver/semver.js         | 1352 +++++
 .../mag/node_modules/serialport/.jshintrc     |   28 -
 .../mag/node_modules/serialport/.npmignore    |    5 -
 .../mag/node_modules/serialport/.travis.yml   |   74 -
 .../mag/node_modules/serialport/AUTHORS       |   18 -
 .../mag/node_modules/serialport/CHANGELOG.md  |  578 ++
 .../mag/node_modules/serialport/Gruntfile.js  |   24 -
 .../mag/node_modules/serialport/LICENSE       |    7 +-
 .../mag/node_modules/serialport/Makefile      |   30 -
 .../mag/node_modules/serialport/README.md     |  608 +-
 .../mag/node_modules/serialport/appveyor.yml  |   80 -
 .../arduinoTest/arduinoEcho/arduinoEcho.ino   |   18 -
 .../serialport/arduinoTest/requiresComPort.js |  118 -
 .../serialport/arduinoTest/stress.js          |   74 -
 .../mag/node_modules/serialport/bin/echo.js   |   34 +
 .../mag/node_modules/serialport/bin/list.js   |   48 +
 .../mag/node_modules/serialport/bin/repl.js   |   52 +
 .../serialport/bin/serialportList.js          |   15 -
 .../serialport/bin/serialportTerminal.js      |   80 -
 .../node_modules/serialport/bin/terminal.js   |  116 +
 .../mag/node_modules/serialport/binding.gyp   |   62 -
 .../node_modules/serialport/build/Makefile    |  355 --
 .../obj.target/action_after_build.stamp.d     |    1 -
 .../obj.target/serialport/src/serialport.o.d  |   32 -
 .../serialport/src/serialport_poller.o.d      |   32 -
 .../serialport/src/serialport_unix.o.d        |   33 -
 .../Release/.deps/Release/serialport.node.d   |    1 -
 .../node-v11-darwin-x64/serialport.node.d     |    1 -
 .../obj.target/serialport/src/serialport.o    |  Bin 193672 -> 0 bytes
 .../serialport/src/serialport_poller.o        |  Bin 120596 -> 0 bytes
 .../serialport/src/serialport_unix.o          |  Bin 119268 -> 0 bytes
 .../build/action_after_build.target.mk        |   32 -
 .../serialport/build/binding.Makefile         |    6 -
 .../node_modules/serialport/build/config.gypi |  140 -
 .../serialport/build/gyp-mac-tool             |  512 --
 .../serialport/build/serialport.target.mk     |  162 -
 .../node-v11-linux-x64/serialport.node        |  Bin 55065 -> 0 bytes
 .../mag/node_modules/serialport/changelog.md  |  146 -
 .../node_modules/serialport/examples/break.js |   39 -
 .../node_modules/serialport/examples/drain.js |   45 -
 .../serialport/examples/logger.js             |   58 -
 .../serialport/examples/readdata.js           |   19 -
 .../node_modules/serialport/examples/reset.js |   43 -
 .../serialport/hwtest/package.json            |   13 -
 .../node_modules/serialport/hwtest/test1.js   |   40 -
 .../node_modules/serialport/hwtest/test2.js   |   14 -
 .../mag/node_modules/serialport/lib/index.js  |   15 +
 .../node_modules/serialport/lib/parsers.js    |   35 +
 .../serialport/node_modules/.bin/node-pre-gyp |    1 -
 .../serialport/node_modules/async/LICENSE     |   19 -
 .../serialport/node_modules/async/README.md   | 1646 ------
 .../node_modules/async/component.json         |   11 -
 .../node_modules/async/lib/async.js           | 1123 ----
 .../node_modules/async/package.json           |   46 -
 .../node_modules/bindings/README.md           |   97 -
 .../node_modules/bindings/bindings.js         |  166 -
 .../node_modules/bindings/package.json        |   37 -
 .../serialport/node_modules/debug/.jshintrc   |    3 -
 .../serialport/node_modules/debug/.npmignore  |    6 -
 .../serialport/node_modules/debug/History.md  |  186 -
 .../serialport/node_modules/debug/Makefile    |   33 -
 .../serialport/node_modules/debug/Readme.md   |  178 -
 .../serialport/node_modules/debug/bower.json  |   28 -
 .../serialport/node_modules/debug/browser.js  |  175 -
 .../node_modules/debug/component.json         |   19 -
 .../serialport/node_modules/debug/debug.js    |  197 -
 .../serialport/node_modules/debug/node.js     |  209 -
 .../debug/node_modules/ms/.npmignore          |    5 -
 .../debug/node_modules/ms/LICENSE             |   20 -
 .../debug/node_modules/ms/README.md           |   35 -
 .../debug/node_modules/ms/index.js            |  123 -
 .../debug/node_modules/ms/package.json        |   31 -
 .../node_modules/debug/package.json           |   52 -
 .../serialport/node_modules/nan/.dntrc        |   30 -
 .../serialport/node_modules/nan/CHANGELOG.md  |  270 -
 .../serialport/node_modules/nan/LICENSE.md    |   13 -
 .../serialport/node_modules/nan/appveyor.yml  |   38 -
 .../serialport/node_modules/nan/nan.h         | 2212 -------
 .../nan/nan_implementation_12_inl.h           |  262 -
 .../nan/nan_implementation_pre_12_inl.h       |  268 -
 .../serialport/node_modules/nan/nan_new.h     |  329 --
 .../node_modules/nan/nan_string_bytes.h       |  312 -
 .../serialport/node_modules/nan/package.json  |   69 -
 .../node_modules/node-pre-gyp/CHANGELOG.md    |  126 -
 .../node_modules/node-pre-gyp/LICENSE         |   27 -
 .../node_modules/node-pre-gyp/README.md       |  448 --
 .../node_modules/node-pre-gyp/appveyor.yml    |   26 -
 .../node-pre-gyp/bin/node-pre-gyp             |  130 -
 .../node-pre-gyp/bin/node-pre-gyp.cmd         |    1 -
 .../node_modules/node-pre-gyp/lib/build.js    |   52 -
 .../node_modules/node-pre-gyp/lib/clean.js    |   24 -
 .../node_modules/node-pre-gyp/lib/info.js     |   40 -
 .../node_modules/node-pre-gyp/lib/install.js  |  198 -
 .../node-pre-gyp/lib/node-pre-gyp.js          |  192 -
 .../node_modules/node-pre-gyp/lib/package.js  |   46 -
 .../node-pre-gyp/lib/pre-binding.js           |   24 -
 .../node_modules/node-pre-gyp/lib/publish.js  |   58 -
 .../node_modules/node-pre-gyp/lib/rebuild.js  |   12 -
 .../node-pre-gyp/lib/reinstall.js             |   12 -
 .../node-pre-gyp/lib/testbinary.js            |   72 -
 .../node-pre-gyp/lib/testpackage.js           |   49 -
 .../node-pre-gyp/lib/unpublish.js             |   41 -
 .../node-pre-gyp/lib/util/abi_crosswalk.json  |  466 --
 .../node-pre-gyp/lib/util/compile.js          |   80 -
 .../lib/util/nw-pre-gyp/index.html            |   26 -
 .../lib/util/nw-pre-gyp/package.json          |    9 -
 .../node-pre-gyp/lib/util/nw_crosswalk.json   |   27 -
 .../node-pre-gyp/lib/util/s3_setup.js         |   21 -
 .../node-pre-gyp/lib/util/versioning.js       |  158 -
 .../node-pre-gyp/node_modules/.bin/nopt       |    1 -
 .../node-pre-gyp/node_modules/.bin/rc         |    1 -
 .../node-pre-gyp/node_modules/.bin/rimraf     |    1 -
 .../node_modules/mkdirp/.npmignore            |    2 -
 .../node_modules/mkdirp/.travis.yml           |    5 -
 .../node-pre-gyp/node_modules/mkdirp/index.js |   97 -
 .../mkdirp/node_modules/minimist/package.json |   52 -
 .../node_modules/mkdirp/package.json          |   43 -
 .../node_modules/mkdirp/test/chmod.js         |   38 -
 .../node_modules/mkdirp/test/clobber.js       |   37 -
 .../node_modules/mkdirp/test/mkdirp.js        |   26 -
 .../node_modules/mkdirp/test/perm.js          |   30 -
 .../node_modules/mkdirp/test/perm_sync.js     |   34 -
 .../node_modules/mkdirp/test/race.js          |   40 -
 .../node_modules/mkdirp/test/rel.js           |   30 -
 .../node_modules/mkdirp/test/root.js          |   18 -
 .../node_modules/mkdirp/test/sync.js          |   30 -
 .../node_modules/mkdirp/test/umask.js         |   26 -
 .../node_modules/mkdirp/test/umask_sync.js    |   30 -
 .../node-pre-gyp/node_modules/nopt/LICENSE    |   23 -
 .../node-pre-gyp/node_modules/nopt/README.md  |  210 -
 .../node_modules/nopt/bin/nopt.js             |   51 -
 .../node_modules/nopt/examples/my-program.js  |   30 -
 .../node_modules/nopt/lib/nopt.js             |  412 --
 .../nopt/node_modules/abbrev/CONTRIBUTING.md  |    3 -
 .../nopt/node_modules/abbrev/LICENSE          |   23 -
 .../nopt/node_modules/abbrev/README.md        |   23 -
 .../nopt/node_modules/abbrev/abbrev.js        |   62 -
 .../nopt/node_modules/abbrev/package.json     |   31 -
 .../nopt/node_modules/abbrev/test.js          |   47 -
 .../node_modules/nopt/package.json            |   41 -
 .../node_modules/nopt/test/basic.js           |  243 -
 .../node-pre-gyp/node_modules/npmlog/LICENSE  |   27 -
 .../node_modules/npmlog/README.md             |  153 -
 .../node_modules/npmlog/example.js            |   39 -
 .../node-pre-gyp/node_modules/npmlog/log.js   |  154 -
 .../npmlog/node_modules/ansi/README.md        |   91 -
 .../npmlog/node_modules/ansi/color-spaces.pl  |   67 -
 .../node_modules/ansi/examples/beep/index.js  |   16 -
 .../node_modules/ansi/examples/clear/index.js |   15 -
 .../ansi/examples/cursorPosition.js           |   32 -
 .../ansi/examples/progress/index.js           |   87 -
 .../node_modules/ansi/examples/starwars.js    |   46 -
 .../npmlog/node_modules/ansi/lib/ansi.js      |  405 --
 .../npmlog/node_modules/ansi/lib/newlines.js  |   71 -
 .../npmlog/node_modules/ansi/package.json     |   49 -
 .../node_modules/npmlog/package.json          |   35 -
 .../node_modules/npmlog/test/basic.js         |  228 -
 .../node-pre-gyp/node_modules/rc/.npmignore   |    3 -
 .../node-pre-gyp/node_modules/rc/README.md    |  127 -
 .../node-pre-gyp/node_modules/rc/index.js     |   42 -
 .../node-pre-gyp/node_modules/rc/lib/utils.js |   58 -
 .../rc/node_modules/deep-extend/.npmignore    |    1 -
 .../rc/node_modules/deep-extend/LICENSE       |   20 -
 .../rc/node_modules/deep-extend/README.md     |   52 -
 .../rc/node_modules/deep-extend/index.js      |   87 -
 .../rc/node_modules/deep-extend/package.json  |   45 -
 .../deep-extend/test/index.spec.js            |   44 -
 .../node_modules/deep-extend/test/mocha.opts  |    1 -
 .../node_modules/rc/node_modules/ini/LICENSE  |   23 -
 .../rc/node_modules/ini/README.md             |   79 -
 .../node_modules/rc/node_modules/ini/ini.js   |  166 -
 .../rc/node_modules/ini/package.json          |   35 -
 .../rc/node_modules/ini/test/bar.js           |   23 -
 .../rc/node_modules/ini/test/fixtures/foo.ini |   47 -
 .../rc/node_modules/ini/test/foo.js           |   71 -
 .../rc/node_modules/minimist/index.js         |  187 -
 .../rc/node_modules/minimist/package.json     |   52 -
 .../rc/node_modules/minimist/readme.markdown  |   73 -
 .../rc/node_modules/minimist/test/bool.js     |  119 -
 .../rc/node_modules/minimist/test/dash.js     |   24 -
 .../minimist/test/default_bool.js             |   20 -
 .../minimist/test/parse_modified.js           |    9 -
 .../node_modules/strip-json-comments/cli.js   |   41 -
 .../strip-json-comments/package.json          |   61 -
 .../strip-json-comments/readme.md             |   74 -
 .../strip-json-comments.js                    |   64 -
 .../node-pre-gyp/node_modules/rc/package.json |   49 -
 .../node-pre-gyp/node_modules/rc/test/test.js |   56 -
 .../node_modules/request/.npmignore           |    2 -
 .../node_modules/request/.travis.yml          |   12 -
 .../node_modules/request/CHANGELOG.md         |  388 --
 .../node_modules/request/README.md            |  395 --
 .../node_modules/request/index.js             |  158 -
 .../node_modules/request/lib/cookies.js       |   36 -
 .../node_modules/request/lib/copy.js          |    8 -
 .../node_modules/request/lib/debug.js         |    7 -
 .../node_modules/request/lib/getSafe.js       |   34 -
 .../node_modules/request/lib/optional.js      |    5 -
 .../request/node_modules/aws-sign2/LICENSE    |   55 -
 .../request/node_modules/aws-sign2/README.md  |    4 -
 .../request/node_modules/aws-sign2/index.js   |  202 -
 .../node_modules/aws-sign2/package.json       |   30 -
 .../node_modules/forever-agent/LICENSE        |   55 -
 .../node_modules/forever-agent/README.md      |    4 -
 .../node_modules/forever-agent/index.js       |  119 -
 .../node_modules/forever-agent/package.json   |   30 -
 .../request/node_modules/form-data/License    |   19 -
 .../request/node_modules/form-data/Readme.md  |  163 -
 .../node_modules/form-data/lib/form_data.js   |  325 -
 .../form-data/node_modules/async/LICENSE      |   19 -
 .../form-data/node_modules/async/README.md    | 1425 -----
 .../node_modules/async/component.json         |   11 -
 .../form-data/node_modules/async/lib/async.js |  958 ---
 .../form-data/node_modules/async/package.json |   45 -
 .../node_modules/combined-stream/.npmignore   |    3 -
 .../node_modules/combined-stream/License      |   19 -
 .../node_modules/combined-stream/Makefile     |    7 -
 .../node_modules/combined-stream/Readme.md    |  132 -
 .../combined-stream/lib/combined_stream.js    |  185 -
 .../node_modules/delayed-stream/.npmignore    |    2 -
 .../node_modules/delayed-stream/License       |   19 -
 .../node_modules/delayed-stream/Makefile      |    7 -
 .../node_modules/delayed-stream/Readme.md     |  154 -
 .../delayed-stream/lib/delayed_stream.js      |   99 -
 .../node_modules/delayed-stream/package.json  |   33 -
 .../delayed-stream/test/common.js             |    6 -
 .../integration/test-delayed-http-upload.js   |   38 -
 .../test-delayed-stream-auto-pause.js         |   21 -
 .../integration/test-delayed-stream-pause.js  |   14 -
 .../test/integration/test-delayed-stream.js   |   48 -
 .../integration/test-handle-source-errors.js  |   15 -
 .../test/integration/test-max-data-size.js    |   18 -
 .../test/integration/test-pipe-resumes.js     |   13 -
 .../test/integration/test-proxy-readable.js   |   13 -
 .../node_modules/delayed-stream/test/run.js   |    7 -
 .../node_modules/combined-stream/package.json |   34 -
 .../combined-stream/test/common.js            |   23 -
 .../combined-stream/test/fixture/file1.txt    |  256 -
 .../combined-stream/test/fixture/file2.txt    |  256 -
 .../test/integration/test-callback-streams.js |   27 -
 .../test/integration/test-data-size.js        |   34 -
 ...delayed-streams-and-buffers-and-strings.js |   38 -
 .../test/integration/test-delayed-streams.js  |   35 -
 .../test/integration/test-empty-string.js     |   39 -
 .../test/integration/test-is-stream-like.js   |   17 -
 .../test/integration/test-max-data-size.js    |   24 -
 .../test/integration/test-unpaused-streams.js |   30 -
 .../node_modules/combined-stream/test/run.js  |    7 -
 .../node_modules/form-data/package.json       |   48 -
 .../request/node_modules/hawk/.npmignore      |   18 -
 .../request/node_modules/hawk/.travis.yml     |    5 -
 .../request/node_modules/hawk/LICENSE         |   24 -
 .../request/node_modules/hawk/Makefile        |   10 -
 .../request/node_modules/hawk/README.md       |  627 --
 .../node_modules/hawk/example/usage.js        |   78 -
 .../request/node_modules/hawk/images/hawk.png |  Bin 6945 -> 0 bytes
 .../request/node_modules/hawk/images/logo.png |  Bin 71732 -> 0 bytes
 .../request/node_modules/hawk/index.js        |    1 -
 .../request/node_modules/hawk/lib/browser.js  |  485 --
 .../request/node_modules/hawk/lib/client.js   |  367 --
 .../request/node_modules/hawk/lib/crypto.js   |  111 -
 .../request/node_modules/hawk/lib/index.js    |   15 -
 .../request/node_modules/hawk/lib/server.js   |  524 --
 .../request/node_modules/hawk/lib/utils.js    |  183 -
 .../hawk/node_modules/boom/.npmignore         |   18 -
 .../hawk/node_modules/boom/.travis.yml        |    5 -
 .../hawk/node_modules/boom/LICENSE            |   24 -
 .../hawk/node_modules/boom/Makefile           |   11 -
 .../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/lib/index.js       |  207 -
 .../hawk/node_modules/boom/package.json       |   49 -
 .../hawk/node_modules/boom/test/index.js      |  245 -
 .../hawk/node_modules/cryptiles/.npmignore    |   18 -
 .../hawk/node_modules/cryptiles/.travis.yml   |    5 -
 .../hawk/node_modules/cryptiles/LICENSE       |   24 -
 .../hawk/node_modules/cryptiles/Makefile      |   11 -
 .../hawk/node_modules/cryptiles/README.md     |    6 -
 .../hawk/node_modules/cryptiles/index.js      |    1 -
 .../hawk/node_modules/cryptiles/lib/index.js  |   68 -
 .../hawk/node_modules/cryptiles/package.json  |   50 -
 .../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/LICENSE            |   33 -
 .../hawk/node_modules/hoek/Makefile           |   10 -
 .../hawk/node_modules/hoek/README.md          |  436 --
 .../hawk/node_modules/hoek/images/hoek.png    |  Bin 37939 -> 0 bytes
 .../hawk/node_modules/hoek/index.js           |    1 -
 .../hawk/node_modules/hoek/lib/escape.js      |  132 -
 .../hawk/node_modules/hoek/lib/index.js       |  585 --
 .../hawk/node_modules/hoek/package.json       |   51 -
 .../hawk/node_modules/hoek/test/escaper.js    |   86 -
 .../hawk/node_modules/hoek/test/index.js      | 1078 ----
 .../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            |   24 -
 .../hawk/node_modules/sntp/Makefile           |   11 -
 .../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 -
 .../hawk/node_modules/sntp/lib/index.js       |  409 --
 .../hawk/node_modules/sntp/package.json       |   50 -
 .../hawk/node_modules/sntp/test/index.js      |  359 --
 .../request/node_modules/hawk/package.json    |   55 -
 .../request/node_modules/hawk/test/browser.js |  771 ---
 .../request/node_modules/hawk/test/client.js  |  206 -
 .../request/node_modules/hawk/test/crypto.js  |   86 -
 .../request/node_modules/hawk/test/index.js   |  316 -
 .../request/node_modules/hawk/test/message.js |  246 -
 .../request/node_modules/hawk/test/readme.js  |   98 -
 .../request/node_modules/hawk/test/server.js  |  686 ---
 .../request/node_modules/hawk/test/uri.js     |  456 --
 .../request/node_modules/hawk/test/utils.js   |  120 -
 .../http-signature/.dir-locals.el             |    6 -
 .../node_modules/http-signature/.npmignore    |    7 -
 .../node_modules/http-signature/LICENSE       |   18 -
 .../node_modules/http-signature/README.md     |   75 -
 .../http-signature/http_signing.md            |  296 -
 .../node_modules/http-signature/lib/index.js  |   25 -
 .../node_modules/http-signature/lib/parser.js |  304 -
 .../node_modules/http-signature/lib/signer.js |  179 -
 .../node_modules/http-signature/lib/util.js   |  249 -
 .../node_modules/http-signature/lib/verify.js |   42 -
 .../node_modules/asn1/.npmignore              |    2 -
 .../http-signature/node_modules/asn1/LICENSE  |   19 -
 .../node_modules/asn1/README.md               |   50 -
 .../node_modules/asn1/lib/ber/errors.js       |   13 -
 .../node_modules/asn1/lib/ber/index.js        |   27 -
 .../node_modules/asn1/lib/ber/reader.js       |  267 -
 .../node_modules/asn1/lib/ber/types.js        |   36 -
 .../node_modules/asn1/lib/ber/writer.js       |  317 -
 .../node_modules/asn1/lib/index.js            |   20 -
 .../node_modules/asn1/package.json            |   45 -
 .../node_modules/asn1/tst/ber/reader.test.js  |  172 -
 .../node_modules/asn1/tst/ber/writer.test.js  |  296 -
 .../node_modules/assert-plus/README.md        |  126 -
 .../node_modules/assert-plus/assert.js        |  196 -
 .../node_modules/assert-plus/package.json     |   22 -
 .../node_modules/ctype/CHANGELOG              |   71 -
 .../http-signature/node_modules/ctype/LICENSE |   24 -
 .../http-signature/node_modules/ctype/README  |   82 -
 .../node_modules/ctype/README.old             |  298 -
 .../http-signature/node_modules/ctype/ctf.js  |  245 -
 .../http-signature/node_modules/ctype/ctio.js | 1485 -----
 .../node_modules/ctype/ctype.js               |  944 ---
 .../ctype/man/man3ctype/ctio.3ctype           |  241 -
 .../node_modules/ctype/package.json           |   20 -
 .../node_modules/ctype/tools/jsl.conf         |  129 -
 .../node_modules/ctype/tools/jsstyle          |  839 ---
 .../node_modules/ctype/tst/ctf/float.json     |   13 -
 .../node_modules/ctype/tst/ctf/int.json       |   13 -
 .../node_modules/ctype/tst/ctf/psinfo.json    |  104 -
 .../node_modules/ctype/tst/ctf/struct.json    |   19 -
 .../node_modules/ctype/tst/ctf/tst.fail.js    |   39 -
 .../node_modules/ctype/tst/ctf/tst.float.js   |   14 -
 .../node_modules/ctype/tst/ctf/tst.int.js     |   14 -
 .../node_modules/ctype/tst/ctf/tst.psinfo.js  |   17 -
 .../node_modules/ctype/tst/ctf/tst.struct.js  |   18 -
 .../node_modules/ctype/tst/ctf/tst.typedef.js |   15 -
 .../node_modules/ctype/tst/ctf/typedef.json   |   14 -
 .../ctype/tst/ctio/float/tst.rfloat.js        |  767 ---
 .../ctype/tst/ctio/float/tst.wfloat.js        |  753 ---
 .../node_modules/ctype/tst/ctio/int/tst.64.js |  638 --
 .../ctype/tst/ctio/int/tst.rint.js            |  101 -
 .../ctype/tst/ctio/int/tst.wbounds.js         |   53 -
 .../ctype/tst/ctio/int/tst.wint.js            |   92 -
 .../ctype/tst/ctio/uint/tst.64.js             |  451 --
 .../ctype/tst/ctio/uint/tst.roundtrip.js      |   81 -
 .../ctype/tst/ctio/uint/tst.ruint.js          |   95 -
 .../ctype/tst/ctio/uint/tst.wuint.js          |  156 -
 .../ctype/tst/ctype/tst.basicr.js             |   50 -
 .../ctype/tst/ctype/tst.basicw.js             |   44 -
 .../node_modules/ctype/tst/ctype/tst.char.js  |   42 -
 .../ctype/tst/ctype/tst.endian.js             |   45 -
 .../ctype/tst/ctype/tst.oldwrite.js           |   28 -
 .../ctype/tst/ctype/tst.readSize.js           |  128 -
 .../ctype/tst/ctype/tst.structw.js            |   28 -
 .../ctype/tst/ctype/tst.writeStruct.js        |   31 -
 .../node_modules/http-signature/package.json  |   38 -
 .../node_modules/json-stringify-safe/LICENSE  |   27 -
 .../json-stringify-safe/README.md             |   49 -
 .../json-stringify-safe/package.json          |   35 -
 .../json-stringify-safe/stringify.js          |   39 -
 .../node_modules/json-stringify-safe/test.js  |  128 -
 .../request/node_modules/mime/LICENSE         |   19 -
 .../request/node_modules/mime/README.md       |   66 -
 .../request/node_modules/mime/mime.js         |  114 -
 .../request/node_modules/mime/package.json    |   38 -
 .../request/node_modules/mime/test.js         |   84 -
 .../node_modules/mime/types/mime.types        | 1588 -----
 .../node_modules/mime/types/node.types        |   77 -
 .../request/node_modules/node-uuid/.npmignore |    2 -
 .../request/node_modules/node-uuid/LICENSE.md |    2 -
 .../request/node_modules/node-uuid/README.md  |  207 -
 .../node-uuid/benchmark/README.md             |   53 -
 .../node-uuid/benchmark/bench.gnu             |  174 -
 .../node_modules/node-uuid/benchmark/bench.sh |   34 -
 .../node-uuid/benchmark/benchmark-native.c    |   34 -
 .../node-uuid/benchmark/benchmark.js          |   84 -
 .../node_modules/node-uuid/component.json     |   18 -
 .../node_modules/node-uuid/package.json       |   37 -
 .../node_modules/node-uuid/test/compare_v1.js |   63 -
 .../node_modules/node-uuid/test/test.html     |   17 -
 .../node_modules/node-uuid/test/test.js       |  228 -
 .../request/node_modules/node-uuid/uuid.js    |  245 -
 .../request/node_modules/oauth-sign/LICENSE   |   55 -
 .../request/node_modules/oauth-sign/README.md |    4 -
 .../request/node_modules/oauth-sign/index.js  |   43 -
 .../node_modules/oauth-sign/package.json      |   33 -
 .../request/node_modules/oauth-sign/test.js   |   49 -
 .../request/node_modules/qs/.gitmodules       |    6 -
 .../request/node_modules/qs/.npmignore        |    7 -
 .../request/node_modules/qs/Readme.md         |   58 -
 .../request/node_modules/qs/index.js          |  366 --
 .../request/node_modules/qs/package.json      |   40 -
 .../node_modules/tough-cookie/.jshintrc       |   70 -
 .../node_modules/tough-cookie/.npmignore      |    3 -
 .../node_modules/tough-cookie/.travis.yml     |    8 -
 .../request/node_modules/tough-cookie/LICENSE |   78 -
 .../node_modules/tough-cookie/README.md       |  412 --
 .../tough-cookie/generate-pubsuffix.js        |  239 -
 .../node_modules/tough-cookie/lib/cookie.js   | 1107 ----
 .../node_modules/tough-cookie/lib/memstore.js |  123 -
 .../tough-cookie/lib/pubsuffix.js             |   69 -
 .../node_modules/tough-cookie/lib/store.js    |   37 -
 .../node_modules/punycode/LICENSE-GPL.txt     |  278 -
 .../node_modules/punycode/LICENSE-MIT.txt     |   20 -
 .../node_modules/punycode/README.md           |  162 -
 .../node_modules/punycode/package.json        |   76 -
 .../node_modules/punycode/punycode.js         |  507 --
 .../node_modules/punycode/punycode.min.js     |    2 -
 .../node_modules/tough-cookie/package.json    |   47 -
 .../tough-cookie/public-suffix.txt            | 5229 -----------------
 .../request/node_modules/tough-cookie/test.js | 1625 -----
 .../node_modules/tunnel-agent/.jshintrc       |    5 -
 .../request/node_modules/tunnel-agent/LICENSE |   55 -
 .../node_modules/tunnel-agent/index.js        |  236 -
 .../node_modules/tunnel-agent/package.json    |   30 -
 .../node_modules/request/package.json         |   60 -
 .../node_modules/request/request.js           | 1362 -----
 .../node-pre-gyp/node_modules/rimraf/AUTHORS  |    6 -
 .../node-pre-gyp/node_modules/rimraf/LICENSE  |   23 -
 .../node_modules/rimraf/README.md             |   30 -
 .../node-pre-gyp/node_modules/rimraf/bin.js   |   33 -
 .../node_modules/rimraf/package.json          |   58 -
 .../node_modules/rimraf/rimraf.js             |  248 -
 .../node_modules/rimraf/test/run.sh           |   16 -
 .../node_modules/rimraf/test/setup.sh         |   47 -
 .../node_modules/rimraf/test/test-async.js    |    5 -
 .../node_modules/rimraf/test/test-sync.js     |    3 -
 .../node_modules/semver/.npmignore            |    1 -
 .../node-pre-gyp/node_modules/semver/LICENSE  |   27 -
 .../node-pre-gyp/node_modules/semver/Makefile |   24 -
 .../node_modules/semver/README.md             |  158 -
 .../node_modules/semver/bin/semver            |  125 -
 .../node-pre-gyp/node_modules/semver/foot.js  |    6 -
 .../node-pre-gyp/node_modules/semver/head.js  |    2 -
 .../node_modules/semver/package.json          |   34 -
 .../node_modules/semver/semver.browser.js     | 1039 ----
 .../node_modules/semver/semver.browser.js.gz  |  Bin 7180 -> 0 bytes
 .../node_modules/semver/semver.js             | 1043 ----
 .../node_modules/semver/semver.min.js         |    1 -
 .../node_modules/semver/semver.min.js.gz      |  Bin 3295 -> 0 bytes
 .../node_modules/semver/test/amd.js           |   15 -
 .../node_modules/semver/test/gtr.js           |  173 -
 .../node_modules/semver/test/index.js         |  584 --
 .../node_modules/semver/test/ltr.js           |  174 -
 .../node_modules/semver/test/no-module.js     |   19 -
 .../node_modules/tar-pack/.npmignore          |   14 -
 .../node_modules/tar-pack/.travis.yml         |    4 -
 .../node_modules/tar-pack/README.md           |   81 -
 .../node_modules/tar-pack/index.js            |  246 -
 .../tar-pack/node_modules/debug/Readme.md     |  115 -
 .../tar-pack/node_modules/debug/debug.js      |  137 -
 .../tar-pack/node_modules/debug/index.js      |    5 -
 .../tar-pack/node_modules/debug/lib/debug.js  |  147 -
 .../tar-pack/node_modules/debug/package.json  |   48 -
 .../node_modules/fstream-ignore/.npmignore    |    1 -
 .../node_modules/fstream-ignore/LICENSE       |   27 -
 .../node_modules/fstream-ignore/README.md     |   22 -
 .../fstream-ignore/example/basic.js           |   13 -
 .../node_modules/fstream-ignore/ignore.js     |  275 -
 .../node_modules/inherits/inherits.js         |    1 -
 .../node_modules/inherits/package.json        |   35 -
 .../node_modules/inherits/test.js             |   25 -
 .../node_modules/minimatch/.npmignore         |    1 -
 .../node_modules/minimatch/LICENSE            |   23 -
 .../node_modules/minimatch/README.md          |  218 -
 .../node_modules/minimatch/minimatch.js       | 1055 ----
 .../node_modules/lru-cache/.npmignore         |    1 -
 .../node_modules/lru-cache/CONTRIBUTORS       |   14 -
 .../minimatch/node_modules/lru-cache/LICENSE  |   23 -
 .../node_modules/lru-cache/README.md          |   97 -
 .../node_modules/lru-cache/lib/lru-cache.js   |  252 -
 .../node_modules/lru-cache/package.json       |   35 -
 .../node_modules/lru-cache/test/basic.js      |  369 --
 .../node_modules/lru-cache/test/foreach.js    |   52 -
 .../lru-cache/test/memory-leak.js             |   50 -
 .../minimatch/node_modules/sigmund/LICENSE    |   27 -
 .../minimatch/node_modules/sigmund/README.md  |   53 -
 .../minimatch/node_modules/sigmund/bench.js   |  283 -
 .../node_modules/sigmund/package.json         |   44 -
 .../minimatch/node_modules/sigmund/sigmund.js |   39 -
 .../node_modules/sigmund/test/basic.js        |   24 -
 .../node_modules/minimatch/package.json       |   42 -
 .../node_modules/minimatch/test/basic.js      |  399 --
 .../minimatch/test/brace-expand.js            |   33 -
 .../node_modules/minimatch/test/caching.js    |   14 -
 .../node_modules/minimatch/test/defaults.js   |  274 -
 .../test/extglob-ending-with-state-char.js    |    8 -
 .../node_modules/fstream-ignore/package.json  |   39 -
 .../node_modules/fstream-ignore/test/.ignore  |    2 -
 .../fstream-ignore/test/.npmignore            |    1 -
 .../fstream-ignore/test/00-setup.js           |   71 -
 .../node_modules/fstream-ignore/test/basic.js |   28 -
 .../fstream-ignore/test/common.js             |   40 -
 .../fstream-ignore/test/ignore-most.js        |   41 -
 .../fstream-ignore/test/nested-ignores.js     |   51 -
 .../fstream-ignore/test/unignore-child.js     |   38 -
 .../fstream-ignore/test/zz-cleanup.js         |   10 -
 .../tar-pack/node_modules/fstream/.npmignore  |    5 -
 .../tar-pack/node_modules/fstream/.travis.yml |    3 -
 .../tar-pack/node_modules/fstream/LICENSE     |   27 -
 .../tar-pack/node_modules/fstream/README.md   |   76 -
 .../fstream/examples/filter-pipe.js           |  131 -
 .../node_modules/fstream/examples/pipe.js     |  115 -
 .../node_modules/fstream/examples/reader.js   |   54 -
 .../fstream/examples/symlink-write.js         |   24 -
 .../tar-pack/node_modules/fstream/fstream.js  |   31 -
 .../node_modules/fstream/lib/abstract.js      |   85 -
 .../node_modules/fstream/lib/collect.js       |   67 -
 .../node_modules/fstream/lib/dir-reader.js    |  251 -
 .../node_modules/fstream/lib/dir-writer.js    |  171 -
 .../node_modules/fstream/lib/file-reader.js   |  147 -
 .../node_modules/fstream/lib/file-writer.js   |  100 -
 .../node_modules/fstream/lib/get-type.js      |   32 -
 .../node_modules/fstream/lib/link-reader.js   |   54 -
 .../node_modules/fstream/lib/link-writer.js   |   95 -
 .../node_modules/fstream/lib/proxy-reader.js  |   93 -
 .../node_modules/fstream/lib/proxy-writer.js  |  109 -
 .../node_modules/fstream/lib/reader.js        |  260 -
 .../node_modules/fstream/lib/socket-reader.js |   38 -
 .../node_modules/fstream/lib/writer.js        |  389 --
 .../fstream/node_modules/graceful-fs/LICENSE  |   27 -
 .../node_modules/graceful-fs/README.md        |   26 -
 .../node_modules/graceful-fs/graceful-fs.js   |  160 -
 .../node_modules/graceful-fs/package.json     |   51 -
 .../node_modules/graceful-fs/polyfills.js     |  228 -
 .../node_modules/graceful-fs/test/open.js     |   39 -
 .../graceful-fs/test/readdir-sort.js          |   21 -
 .../fstream/node_modules/inherits/LICENSE     |   16 -
 .../fstream/node_modules/inherits/README.md   |   42 -
 .../fstream/node_modules/inherits/inherits.js |    1 -
 .../node_modules/inherits/inherits_browser.js |   23 -
 .../node_modules/inherits/package.json        |   35 -
 .../fstream/node_modules/inherits/test.js     |   25 -
 .../fstream/node_modules/mkdirp/.npmignore    |    2 -
 .../fstream/node_modules/mkdirp/.travis.yml   |    5 -
 .../fstream/node_modules/mkdirp/LICENSE       |   21 -
 .../node_modules/mkdirp/examples/pow.js       |    6 -
 .../fstream/node_modules/mkdirp/index.js      |   82 -
 .../fstream/node_modules/mkdirp/package.json  |   36 -
 .../node_modules/mkdirp/readme.markdown       |   63 -
 .../fstream/node_modules/mkdirp/test/chmod.js |   38 -
 .../node_modules/mkdirp/test/clobber.js       |   37 -
 .../node_modules/mkdirp/test/mkdirp.js        |   28 -
 .../fstream/node_modules/mkdirp/test/perm.js  |   32 -
 .../node_modules/mkdirp/test/perm_sync.js     |   39 -
 .../fstream/node_modules/mkdirp/test/race.js  |   41 -
 .../fstream/node_modules/mkdirp/test/rel.js   |   32 -
 .../node_modules/mkdirp/test/return.js        |   25 -
 .../node_modules/mkdirp/test/return_sync.js   |   24 -
 .../fstream/node_modules/mkdirp/test/root.js  |   18 -
 .../fstream/node_modules/mkdirp/test/sync.js  |   32 -
 .../fstream/node_modules/mkdirp/test/umask.js |   28 -
 .../node_modules/mkdirp/test/umask_sync.js    |   32 -
 .../node_modules/fstream/package.json         |   41 -
 .../node_modules/graceful-fs/.npmignore       |    1 -
 .../tar-pack/node_modules/graceful-fs/LICENSE |   27 -
 .../node_modules/graceful-fs/README.md        |   33 -
 .../node_modules/graceful-fs/graceful-fs.js   |  442 --
 .../node_modules/graceful-fs/package.json     |   51 -
 .../node_modules/graceful-fs/test/open.js     |   46 -
 .../node_modules/graceful-fs/test/ulimit.js   |  158 -
 .../tar-pack/node_modules/once/LICENSE        |   27 -
 .../tar-pack/node_modules/once/README.md      |   33 -
 .../tar-pack/node_modules/once/once.js        |   19 -
 .../tar-pack/node_modules/once/package.json   |   42 -
 .../tar-pack/node_modules/once/test/once.js   |   18 -
 .../node_modules/readable-stream/.npmignore   |    5 -
 .../node_modules/readable-stream/LICENSE      |   27 -
 .../node_modules/readable-stream/README.md    |   15 -
 .../node_modules/readable-stream/duplex.js    |    1 -
 .../readable-stream/lib/_stream_duplex.js     |   89 -
 .../readable-stream/lib/_stream_readable.js   |  959 ---
 .../readable-stream/lib/_stream_transform.js  |  210 -
 .../readable-stream/lib/_stream_writable.js   |  387 --
 .../node_modules/core-util-is/lib/util.js     |  107 -
 .../node_modules/core-util-is/package.json    |   37 -
 .../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        |   35 -
 .../node_modules/inherits/test.js             |   25 -
 .../node_modules/isarray/README.md            |   54 -
 .../node_modules/isarray/build/build.js       |  209 -
 .../node_modules/isarray/index.js             |    3 -
 .../node_modules/isarray/package.json         |   38 -
 .../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      |  200 -
 .../node_modules/string_decoder/package.json  |   34 -
 .../node_modules/readable-stream/package.json |   46 -
 .../readable-stream/passthrough.js            |    1 -
 .../node_modules/readable-stream/readable.js  |    6 -
 .../node_modules/readable-stream/transform.js |    1 -
 .../node_modules/readable-stream/writable.js  |    1 -
 .../tar-pack/node_modules/uid-number/LICENCE  |   25 -
 .../node_modules/uid-number/README.md         |   17 -
 .../node_modules/uid-number/get-uid-gid.js    |   24 -
 .../node_modules/uid-number/package.json      |   32 -
 .../node_modules/uid-number/uid-number.js     |   54 -
 .../node_modules/tar-pack/package.json        |   42 -
 .../tar-pack/test/fixtures/packed-file.txt    |    1 -
 .../tar-pack/test/fixtures/packed.tar         |  Bin 3584 -> 0 bytes
 .../tar-pack/test/fixtures/packed.tar.gz      |  Bin 152 -> 0 bytes
 .../tar-pack/test/fixtures/to-pack/bar.txt    |    1 -
 .../tar-pack/test/fixtures/to-pack/foo.txt    |    1 -
 .../node_modules/tar-pack/test/index.js       |   67 -
 .../node-pre-gyp/node_modules/tar/.npmignore  |    5 -
 .../node-pre-gyp/node_modules/tar/.travis.yml |    3 -
 .../node-pre-gyp/node_modules/tar/LICENCE     |   25 -
 .../node-pre-gyp/node_modules/tar/README.md   |   46 -
 .../node_modules/tar/examples/extracter.js    |   11 -
 .../node_modules/tar/examples/reader.js       |   36 -
 .../node_modules/tar/lib/buffer-entry.js      |   30 -
 .../node_modules/tar/lib/entry-writer.js      |  169 -
 .../node_modules/tar/lib/entry.js             |  213 -
 .../tar/lib/extended-header-writer.js         |  191 -
 .../node_modules/tar/lib/extended-header.js   |  140 -
 .../node_modules/tar/lib/extract.js           |   78 -
 .../tar/lib/global-header-writer.js           |   14 -
 .../node_modules/tar/lib/header.js            |  385 --
 .../node-pre-gyp/node_modules/tar/lib/pack.js |  231 -
 .../node_modules/tar/lib/parse.js             |  270 -
 .../tar/node_modules/block-stream/LICENCE     |   25 -
 .../tar/node_modules/block-stream/README.md   |   14 -
 .../block-stream/bench/block-stream-pause.js  |   70 -
 .../block-stream/bench/block-stream.js        |   68 -
 .../block-stream/bench/dropper-pause.js       |   70 -
 .../block-stream/bench/dropper.js             |   68 -
 .../node_modules/block-stream/block-stream.js |  209 -
 .../node_modules/block-stream/package.json    |   38 -
 .../node_modules/block-stream/test/basic.js   |   27 -
 .../block-stream/test/nopad-thorough.js       |   68 -
 .../node_modules/block-stream/test/nopad.js   |   57 -
 .../block-stream/test/pause-resume.js         |   73 -
 .../block-stream/test/thorough.js             |   68 -
 .../block-stream/test/two-stream.js           |   59 -
 .../tar/node_modules/fstream/.npmignore       |    5 -
 .../tar/node_modules/fstream/.travis.yml      |    3 -
 .../tar/node_modules/fstream/LICENSE          |   27 -
 .../tar/node_modules/fstream/README.md        |   76 -
 .../fstream/examples/filter-pipe.js           |  131 -
 .../tar/node_modules/fstream/examples/pipe.js |  115 -
 .../node_modules/fstream/examples/reader.js   |   54 -
 .../fstream/examples/symlink-write.js         |   24 -
 .../tar/node_modules/fstream/fstream.js       |   31 -
 .../tar/node_modules/fstream/lib/abstract.js  |   85 -
 .../tar/node_modules/fstream/lib/collect.js   |   67 -
 .../node_modules/fstream/lib/dir-reader.js    |  251 -
 .../node_modules/fstream/lib/dir-writer.js    |  171 -
 .../node_modules/fstream/lib/file-reader.js   |  147 -
 .../node_modules/fstream/lib/file-writer.js   |  100 -
 .../tar/node_modules/fstream/lib/get-type.js  |   32 -
 .../node_modules/fstream/lib/link-reader.js   |   54 -
 .../node_modules/fstream/lib/link-writer.js   |   95 -
 .../node_modules/fstream/lib/proxy-reader.js  |   93 -
 .../node_modules/fstream/lib/proxy-writer.js  |  109 -
 .../tar/node_modules/fstream/lib/reader.js    |  260 -
 .../node_modules/fstream/lib/socket-reader.js |   38 -
 .../tar/node_modules/fstream/lib/writer.js    |  389 --
 .../node_modules/graceful-fs/.npmignore       |    1 -
 .../fstream/node_modules/graceful-fs/LICENSE  |   27 -
 .../node_modules/graceful-fs/README.md        |   26 -
 .../node_modules/graceful-fs/graceful-fs.js   |  160 -
 .../node_modules/graceful-fs/package.json     |   51 -
 .../node_modules/graceful-fs/polyfills.js     |  228 -
 .../node_modules/graceful-fs/test/open.js     |   39 -
 .../graceful-fs/test/readdir-sort.js          |   21 -
 .../fstream/node_modules/mkdirp/.npmignore    |    2 -
 .../fstream/node_modules/mkdirp/.travis.yml   |    5 -
 .../fstream/node_modules/mkdirp/LICENSE       |   21 -
 .../node_modules/mkdirp/examples/pow.js       |    6 -
 .../fstream/node_modules/mkdirp/index.js      |   82 -
 .../fstream/node_modules/mkdirp/package.json  |   36 -
 .../node_modules/mkdirp/readme.markdown       |   63 -
 .../fstream/node_modules/mkdirp/test/chmod.js |   38 -
 .../node_modules/mkdirp/test/clobber.js       |   37 -
 .../node_modules/mkdirp/test/mkdirp.js        |   28 -
 .../fstream/node_modules/mkdirp/test/perm.js  |   32 -
 .../node_modules/mkdirp/test/perm_sync.js     |   39 -
 .../fstream/node_modules/mkdirp/test/race.js  |   41 -
 .../fstream/node_modules/mkdirp/test/rel.js   |   32 -
 .../node_modules/mkdirp/test/return.js        |   25 -
 .../node_modules/mkdirp/test/return_sync.js   |   24 -
 .../fstream/node_modules/mkdirp/test/root.js  |   18 -
 .../fstream/node_modules/mkdirp/test/sync.js  |   32 -
 .../fstream/node_modules/mkdirp/test/umask.js |   28 -
 .../node_modules/mkdirp/test/umask_sync.js    |   32 -
 .../tar/node_modules/fstream/package.json     |   41 -
 .../tar/node_modules/inherits/LICENSE         |   16 -
 .../tar/node_modules/inherits/README.md       |   42 -
 .../tar/node_modules/inherits/inherits.js     |    1 -
 .../node_modules/inherits/inherits_browser.js |   23 -
 .../tar/node_modules/inherits/package.json    |   35 -
 .../tar/node_modules/inherits/test.js         |   25 -
 .../node_modules/tar/package.json             |   38 -
 .../node-pre-gyp/node_modules/tar/tar.js      |  173 -
 .../tar/test/00-setup-fixtures.js             |   53 -
 .../node_modules/tar/test/extract.js          |  358 --
 .../node_modules/tar/test/fixtures.tgz        |  Bin 19205 -> 0 bytes
 .../node_modules/tar/test/header.js           |  183 -
 .../tar/test/pack-no-proprietary.js           |  854 ---
 .../node_modules/tar/test/pack.js             |  897 ---
 .../node_modules/tar/test/parse.js            |  359 --
 .../node_modules/tar/test/zz-cleanup.js       |   20 -
 .../node_modules/node-pre-gyp/package.json    |   85 -
 .../node_modules/optimist/.travis.yml         |    4 -
 .../serialport/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 -
 .../serialport/node_modules/optimist/index.js |  343 --
 .../node_modules/minimist/.travis.yml         |    4 -
 .../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/.npmignore |    1 -
 .../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        |   44 -
 .../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        |   46 -
 .../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/dash.js        |   31 -
 .../node_modules/optimist/test/parse.js       |  446 --
 .../optimist/test/parse_modified.js           |   14 -
 .../node_modules/optimist/test/short.js       |   16 -
 .../node_modules/optimist/test/usage.js       |  292 -
 .../node_modules/optimist/test/whitespace.js  |    8 -
 .../serialport/node_modules/sf/.npmignore     |    2 -
 .../serialport/node_modules/sf/.travis.yml    |    3 -
 .../serialport/node_modules/sf/README.md      |  148 -
 .../serialport/node_modules/sf/package.json   |   47 -
 .../serialport/node_modules/sf/sf.js          |  831 ---
 .../node_modules/sf/test/indentTest.js        |   62 -
 .../node_modules/sf/test/stringFormatTest.js  |  535 --
 .../node_modules/sf/test/timeSpanTest.js      |   29 -
 .../mag/node_modules/serialport/package.json  |  230 +-
 .../mag/node_modules/serialport/parsers.js    |   42 -
 .../serialport/publish-binaries.md            |   82 -
 .../serialport/sandbox/disconnect.js          |   53 -
 .../mag/node_modules/serialport/serialport.js |  689 ---
 .../serialport/src/serialport.cpp             |  618 --
 .../node_modules/serialport/src/serialport.h  |  193 -
 .../serialport/src/serialport_poller.cpp      |  130 -
 .../serialport/src/serialport_poller.h        |   35 -
 .../serialport/src/serialport_unix.cpp        |  745 ---
 .../serialport/src/serialport_win.cpp         |  510 --
 .../serialport/src/win/AutoHModule.h          |   72 -
 .../serialport/src/win/AutoHandle.h           |   62 -
 .../serialport/src/win/AutoHeapAlloc.h        |   72 -
 .../serialport/src/win/disphelper.c           | 1292 ----
 .../serialport/src/win/disphelper.h           |  731 ---
 .../serialport/src/win/enumser.cpp            | 1186 ----
 .../node_modules/serialport/src/win/enumser.h |  185 -
 .../node_modules/serialport/src/win/stdafx.h  |   51 -
 .../serialport/src/win/stdstring.h            | 4351 --------------
 .../mag/node_modules/serialport/test.js       |    8 +
 .../node_modules/serialport/test/parsers.js   |   47 -
 .../serialport/test/serialport-basic.js       |  275 -
 .../serialport/test/serialport-c.js           |   35 -
 .../serialport/test_mocks/linux-hardware.js   |  163 -
 .../node_modules/set-blocking/CHANGELOG.md    |   26 +
 .../mag/node_modules/set-blocking/LICENSE.txt |   14 +
 .../mag/node_modules/set-blocking/README.md   |   31 +
 .../mag/node_modules/set-blocking/index.js    |    7 +
 .../node_modules/set-blocking/package.json    |   98 +
 .../mag/node_modules/set-getter/LICENSE       |   21 +
 .../mag/node_modules/set-getter/README.md     |  109 +
 .../mag/node_modules/set-getter/index.js      |   83 +
 .../mag/node_modules/set-getter/package.json  |  105 +
 .../mag/node_modules/set-value/LICENSE        |   21 +
 .../mag/node_modules/set-value/README.md      |  234 +
 .../mag/node_modules/set-value/index.js       |  116 +
 .../mag/node_modules/set-value/package.json   |  203 +
 .../mag/node_modules/shallow-clone/LICENSE    |   21 +
 .../mag/node_modules/shallow-clone/README.md  |  115 +
 .../mag/node_modules/shallow-clone/index.js   |   57 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  342 ++
 .../node_modules/kind-of/index.js             |  147 +
 .../node_modules/kind-of/package.json         |  179 +
 .../node_modules/shallow-clone/package.json   |  140 +
 .../mag/node_modules/signal-exit/CHANGELOG.md |   27 +
 .../mag/node_modules/signal-exit/LICENSE.txt  |   16 +
 .../mag/node_modules/signal-exit/README.md    |   40 +
 .../mag/node_modules/signal-exit/index.js     |  157 +
 .../mag/node_modules/signal-exit/package.json |   98 +
 .../mag/node_modules/signal-exit/signals.js   |   53 +
 .../node_modules/simple-concat/.travis.yml    |    3 +
 .../mag/node_modules/simple-concat/LICENSE    |   20 +
 .../mag/node_modules/simple-concat/README.md  |   42 +
 .../mag/node_modules/simple-concat/index.js   |   14 +
 .../node_modules/simple-concat/package.json   |   85 +
 .../node_modules/simple-concat/test/basic.js  |   41 +
 .../mag/node_modules/simple-get/LICENSE       |   20 +
 .../mag/node_modules/simple-get/README.md     |  306 +
 .../mag/node_modules/simple-get/index.js      |  113 +
 .../mag/node_modules/simple-get/package.json  |  109 +
 .../mag/node_modules/static-extend/LICENSE    |   21 +
 .../mag/node_modules/static-extend/index.js   |   90 +
 .../node_modules/define-property/LICENSE      |   21 +
 .../node_modules/define-property/README.md    |   77 +
 .../node_modules/define-property/index.js     |   31 +
 .../node_modules/define-property/package.json |  105 +
 .../is-accessor-descriptor/LICENSE            |   21 +
 .../is-accessor-descriptor/README.md          |  123 +
 .../is-accessor-descriptor/index.js           |   69 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  261 +
 .../node_modules/kind-of/index.js             |  116 +
 .../node_modules/kind-of/package.json         |  172 +
 .../is-accessor-descriptor/package.json       |  117 +
 .../node_modules/is-data-descriptor/LICENSE   |   21 +
 .../node_modules/is-data-descriptor/README.md |  128 +
 .../node_modules/is-data-descriptor/index.js  |   55 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  261 +
 .../node_modules/kind-of/index.js             |  116 +
 .../node_modules/kind-of/package.json         |  172 +
 .../is-data-descriptor/package.json           |  116 +
 .../node_modules/is-descriptor/LICENSE        |   21 +
 .../node_modules/is-descriptor/README.md      |  193 +
 .../node_modules/is-descriptor/index.js       |   22 +
 .../node_modules/is-descriptor/package.json   |  142 +
 .../node_modules/kind-of/LICENSE              |   21 +
 .../node_modules/kind-of/README.md            |  342 ++
 .../node_modules/kind-of/index.js             |  147 +
 .../node_modules/kind-of/package.json         |  179 +
 .../node_modules/static-extend/package.json   |  123 +
 .../mag/node_modules/string-width/index.js    |   37 +
 .../mag/node_modules/string-width/license     |   21 +
 .../node_modules/string-width/package.json    |  116 +
 .../mag/node_modules/string-width/readme.md   |   42 +
 .../node_modules/string_decoder/.travis.yml   |   50 +
 .../mag/node_modules/string_decoder/LICENSE   |   48 +
 .../mag/node_modules/string_decoder/README.md |   47 +
 .../string_decoder/lib/string_decoder.js      |  296 +
 .../node_modules/string_decoder/package.json  |  105 +
 .../mag/node_modules/strip-ansi/index.js      |    6 +
 .../mag/node_modules/strip-ansi/license       |   21 +
 .../mag/node_modules/strip-ansi/package.json  |  116 +
 .../mag/node_modules/strip-ansi/readme.md     |   33 +
 .../mag/node_modules/strip-color/LICENSE      |   21 +
 .../mag/node_modules/strip-color/README.md    |   58 +
 .../mag/node_modules/strip-color/index.js     |   12 +
 .../mag/node_modules/strip-color/package.json |  133 +
 .../node_modules/strip-json-comments/index.js |   70 +
 .../node_modules/strip-json-comments/license  |   21 +
 .../strip-json-comments/package.json          |  102 +
 .../strip-json-comments/readme.md             |   64 +
 .../mag/node_modules/success-symbol/LICENSE   |   21 +
 .../mag/node_modules/success-symbol/README.md |   52 +
 .../mag/node_modules/success-symbol/index.js  |    1 +
 .../node_modules/success-symbol/package.json  |  107 +
 .../node_modules/async => tar-fs}/.travis.yml |    0
 input_devices/mag/node_modules/tar-fs/LICENSE |   21 +
 .../mag/node_modules/tar-fs/README.md         |  163 +
 .../mag/node_modules/tar-fs/index.js          |  345 ++
 .../tar-fs/node_modules/pump/.travis.yml      |    5 +
 .../tar-fs/node_modules/pump/LICENSE          |   21 +
 .../tar-fs/node_modules/pump/README.md        |   56 +
 .../tar-fs/node_modules/pump/index.js         |   80 +
 .../tar-fs/node_modules/pump/package.json     |   88 +
 .../tar-fs/node_modules/pump/test-browser.js  |   58 +
 .../tar-fs/node_modules/pump/test.js          |   46 +
 .../mag/node_modules/tar-fs/package.json      |  105 +
 .../tar-fs/test/fixtures/a/hello.txt          |    1 +
 .../tar-fs/test/fixtures/b/a/test.txt         |    1 +
 .../test/fixtures/d/file1}                    |    0
 .../test/fixtures/d/file2}                    |    0
 .../test/fixtures/d/sub-dir/file5}            |    0
 .../test/fixtures/d/sub-files/file3}          |    0
 .../tar-fs/test/fixtures/d/sub-files/file4    |    0
 .../tar-fs/test/fixtures/e/directory/.ignore  |    0
 .../node_modules/tar-fs/test/fixtures/e/file  |    0
 .../tar-fs/test/fixtures/invalid.tar          |  Bin 0 -> 2560 bytes
 .../mag/node_modules/tar-fs/test/index.js     |  346 ++
 .../mag/node_modules/tar-stream/LICENSE       |   21 +
 .../mag/node_modules/tar-stream/README.md     |  168 +
 .../mag/node_modules/tar-stream/extract.js    |  258 +
 .../mag/node_modules/tar-stream/headers.js    |  283 +
 .../mag/node_modules/tar-stream/index.js      |    2 +
 .../mag/node_modules/tar-stream/pack.js       |  255 +
 .../mag/node_modules/tar-stream/package.json  |  119 +
 .../node_modules/terminal-paginator/LICENSE   |   21 +
 .../node_modules/terminal-paginator/README.md |   70 +
 .../node_modules/terminal-paginator/index.js  |   86 +
 .../node_modules/debug/.coveralls.yml         |    1 +
 .../node_modules/debug/.eslintrc              |   11 +
 .../node_modules/debug/.npmignore             |    9 +
 .../node_modules/debug/.travis.yml            |   14 +
 .../node_modules/debug/CHANGELOG.md           |  362 ++
 .../node_modules/debug/LICENSE                |   19 +
 .../node_modules/debug/Makefile               |   50 +
 .../node_modules/debug/README.md              |  312 +
 .../node_modules/debug/component.json         |   19 +
 .../node_modules/debug/karma.conf.js          |   70 +
 .../node_modules/debug/node.js                |    1 +
 .../node_modules/debug/package.json           |  128 +
 .../node_modules/debug/src/browser.js         |  185 +
 .../node_modules/debug/src/debug.js           |  202 +
 .../node_modules/debug/src/index.js           |   10 +
 .../node_modules/debug/src/inspector-log.js   |   15 +
 .../node_modules/debug/src/node.js            |  248 +
 .../node_modules/ms/index.js                  |  152 +
 .../node_modules/ms/license.md                |   21 +
 .../node_modules/ms/package.json              |  101 +
 .../node_modules/ms/readme.md                 |   51 +
 .../terminal-paginator/package.json           |  139 +
 .../mag/node_modules/time-stamp/LICENSE       |   21 +
 .../mag/node_modules/time-stamp/README.md     |  132 +
 .../mag/node_modules/time-stamp/index.js      |   56 +
 .../mag/node_modules/time-stamp/package.json  |  145 +
 .../mag/node_modules/to-buffer/.travis.yml    |    9 +
 .../mag/node_modules/to-buffer/LICENSE        |   21 +
 .../mag/node_modules/to-buffer/README.md      |   23 +
 .../mag/node_modules/to-buffer/index.js       |   14 +
 .../mag/node_modules/to-buffer/package.json   |   83 +
 .../mag/node_modules/to-buffer/test.js        |   26 +
 .../mag/node_modules/to-object-path/LICENSE   |   21 +
 .../mag/node_modules/to-object-path/README.md |   71 +
 .../mag/node_modules/to-object-path/index.js  |   33 +
 .../node_modules/to-object-path/package.json  |  102 +
 .../mag/node_modules/toggle-array/LICENSE     |   21 +
 .../mag/node_modules/toggle-array/README.md   |  128 +
 .../mag/node_modules/toggle-array/index.js    |   42 +
 .../node_modules/toggle-array/package.json    |  111 +
 .../request => tunnel-agent}/LICENSE          |    0
 .../node_modules => }/tunnel-agent/README.md  |    0
 .../mag/node_modules/tunnel-agent/index.js    |  244 +
 .../node_modules/tunnel-agent/package.json    |   94 +
 .../node_modules/util-deprecate/History.md    |   16 +
 .../mag/node_modules/util-deprecate/LICENSE   |   24 +
 .../mag/node_modules/util-deprecate/README.md |   53 +
 .../node_modules/util-deprecate/browser.js    |   67 +
 .../mag/node_modules/util-deprecate/node.js   |    6 +
 .../node_modules/util-deprecate/package.json  |   81 +
 .../mag/node_modules/warning-symbol/LICENSE   |   21 +
 .../mag/node_modules/warning-symbol/README.md |   53 +
 .../mag/node_modules/warning-symbol/index.js  |    1 +
 .../node_modules/warning-symbol/package.json  |  106 +
 .../mag/node_modules/which-pm-runs/LICENSE    |   21 +
 .../mag/node_modules/which-pm-runs/README.md  |   29 +
 .../mag/node_modules/which-pm-runs/index.js   |   17 +
 .../node_modules/which-pm-runs/package.json   |   89 +
 .../mag/node_modules/wide-align/LICENSE       |   14 +
 .../mag/node_modules/wide-align/README.md     |   47 +
 .../mag/node_modules/wide-align/align.js      |   65 +
 .../mag/node_modules/wide-align/package.json  |   97 +
 .../mag/node_modules/window-size/LICENSE      |   21 +
 .../mag/node_modules/window-size/README.md    |  166 +
 .../mag/node_modules/window-size/cli.js       |   30 +
 .../mag/node_modules/window-size/index.js     |   35 +
 .../node_modules/is-number/LICENSE            |   21 +
 .../node_modules/is-number/README.md          |  115 +
 .../node_modules/is-number/index.js           |   22 +
 .../node_modules/is-number/package.json       |  152 +
 .../mag/node_modules/window-size/package.json |  170 +
 .../mag/node_modules/window-size/utils.js     |  124 +
 input_devices/mag/node_modules/wrappy/LICENSE |   15 +
 .../mag/node_modules/wrappy/README.md         |   36 +
 .../mag/node_modules/wrappy/package.json      |   88 +
 .../mag/node_modules/wrappy/wrappy.js         |   33 +
 input_devices/mag/node_modules/ws/.npmignore  |   11 -
 input_devices/mag/node_modules/ws/.travis.yml |    5 -
 input_devices/mag/node_modules/ws/LICENSE     |   21 +
 input_devices/mag/node_modules/ws/Makefile    |   40 -
 input_devices/mag/node_modules/ws/README.md   |  404 +-
 input_devices/mag/node_modules/ws/browser.js  |    8 +
 input_devices/mag/node_modules/ws/index.js    |   50 +-
 .../mag/node_modules/ws/lib/BufferPool.js     |   59 -
 .../ws/lib/BufferUtil.fallback.js             |   47 -
 .../mag/node_modules/ws/lib/BufferUtil.js     |   13 -
 .../mag/node_modules/ws/lib/ErrorCodes.js     |   24 -
 .../mag/node_modules/ws/lib/Extensions.js     |   70 -
 .../node_modules/ws/lib/PerMessageDeflate.js  |  289 -
 .../mag/node_modules/ws/lib/Receiver.hixie.js |  180 -
 .../mag/node_modules/ws/lib/Receiver.js       |  698 ---
 .../mag/node_modules/ws/lib/Sender.hixie.js   |  120 -
 .../mag/node_modules/ws/lib/Sender.js         |  309 -
 .../ws/lib/Validation.fallback.js             |   12 -
 .../mag/node_modules/ws/lib/Validation.js     |   13 -
 .../mag/node_modules/ws/lib/WebSocket.js      |  937 ---
 .../node_modules/ws/lib/WebSocketServer.js    |  501 --
 .../mag/node_modules/ws/lib/browser.js        |   43 -
 .../mag/node_modules/ws/lib/buffer-util.js    |   72 +
 .../mag/node_modules/ws/lib/constants.js      |   10 +
 .../mag/node_modules/ws/lib/event-target.js   |  170 +
 .../mag/node_modules/ws/lib/extension.js      |  211 +
 .../node_modules/ws/lib/permessage-deflate.js |  508 ++
 .../mag/node_modules/ws/lib/receiver.js       |  513 ++
 .../mag/node_modules/ws/lib/sender.js         |  401 ++
 .../mag/node_modules/ws/lib/validation.js     |   29 +
 .../node_modules/ws/lib/websocket-server.js   |  372 ++
 .../mag/node_modules/ws/lib/websocket.js      |  827 +++
 .../ws/node_modules/bufferutil/.npmignore     |    3 -
 .../ws/node_modules/bufferutil/binding.gyp    |   10 -
 .../ws/node_modules/bufferutil/build/Makefile |  332 --
 .../Release/.deps/Release/bufferutil.node.d   |    1 -
 .../Release/obj.target/bufferutil.node.d      |    1 -
 .../obj.target/bufferutil/src/bufferutil.o.d  |   30 -
 .../bufferutil/build/Release/bufferutil.node  |  Bin 24762 -> 0 bytes
 .../build/Release/obj.target/bufferutil.node  |  Bin 24762 -> 0 bytes
 .../obj.target/bufferutil/src/bufferutil.o    |  Bin 20232 -> 0 bytes
 .../bufferutil/build/binding.Makefile         |    6 -
 .../bufferutil/build/bufferutil.target.mk     |  133 -
 .../node_modules/bufferutil/build/config.gypi |  116 -
 .../ws/node_modules/bufferutil/fallback.js    |   52 -
 .../ws/node_modules/bufferutil/index.js       |    7 -
 .../node_modules/bindings/README.md           |   97 -
 .../node_modules/bindings/bindings.js         |  166 -
 .../node_modules/bindings/package.json        |   33 -
 .../bufferutil/node_modules/nan/.dntrc        |   30 -
 .../bufferutil/node_modules/nan/CHANGELOG.md  |  265 -
 .../bufferutil/node_modules/nan/LICENSE.md    |   13 -
 .../bufferutil/node_modules/nan/appveyor.yml  |   37 -
 .../node_modules/nan/include_dirs.js          |    1 -
 .../bufferutil/node_modules/nan/nan.h         | 2174 -------
 .../nan/nan_implementation_12_inl.h           |  262 -
 .../nan/nan_implementation_pre_12_inl.h       |  268 -
 .../bufferutil/node_modules/nan/nan_new.h     |  329 --
 .../node_modules/nan/nan_string_bytes.h       |  312 -
 .../bufferutil/node_modules/nan/package.json  |   65 -
 .../ws/node_modules/bufferutil/package.json   |   35 -
 .../node_modules/bufferutil/src/bufferutil.cc |  121 -
 .../ws/node_modules/options/.npmignore        |    7 -
 .../ws/node_modules/options/Makefile          |   12 -
 .../ws/node_modules/options/README.md         |   69 -
 .../ws/node_modules/options/lib/options.js    |   86 -
 .../ws/node_modules/options/package.json      |   32 -
 .../ws/node_modules/ultron/.npmignore         |    3 -
 .../ws/node_modules/ultron/.travis.yml        |   17 -
 .../ws/node_modules/ultron/README.md          |   97 -
 .../ws/node_modules/ultron/index.js           |  125 -
 .../ws/node_modules/ultron/package.json       |   46 -
 .../ws/node_modules/ultron/test.js            |  327 --
 .../ws/node_modules/utf-8-validate/.npmignore |    3 -
 .../node_modules/utf-8-validate/binding.gyp   |   10 -
 .../utf-8-validate/build/Makefile             |  332 --
 .../Release/obj.target/validation.node.d      |    1 -
 .../obj.target/validation/src/validation.o.d  |   30 -
 .../Release/.deps/Release/validation.node.d   |    1 -
 .../build/Release/obj.target/validation.node  |  Bin 20472 -> 0 bytes
 .../obj.target/validation/src/validation.o    |  Bin 17856 -> 0 bytes
 .../build/Release/validation.node             |  Bin 20472 -> 0 bytes
 .../utf-8-validate/build/binding.Makefile     |    6 -
 .../utf-8-validate/build/config.gypi          |  116 -
 .../utf-8-validate/build/validation.target.mk |  133 -
 .../node_modules/utf-8-validate/fallback.js   |   13 -
 .../ws/node_modules/utf-8-validate/index.js   |    7 -
 .../node_modules/bindings/README.md           |   97 -
 .../node_modules/bindings/bindings.js         |  166 -
 .../node_modules/bindings/package.json        |   33 -
 .../utf-8-validate/node_modules/nan/.dntrc    |   30 -
 .../node_modules/nan/CHANGELOG.md             |  265 -
 .../node_modules/nan/LICENSE.md               |   13 -
 .../node_modules/nan/appveyor.yml             |   37 -
 .../node_modules/nan/include_dirs.js          |    1 -
 .../utf-8-validate/node_modules/nan/nan.h     | 2174 -------
 .../nan/nan_implementation_12_inl.h           |  262 -
 .../nan/nan_implementation_pre_12_inl.h       |  268 -
 .../utf-8-validate/node_modules/nan/nan_new.h |  329 --
 .../node_modules/nan/nan_string_bytes.h       |  312 -
 .../node_modules/nan/package.json             |   65 -
 .../node_modules/utf-8-validate/package.json  |   35 -
 .../utf-8-validate/src/validation.cc          |  148 -
 .../mag/node_modules/ws/package.json          |  139 +-
 .../mag/node_modules/xtend/.jshintrc          |   30 +
 .../node_modules/ansi => xtend}/.npmignore    |    0
 input_devices/mag/node_modules/xtend/LICENCE  |   19 +
 input_devices/mag/node_modules/xtend/Makefile |    4 +
 .../mag/node_modules/xtend/README.md          |   32 +
 .../mag/node_modules/xtend/immutable.js       |   19 +
 .../mag/node_modules/xtend/mutable.js         |   17 +
 .../mag/node_modules/xtend/package.json       |  109 +
 input_devices/mag/node_modules/xtend/test.js  |   83 +
 2137 files changed, 115041 insertions(+), 117949 deletions(-)
 create mode 120000 input_devices/mag/node_modules/.bin/detect-libc
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/.bin/mkdirp (100%)
 create mode 120000 input_devices/mag/node_modules/.bin/prebuild-install
 create mode 120000 input_devices/mag/node_modules/.bin/prominode
 create mode 120000 input_devices/mag/node_modules/.bin/rc
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/.bin/semver (100%)
 create mode 120000 input_devices/mag/node_modules/.bin/serialport-list
 create mode 120000 input_devices/mag/node_modules/.bin/serialport-repl
 create mode 120000 input_devices/mag/node_modules/.bin/serialport-term
 delete mode 120000 input_devices/mag/node_modules/.bin/serialportlist
 delete mode 120000 input_devices/mag/node_modules/.bin/serialportterm
 create mode 120000 input_devices/mag/node_modules/.bin/window-size
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-abstract/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-abstract/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-abstract/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-abstract/binding-abstract.js
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-abstract/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-mock/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-mock/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-mock/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-mock/binding-mock.js
 create mode 100644 input_devices/mag/node_modules/@serialport/binding-mock/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/binding.gyp
 create mode 100755 input_devices/mag/node_modules/@serialport/bindings/build/Release/bindings.node
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/bindings-test.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/bindings-win32-sn-parser-test.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/darwin.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/index.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/linux-list-test.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/linux-list.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/linux.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/poller.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/unix-read.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/unix-write.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/util.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/win32-sn-parser.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/lib/win32.js
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.cpp
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.h
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/poller.cpp
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/poller.h
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/serialport.cpp
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/serialport.h
 create mode 100755 input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.cpp
 create mode 100755 input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.h
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.cpp
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.h
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.cpp
 create mode 100644 input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.h
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-byte-length/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-byte-length/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-byte-length/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-byte-length/byte-length.js
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-byte-length/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-cctalk/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-cctalk/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-cctalk/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-cctalk/cctalk.js
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-cctalk/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-delimiter/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-delimiter/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-delimiter/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-delimiter/delimiter.js
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-delimiter/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-readline/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-readline/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-readline/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-readline/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-readline/readline.js
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-ready/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-ready/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-ready/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-ready/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-ready/ready.js
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-regex/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-regex/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-regex/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-regex/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/parser-regex/regex.js
 create mode 100644 input_devices/mag/node_modules/@serialport/stream/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/@serialport/stream/LICENSE
 create mode 100644 input_devices/mag/node_modules/@serialport/stream/README.md
 create mode 100644 input_devices/mag/node_modules/@serialport/stream/package.json
 create mode 100644 input_devices/mag/node_modules/@serialport/stream/stream.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgblack/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bgblack/README.md
 create mode 100644 input_devices/mag/node_modules/ansi-bgblack/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgblack/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bgblue/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bgblue/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgblue/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bgblue/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-bgcyan/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bgcyan/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgcyan/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bgcyan/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-bggreen/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bggreen/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bggreen/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bggreen/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-bgmagenta/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bgmagenta/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgmagenta/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bgmagenta/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-bgred/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bgred/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgred/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bgred/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-bgwhite/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bgwhite/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgwhite/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bgwhite/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-bgyellow/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bgyellow/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bgyellow/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bgyellow/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-black/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-black/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-black/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-black/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-blue/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-blue/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-blue/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-blue/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-bold/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-bold/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-bold/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-bold/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-colors/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-colors/README.md
 create mode 100644 input_devices/mag/node_modules/ansi-colors/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-colors/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-cyan/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-cyan/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-cyan/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-cyan/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-dim/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-dim/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-dim/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-dim/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-gray/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-gray/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-gray/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-gray/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-green/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-green/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-green/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-green/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-grey/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-grey/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-grey/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-grey/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-hidden/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-hidden/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-hidden/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-hidden/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-inverse/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-inverse/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-inverse/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-inverse/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-italic/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-italic/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-italic/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-italic/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-magenta/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-magenta/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-magenta/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-magenta/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-red/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-red/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-red/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-red/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-regex/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-regex/license
 create mode 100644 input_devices/mag/node_modules/ansi-regex/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-regex/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-reset/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-reset/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-reset/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-reset/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-strikethrough/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-strikethrough/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-strikethrough/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-strikethrough/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-underline/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-underline/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-underline/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-underline/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-white/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-white/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-white/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-white/readme.md
 create mode 100644 input_devices/mag/node_modules/ansi-wrap/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-wrap/README.md
 create mode 100644 input_devices/mag/node_modules/ansi-wrap/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-wrap/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-yellow/LICENSE
 create mode 100644 input_devices/mag/node_modules/ansi-yellow/index.js
 create mode 100644 input_devices/mag/node_modules/ansi-yellow/package.json
 create mode 100644 input_devices/mag/node_modules/ansi-yellow/readme.md
 create mode 100644 input_devices/mag/node_modules/aproba/LICENSE
 create mode 100644 input_devices/mag/node_modules/aproba/README.md
 create mode 100644 input_devices/mag/node_modules/aproba/index.js
 create mode 100644 input_devices/mag/node_modules/aproba/package.json
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/CHANGES.md
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/LICENSE
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/README.md
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/index.js
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/package.json
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/tracker-base.js
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/tracker-group.js
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/tracker-stream.js
 create mode 100644 input_devices/mag/node_modules/are-we-there-yet/tracker.js
 create mode 100755 input_devices/mag/node_modules/arr-flatten/LICENSE
 create mode 100755 input_devices/mag/node_modules/arr-flatten/README.md
 create mode 100644 input_devices/mag/node_modules/arr-flatten/index.js
 create mode 100644 input_devices/mag/node_modules/arr-flatten/package.json
 create mode 100644 input_devices/mag/node_modules/arr-swap/LICENSE
 create mode 100644 input_devices/mag/node_modules/arr-swap/README.md
 create mode 100644 input_devices/mag/node_modules/arr-swap/index.js
 create mode 100644 input_devices/mag/node_modules/arr-swap/node_modules/is-number/LICENSE
 create mode 100644 input_devices/mag/node_modules/arr-swap/node_modules/is-number/README.md
 create mode 100644 input_devices/mag/node_modules/arr-swap/node_modules/is-number/index.js
 create mode 100644 input_devices/mag/node_modules/arr-swap/node_modules/is-number/package.json
 create mode 100644 input_devices/mag/node_modules/arr-swap/package.json
 create mode 100644 input_devices/mag/node_modules/async-limiter/.travis.yml
 create mode 100644 input_devices/mag/node_modules/async-limiter/LICENSE
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/coverage.json
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/base.css
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/index.html
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.css
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.js
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov-report/sorter.js
 create mode 100644 input_devices/mag/node_modules/async-limiter/coverage/lcov.info
 create mode 100644 input_devices/mag/node_modules/async-limiter/index.js
 create mode 100644 input_devices/mag/node_modules/async-limiter/package.json
 create mode 100644 input_devices/mag/node_modules/async-limiter/readme.md
 create mode 100644 input_devices/mag/node_modules/bindings/README.md
 create mode 100644 input_devices/mag/node_modules/bindings/bindings.js
 create mode 100644 input_devices/mag/node_modules/bindings/package.json
 create mode 100644 input_devices/mag/node_modules/bl/.jshintrc
 create mode 100644 input_devices/mag/node_modules/bl/.travis.yml
 create mode 100644 input_devices/mag/node_modules/bl/LICENSE.md
 create mode 100644 input_devices/mag/node_modules/bl/README.md
 create mode 100644 input_devices/mag/node_modules/bl/bl.js
 create mode 100644 input_devices/mag/node_modules/bl/package.json
 create mode 100644 input_devices/mag/node_modules/bl/test/test.js
 create mode 100644 input_devices/mag/node_modules/buffer-alloc-unsafe/index.js
 create mode 100644 input_devices/mag/node_modules/buffer-alloc-unsafe/package.json
 create mode 100644 input_devices/mag/node_modules/buffer-alloc-unsafe/readme.md
 create mode 100644 input_devices/mag/node_modules/buffer-alloc/index.js
 create mode 100644 input_devices/mag/node_modules/buffer-alloc/package.json
 create mode 100644 input_devices/mag/node_modules/buffer-alloc/readme.md
 create mode 100644 input_devices/mag/node_modules/buffer-fill/index.js
 create mode 100644 input_devices/mag/node_modules/buffer-fill/package.json
 create mode 100644 input_devices/mag/node_modules/buffer-fill/readme.md
 create mode 100644 input_devices/mag/node_modules/choices-separator/LICENSE
 create mode 100644 input_devices/mag/node_modules/choices-separator/README.md
 create mode 100644 input_devices/mag/node_modules/choices-separator/index.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/.coveralls.yml
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/.eslintrc
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/.npmignore
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/.travis.yml
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/LICENSE
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/Makefile
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/README.md
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/component.json
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/karma.conf.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/node.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/package.json
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/src/browser.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/src/debug.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/src/index.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/src/inspector-log.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/debug/src/node.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/ms/index.js
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/ms/license.md
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/ms/package.json
 create mode 100644 input_devices/mag/node_modules/choices-separator/node_modules/ms/readme.md
 create mode 100644 input_devices/mag/node_modules/choices-separator/package.json
 create mode 100644 input_devices/mag/node_modules/chownr/LICENSE
 create mode 100644 input_devices/mag/node_modules/chownr/README.md
 create mode 100644 input_devices/mag/node_modules/chownr/chownr.js
 create mode 100644 input_devices/mag/node_modules/chownr/package.json
 create mode 100644 input_devices/mag/node_modules/clone-deep/LICENSE
 create mode 100644 input_devices/mag/node_modules/clone-deep/README.md
 create mode 100644 input_devices/mag/node_modules/clone-deep/index.js
 create mode 100644 input_devices/mag/node_modules/clone-deep/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/clone-deep/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/clone-deep/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/clone-deep/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/clone-deep/package.json
 create mode 100644 input_devices/mag/node_modules/code-point-at/index.js
 create mode 100644 input_devices/mag/node_modules/code-point-at/license
 create mode 100644 input_devices/mag/node_modules/code-point-at/package.json
 create mode 100644 input_devices/mag/node_modules/code-point-at/readme.md
 create mode 100644 input_devices/mag/node_modules/collection-visit/LICENSE
 create mode 100644 input_devices/mag/node_modules/collection-visit/README.md
 create mode 100644 input_devices/mag/node_modules/collection-visit/index.js
 create mode 100644 input_devices/mag/node_modules/collection-visit/package.json
 create mode 100644 input_devices/mag/node_modules/commander/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/commander/LICENSE
 create mode 100644 input_devices/mag/node_modules/commander/Readme.md
 create mode 100644 input_devices/mag/node_modules/commander/index.js
 create mode 100644 input_devices/mag/node_modules/commander/package.json
 create mode 100644 input_devices/mag/node_modules/commander/typings/index.d.ts
 create mode 100644 input_devices/mag/node_modules/component-emitter/History.md
 create mode 100644 input_devices/mag/node_modules/component-emitter/LICENSE
 create mode 100644 input_devices/mag/node_modules/component-emitter/Readme.md
 create mode 100644 input_devices/mag/node_modules/component-emitter/index.js
 create mode 100644 input_devices/mag/node_modules/component-emitter/package.json
 create mode 100644 input_devices/mag/node_modules/console-control-strings/LICENSE
 create mode 100644 input_devices/mag/node_modules/console-control-strings/README.md
 create mode 100644 input_devices/mag/node_modules/console-control-strings/README.md~
 create mode 100644 input_devices/mag/node_modules/console-control-strings/index.js
 create mode 100644 input_devices/mag/node_modules/console-control-strings/package.json
 create mode 100644 input_devices/mag/node_modules/copy-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/copy-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/copy-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/core-util-is/LICENSE
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules => }/core-util-is/README.md (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules => }/core-util-is/float.patch (100%)
 create mode 100644 input_devices/mag/node_modules/core-util-is/lib/util.js
 create mode 100644 input_devices/mag/node_modules/core-util-is/package.json
 create mode 100644 input_devices/mag/node_modules/core-util-is/test.js
 create mode 100644 input_devices/mag/node_modules/debug/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/debug/LICENSE
 create mode 100644 input_devices/mag/node_modules/debug/README.md
 create mode 100644 input_devices/mag/node_modules/debug/dist/debug.js
 create mode 100644 input_devices/mag/node_modules/debug/node.js
 create mode 100644 input_devices/mag/node_modules/debug/package.json
 create mode 100644 input_devices/mag/node_modules/debug/src/browser.js
 create mode 100644 input_devices/mag/node_modules/debug/src/common.js
 create mode 100644 input_devices/mag/node_modules/debug/src/index.js
 create mode 100644 input_devices/mag/node_modules/debug/src/node.js
 create mode 100644 input_devices/mag/node_modules/decompress-response/index.js
 create mode 100644 input_devices/mag/node_modules/decompress-response/license
 create mode 100644 input_devices/mag/node_modules/decompress-response/package.json
 create mode 100644 input_devices/mag/node_modules/decompress-response/readme.md
 create mode 100644 input_devices/mag/node_modules/deep-extend/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/deep-extend/LICENSE
 create mode 100644 input_devices/mag/node_modules/deep-extend/README.md
 create mode 100644 input_devices/mag/node_modules/deep-extend/index.js
 create mode 100644 input_devices/mag/node_modules/deep-extend/lib/deep-extend.js
 create mode 100644 input_devices/mag/node_modules/deep-extend/package.json
 create mode 100644 input_devices/mag/node_modules/define-property/LICENSE
 create mode 100644 input_devices/mag/node_modules/define-property/README.md
 create mode 100644 input_devices/mag/node_modules/define-property/index.js
 create mode 100644 input_devices/mag/node_modules/define-property/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs => delegates}/.npmignore (100%)
 create mode 100644 input_devices/mag/node_modules/delegates/History.md
 create mode 100644 input_devices/mag/node_modules/delegates/License
 create mode 100644 input_devices/mag/node_modules/delegates/Makefile
 create mode 100644 input_devices/mag/node_modules/delegates/Readme.md
 create mode 100644 input_devices/mag/node_modules/delegates/index.js
 create mode 100644 input_devices/mag/node_modules/delegates/package.json
 create mode 100644 input_devices/mag/node_modules/delegates/test/index.js
 create mode 100644 input_devices/mag/node_modules/detect-libc/.npmignore
 create mode 100644 input_devices/mag/node_modules/detect-libc/LICENSE
 create mode 100644 input_devices/mag/node_modules/detect-libc/README.md
 create mode 100755 input_devices/mag/node_modules/detect-libc/bin/detect-libc.js
 create mode 100644 input_devices/mag/node_modules/detect-libc/lib/detect-libc.js
 create mode 100644 input_devices/mag/node_modules/detect-libc/package.json
 create mode 100644 input_devices/mag/node_modules/end-of-stream/LICENSE
 create mode 100644 input_devices/mag/node_modules/end-of-stream/README.md
 create mode 100644 input_devices/mag/node_modules/end-of-stream/index.js
 create mode 100644 input_devices/mag/node_modules/end-of-stream/package.json
 create mode 100644 input_devices/mag/node_modules/error-symbol/LICENSE
 create mode 100644 input_devices/mag/node_modules/error-symbol/README.md
 create mode 100644 input_devices/mag/node_modules/error-symbol/index.js
 create mode 100644 input_devices/mag/node_modules/error-symbol/package.json
 create mode 100644 input_devices/mag/node_modules/expand-template/.travis.yml
 create mode 100644 input_devices/mag/node_modules/expand-template/README.md
 create mode 100644 input_devices/mag/node_modules/expand-template/index.js
 create mode 100644 input_devices/mag/node_modules/expand-template/package.json
 create mode 100644 input_devices/mag/node_modules/expand-template/test.js
 create mode 100644 input_devices/mag/node_modules/extend-shallow/LICENSE
 create mode 100644 input_devices/mag/node_modules/extend-shallow/README.md
 create mode 100644 input_devices/mag/node_modules/extend-shallow/index.js
 create mode 100644 input_devices/mag/node_modules/extend-shallow/package.json
 create mode 100644 input_devices/mag/node_modules/for-in/LICENSE
 create mode 100644 input_devices/mag/node_modules/for-in/README.md
 create mode 100644 input_devices/mag/node_modules/for-in/index.js
 create mode 100644 input_devices/mag/node_modules/for-in/package.json
 create mode 100644 input_devices/mag/node_modules/for-own/LICENSE
 create mode 100644 input_devices/mag/node_modules/for-own/README.md
 create mode 100644 input_devices/mag/node_modules/for-own/index.js
 create mode 100644 input_devices/mag/node_modules/for-own/package.json
 create mode 100644 input_devices/mag/node_modules/fs-constants/LICENSE
 create mode 100644 input_devices/mag/node_modules/fs-constants/README.md
 create mode 100644 input_devices/mag/node_modules/fs-constants/browser.js
 create mode 100644 input_devices/mag/node_modules/fs-constants/index.js
 create mode 100644 input_devices/mag/node_modules/fs-constants/package.json
 create mode 100644 input_devices/mag/node_modules/gauge/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/gauge/LICENSE
 create mode 100644 input_devices/mag/node_modules/gauge/README.md
 create mode 100644 input_devices/mag/node_modules/gauge/base-theme.js
 create mode 100644 input_devices/mag/node_modules/gauge/error.js
 create mode 100644 input_devices/mag/node_modules/gauge/has-color.js
 create mode 100644 input_devices/mag/node_modules/gauge/index.js
 create mode 100644 input_devices/mag/node_modules/gauge/package.json
 create mode 100644 input_devices/mag/node_modules/gauge/plumbing.js
 create mode 100644 input_devices/mag/node_modules/gauge/process.js
 create mode 100644 input_devices/mag/node_modules/gauge/progress-bar.js
 create mode 100644 input_devices/mag/node_modules/gauge/render-template.js
 create mode 100644 input_devices/mag/node_modules/gauge/set-immediate.js
 create mode 100644 input_devices/mag/node_modules/gauge/set-interval.js
 create mode 100644 input_devices/mag/node_modules/gauge/spin.js
 create mode 100644 input_devices/mag/node_modules/gauge/template-item.js
 create mode 100644 input_devices/mag/node_modules/gauge/theme-set.js
 create mode 100644 input_devices/mag/node_modules/gauge/themes.js
 create mode 100644 input_devices/mag/node_modules/gauge/wide-truncate.js
 create mode 100644 input_devices/mag/node_modules/github-from-package/.travis.yml
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist => github-from-package}/LICENSE (100%)
 create mode 100644 input_devices/mag/node_modules/github-from-package/example/package.json
 create mode 100644 input_devices/mag/node_modules/github-from-package/example/url.js
 create mode 100644 input_devices/mag/node_modules/github-from-package/index.js
 create mode 100644 input_devices/mag/node_modules/github-from-package/package.json
 create mode 100644 input_devices/mag/node_modules/github-from-package/readme.markdown
 create mode 100644 input_devices/mag/node_modules/github-from-package/test/a.json
 create mode 100644 input_devices/mag/node_modules/github-from-package/test/b.json
 create mode 100644 input_devices/mag/node_modules/github-from-package/test/c.json
 create mode 100644 input_devices/mag/node_modules/github-from-package/test/d.json
 create mode 100644 input_devices/mag/node_modules/github-from-package/test/e.json
 create mode 100644 input_devices/mag/node_modules/github-from-package/test/url.js
 create mode 100644 input_devices/mag/node_modules/has-unicode/LICENSE
 create mode 100644 input_devices/mag/node_modules/has-unicode/README.md
 create mode 100644 input_devices/mag/node_modules/has-unicode/index.js
 create mode 100644 input_devices/mag/node_modules/has-unicode/package.json
 create mode 100644 input_devices/mag/node_modules/info-symbol/LICENSE
 create mode 100644 input_devices/mag/node_modules/info-symbol/README.md
 create mode 100644 input_devices/mag/node_modules/info-symbol/index.js
 create mode 100644 input_devices/mag/node_modules/info-symbol/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules => }/inherits/LICENSE (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules => }/inherits/README.md (100%)
 create mode 100644 input_devices/mag/node_modules/inherits/inherits.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules => }/inherits/inherits_browser.js (100%)
 create mode 100644 input_devices/mag/node_modules/inherits/package.json
 create mode 100644 input_devices/mag/node_modules/ini/LICENSE
 create mode 100644 input_devices/mag/node_modules/ini/README.md
 create mode 100644 input_devices/mag/node_modules/ini/ini.js
 create mode 100644 input_devices/mag/node_modules/ini/package.json
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/is-accessor-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/is-buffer/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-buffer/README.md
 create mode 100644 input_devices/mag/node_modules/is-buffer/index.js
 create mode 100644 input_devices/mag/node_modules/is-buffer/package.json
 create mode 100644 input_devices/mag/node_modules/is-buffer/test/basic.js
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/is-data-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/is-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/is-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/is-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/is-extendable/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-extendable/README.md
 create mode 100644 input_devices/mag/node_modules/is-extendable/index.js
 create mode 100644 input_devices/mag/node_modules/is-extendable/package.json
 create mode 100644 input_devices/mag/node_modules/is-fullwidth-code-point/index.js
 create mode 100644 input_devices/mag/node_modules/is-fullwidth-code-point/license
 create mode 100644 input_devices/mag/node_modules/is-fullwidth-code-point/package.json
 create mode 100644 input_devices/mag/node_modules/is-fullwidth-code-point/readme.md
 create mode 100644 input_devices/mag/node_modules/is-number/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-number/README.md
 create mode 100644 input_devices/mag/node_modules/is-number/index.js
 create mode 100644 input_devices/mag/node_modules/is-number/package.json
 create mode 100644 input_devices/mag/node_modules/is-plain-object/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-plain-object/README.md
 create mode 100644 input_devices/mag/node_modules/is-plain-object/index.d.ts
 create mode 100644 input_devices/mag/node_modules/is-plain-object/index.js
 create mode 100644 input_devices/mag/node_modules/is-plain-object/package.json
 create mode 100644 input_devices/mag/node_modules/is-windows/LICENSE
 create mode 100644 input_devices/mag/node_modules/is-windows/README.md
 create mode 100644 input_devices/mag/node_modules/is-windows/index.js
 create mode 100644 input_devices/mag/node_modules/is-windows/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/nopt => isarray}/.npmignore (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist => isarray}/.travis.yml (100%)
 create mode 100644 input_devices/mag/node_modules/isarray/Makefile
 create mode 100644 input_devices/mag/node_modules/isarray/README.md
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules => }/isarray/component.json (100%)
 create mode 100644 input_devices/mag/node_modules/isarray/index.js
 create mode 100644 input_devices/mag/node_modules/isarray/package.json
 create mode 100644 input_devices/mag/node_modules/isarray/test.js
 create mode 100644 input_devices/mag/node_modules/isobject/LICENSE
 create mode 100644 input_devices/mag/node_modules/isobject/README.md
 create mode 100644 input_devices/mag/node_modules/isobject/index.d.ts
 create mode 100644 input_devices/mag/node_modules/isobject/index.js
 create mode 100644 input_devices/mag/node_modules/isobject/package.json
 create mode 100644 input_devices/mag/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/koalas/LICENSE
 create mode 100644 input_devices/mag/node_modules/koalas/README.md
 create mode 100644 input_devices/mag/node_modules/koalas/index.js
 create mode 100644 input_devices/mag/node_modules/koalas/package.json
 create mode 100644 input_devices/mag/node_modules/lazy-cache/LICENSE
 create mode 100644 input_devices/mag/node_modules/lazy-cache/README.md
 create mode 100644 input_devices/mag/node_modules/lazy-cache/index.js
 create mode 100644 input_devices/mag/node_modules/lazy-cache/package.json
 create mode 100644 input_devices/mag/node_modules/log-ok/LICENSE
 create mode 100644 input_devices/mag/node_modules/log-ok/index.js
 create mode 100644 input_devices/mag/node_modules/log-ok/package.json
 create mode 100644 input_devices/mag/node_modules/log-utils/LICENSE
 create mode 100644 input_devices/mag/node_modules/log-utils/index.js
 create mode 100644 input_devices/mag/node_modules/log-utils/package.json
 create mode 100644 input_devices/mag/node_modules/map-visit/LICENSE
 create mode 100644 input_devices/mag/node_modules/map-visit/README.md
 create mode 100644 input_devices/mag/node_modules/map-visit/index.js
 create mode 100644 input_devices/mag/node_modules/map-visit/package.json
 create mode 100644 input_devices/mag/node_modules/mimic-response/index.js
 create mode 100644 input_devices/mag/node_modules/mimic-response/license
 create mode 100644 input_devices/mag/node_modules/mimic-response/package.json
 create mode 100644 input_devices/mag/node_modules/mimic-response/readme.md
 create mode 100644 input_devices/mag/node_modules/minimist/.travis.yml
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules => }/minimist/LICENSE (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules => }/minimist/example/parse.js (100%)
 create mode 100644 input_devices/mag/node_modules/minimist/index.js
 create mode 100644 input_devices/mag/node_modules/minimist/package.json
 create mode 100644 input_devices/mag/node_modules/minimist/readme.markdown
 create mode 100644 input_devices/mag/node_modules/minimist/test/all_bool.js
 create mode 100644 input_devices/mag/node_modules/minimist/test/bool.js
 create mode 100644 input_devices/mag/node_modules/minimist/test/dash.js
 create mode 100644 input_devices/mag/node_modules/minimist/test/default_bool.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules => }/minimist/test/dotted.js (100%)
 create mode 100644 input_devices/mag/node_modules/minimist/test/kv_short.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules => }/minimist/test/long.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules => }/minimist/test/num.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules => }/minimist/test/parse.js (100%)
 create mode 100644 input_devices/mag/node_modules/minimist/test/parse_modified.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules => }/minimist/test/short.js (100%)
 create mode 100644 input_devices/mag/node_modules/minimist/test/stop_early.js
 create mode 100644 input_devices/mag/node_modules/minimist/test/unknown.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules => }/minimist/test/whitespace.js (100%)
 create mode 100644 input_devices/mag/node_modules/mixin-object/LICENSE
 create mode 100644 input_devices/mag/node_modules/mixin-object/README.md
 create mode 100644 input_devices/mag/node_modules/mixin-object/index.js
 create mode 100644 input_devices/mag/node_modules/mixin-object/node_modules/for-in/LICENSE
 create mode 100644 input_devices/mag/node_modules/mixin-object/node_modules/for-in/README.md
 create mode 100644 input_devices/mag/node_modules/mixin-object/node_modules/for-in/index.js
 create mode 100644 input_devices/mag/node_modules/mixin-object/node_modules/for-in/package.json
 create mode 100644 input_devices/mag/node_modules/mixin-object/package.json
 create mode 100644 input_devices/mag/node_modules/mkdirp/.travis.yml
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/LICENSE (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/bin/cmd.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/bin/usage.txt (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/examples/pow.js (100%)
 create mode 100644 input_devices/mag/node_modules/mkdirp/index.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc => mkdirp}/node_modules/minimist/.travis.yml (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/optimist => mkdirp}/node_modules/minimist/LICENSE (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc => mkdirp}/node_modules/minimist/example/parse.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/node_modules/minimist/index.js (100%)
 create mode 100644 input_devices/mag/node_modules/mkdirp/node_modules/minimist/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/node_modules/minimist/readme.markdown (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/node_modules/minimist/test/dash.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/node_modules/minimist/test/default_bool.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/node_modules/minimist/test/dotted.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc => mkdirp}/node_modules/minimist/test/long.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/node_modules/minimist/test/parse.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/node_modules/minimist/test/parse_modified.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc => mkdirp}/node_modules/minimist/test/short.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/rc => mkdirp}/node_modules/minimist/test/whitespace.js (100%)
 create mode 100644 input_devices/mag/node_modules/mkdirp/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/readme.markdown (100%)
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/chmod.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/clobber.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/mkdirp.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/test/opts_fs.js (81%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/test/opts_fs_sync.js (81%)
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/perm.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/perm_sync.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/race.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/rel.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/test/return.js (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/mkdirp/test/return_sync.js (100%)
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/root.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/sync.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/umask.js
 create mode 100644 input_devices/mag/node_modules/mkdirp/test/umask_sync.js
 create mode 100644 input_devices/mag/node_modules/ms/index.js
 create mode 100644 input_devices/mag/node_modules/ms/license.md
 create mode 100644 input_devices/mag/node_modules/ms/package.json
 create mode 100644 input_devices/mag/node_modules/ms/readme.md
 create mode 100644 input_devices/mag/node_modules/mute-stream/.nyc_output/33508.json
 create mode 100644 input_devices/mag/node_modules/mute-stream/.nyc_output/33510.json
 create mode 100644 input_devices/mag/node_modules/mute-stream/.travis.yml
 create mode 100644 input_devices/mag/node_modules/mute-stream/LICENSE
 create mode 100644 input_devices/mag/node_modules/mute-stream/README.md
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/index.html
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/mute.js.html
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/base.css
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/index.html
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.css
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.js
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/sort-arrow-sprite.png
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov-report/sorter.js
 create mode 100644 input_devices/mag/node_modules/mute-stream/coverage/lcov.info
 create mode 100644 input_devices/mag/node_modules/mute-stream/mute.js
 create mode 100644 input_devices/mag/node_modules/mute-stream/package.json
 create mode 100644 input_devices/mag/node_modules/mute-stream/test/basic.js
 create mode 100644 input_devices/mag/node_modules/nan/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/nan/LICENSE.md
 create mode 100644 input_devices/mag/node_modules/nan/README.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/asyncworker.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/buffers.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/callback.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/converters.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/errors.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/json.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/maybe_types.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/methods.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/new.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/node_misc.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/object_wrappers.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/persistent.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/scopes.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/script.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/string_bytes.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/v8_internals.md
 create mode 100644 input_devices/mag/node_modules/nan/doc/v8_misc.md
 rename input_devices/mag/node_modules/{serialport/node_modules => }/nan/include_dirs.js (100%)
 create mode 100644 input_devices/mag/node_modules/nan/nan-2.11.1.tgz
 create mode 100644 input_devices/mag/node_modules/nan/nan.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_callbacks.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_callbacks_12_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_callbacks_pre_12_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_converters.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_converters_43_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_converters_pre_43_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_define_own_property_helper.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_implementation_12_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_implementation_pre_12_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_json.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_maybe_43_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_maybe_pre_43_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_new.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_object_wrap.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_persistent_12_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_persistent_pre_12_inl.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_private.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_string_bytes.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_typedarray_contents.h
 create mode 100644 input_devices/mag/node_modules/nan/nan_weak.h
 create mode 100644 input_devices/mag/node_modules/nan/package.json
 create mode 100755 input_devices/mag/node_modules/nan/tools/1to2.js
 create mode 100644 input_devices/mag/node_modules/nan/tools/README.md
 create mode 100644 input_devices/mag/node_modules/nan/tools/package.json
 create mode 100644 input_devices/mag/node_modules/napi-build-utils/LICENSE
 create mode 100644 input_devices/mag/node_modules/napi-build-utils/README.md
 create mode 100644 input_devices/mag/node_modules/napi-build-utils/index.js
 create mode 100644 input_devices/mag/node_modules/napi-build-utils/index.md
 create mode 100644 input_devices/mag/node_modules/napi-build-utils/napi-build-utils-1.0.0.tgz
 create mode 100644 input_devices/mag/node_modules/napi-build-utils/package.json
 create mode 100644 input_devices/mag/node_modules/node-abi/.travis.yml
 create mode 100644 input_devices/mag/node_modules/node-abi/CODE_OF_CONDUCT.md
 create mode 100644 input_devices/mag/node_modules/node-abi/CONTRIBUTING.md
 create mode 100644 input_devices/mag/node_modules/node-abi/LICENSE
 create mode 100644 input_devices/mag/node_modules/node-abi/README.md
 create mode 100644 input_devices/mag/node_modules/node-abi/index.js
 create mode 100644 input_devices/mag/node_modules/node-abi/package.json
 create mode 100644 input_devices/mag/node_modules/node-abi/test/index.js
 create mode 100644 input_devices/mag/node_modules/noop-logger/.npmignore
 create mode 100644 input_devices/mag/node_modules/noop-logger/History.md
 create mode 100644 input_devices/mag/node_modules/noop-logger/Makefile
 create mode 100644 input_devices/mag/node_modules/noop-logger/Readme.md
 create mode 100644 input_devices/mag/node_modules/noop-logger/circle.yml
 create mode 100644 input_devices/mag/node_modules/noop-logger/lib/index.js
 create mode 100644 input_devices/mag/node_modules/noop-logger/package.json
 create mode 100644 input_devices/mag/node_modules/noop-logger/test/index.js
 create mode 100644 input_devices/mag/node_modules/npmlog/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/npmlog/LICENSE
 create mode 100644 input_devices/mag/node_modules/npmlog/README.md
 create mode 100644 input_devices/mag/node_modules/npmlog/log.js
 create mode 100644 input_devices/mag/node_modules/npmlog/package.json
 create mode 100644 input_devices/mag/node_modules/number-is-nan/index.js
 create mode 100644 input_devices/mag/node_modules/number-is-nan/license
 create mode 100644 input_devices/mag/node_modules/number-is-nan/package.json
 create mode 100644 input_devices/mag/node_modules/number-is-nan/readme.md
 create mode 100644 input_devices/mag/node_modules/object-assign/index.js
 create mode 100644 input_devices/mag/node_modules/object-assign/license
 create mode 100644 input_devices/mag/node_modules/object-assign/package.json
 create mode 100644 input_devices/mag/node_modules/object-assign/readme.md
 create mode 100644 input_devices/mag/node_modules/object-copy/LICENSE
 create mode 100644 input_devices/mag/node_modules/object-copy/index.js
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/define-property/LICENSE
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/define-property/README.md
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/define-property/index.js
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/define-property/package.json
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/object-copy/package.json
 create mode 100644 input_devices/mag/node_modules/object-visit/LICENSE
 create mode 100644 input_devices/mag/node_modules/object-visit/README.md
 create mode 100644 input_devices/mag/node_modules/object-visit/index.js
 create mode 100644 input_devices/mag/node_modules/object-visit/package.json
 create mode 100644 input_devices/mag/node_modules/once/LICENSE
 create mode 100644 input_devices/mag/node_modules/once/README.md
 create mode 100644 input_devices/mag/node_modules/once/once.js
 create mode 100644 input_devices/mag/node_modules/once/package.json
 create mode 100644 input_devices/mag/node_modules/os-homedir/index.js
 create mode 100644 input_devices/mag/node_modules/os-homedir/license
 create mode 100644 input_devices/mag/node_modules/os-homedir/package.json
 create mode 100644 input_devices/mag/node_modules/os-homedir/readme.md
 create mode 100644 input_devices/mag/node_modules/pointer-symbol/LICENSE
 create mode 100644 input_devices/mag/node_modules/pointer-symbol/README.md
 create mode 100644 input_devices/mag/node_modules/pointer-symbol/index.js
 create mode 100644 input_devices/mag/node_modules/pointer-symbol/package.json
 create mode 100644 input_devices/mag/node_modules/prebuild-install/.travis.yml
 create mode 100644 input_devices/mag/node_modules/prebuild-install/CONTRIBUTING.md
 create mode 100644 input_devices/mag/node_modules/prebuild-install/LICENSE
 create mode 100644 input_devices/mag/node_modules/prebuild-install/README.md
 create mode 100644 input_devices/mag/node_modules/prebuild-install/appveyor.yml
 create mode 100644 input_devices/mag/node_modules/prebuild-install/asset.js
 create mode 100755 input_devices/mag/node_modules/prebuild-install/bin.js
 create mode 100644 input_devices/mag/node_modules/prebuild-install/download.js
 create mode 100644 input_devices/mag/node_modules/prebuild-install/error.js
 create mode 100644 input_devices/mag/node_modules/prebuild-install/help.txt
 create mode 100644 input_devices/mag/node_modules/prebuild-install/index.js
 create mode 100644 input_devices/mag/node_modules/prebuild-install/log.js
 create mode 100644 input_devices/mag/node_modules/prebuild-install/package.json
 create mode 100644 input_devices/mag/node_modules/prebuild-install/proxy.js
 create mode 100644 input_devices/mag/node_modules/prebuild-install/rc.js
 create mode 100644 input_devices/mag/node_modules/prebuild-install/util.js
 create mode 100644 input_devices/mag/node_modules/process-nextick-args/index.js
 create mode 100644 input_devices/mag/node_modules/process-nextick-args/license.md
 create mode 100644 input_devices/mag/node_modules/process-nextick-args/package.json
 create mode 100644 input_devices/mag/node_modules/process-nextick-args/readme.md
 create mode 100644 input_devices/mag/node_modules/promirepl/.npmignore
 create mode 100644 input_devices/mag/node_modules/promirepl/LICENSE
 create mode 100644 input_devices/mag/node_modules/promirepl/README.md
 create mode 100755 input_devices/mag/node_modules/promirepl/bin/prominode.js
 create mode 100644 input_devices/mag/node_modules/promirepl/index.js
 create mode 100644 input_devices/mag/node_modules/promirepl/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-actions/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-actions/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-actions/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/.coveralls.yml
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/.eslintrc
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/.npmignore
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/.travis.yml
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/Makefile
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/component.json
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/karma.conf.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/node.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/browser.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/debug.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/inspector-log.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/node.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/ms/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/ms/license.md
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/ms/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-actions/node_modules/ms/readme.md
 create mode 100644 input_devices/mag/node_modules/prompt-actions/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-base/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-base/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-base/changelog.md
 create mode 100644 input_devices/mag/node_modules/prompt-base/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-base/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.coveralls.yml
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.eslintrc
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.npmignore
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.travis.yml
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/Makefile
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/component.json
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/karma.conf.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/node.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/browser.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/debug.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/inspector-log.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/node.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/license.md
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/readme.md
 create mode 100644 input_devices/mag/node_modules/prompt-checkbox/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-choices/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-choices/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-choices/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-choices/lib/choice.js
 create mode 100644 input_devices/mag/node_modules/prompt-choices/lib/utils.js
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/define-property/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/define-property/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/define-property/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/define-property/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/define-property/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-choices/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-list/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-list/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-list/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-list/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-question/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-question/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-question/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-question/lib/utils.js
 create mode 100644 input_devices/mag/node_modules/prompt-question/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-question/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-question/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-question/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-question/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-radio/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-radio/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-radio/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/.coveralls.yml
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/.eslintrc
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/.npmignore
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/.travis.yml
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/LICENSE
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/Makefile
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/README.md
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/component.json
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/karma.conf.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/node.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/browser.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/debug.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/inspector-log.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/node.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/ms/index.js
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/ms/license.md
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/ms/package.json
 create mode 100644 input_devices/mag/node_modules/prompt-radio/node_modules/ms/readme.md
 create mode 100644 input_devices/mag/node_modules/prompt-radio/package.json
 create mode 100644 input_devices/mag/node_modules/pump/.travis.yml
 create mode 100644 input_devices/mag/node_modules/pump/LICENSE
 create mode 100644 input_devices/mag/node_modules/pump/README.md
 create mode 100644 input_devices/mag/node_modules/pump/index.js
 create mode 100644 input_devices/mag/node_modules/pump/package.json
 create mode 100644 input_devices/mag/node_modules/pump/test-browser.js
 create mode 100644 input_devices/mag/node_modules/pump/test-node.js
 create mode 100644 input_devices/mag/node_modules/radio-symbol/LICENSE
 create mode 100644 input_devices/mag/node_modules/radio-symbol/README.md
 create mode 100644 input_devices/mag/node_modules/radio-symbol/index.js
 create mode 100644 input_devices/mag/node_modules/radio-symbol/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/rc/LICENSE.APACHE2 (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/rc/LICENSE.BSD (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/rc/LICENSE.MIT (100%)
 create mode 100644 input_devices/mag/node_modules/rc/README.md
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/rc/browser.js (100%)
 create mode 100755 input_devices/mag/node_modules/rc/cli.js
 create mode 100755 input_devices/mag/node_modules/rc/index.js
 create mode 100644 input_devices/mag/node_modules/rc/lib/utils.js
 create mode 100644 input_devices/mag/node_modules/rc/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules => }/rc/test/ini.js (100%)
 create mode 100644 input_devices/mag/node_modules/rc/test/nested-env-vars.js
 create mode 100644 input_devices/mag/node_modules/rc/test/test.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/.travis.yml
 create mode 100644 input_devices/mag/node_modules/readable-stream/CONTRIBUTING.md
 create mode 100644 input_devices/mag/node_modules/readable-stream/GOVERNANCE.md
 create mode 100644 input_devices/mag/node_modules/readable-stream/LICENSE
 create mode 100644 input_devices/mag/node_modules/readable-stream/README.md
 create mode 100644 input_devices/mag/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md
 create mode 100644 input_devices/mag/node_modules/readable-stream/duplex-browser.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/duplex.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/_stream_duplex.js
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules => }/readable-stream/lib/_stream_passthrough.js (91%)
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/_stream_readable.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/_stream_transform.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/_stream_writable.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/internal/streams/BufferList.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/internal/streams/destroy.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream-browser.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/package.json
 create mode 100644 input_devices/mag/node_modules/readable-stream/passthrough.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/readable-browser.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/readable.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/transform.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/writable-browser.js
 create mode 100644 input_devices/mag/node_modules/readable-stream/writable.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/LICENSE
 create mode 100644 input_devices/mag/node_modules/readline-ui/README.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/index.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/index.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/license
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/package.json
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/readme.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/.coveralls.yml
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/.eslintrc
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/.npmignore
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/.travis.yml
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/LICENSE
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/Makefile
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/README.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/component.json
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/karma.conf.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/node.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/package.json
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/src/browser.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/src/debug.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/src/index.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/src/inspector-log.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/debug/src/node.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/index.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/license
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/package.json
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/readme.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ms/index.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ms/license.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ms/package.json
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/ms/readme.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/string-width/index.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/string-width/license
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/string-width/package.json
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/string-width/readme.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/index.js
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/license
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/package.json
 create mode 100644 input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/readme.md
 create mode 100644 input_devices/mag/node_modules/readline-ui/package.json
 create mode 100644 input_devices/mag/node_modules/readline-utils/LICENSE
 create mode 100644 input_devices/mag/node_modules/readline-utils/README.md
 create mode 100644 input_devices/mag/node_modules/readline-utils/index.js
 create mode 100644 input_devices/mag/node_modules/readline-utils/node_modules/is-number/LICENSE
 create mode 100644 input_devices/mag/node_modules/readline-utils/node_modules/is-number/README.md
 create mode 100644 input_devices/mag/node_modules/readline-utils/node_modules/is-number/index.js
 create mode 100644 input_devices/mag/node_modules/readline-utils/node_modules/is-number/package.json
 create mode 100644 input_devices/mag/node_modules/readline-utils/package.json
 create mode 100644 input_devices/mag/node_modules/safe-buffer/LICENSE
 create mode 100644 input_devices/mag/node_modules/safe-buffer/README.md
 create mode 100644 input_devices/mag/node_modules/safe-buffer/index.d.ts
 create mode 100644 input_devices/mag/node_modules/safe-buffer/index.js
 create mode 100644 input_devices/mag/node_modules/safe-buffer/package.json
 create mode 100644 input_devices/mag/node_modules/semver/LICENSE
 create mode 100644 input_devices/mag/node_modules/semver/README.md
 create mode 100755 input_devices/mag/node_modules/semver/bin/semver
 create mode 100644 input_devices/mag/node_modules/semver/package.json
 create mode 100644 input_devices/mag/node_modules/semver/range.bnf
 create mode 100644 input_devices/mag/node_modules/semver/semver.js
 delete mode 100644 input_devices/mag/node_modules/serialport/.jshintrc
 delete mode 100644 input_devices/mag/node_modules/serialport/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/AUTHORS
 create mode 100644 input_devices/mag/node_modules/serialport/CHANGELOG.md
 delete mode 100644 input_devices/mag/node_modules/serialport/Gruntfile.js
 delete mode 100644 input_devices/mag/node_modules/serialport/Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/appveyor.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/arduinoTest/arduinoEcho/arduinoEcho.ino
 delete mode 100644 input_devices/mag/node_modules/serialport/arduinoTest/requiresComPort.js
 delete mode 100644 input_devices/mag/node_modules/serialport/arduinoTest/stress.js
 create mode 100755 input_devices/mag/node_modules/serialport/bin/echo.js
 create mode 100755 input_devices/mag/node_modules/serialport/bin/list.js
 create mode 100755 input_devices/mag/node_modules/serialport/bin/repl.js
 delete mode 100755 input_devices/mag/node_modules/serialport/bin/serialportList.js
 delete mode 100755 input_devices/mag/node_modules/serialport/bin/serialportTerminal.js
 create mode 100755 input_devices/mag/node_modules/serialport/bin/terminal.js
 delete mode 100644 input_devices/mag/node_modules/serialport/binding.gyp
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/action_after_build.stamp.d
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport.o.d
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_poller.o.d
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_unix.o.d
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/.deps/Release/serialport.node.d
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/.deps/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node.d
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport.o
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport_poller.o
 delete mode 100644 input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport_unix.o
 delete mode 100644 input_devices/mag/node_modules/serialport/build/action_after_build.target.mk
 delete mode 100644 input_devices/mag/node_modules/serialport/build/binding.Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/build/config.gypi
 delete mode 100755 input_devices/mag/node_modules/serialport/build/gyp-mac-tool
 delete mode 100644 input_devices/mag/node_modules/serialport/build/serialport.target.mk
 delete mode 100755 input_devices/mag/node_modules/serialport/build/serialport/v1.6.3/Release/node-v11-linux-x64/serialport.node
 delete mode 100644 input_devices/mag/node_modules/serialport/changelog.md
 delete mode 100644 input_devices/mag/node_modules/serialport/examples/break.js
 delete mode 100644 input_devices/mag/node_modules/serialport/examples/drain.js
 delete mode 100644 input_devices/mag/node_modules/serialport/examples/logger.js
 delete mode 100644 input_devices/mag/node_modules/serialport/examples/readdata.js
 delete mode 100644 input_devices/mag/node_modules/serialport/examples/reset.js
 delete mode 100644 input_devices/mag/node_modules/serialport/hwtest/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/hwtest/test1.js
 delete mode 100644 input_devices/mag/node_modules/serialport/hwtest/test2.js
 create mode 100644 input_devices/mag/node_modules/serialport/lib/index.js
 create mode 100644 input_devices/mag/node_modules/serialport/lib/parsers.js
 delete mode 120000 input_devices/mag/node_modules/serialport/node_modules/.bin/node-pre-gyp
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/async/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/async/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/async/component.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/async/lib/async.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/async/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/bindings/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/bindings/bindings.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/bindings/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/.jshintrc
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/History.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/Readme.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/bower.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/browser.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/component.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/debug.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/node.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/debug/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/.dntrc
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/CHANGELOG.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/LICENSE.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/appveyor.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/nan.h
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_12_inl.h
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_pre_12_inl.h
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/nan_new.h
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/nan_string_bytes.h
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/nan/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/CHANGELOG.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/appveyor.yml
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp.cmd
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/build.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/clean.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/info.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/install.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/node-pre-gyp.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/package.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/pre-binding.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/publish.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/rebuild.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/reinstall.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testbinary.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testpackage.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/unpublish.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/abi_crosswalk.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/compile.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/index.html
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw_crosswalk.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/s3_setup.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/versioning.js
 delete mode 120000 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/nopt
 delete mode 120000 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rc
 delete mode 120000 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rimraf
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/chmod.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/clobber.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/mkdirp.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/race.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/rel.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/root.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/bin/nopt.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/examples/my-program.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/lib/nopt.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/abbrev.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/test/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/example.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/log.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/color-spaces.pl
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/beep/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/clear/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/cursorPosition.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/progress/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/starwars.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/ansi.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/newlines.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/test/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/lib/utils.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/index.spec.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/mocha.opts
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/ini.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/bar.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/fixtures/foo.ini
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/foo.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/readme.markdown
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/bool.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/dash.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/default_bool.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/parse_modified.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/cli.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/readme.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/strip-json-comments.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/test/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/CHANGELOG.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/cookies.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/copy.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/debug.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/getSafe.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/optional.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/License
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/Readme.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/lib/form_data.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/component.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/License
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.npmignore
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.travis.yml
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/LICENSE
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/Makefile
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/example/usage.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/images/hawk.png
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/images/logo.png
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/browser.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/client.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/crypto.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/server.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/utils.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/Makefile
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/images/boom.png
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/package.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/images/hoek.png
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.npmignore
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/package.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/package.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/browser.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/client.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/crypto.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/index.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/message.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/readme.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/server.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/uri.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/utils.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.dir-locals.el
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/http_signing.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/parser.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/signer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/util.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/verify.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README.old
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/stringify.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/mime.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/mime.types
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/node.types
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/LICENSE.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.sh
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/component.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/compare_v1.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.html
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/uuid.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.gitmodules
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/Readme.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.jshintrc
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/generate-pubsuffix.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/cookie.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/memstore.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/pubsuffix.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/store.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-GPL.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-MIT.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.min.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/public-suffix.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/.jshintrc
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/package.json
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/request.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/AUTHORS
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/bin.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/rimraf.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/run.sh
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/setup.sh
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-async.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/Makefile
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/bin/semver
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/foot.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/head.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.browser.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.browser.js.gz
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.min.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.min.js.gz
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/amd.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/gtr.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/ltr.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/no-module.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/Readme.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/debug.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/lib/debug.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/example/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/ignore.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/inherits.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/minimatch.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/foreach.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/bench.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/sigmund.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/test/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/brace-expand.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/caching.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/defaults.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/extglob-ending-with-state-char.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.ignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/00-setup.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/common.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/ignore-most.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/nested-ignores.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/unignore-child.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/zz-cleanup.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/filter-pipe.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/pipe.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/symlink-write.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/fstream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/abstract.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/collect.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/get-type.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/socket-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/polyfills.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/open.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits_browser.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/examples/pow.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/readme.markdown
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/chmod.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/clobber.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/race.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/rel.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/root.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/graceful-fs.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/open.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/ulimit.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/once.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/test/once.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/duplex.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_duplex.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_readable.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_transform.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_writable.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/lib/util.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/util.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits_browser.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/build/build.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/passthrough.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/readable.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/transform.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/writable.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/LICENCE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/README.md
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/get-uid-gid.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/uid-number.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed-file.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed.tar
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed.tar.gz
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/bar.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/foo.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/LICENCE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/extracter.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/buffer-entry.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extract.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/global-header-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/header.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/pack.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/parse.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/LICENCE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream-pause.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper-pause.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/block-stream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad-thorough.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/pause-resume.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/thorough.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/two-stream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/filter-pipe.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/pipe.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/symlink-write.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/fstream.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/abstract.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/collect.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/get-type.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/socket-reader.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/writer.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/polyfills.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/open.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/examples/pow.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/readme.markdown
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/chmod.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/clobber.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/race.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/rel.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/root.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits_browser.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/tar.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/00-setup-fixtures.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/extract.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/fixtures.tgz
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/header.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack-no-proprietary.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/parse.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/zz-cleanup.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/LICENSE
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/bool.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/boolean_double.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/boolean_single.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/default_hash.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/default_singles.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/divide.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count_options.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count_wrap.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/nonopt.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/reflect.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/short.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/string.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/usage-options.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/example/xup.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/example/parse.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/readme.markdown
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/bool.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dash.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/default_bool.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dotted.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/long.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/num.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse_modified.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/short.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/whitespace.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/README.markdown
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/example/center.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/example/meat.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/index.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/break.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/idleness.txt
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/wrap.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/readme.markdown
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/_.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/_/argv.js
 delete mode 100755 input_devices/mag/node_modules/serialport/node_modules/optimist/test/_/bin.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/dash.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/parse.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/parse_modified.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/short.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/usage.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/optimist/test/whitespace.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/.npmignore
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/README.md
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/package.json
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/sf.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/test/indentTest.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/test/stringFormatTest.js
 delete mode 100644 input_devices/mag/node_modules/serialport/node_modules/sf/test/timeSpanTest.js
 delete mode 100644 input_devices/mag/node_modules/serialport/parsers.js
 delete mode 100644 input_devices/mag/node_modules/serialport/publish-binaries.md
 delete mode 100644 input_devices/mag/node_modules/serialport/sandbox/disconnect.js
 delete mode 100644 input_devices/mag/node_modules/serialport/serialport.js
 delete mode 100644 input_devices/mag/node_modules/serialport/src/serialport.cpp
 delete mode 100644 input_devices/mag/node_modules/serialport/src/serialport.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/serialport_poller.cpp
 delete mode 100644 input_devices/mag/node_modules/serialport/src/serialport_poller.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/serialport_unix.cpp
 delete mode 100644 input_devices/mag/node_modules/serialport/src/serialport_win.cpp
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/AutoHModule.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/AutoHandle.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/AutoHeapAlloc.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/disphelper.c
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/disphelper.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/enumser.cpp
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/enumser.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/stdafx.h
 delete mode 100644 input_devices/mag/node_modules/serialport/src/win/stdstring.h
 create mode 100644 input_devices/mag/node_modules/serialport/test.js
 delete mode 100644 input_devices/mag/node_modules/serialport/test/parsers.js
 delete mode 100644 input_devices/mag/node_modules/serialport/test/serialport-basic.js
 delete mode 100644 input_devices/mag/node_modules/serialport/test/serialport-c.js
 delete mode 100644 input_devices/mag/node_modules/serialport/test_mocks/linux-hardware.js
 create mode 100644 input_devices/mag/node_modules/set-blocking/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/set-blocking/LICENSE.txt
 create mode 100644 input_devices/mag/node_modules/set-blocking/README.md
 create mode 100644 input_devices/mag/node_modules/set-blocking/index.js
 create mode 100644 input_devices/mag/node_modules/set-blocking/package.json
 create mode 100644 input_devices/mag/node_modules/set-getter/LICENSE
 create mode 100644 input_devices/mag/node_modules/set-getter/README.md
 create mode 100644 input_devices/mag/node_modules/set-getter/index.js
 create mode 100644 input_devices/mag/node_modules/set-getter/package.json
 create mode 100644 input_devices/mag/node_modules/set-value/LICENSE
 create mode 100644 input_devices/mag/node_modules/set-value/README.md
 create mode 100644 input_devices/mag/node_modules/set-value/index.js
 create mode 100644 input_devices/mag/node_modules/set-value/package.json
 create mode 100644 input_devices/mag/node_modules/shallow-clone/LICENSE
 create mode 100644 input_devices/mag/node_modules/shallow-clone/README.md
 create mode 100644 input_devices/mag/node_modules/shallow-clone/index.js
 create mode 100644 input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/shallow-clone/package.json
 create mode 100644 input_devices/mag/node_modules/signal-exit/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/signal-exit/LICENSE.txt
 create mode 100644 input_devices/mag/node_modules/signal-exit/README.md
 create mode 100644 input_devices/mag/node_modules/signal-exit/index.js
 create mode 100644 input_devices/mag/node_modules/signal-exit/package.json
 create mode 100644 input_devices/mag/node_modules/signal-exit/signals.js
 create mode 100644 input_devices/mag/node_modules/simple-concat/.travis.yml
 create mode 100644 input_devices/mag/node_modules/simple-concat/LICENSE
 create mode 100644 input_devices/mag/node_modules/simple-concat/README.md
 create mode 100644 input_devices/mag/node_modules/simple-concat/index.js
 create mode 100644 input_devices/mag/node_modules/simple-concat/package.json
 create mode 100644 input_devices/mag/node_modules/simple-concat/test/basic.js
 create mode 100644 input_devices/mag/node_modules/simple-get/LICENSE
 create mode 100644 input_devices/mag/node_modules/simple-get/README.md
 create mode 100644 input_devices/mag/node_modules/simple-get/index.js
 create mode 100644 input_devices/mag/node_modules/simple-get/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/define-property/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/define-property/README.md
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/define-property/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/define-property/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/README.md
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/kind-of/LICENSE
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/kind-of/README.md
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/kind-of/index.js
 create mode 100644 input_devices/mag/node_modules/static-extend/node_modules/kind-of/package.json
 create mode 100644 input_devices/mag/node_modules/static-extend/package.json
 create mode 100644 input_devices/mag/node_modules/string-width/index.js
 create mode 100644 input_devices/mag/node_modules/string-width/license
 create mode 100644 input_devices/mag/node_modules/string-width/package.json
 create mode 100644 input_devices/mag/node_modules/string-width/readme.md
 create mode 100644 input_devices/mag/node_modules/string_decoder/.travis.yml
 create mode 100644 input_devices/mag/node_modules/string_decoder/LICENSE
 create mode 100644 input_devices/mag/node_modules/string_decoder/README.md
 create mode 100644 input_devices/mag/node_modules/string_decoder/lib/string_decoder.js
 create mode 100644 input_devices/mag/node_modules/string_decoder/package.json
 create mode 100644 input_devices/mag/node_modules/strip-ansi/index.js
 create mode 100644 input_devices/mag/node_modules/strip-ansi/license
 create mode 100644 input_devices/mag/node_modules/strip-ansi/package.json
 create mode 100644 input_devices/mag/node_modules/strip-ansi/readme.md
 create mode 100644 input_devices/mag/node_modules/strip-color/LICENSE
 create mode 100644 input_devices/mag/node_modules/strip-color/README.md
 create mode 100644 input_devices/mag/node_modules/strip-color/index.js
 create mode 100644 input_devices/mag/node_modules/strip-color/package.json
 create mode 100644 input_devices/mag/node_modules/strip-json-comments/index.js
 create mode 100644 input_devices/mag/node_modules/strip-json-comments/license
 create mode 100644 input_devices/mag/node_modules/strip-json-comments/package.json
 create mode 100644 input_devices/mag/node_modules/strip-json-comments/readme.md
 create mode 100644 input_devices/mag/node_modules/success-symbol/LICENSE
 create mode 100644 input_devices/mag/node_modules/success-symbol/README.md
 create mode 100644 input_devices/mag/node_modules/success-symbol/index.js
 create mode 100644 input_devices/mag/node_modules/success-symbol/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/async => tar-fs}/.travis.yml (100%)
 create mode 100644 input_devices/mag/node_modules/tar-fs/LICENSE
 create mode 100644 input_devices/mag/node_modules/tar-fs/README.md
 create mode 100644 input_devices/mag/node_modules/tar-fs/index.js
 create mode 100644 input_devices/mag/node_modules/tar-fs/node_modules/pump/.travis.yml
 create mode 100644 input_devices/mag/node_modules/tar-fs/node_modules/pump/LICENSE
 create mode 100644 input_devices/mag/node_modules/tar-fs/node_modules/pump/README.md
 create mode 100644 input_devices/mag/node_modules/tar-fs/node_modules/pump/index.js
 create mode 100644 input_devices/mag/node_modules/tar-fs/node_modules/pump/package.json
 create mode 100644 input_devices/mag/node_modules/tar-fs/node_modules/pump/test-browser.js
 create mode 100644 input_devices/mag/node_modules/tar-fs/node_modules/pump/test.js
 create mode 100644 input_devices/mag/node_modules/tar-fs/package.json
 create mode 100644 input_devices/mag/node_modules/tar-fs/test/fixtures/a/hello.txt
 create mode 100644 input_devices/mag/node_modules/tar-fs/test/fixtures/b/a/test.txt
 rename input_devices/mag/node_modules/{serialport/build/Release/linker.lock => tar-fs/test/fixtures/d/file1} (100%)
 rename input_devices/mag/node_modules/{serialport/build/Release/obj.target/action_after_build.stamp => tar-fs/test/fixtures/d/file2} (100%)
 rename input_devices/mag/node_modules/{ws/node_modules/bufferutil/build/Release/linker.lock => tar-fs/test/fixtures/d/sub-dir/file5} (100%)
 rename input_devices/mag/node_modules/{ws/node_modules/utf-8-validate/build/Release/linker.lock => tar-fs/test/fixtures/d/sub-files/file3} (100%)
 create mode 100644 input_devices/mag/node_modules/tar-fs/test/fixtures/d/sub-files/file4
 create mode 100644 input_devices/mag/node_modules/tar-fs/test/fixtures/e/directory/.ignore
 create mode 100644 input_devices/mag/node_modules/tar-fs/test/fixtures/e/file
 create mode 100644 input_devices/mag/node_modules/tar-fs/test/fixtures/invalid.tar
 create mode 100644 input_devices/mag/node_modules/tar-fs/test/index.js
 create mode 100644 input_devices/mag/node_modules/tar-stream/LICENSE
 create mode 100644 input_devices/mag/node_modules/tar-stream/README.md
 create mode 100644 input_devices/mag/node_modules/tar-stream/extract.js
 create mode 100644 input_devices/mag/node_modules/tar-stream/headers.js
 create mode 100644 input_devices/mag/node_modules/tar-stream/index.js
 create mode 100644 input_devices/mag/node_modules/tar-stream/pack.js
 create mode 100644 input_devices/mag/node_modules/tar-stream/package.json
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/LICENSE
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/README.md
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/index.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.coveralls.yml
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.eslintrc
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.npmignore
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.travis.yml
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/CHANGELOG.md
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/LICENSE
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/Makefile
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/README.md
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/component.json
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/karma.conf.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/node.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/package.json
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/browser.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/debug.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/index.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/inspector-log.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/node.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/ms/index.js
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/ms/license.md
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/ms/package.json
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/node_modules/ms/readme.md
 create mode 100644 input_devices/mag/node_modules/terminal-paginator/package.json
 create mode 100644 input_devices/mag/node_modules/time-stamp/LICENSE
 create mode 100644 input_devices/mag/node_modules/time-stamp/README.md
 create mode 100644 input_devices/mag/node_modules/time-stamp/index.js
 create mode 100644 input_devices/mag/node_modules/time-stamp/package.json
 create mode 100644 input_devices/mag/node_modules/to-buffer/.travis.yml
 create mode 100644 input_devices/mag/node_modules/to-buffer/LICENSE
 create mode 100644 input_devices/mag/node_modules/to-buffer/README.md
 create mode 100644 input_devices/mag/node_modules/to-buffer/index.js
 create mode 100644 input_devices/mag/node_modules/to-buffer/package.json
 create mode 100644 input_devices/mag/node_modules/to-buffer/test.js
 create mode 100644 input_devices/mag/node_modules/to-object-path/LICENSE
 create mode 100644 input_devices/mag/node_modules/to-object-path/README.md
 create mode 100644 input_devices/mag/node_modules/to-object-path/index.js
 create mode 100644 input_devices/mag/node_modules/to-object-path/package.json
 create mode 100644 input_devices/mag/node_modules/toggle-array/LICENSE
 create mode 100644 input_devices/mag/node_modules/toggle-array/README.md
 create mode 100644 input_devices/mag/node_modules/toggle-array/index.js
 create mode 100644 input_devices/mag/node_modules/toggle-array/package.json
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/request => tunnel-agent}/LICENSE (100%)
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/request/node_modules => }/tunnel-agent/README.md (100%)
 create mode 100644 input_devices/mag/node_modules/tunnel-agent/index.js
 create mode 100644 input_devices/mag/node_modules/tunnel-agent/package.json
 create mode 100644 input_devices/mag/node_modules/util-deprecate/History.md
 create mode 100644 input_devices/mag/node_modules/util-deprecate/LICENSE
 create mode 100644 input_devices/mag/node_modules/util-deprecate/README.md
 create mode 100644 input_devices/mag/node_modules/util-deprecate/browser.js
 create mode 100644 input_devices/mag/node_modules/util-deprecate/node.js
 create mode 100644 input_devices/mag/node_modules/util-deprecate/package.json
 create mode 100644 input_devices/mag/node_modules/warning-symbol/LICENSE
 create mode 100644 input_devices/mag/node_modules/warning-symbol/README.md
 create mode 100644 input_devices/mag/node_modules/warning-symbol/index.js
 create mode 100644 input_devices/mag/node_modules/warning-symbol/package.json
 create mode 100644 input_devices/mag/node_modules/which-pm-runs/LICENSE
 create mode 100644 input_devices/mag/node_modules/which-pm-runs/README.md
 create mode 100644 input_devices/mag/node_modules/which-pm-runs/index.js
 create mode 100644 input_devices/mag/node_modules/which-pm-runs/package.json
 create mode 100644 input_devices/mag/node_modules/wide-align/LICENSE
 create mode 100644 input_devices/mag/node_modules/wide-align/README.md
 create mode 100644 input_devices/mag/node_modules/wide-align/align.js
 create mode 100644 input_devices/mag/node_modules/wide-align/package.json
 create mode 100644 input_devices/mag/node_modules/window-size/LICENSE
 create mode 100644 input_devices/mag/node_modules/window-size/README.md
 create mode 100755 input_devices/mag/node_modules/window-size/cli.js
 create mode 100644 input_devices/mag/node_modules/window-size/index.js
 create mode 100644 input_devices/mag/node_modules/window-size/node_modules/is-number/LICENSE
 create mode 100644 input_devices/mag/node_modules/window-size/node_modules/is-number/README.md
 create mode 100644 input_devices/mag/node_modules/window-size/node_modules/is-number/index.js
 create mode 100644 input_devices/mag/node_modules/window-size/node_modules/is-number/package.json
 create mode 100644 input_devices/mag/node_modules/window-size/package.json
 create mode 100644 input_devices/mag/node_modules/window-size/utils.js
 create mode 100644 input_devices/mag/node_modules/wrappy/LICENSE
 create mode 100644 input_devices/mag/node_modules/wrappy/README.md
 create mode 100644 input_devices/mag/node_modules/wrappy/package.json
 create mode 100644 input_devices/mag/node_modules/wrappy/wrappy.js
 delete mode 100644 input_devices/mag/node_modules/ws/.npmignore
 delete mode 100644 input_devices/mag/node_modules/ws/.travis.yml
 create mode 100644 input_devices/mag/node_modules/ws/LICENSE
 delete mode 100644 input_devices/mag/node_modules/ws/Makefile
 create mode 100644 input_devices/mag/node_modules/ws/browser.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/BufferPool.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/BufferUtil.fallback.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/BufferUtil.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/ErrorCodes.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/Extensions.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/PerMessageDeflate.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/Receiver.hixie.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/Receiver.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/Sender.hixie.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/Sender.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/Validation.fallback.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/Validation.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/WebSocket.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/WebSocketServer.js
 delete mode 100644 input_devices/mag/node_modules/ws/lib/browser.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/buffer-util.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/constants.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/event-target.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/extension.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/permessage-deflate.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/receiver.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/sender.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/validation.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/websocket-server.js
 create mode 100644 input_devices/mag/node_modules/ws/lib/websocket.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/.npmignore
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/binding.gyp
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Makefile
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/bufferutil.node.d
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil.node.d
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d
 delete mode 100755 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/bufferutil.node
 delete mode 100755 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/obj.target/bufferutil.node
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/obj.target/bufferutil/src/bufferutil.o
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/binding.Makefile
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/bufferutil.target.mk
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/build/config.gypi
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/fallback.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/index.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/README.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/bindings.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/.dntrc
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/CHANGELOG.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/LICENSE.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/appveyor.yml
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/include_dirs.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_12_inl.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_pre_12_inl.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_new.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_string_bytes.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/bufferutil/src/bufferutil.cc
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/options/.npmignore
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/options/Makefile
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/options/README.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/options/lib/options.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/options/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/ultron/.npmignore
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/ultron/.travis.yml
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/ultron/README.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/ultron/index.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/ultron/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/ultron/test.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/.npmignore
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/binding.gyp
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Makefile
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation.node.d
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation/src/validation.o.d
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/validation.node.d
 delete mode 100755 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/obj.target/validation.node
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/obj.target/validation/src/validation.o
 delete mode 100755 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/validation.node
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/binding.Makefile
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/config.gypi
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/validation.target.mk
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/fallback.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/index.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/README.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/bindings.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/.dntrc
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/CHANGELOG.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/LICENSE.md
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/appveyor.yml
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/include_dirs.js
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_12_inl.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_pre_12_inl.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_new.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_string_bytes.h
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/package.json
 delete mode 100644 input_devices/mag/node_modules/ws/node_modules/utf-8-validate/src/validation.cc
 create mode 100644 input_devices/mag/node_modules/xtend/.jshintrc
 rename input_devices/mag/node_modules/{serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi => xtend}/.npmignore (100%)
 create mode 100644 input_devices/mag/node_modules/xtend/LICENCE
 create mode 100644 input_devices/mag/node_modules/xtend/Makefile
 create mode 100644 input_devices/mag/node_modules/xtend/README.md
 create mode 100644 input_devices/mag/node_modules/xtend/immutable.js
 create mode 100644 input_devices/mag/node_modules/xtend/mutable.js
 create mode 100644 input_devices/mag/node_modules/xtend/package.json
 create mode 100644 input_devices/mag/node_modules/xtend/test.js

diff --git a/input_devices/mag/hello.mag.45.js b/input_devices/mag/hello.mag.45.js
index c9613ca3..d43e2a78 100644
--- a/input_devices/mag/hello.mag.45.js
+++ b/input_devices/mag/hello.mag.45.js
@@ -14,15 +14,19 @@
 // liability.
 //
 var server_port = '1234'
-var client_address = '127.0.0.1'
+var client_address = '::ffff:127.0.0.1'
 var serial_port = "/dev/ttyUSB0"
 var baud = 9600
 var samples = 100
 //
 // open serial port
 //
-var SerialPort = require("serialport").SerialPort
-var sp = new SerialPort(serial_port,{baudrate:baud})
+var SerialPort = require("serialport")
+var sp = new SerialPort(serial_port,{baudRate:baud})
+sp.on('error',function(err) {
+   console.log("error: "+err)
+   process.exit(-1)
+   })
 //
 // look for framing and then update field value
 //
@@ -33,24 +37,18 @@ var byte5 = 0
 var byte6 = 0
 var byte7 = 0
 var value = 0
-sp.open(function(error) {
-   if (error) {
-      console.log('can not open '+serial_port)
-      }
-   else {
-      console.log('opened '+serial_port)
-      sp.on('data',function(data) {
-         byte1 = byte2
-         byte2 = byte3
-         byte3 = byte4
-         byte4 = byte5
-         byte5 = byte6
-         byte6 = byte7
-         byte7 = data[0]
-         if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)) {
-            value = (byte5 + 256*byte6 + 256*256*byte7)/samples
-            }
-         })
+var ByteLength = SerialPort.parsers.ByteLength
+var parser = sp.pipe(new ByteLength({length:1}));
+parser.on('data',function(data) {
+   byte1 = byte2
+   byte2 = byte3
+   byte3 = byte4
+   byte4 = byte5
+   byte5 = byte6
+   byte6 = byte7
+   byte7 = data[0]
+   if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)) {
+      value = (byte5 + 256*byte6 + 256*256*byte7)/samples
       }
    })
 //
@@ -61,7 +59,7 @@ var Server = require('ws').Server
 wss = new Server({port:server_port})
 wss.on('connection', function(ws) {
    if (ws._socket.remoteAddress != client_address) {
-      console.log("error: client address doesn't match")
+      console.log("error: client address "+ws._socket.remoteAddress+" doesn't match")
       return
       }
    console.log("connected to "+client_address+" on port "+server_port)
diff --git a/input_devices/mag/node_modules/.bin/detect-libc b/input_devices/mag/node_modules/.bin/detect-libc
new file mode 120000
index 00000000..b4c4b767
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/detect-libc
@@ -0,0 +1 @@
+../detect-libc/bin/detect-libc.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/mkdirp b/input_devices/mag/node_modules/.bin/mkdirp
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/mkdirp
rename to input_devices/mag/node_modules/.bin/mkdirp
diff --git a/input_devices/mag/node_modules/.bin/prebuild-install b/input_devices/mag/node_modules/.bin/prebuild-install
new file mode 120000
index 00000000..12a458dd
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/prebuild-install
@@ -0,0 +1 @@
+../prebuild-install/bin.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/.bin/prominode b/input_devices/mag/node_modules/.bin/prominode
new file mode 120000
index 00000000..2b21cfb8
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/prominode
@@ -0,0 +1 @@
+../promirepl/bin/prominode.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/.bin/rc b/input_devices/mag/node_modules/.bin/rc
new file mode 120000
index 00000000..48b3cda7
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/rc
@@ -0,0 +1 @@
+../rc/cli.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/semver b/input_devices/mag/node_modules/.bin/semver
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/semver
rename to input_devices/mag/node_modules/.bin/semver
diff --git a/input_devices/mag/node_modules/.bin/serialport-list b/input_devices/mag/node_modules/.bin/serialport-list
new file mode 120000
index 00000000..316ae6a4
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/serialport-list
@@ -0,0 +1 @@
+../serialport/bin/list.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/.bin/serialport-repl b/input_devices/mag/node_modules/.bin/serialport-repl
new file mode 120000
index 00000000..881e98d4
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/serialport-repl
@@ -0,0 +1 @@
+../serialport/bin/repl.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/.bin/serialport-term b/input_devices/mag/node_modules/.bin/serialport-term
new file mode 120000
index 00000000..660f9b56
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/serialport-term
@@ -0,0 +1 @@
+../serialport/bin/terminal.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/.bin/serialportlist b/input_devices/mag/node_modules/.bin/serialportlist
deleted file mode 120000
index 5fa87b27..00000000
--- a/input_devices/mag/node_modules/.bin/serialportlist
+++ /dev/null
@@ -1 +0,0 @@
-../serialport/bin/serialportList.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/.bin/serialportterm b/input_devices/mag/node_modules/.bin/serialportterm
deleted file mode 120000
index be4d3343..00000000
--- a/input_devices/mag/node_modules/.bin/serialportterm
+++ /dev/null
@@ -1 +0,0 @@
-../serialport/bin/serialportTerminal.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/.bin/window-size b/input_devices/mag/node_modules/.bin/window-size
new file mode 120000
index 00000000..e84c8ece
--- /dev/null
+++ b/input_devices/mag/node_modules/.bin/window-size
@@ -0,0 +1 @@
+../window-size/cli.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/@serialport/binding-abstract/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/binding-abstract/CHANGELOG.md
new file mode 100644
index 00000000..c5f55f8b
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-abstract/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/binding-abstract@2.0.0...@serialport/binding-abstract@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/binding-abstract
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/binding-abstract
diff --git a/input_devices/mag/node_modules/@serialport/binding-abstract/LICENSE b/input_devices/mag/node_modules/@serialport/binding-abstract/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-abstract/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/binding-abstract/README.md b/input_devices/mag/node_modules/@serialport/binding-abstract/README.md
new file mode 100644
index 00000000..df7bda10
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-abstract/README.md
@@ -0,0 +1,14 @@
+# @serialport/BindingAbstract
+
+This Abstract binding class is the base for all serialport bindings. You wouldn't use this class directly but instead extend it to make a new binding for a different platform or underling technology.
+
+This is currently used for the win32, linux, darwin and mock bindings.
+
+This is how you use it.
+```js
+class MockBinding extends AbstractBinding {
+  constructor(opt) {
+    super(opt)
+  }
+}
+```
diff --git a/input_devices/mag/node_modules/@serialport/binding-abstract/binding-abstract.js b/input_devices/mag/node_modules/@serialport/binding-abstract/binding-abstract.js
new file mode 100644
index 00000000..8052f98c
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-abstract/binding-abstract.js
@@ -0,0 +1,230 @@
+const debug = require('debug')('@serialport/binding-abstract')
+
+/**
+ * @name Binding
+ * @type {AbstractBinding}
+ * @since 5.0.0
+ * @description The `Binding` is how Node-SerialPort talks to the underlying system. By default, we auto detect Windows, Linux and OS X, and load the appropriate module for your system. You can assign `SerialPort.Binding` to any binding you like. Find more by searching at [npm](https://npmjs.org/).
+  Prevent auto loading the default bindings by requiring SerialPort with:
+  ```js
+  var SerialPort = require('@serialport/stream');
+  SerialPort.Binding = MyBindingClass;
+  ```
+ */
+
+/**
+ * You never have to use `Binding` objects directly. SerialPort uses them to access the underlying hardware. This documentation is geared towards people who are making bindings for different platforms. This class can be inherited from to get type checking for each method.
+ * @class AbstractBinding
+ * @param {object} options options for the biding
+ * @property {boolean} isOpen Required property. `true` if the port is open, `false` otherwise. Should be read-only.
+ * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+ * @since 5.0.0
+ */
+class AbstractBinding {
+  /**
+   * Retrieves a list of available serial ports with metadata. The `comName` must be guaranteed, and all other fields should be undefined if unavailable. The `comName` is either the path or an identifier (eg `COM1`) used to open the serialport.
+   * @returns {Promise} resolves to an array of port [info objects](#module_serialport--SerialPort.list).
+   */
+  static list() {
+    debug('list')
+    return Promise.resolve()
+  }
+
+  constructor(opt) {
+    if (typeof opt !== 'object') {
+      throw new TypeError('"options" is not an object')
+    }
+  }
+
+  /**
+   * Opens a connection to the serial port referenced by the path.
+   * @param {string} path the path or com port to open
+   * @param {openOptions} options openOptions for the serialport
+   * @returns {Promise} Resolves after the port is opened and configured.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  open(path, options) {
+    if (!path) {
+      throw new TypeError('"path" is not a valid port')
+    }
+
+    if (typeof options !== 'object') {
+      throw new TypeError('"options" is not an object')
+    }
+    debug('open')
+
+    if (this.isOpen) {
+      return Promise.reject(new Error('Already open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Closes an open connection
+   * @returns {Promise} Resolves once the connection is closed.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  close() {
+    debug('close')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Request a number of bytes from the SerialPort. This function is similar to Node's [`fs.read`](http://nodejs.org/api/fs.html#fs_fs_read_fd_buffer_offset_length_position_callback) except it will always return at least one byte.
+
+The in progress reads must error when the port is closed with an error object that has the property `canceled` equal to `true`. Any other error will cause a disconnection.
+
+   * @param {buffer} buffer Accepts a [`Buffer`](http://nodejs.org/api/buffer.html) object.
+   * @param {integer} offset The offset in the buffer to start writing at.
+   * @param {integer} length Specifies the maximum number of bytes to read.
+   * @returns {Promise} Resolves with the number of bytes read after a read operation.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  read(buffer, offset, length) {
+    if (!Buffer.isBuffer(buffer)) {
+      throw new TypeError('"buffer" is not a Buffer')
+    }
+
+    if (typeof offset !== 'number') {
+      throw new TypeError('"offset" is not an integer')
+    }
+
+    if (typeof length !== 'number') {
+      throw new TypeError('"length" is not an integer')
+    }
+
+    debug('read')
+    if (buffer.length < offset + length) {
+      return Promise.reject(new Error('buffer is too small'))
+    }
+
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Write bytes to the SerialPort. Only called when there is no pending write operation.
+
+The in progress writes must error when the port is closed with an error object that has the property `canceled` equal to `true`. Any other error will cause a disconnection.
+
+   * @param {buffer} buffer - Accepts a [`Buffer`](http://nodejs.org/api/buffer.html) object.
+   * @returns {Promise} Resolves after the data is passed to the operating system for writing.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  write(buffer) {
+    if (!Buffer.isBuffer(buffer)) {
+      throw new TypeError('"buffer" is not a Buffer')
+    }
+
+    debug('write', buffer.length, 'bytes')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Changes connection settings on an open port. Only `baudRate` is supported.
+   * @param {object=} options Only supports `baudRate`.
+   * @param {number=} [options.baudRate] If provided a baud rate that the bindings do not support, it should pass an error to the callback.
+   * @returns {Promise} Resolves once the port's baud rate changes.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  update(options) {
+    if (typeof options !== 'object') {
+      throw TypeError('"options" is not an object')
+    }
+
+    if (typeof options.baudRate !== 'number') {
+      throw new TypeError('"options.baudRate" is not a number')
+    }
+
+    debug('update')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Set control flags on an open port.
+   * @param {object=} options All options are operating system default when the port is opened. Every flag is set on each call to the provided or default values. All options are always provided.
+   * @param {Boolean} [options.brk=false] flag for brk
+   * @param {Boolean} [options.cts=false] flag for cts
+   * @param {Boolean} [options.dsr=false] flag for dsr
+   * @param {Boolean} [options.dtr=true] flag for dtr
+   * @param {Boolean} [options.rts=true] flag for rts
+   * @returns {Promise} Resolves once the port's flags are set.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  set(options) {
+    if (typeof options !== 'object') {
+      throw new TypeError('"options" is not an object')
+    }
+    debug('set')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Get the control flags (CTS, DSR, DCD) on the open port.
+   * @returns {Promise} Resolves with the retrieved flags.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  get() {
+    debug('get')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Get the OS reported baud rate for the open port.
+   * Used mostly for debugging custom baud rates.
+   * @returns {Promise} Resolves with the current baud rate.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  getBaudRate() {
+    debug('getBuadRate')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Flush (discard) data received but not read, and written but not transmitted.
+   * @returns {Promise} Resolves once the flush operation finishes.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  flush() {
+    debug('flush')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+
+  /**
+   * Drain waits until all output data is transmitted to the serial port. An in progress write should be completed before this returns.
+   * @returns {Promise} Resolves once the drain operation finishes.
+   * @throws {TypeError} When given invalid arguments, a `TypeError` is thrown.
+   */
+  drain() {
+    debug('drain')
+    if (!this.isOpen) {
+      return Promise.reject(new Error('Port is not open'))
+    }
+    return Promise.resolve()
+  }
+}
+
+module.exports = AbstractBinding
diff --git a/input_devices/mag/node_modules/@serialport/binding-abstract/package.json b/input_devices/mag/node_modules/@serialport/binding-abstract/package.json
new file mode 100644
index 00000000..fe9c7e0a
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-abstract/package.json
@@ -0,0 +1,84 @@
+{
+  "_args": [
+    [
+      "@serialport/binding-abstract@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/binding-mock"
+    ]
+  ],
+  "_from": "@serialport/binding-abstract@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/binding-abstract@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/binding-abstract",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/binding-abstract_2.0.1_1535513343735_0.10952168417214336"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/binding-abstract",
+    "raw": "@serialport/binding-abstract@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/binding-mock",
+    "/@serialport/bindings"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-2.0.1.tgz",
+  "_shasum": "2c92c10c37c4f27d374c714a05b111f3a69b1254",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/binding-abstract@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/binding-mock",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {
+    "debug": "^3.1.0"
+  },
+  "description": "This Abstract binding class is the base for all serialport bindings. You wouldn't use this class directly but instead extend it to make a new binding for a different platform or underling technology.",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-l4M35BV0ty4x6UoViCKD45XIWE/cSrCA+PbHGByhYu22R9biDbWaI7vjaVYVefYCBRvIez11Kw0JN9tkQMEY+A==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMACRA9TVsSAnZWagAAVSgP/jg7hOqRz8zr026wM9y8\npruk/rw3lQeUV6AnCiN+b3iRjyusyMMsij0NJyCdH3RZMDZ0Kji2PWKrs+W+\n33YctwL49s1ofYqNfB473LaaZr07+KosFEOx4/CZtjpdoDQNfR/7G/tA2bOw\n6h4wUqFT2naA4rrT+IV1I5gg1y+21HXfogmPbaeT7ORxi86K2DFp8mTLfbD5\nxqPLlAAmAs0GyXABPNz9QufnqVT2ExdoC7YZfEbTAs1R2J3pfPdf+453GzhL\nXCKAHlzEdUo99eNg4Gve04EjNI4/1/AvLL1qN1NATf2tQHEL4LpTGHxe6n8M\nWxCiEaIUDqpMdqM9Mh/X4Hp9eeC/nEi8p96T8RX7SjzGJl54yO2qoz4VUR6C\nkIHrI8Y4UCgsJRbLtZHptqp0WyjsrmzaQShgEWxw+X/VENmgvi3jAztZgOnj\nONDHH6e4+RvjJv062TN4zMegcGHcUisw7wI2mBKFZZAnteyk1T5consnWA3h\nxB/Ygyx602HFVZ5laNWdxEsdiQ9b+aHwYsI9sxOGduItfPY2jdnOcGjXf2NG\nugKFSIqf/zivrPGAMDxgmplNl0azU/ZFmB0fNjA8fYjwyj4z3vwcxDrmpkz5\nE7fBx0KBrQSNUTUfLAkjkMaDk9He4V49m2q22swxw7g8+IFUBxKoIdwGO+kM\nTG+7\r\n=Suw6\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "2c92c10c37c4f27d374c714a05b111f3a69b1254",
+    "tarball": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-2.0.1.tgz",
+    "unpackedSize": 10920
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "binding-abstract.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/binding-abstract",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/binding-mock/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/binding-mock/CHANGELOG.md
new file mode 100644
index 00000000..c2d9bb93
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-mock/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/binding-mock@2.0.0...@serialport/binding-mock@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/binding-mock
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/binding-mock
diff --git a/input_devices/mag/node_modules/@serialport/binding-mock/LICENSE b/input_devices/mag/node_modules/@serialport/binding-mock/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-mock/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/binding-mock/README.md b/input_devices/mag/node_modules/@serialport/binding-mock/README.md
new file mode 100644
index 00000000..ada69937
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-mock/README.md
@@ -0,0 +1,11 @@
+# @serialport/BindingMock
+
+This stream does some neat stuff.
+
+This is why you'd use it.
+
+This is how you use it.
+```js
+const bindingMock = new BindingMock()
+
+```
diff --git a/input_devices/mag/node_modules/@serialport/binding-mock/binding-mock.js b/input_devices/mag/node_modules/@serialport/binding-mock/binding-mock.js
new file mode 100644
index 00000000..29606c84
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-mock/binding-mock.js
@@ -0,0 +1,258 @@
+const debug = require('debug')('@serialport/binding-mock')
+const AbstractBinding = require('@serialport/binding-abstract')
+
+let ports = {}
+let serialNumber = 0
+
+function resolveNextTick(value) {
+  return new Promise(resolve => process.nextTick(() => resolve(value)))
+}
+
+/**
+ * Mock bindings for pretend serialport access
+ */
+class MockBinding extends AbstractBinding {
+  constructor(opt) {
+    super(opt)
+    this.pendingRead = null // thunk for a promise or null
+    this.isOpen = false
+    this.port = null
+    this.lastWrite = null
+    this.recording = Buffer.alloc(0)
+    this.writeOperation = null // in flight promise or null
+  }
+
+  // Reset mocks
+  static reset() {
+    ports = {}
+  }
+
+  // Create a mock port
+  static createPort(path, opt) {
+    serialNumber++
+    opt = Object.assign(
+      {
+        echo: false,
+        record: false,
+        readyData: Buffer.from('READY'),
+      },
+      opt
+    )
+
+    ports[path] = {
+      data: Buffer.alloc(0),
+      echo: opt.echo,
+      record: opt.record,
+      readyData: Buffer.from(opt.readyData),
+      info: {
+        comName: path,
+        manufacturer: 'The J5 Robotics Company',
+        serialNumber,
+        pnpId: undefined,
+        locationId: undefined,
+        vendorId: undefined,
+        productId: undefined,
+      },
+    }
+    debug(serialNumber, 'created port', JSON.stringify({ path, opt }))
+  }
+
+  static list() {
+    const info = Object.keys(ports).map(path => {
+      return ports[path].info
+    })
+    return Promise.resolve(info)
+  }
+
+  // Emit data on a mock port
+  emitData(data) {
+    if (!this.isOpen) {
+      throw new Error('Port must be open to pretend to receive data')
+    }
+    if (!Buffer.isBuffer(data)) {
+      data = Buffer.from(data)
+    }
+    debug(
+      this.serialNumber,
+      'emitting data - pending read:',
+      Boolean(this.pendingRead)
+    )
+    this.port.data = Buffer.concat([this.port.data, data])
+    if (this.pendingRead) {
+      process.nextTick(this.pendingRead)
+      this.pendingRead = null
+    }
+  }
+
+  open(path, opt) {
+    debug(null, `opening path ${path}`)
+    const port = (this.port = ports[path])
+    return super
+      .open(path, opt)
+      .then(resolveNextTick)
+      .then(() => {
+        if (!port) {
+          return Promise.reject(
+            new Error(
+              `Port does not exist - please call MockBinding.createPort('${path}') first`
+            )
+          )
+        }
+        this.serialNumber = port.info.serialNumber
+
+        if (port.openOpt && port.openOpt.lock) {
+          return Promise.reject(new Error('Port is locked cannot open'))
+        }
+
+        if (this.isOpen) {
+          return Promise.reject(new Error('Open: binding is already open'))
+        }
+
+        port.openOpt = Object.assign({}, opt)
+        this.isOpen = true
+        debug(this.serialNumber, 'port is open')
+        if (port.echo) {
+          process.nextTick(() => {
+            if (this.isOpen) {
+              debug(this.serialNumber, 'emitting ready data')
+              this.emitData(port.readyData)
+            }
+          })
+        }
+      })
+  }
+
+  close() {
+    const port = this.port
+    debug(this.serialNumber, 'closing port')
+    if (!port) {
+      return Promise.reject(new Error('already closed'))
+    }
+
+    return super.close().then(() => {
+      delete port.openOpt
+      // reset data on close
+      port.data = Buffer.alloc(0)
+      debug(this.serialNumber, 'port is closed')
+      delete this.port
+      delete this.serialNumber
+      this.isOpen = false
+      if (this.pendingRead) {
+        this.pendingRead(new Error('port is closed'))
+      }
+    })
+  }
+
+  read(buffer, offset, length) {
+    debug(this.serialNumber, 'reading', length, 'bytes')
+    return super
+      .read(buffer, offset, length)
+      .then(resolveNextTick)
+      .then(() => {
+        if (!this.isOpen) {
+          throw new Error('Read canceled')
+        }
+        if (this.port.data.length <= 0) {
+          return new Promise((resolve, reject) => {
+            this.pendingRead = err => {
+              if (err) {
+                return reject(err)
+              }
+              this.read(buffer, offset, length).then(resolve, reject)
+            }
+          })
+        }
+        const data = this.port.data.slice(0, length)
+        const readLength = data.copy(buffer, offset)
+        this.port.data = this.port.data.slice(length)
+        debug(this.serialNumber, 'read', readLength, 'bytes')
+        return readLength
+      })
+  }
+
+  write(buffer) {
+    debug(this.serialNumber, 'writing')
+    if (this.writeOperation) {
+      throw new Error(
+        'Overlapping writes are not supported and should be queued by the serialport object'
+      )
+    }
+    this.writeOperation = super
+      .write(buffer)
+      .then(resolveNextTick)
+      .then(() => {
+        if (!this.isOpen) {
+          throw new Error('Write canceled')
+        }
+        const data = (this.lastWrite = Buffer.from(buffer)) // copy
+        if (this.port.record) {
+          this.recording = Buffer.concat([this.recording, data])
+        }
+        if (this.port.echo) {
+          process.nextTick(() => {
+            if (this.isOpen) {
+              this.emitData(data)
+            }
+          })
+        }
+        this.writeOperation = null
+        debug(this.serialNumber, 'writing finished')
+      })
+    return this.writeOperation
+  }
+
+  update(opt) {
+    return super
+      .update(opt)
+      .then(resolveNextTick)
+      .then(() => {
+        this.port.openOpt.baudRate = opt.baudRate
+      })
+  }
+
+  set(opt) {
+    return super.set(opt).then(resolveNextTick)
+  }
+
+  get() {
+    return super
+      .get()
+      .then(resolveNextTick)
+      .then(() => {
+        return {
+          cts: true,
+          dsr: false,
+          dcd: false,
+        }
+      })
+  }
+
+  getBaudRate() {
+    return super
+      .getBaudRate()
+      .then(resolveNextTick)
+      .then(() => {
+        return {
+          baudRate: this.port.openOpt.baudRate,
+        }
+      })
+  }
+
+  flush() {
+    return super
+      .flush()
+      .then(resolveNextTick)
+      .then(() => {
+        this.port.data = Buffer.alloc(0)
+      })
+  }
+
+  drain() {
+    return super
+      .drain()
+      .then(() => this.writeOperation)
+      .then(() => resolveNextTick())
+  }
+}
+
+module.exports = MockBinding
diff --git a/input_devices/mag/node_modules/@serialport/binding-mock/package.json b/input_devices/mag/node_modules/@serialport/binding-mock/package.json
new file mode 100644
index 00000000..b5deb171
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/binding-mock/package.json
@@ -0,0 +1,85 @@
+{
+  "_args": [
+    [
+      "@serialport/binding-mock@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/binding-mock@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/binding-mock@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/binding-mock",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/binding-mock_2.0.1_1535513359292_0.6606021593877329"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/binding-mock",
+    "raw": "@serialport/binding-mock@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/stream",
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-2.0.1.tgz",
+  "_shasum": "724057db18d23d3c5c3b7ff17b98e045f370ac45",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/binding-mock@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {
+    "@serialport/binding-abstract": "^2.0.1",
+    "debug": "^3.1.0"
+  },
+  "description": "This stream does some neat stuff.",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-1oCxzljZY2Tj/Ws/Qa2+vEgYYTSMvzxOhyO2nAiDiEQ49oTc1XT5onbNXTeKw+T1+5uHBqol4R9TEgV4+Oi0Mw==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMPCRA9TVsSAnZWagAAA6MQAIblPJTTfexIPiawVkpF\nyql4a8KGyy77OAgiWFSspqbkVW1cWmZt0JybG8EnwCt70EbswyZ2aUAizo1K\nJgeu1jbM8C/arU3uwQkkpNoAhl7etR8oWKmBifr+UdL2d1xcyxv6fWFfY0am\nK6340A9uM7DUpeGdOTv6k6FGPv/5hHJ1IZIDE7kizoCXBSQjW24h6RcF/cC+\npR4oQB4KA+e3PUvtAvgYQw++pK5/4qTsObR+LeQddyVphhed4/Rc3Q80hfp5\n7jtfHmqwEklAqiTA4qaQqTnOd6Xd3ncln4E2mpzFjPJKGboPVKkKyDAeY8dN\nWykMeMp/SnNskEIbqiEkP6LK8JQUJb1/RVLY2Je4LWBrAJqAUH/V4L5T7OLi\nKiz/rn/bEEyjgBTVRsBDGOh1BNLRd20ftAO3oWa9Ox4W+zu6R30QNKPZSwpz\nPZiM8O8OyW2xf4QPxWVP3LZ6oM7V6+BeXdJMxDEWvd6PG4ukMuDZUZYu0PlC\n47+9V0GkE1dUvsH8uVmUqJyQEgF5YaHi00ztKNCEUjrTCb5N6qEYA4zcnAp8\nx017fB43pxlOhaIwCCVTeiQ2vghrI4Sawrh3Af2EyuNX8bJMmWarqyJ5cLlT\nGP5bbiRC0D6NmlLBscb5aUNfmNZ55Xphc/P+2Q3YSdvzFIV5S+4Lol6j6Qjv\nO6TO\r\n=2gpx\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "724057db18d23d3c5c3b7ff17b98e045f370ac45",
+    "tarball": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-2.0.1.tgz",
+    "unpackedSize": 8501
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "binding-mock.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/binding-mock",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/bindings/CHANGELOG.md
new file mode 100644
index 00000000..c6653312
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/CHANGELOG.md
@@ -0,0 +1,30 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.2"></a>
+## [2.0.2](https://github.com/node-serialport/node-serialport/compare/@serialport/bindings@2.0.1...@serialport/bindings@2.0.2) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/bindings
+
+
+
+
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/bindings@2.0.0...@serialport/bindings@2.0.1) (2018-08-29)
+
+
+### Bug Fixes
+
+* prebuild now pays attention to lerna tags ([#1639](https://github.com/node-serialport/node-serialport/issues/1639)) ([d3d553f](https://github.com/node-serialport/node-serialport/commit/d3d553f))
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/bindings
diff --git a/input_devices/mag/node_modules/@serialport/bindings/LICENSE b/input_devices/mag/node_modules/@serialport/bindings/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/bindings/README.md b/input_devices/mag/node_modules/@serialport/bindings/README.md
new file mode 100644
index 00000000..60afa139
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/README.md
@@ -0,0 +1,11 @@
+# @serialport/Bindings
+
+This package does some neat stuff.
+
+This is why you'd use it.
+
+This is how you use it.
+```js
+const bindings = new Bindings()
+
+```
diff --git a/input_devices/mag/node_modules/@serialport/bindings/binding.gyp b/input_devices/mag/node_modules/@serialport/bindings/binding.gyp
new file mode 100644
index 00000000..a085d213
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/binding.gyp
@@ -0,0 +1,57 @@
+{
+  'targets': [{
+    'target_name': 'bindings',
+    'sources': [
+      'src/serialport.cpp'
+    ],
+    'include_dirs': [
+      '<!(node -e "require(\'nan\')")'
+    ],
+    'conditions': [
+      ['OS=="win"',
+        {
+          'sources': [
+            'src/serialport_win.cpp'
+          ],
+          'msvs_settings': {
+            'VCCLCompilerTool': {
+              'ExceptionHandling': '2',
+              'DisableSpecificWarnings': [ '4530', '4506' ],
+            }
+          }
+        }
+      ],
+      ['OS=="mac"',
+        {
+          'sources': [
+            'src/serialport_unix.cpp',
+            'src/poller.cpp',
+            'src/darwin_list.cpp'
+          ],
+          'xcode_settings': {
+            'OTHER_LDFLAGS': [
+              '-framework CoreFoundation -framework IOKit'
+            ]
+          }
+        }
+      ],
+      ['OS=="linux"',
+        {
+          'sources': [
+            'src/serialport_unix.cpp',
+            'src/poller.cpp',
+            'src/serialport_linux.cpp'
+          ]
+        }
+      ],
+      ['OS!="win"',
+        {
+          'sources': [
+            'src/serialport_unix.cpp',
+            'src/poller.cpp'
+          ]
+        }
+      ]
+    ]
+  }],
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/build/Release/bindings.node b/input_devices/mag/node_modules/@serialport/bindings/build/Release/bindings.node
new file mode 100755
index 0000000000000000000000000000000000000000..e7488ccce8159cc391ea685b679bee93dc49aeb7
GIT binary patch
literal 56320
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
Oq4vK=7KGY`ECc}OqWq5l

literal 0
HcmV?d00001

diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/bindings-test.js b/input_devices/mag/node_modules/@serialport/bindings/lib/bindings-test.js
new file mode 100644
index 00000000..a4306965
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/bindings-test.js
@@ -0,0 +1,650 @@
+let platform
+switch (process.platform) {
+  case 'win32':
+  case 'darwin':
+  case 'linux':
+    platform = process.platform
+    break
+  default:
+    throw new Error(`Unknown platform "${process.platform}"`)
+}
+
+const defaultOpenOptions = Object.freeze({
+  baudRate: 9600,
+  dataBits: 8,
+  hupcl: true,
+  lock: true,
+  parity: 'none',
+  rtscts: false,
+  stopBits: 1,
+  xany: false,
+  xoff: false,
+  xon: false,
+})
+
+const defaultSetFlags = Object.freeze({
+  brk: false,
+  cts: false,
+  dtr: true,
+  dts: false,
+  rts: true,
+})
+
+const listFields = [
+  'comName',
+  'manufacturer',
+  'serialNumber',
+  'pnpId',
+  'locationId',
+  'vendorId',
+  'productId',
+]
+
+const bindingsToTest = ['mock', platform]
+
+function disconnect(err) {
+  throw err || new Error('Unknown disconnection')
+}
+
+// All bindings are required to work with an "echo" firmware
+// The echo firmware should respond with this data when it's
+// ready to echo. This allows for remote device bootup.
+// the default firmware is called arduinoEcho.ino
+const readyData = Buffer.from('READY')
+
+// Test our mock binding and the binding for the platform we're running on
+bindingsToTest.forEach(bindingName => {
+  const Binding =
+    bindingName === 'mock'
+      ? require('@serialport/binding-mock')
+      : require(`./${bindingName}`)
+  let testPort = process.env.TEST_PORT
+
+  if (bindingName === 'mock') {
+    testPort = '/dev/exists'
+  }
+
+  // eslint-disable-next-line no-use-before-define
+  testBinding(bindingName, Binding, testPort)
+})
+
+function testBinding(bindingName, Binding, testPort) {
+  const testFeature = makeTestFeature(bindingName)
+
+  describe(`bindings/${bindingName}`, () => {
+    before(() => {
+      if (bindingName === 'mock') {
+        Binding.createPort(testPort, { echo: true, readyData })
+      }
+    })
+
+    describe('static method', () => {
+      describe('.list', () => {
+        it('returns an array', () => {
+          return Binding.list().then(ports => {
+            assert.isArray(ports)
+          })
+        })
+
+        it('has objects with undefined when there is no data', () => {
+          return Binding.list().then(ports => {
+            assert.isArray(ports)
+            if (ports.length === 0) {
+              console.log('no ports to test')
+              return
+            }
+            ports.forEach(port => {
+              assert.containSubset(Object.keys(port), listFields)
+              Object.keys(port).forEach(key => {
+                assert.notEqual(
+                  port[key],
+                  '',
+                  'empty values should be undefined'
+                )
+                assert.isNotNull(port[key], 'empty values should be undefined')
+              })
+            })
+          })
+        })
+      })
+    })
+
+    describe('constructor', () => {
+      it('creates a binding object', () => {
+        const binding = new Binding({
+          disconnect,
+        })
+        assert.instanceOf(binding, Binding)
+      })
+
+      it('throws when not given an options object', done => {
+        try {
+          new Binding()
+        } catch (e) {
+          assert.instanceOf(e, TypeError)
+          done()
+        }
+      })
+    })
+
+    describe('instance property', () => {
+      describe('#isOpen', () => {
+        if (!testPort) {
+          it(
+            'Cannot be tested. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        let binding
+        beforeEach(() => {
+          binding = new Binding({
+            disconnect,
+          })
+        })
+
+        it('is true after open and false after close', () => {
+          assert.equal(binding.isOpen, false)
+          return binding.open(testPort, defaultOpenOptions).then(() => {
+            assert.equal(binding.isOpen, true)
+            return binding.close().then(() => {
+              assert.equal(binding.isOpen, false)
+            })
+          })
+        })
+      })
+    })
+
+    describe('instance method', () => {
+      describe('#open', () => {
+        let binding
+        beforeEach(() => {
+          binding = new Binding({
+            disconnect,
+          })
+        })
+
+        it('errors when providing a bad port', () => {
+          return binding.open('COMBAD', defaultOpenOptions).catch(err => {
+            assert.instanceOf(err, Error)
+            assert.include(err.message, 'COMBAD')
+            assert.equal(binding.isOpen, false)
+          })
+        })
+
+        it('throws when not given a path', done => {
+          try {
+            binding.open('')
+          } catch (e) {
+            assert.instanceOf(e, TypeError)
+            done()
+          }
+        })
+
+        it('throws when not given options', done => {
+          try {
+            binding.open('COMBAD')
+          } catch (e) {
+            assert.instanceOf(e, TypeError)
+            done()
+          }
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        it('cannot open if already open', () => {
+          const options = Object.assign({}, defaultOpenOptions, {
+            lock: false,
+          })
+          return binding.open(testPort, options).then(() => {
+            return binding.open(testPort, options).catch(err => {
+              assert.instanceOf(err, Error)
+              return binding.close()
+            })
+          })
+        })
+
+        it('keeps open state', () => {
+          return binding.open(testPort, defaultOpenOptions).then(() => {
+            assert.equal(binding.isOpen, true)
+            return binding.close()
+          })
+        })
+
+        describe('arbitrary baud rates', () => {
+          ;[25000, 1000000, 250000].forEach(testBaud => {
+            describe(`${testBaud} baud`, () => {
+              const customRates = Object.assign({}, defaultOpenOptions, {
+                baudRate: testBaud,
+              })
+              testFeature(
+                `baudrate.${testBaud}`,
+                `opens at ${testBaud} baud`,
+                () => {
+                  return binding.open(testPort, customRates).then(() => {
+                    assert.equal(binding.isOpen, true)
+                    return binding.close()
+                  })
+                }
+              )
+
+              testFeature(
+                `baudrate.${testBaud}_check`,
+                `sets ${testBaud} baud successfully`,
+                () => {
+                  return binding
+                    .open(testPort, customRates)
+                    .then(() => binding.getBaudRate())
+                    .then(res => {
+                      assert.equal(res.baudRate, customRates.baudRate)
+                      return binding.close()
+                    })
+                }
+              )
+            })
+          })
+        })
+
+        describe('optional locking', () => {
+          it('locks the port by default', () => {
+            const binding2 = new Binding({ disconnect })
+
+            return binding
+              .open(testPort, defaultOpenOptions)
+              .then(() => {
+                assert.equal(binding.isOpen, true)
+              })
+              .then(() => {
+                return binding2
+                  .open(testPort, defaultOpenOptions)
+                  .catch(err => {
+                    assert.instanceOf(err, Error)
+                    assert.equal(binding2.isOpen, false)
+                    return binding.close()
+                  })
+              })
+          })
+
+          testFeature('open.unlock', 'can unlock the port', () => {
+            const noLock = Object.assign({}, defaultOpenOptions, {
+              lock: false,
+            })
+            const binding2 = new Binding({ disconnect })
+
+            return binding
+              .open(testPort, noLock)
+              .then(() => assert.equal(binding.isOpen, true))
+              .then(() => binding2.open(testPort, noLock))
+              .then(() => assert.equal(binding2.isOpen, true))
+              .then(() => Promise.all([binding.close(), binding2.close()]))
+          })
+        })
+      })
+
+      describe('#close', () => {
+        let binding
+        beforeEach(() => {
+          binding = new Binding({ disconnect })
+        })
+
+        it('errors when already closed', () => {
+          return binding.close().catch(err => {
+            assert.instanceOf(err, Error)
+          })
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        it('closes an open file descriptor', () => {
+          return binding.open(testPort, defaultOpenOptions).then(() => {
+            assert.equal(binding.isOpen, true)
+            return binding.close()
+          })
+        })
+      })
+
+      describe('#update', () => {
+        it('throws when not given an object', done => {
+          const binding = new Binding({ disconnect })
+
+          try {
+            binding.update()
+          } catch (e) {
+            assert.instanceOf(e, TypeError)
+            done()
+          }
+        })
+
+        it('errors asynchronously when not open', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          let noZalgo = false
+          binding.update({ baudRate: 9600 }).catch(err => {
+            assert.instanceOf(err, Error)
+            assert(noZalgo)
+            done()
+          })
+          noZalgo = true
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        let binding
+        beforeEach(() => {
+          binding = new Binding({ disconnect })
+          return binding.open(testPort, defaultOpenOptions)
+        })
+
+        afterEach(() => binding.close())
+
+        it('throws errors when updating nothing', done => {
+          try {
+            binding.update({})
+          } catch (err) {
+            assert.instanceOf(err, Error)
+            done()
+          }
+        })
+
+        it('errors when not called with options', done => {
+          try {
+            binding.set(() => {})
+          } catch (e) {
+            assert.instanceOf(e, Error)
+            done()
+          }
+        })
+
+        it('updates baudRate', () => {
+          return binding.update({ baudRate: 57600 })
+        })
+      })
+
+      describe('#write', () => {
+        it('errors asynchronously when not open', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          let noZalgo = false
+          binding.write(Buffer.from([])).catch(err => {
+            assert.instanceOf(err, Error)
+            assert(noZalgo)
+            done()
+          })
+          noZalgo = true
+        })
+
+        it('throws when not given a buffer', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          try {
+            binding.write(null)
+          } catch (e) {
+            assert.instanceOf(e, TypeError)
+            done()
+          }
+        })
+
+        if (!testPort) {
+          it(`Cannot be tested as we have no test ports on ${platform}`)
+          return
+        }
+
+        let binding
+        beforeEach(() => {
+          binding = new Binding({
+            disconnect,
+          })
+          return binding.open(testPort, defaultOpenOptions)
+        })
+
+        afterEach(() => binding.close())
+
+        it('resolves after a small write', () => {
+          const data = Buffer.from('simple write of 24 bytes')
+          return binding.write(data)
+        })
+
+        it('resolves after a large write (2k)', function() {
+          this.timeout(20000)
+          const data = Buffer.alloc(1024 * 2)
+          return binding.write(data)
+        })
+      })
+
+      describe('#drain', () => {
+        it('errors asynchronously when not open', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          let noZalgo = false
+          binding.drain().catch(err => {
+            assert.instanceOf(err, Error)
+            assert(noZalgo)
+            done()
+          })
+          noZalgo = true
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        let binding
+        beforeEach(() => {
+          binding = new Binding({
+            disconnect,
+          })
+          return binding.open(testPort, defaultOpenOptions)
+        })
+
+        afterEach(() => binding.close())
+
+        it('drains the port', () => {
+          return binding.drain()
+        })
+
+        it('waits for in progress writes to finish', function(done) {
+          this.timeout(10000)
+          let finishedWrite = false
+          binding
+            .write(Buffer.alloc(1024 * 2))
+            .then(() => {
+              finishedWrite = true
+            })
+            .catch(done)
+          binding
+            .drain(() => {
+              assert.isTrue(finishedWrite)
+            })
+            .then(done, done)
+        })
+      })
+
+      describe('#flush', () => {
+        it('errors asynchronously when not open', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          let noZalgo = false
+          binding.flush().catch(err => {
+            assert.instanceOf(err, Error)
+            assert(noZalgo)
+            done()
+          })
+          noZalgo = true
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        let binding
+        beforeEach(() => {
+          binding = new Binding({
+            disconnect,
+          })
+          return binding.open(testPort, defaultOpenOptions)
+        })
+
+        afterEach(() => binding.close())
+
+        it('flushes the port', () => {
+          return binding.flush()
+        })
+      })
+
+      describe('#set', () => {
+        it('errors asynchronously when not open', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          let noZalgo = false
+          binding.set(defaultSetFlags).catch(err => {
+            assert.instanceOf(err, Error)
+            assert(noZalgo)
+            done()
+          })
+          noZalgo = true
+        })
+
+        it('throws when not called with options', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          try {
+            binding.set(() => {})
+          } catch (e) {
+            assert.instanceOf(e, TypeError)
+            done()
+          }
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        let binding
+        beforeEach(() => {
+          binding = new Binding({
+            disconnect,
+          })
+          return binding.open(testPort, defaultOpenOptions)
+        })
+
+        afterEach(() => binding.close())
+
+        testFeature('set.set', 'sets flags on the port', () => {
+          return binding.set(defaultSetFlags)
+        })
+      })
+
+      // because of the nature of opening and closing the ports a fair amount of data
+      // is left over on the pipe and isn't cleared when flushed on unix
+      describe('#read', () => {
+        it('errors asynchronously when not open', done => {
+          const binding = new Binding({ disconnect })
+          const buffer = Buffer.alloc(5)
+          let noZalgo = false
+          binding.read(buffer, 0, buffer.length).catch(err => {
+            assert.instanceOf(err, Error)
+            assert(noZalgo)
+            done()
+          })
+          noZalgo = true
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        let binding, buffer
+        beforeEach(() => {
+          buffer = Buffer.alloc(readyData.length)
+          binding = new Binding({ disconnect })
+          return binding.open(testPort, defaultOpenOptions)
+        })
+
+        afterEach(() => binding.close())
+
+        it("doesn't throw if the port is open", () => {
+          return binding.read(buffer, 0, buffer.length)
+        })
+
+        it('returns at maximum the requested number of bytes', () => {
+          return binding.read(buffer, 0, 1).then(bytesRead => {
+            assert.equal(bytesRead, 1)
+          })
+        })
+      })
+
+      describe('#get', () => {
+        it('errors asynchronously when not open', done => {
+          const binding = new Binding({
+            disconnect,
+          })
+          let noZalgo = false
+          binding.get().catch(err => {
+            assert.instanceOf(err, Error)
+            assert(noZalgo)
+            done()
+          })
+          noZalgo = true
+        })
+
+        if (!testPort) {
+          it(
+            'Cannot be tested further. Set the TEST_PORT env var with an available serialport for more testing.'
+          )
+          return
+        }
+
+        let binding
+        beforeEach(() => {
+          binding = new Binding({ disconnect })
+          return binding.open(testPort, defaultOpenOptions)
+        })
+
+        afterEach(() => binding.close())
+
+        testFeature('get.get', 'gets modem line status from the port', () => {
+          return binding.get().then(status => {
+            assert.isObject(status)
+            assert.isBoolean(status.cts)
+            assert.isBoolean(status.dsr)
+            assert.isBoolean(status.dcd)
+          })
+        })
+      })
+    })
+  })
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/bindings-win32-sn-parser-test.js b/input_devices/mag/node_modules/@serialport/bindings/lib/bindings-win32-sn-parser-test.js
new file mode 100644
index 00000000..0e2818f2
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/bindings-win32-sn-parser-test.js
@@ -0,0 +1,38 @@
+const serialNumParser = require('./win32-sn-parser')
+
+const devices = {
+  'FTDI Device': {
+    pnpId: 'FTDIBUS\\VID_0403+PID_6015+DO004ZB7A\\0000',
+    serialNumber: 'DO004ZB7',
+  },
+  'Arduino Mega': {
+    pnpId: 'USB\\VID_2341&PID_0042\\85531303630351C081D2',
+    serialNumber: '85531303630351C081D2',
+  },
+  'Atlas Scientific EZO-RGB Sensor': {
+    pnpId: 'FTDIBUS\\VID_0403+PID_6015+DJ1XJE67A\\0000',
+    serialNumber: 'DJ1XJE67',
+  },
+  'Gearmo FTDI2-LED USB RS-232 Serial Adapter': {
+    pnpId: 'FTDIBUS\\VID_0403+PID_6001+AL1WHZWFA\\0000',
+    serialNumber: 'AL1WHZWF',
+  },
+  'Arducam Nano V3.0 (Arduino Nano with FTDI)': {
+    pnpId: 'FTDIBUS\\VID_0403+PID_6001+A51MAMMEA\\0000',
+    serialNumber: 'A51MAMME',
+  },
+  'Pretend Device with an unknown pnp id': {
+    pnpId: 'WATEVER\\Whoever\\However!',
+    serialNumber: null,
+  },
+}
+
+describe('serialNumParser', () => {
+  Object.keys(devices).forEach(device => {
+    it(`parses pnp id for ${device}`, () => {
+      const pnpId = devices[device].pnpId
+      const serialNumber = devices[device].serialNumber
+      assert.equal(serialNumParser(pnpId), serialNumber)
+    })
+  })
+})
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/darwin.js b/input_devices/mag/node_modules/@serialport/bindings/lib/darwin.js
new file mode 100644
index 00000000..703367a8
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/darwin.js
@@ -0,0 +1,109 @@
+const binding = require('bindings')('bindings.node')
+const AbstractBinding = require('@serialport/binding-abstract')
+const Poller = require('./poller')
+const promisify = require('./util').promisify
+const unixRead = require('./unix-read')
+const unixWrite = require('./unix-write')
+
+const defaultBindingOptions = Object.freeze({
+  vmin: 1,
+  vtime: 0,
+})
+
+/**
+ * The Darwin binding layer for OSX
+ */
+class DarwinBinding extends AbstractBinding {
+  static list() {
+    return promisify(binding.list)()
+  }
+
+  constructor(opt) {
+    super(opt)
+    this.bindingOptions = Object.assign(
+      {},
+      defaultBindingOptions,
+      opt.bindingOptions || {}
+    )
+    this.fd = null
+    this.writeOperation = null
+  }
+
+  get isOpen() {
+    return this.fd !== null
+  }
+
+  open(path, options) {
+    return super
+      .open(path, options)
+      .then(() => {
+        this.openOptions = Object.assign({}, this.bindingOptions, options)
+        return promisify(binding.open)(path, this.openOptions)
+      })
+      .then(fd => {
+        this.fd = fd
+        this.poller = new Poller(fd)
+      })
+  }
+
+  close() {
+    return super.close().then(() => {
+      const fd = this.fd
+      this.poller.stop()
+      this.poller.destroy()
+      this.poller = null
+      this.openOptions = null
+      this.fd = null
+      return promisify(binding.close)(fd)
+    })
+  }
+
+  read(buffer, offset, length) {
+    return super
+      .read(buffer, offset, length)
+      .then(() => unixRead.call(this, buffer, offset, length))
+  }
+
+  write(buffer) {
+    this.writeOperation = super
+      .write(buffer)
+      .then(() => unixWrite.call(this, buffer))
+      .then(() => {
+        this.writeOperation = null
+      })
+    return this.writeOperation
+  }
+
+  update(options) {
+    return super
+      .update(options)
+      .then(() => promisify(binding.update)(this.fd, options))
+  }
+
+  set(options) {
+    return super
+      .set(options)
+      .then(() => promisify(binding.set)(this.fd, options))
+  }
+
+  get() {
+    return super.get().then(() => promisify(binding.get)(this.fd))
+  }
+
+  getBaudRate() {
+    return super.get().then(() => promisify(binding.getBaudRate)(this.fd))
+  }
+
+  drain() {
+    return super
+      .drain()
+      .then(() => Promise.resolve(this.writeOperation))
+      .then(() => promisify(binding.drain)(this.fd))
+  }
+
+  flush() {
+    return super.flush().then(() => promisify(binding.flush)(this.fd))
+  }
+}
+
+module.exports = DarwinBinding
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/index.js b/input_devices/mag/node_modules/@serialport/bindings/lib/index.js
new file mode 100644
index 00000000..c09875b7
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/index.js
@@ -0,0 +1,15 @@
+const debug = require('debug')('@serialport/bindings')
+
+switch (process.platform) {
+  case 'win32':
+    debug('loading WindowsBinding')
+    module.exports = require('./win32')
+    break
+  case 'darwin':
+    debug('loading DarwinBinding')
+    module.exports = require('./darwin')
+    break
+  default:
+    debug('loading LinuxBinding')
+    module.exports = require('./linux')
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/linux-list-test.js b/input_devices/mag/node_modules/@serialport/bindings/lib/linux-list-test.js
new file mode 100644
index 00000000..cae84d25
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/linux-list-test.js
@@ -0,0 +1,116 @@
+const listLinux = require('./mocks/linux-list')
+
+const ports = String.raw`
+P: /devices/platform/serial8250/tty/ttyS0
+N: ttyS0
+E: DEVNAME=/dev/ttyS0
+E: DEVPATH=/devices/platform/serial8250/tty/ttyS0
+E: MAJOR=4
+E: MINOR=64
+E: SUBSYSTEM=tty
+
+P: /devices/platform/serial8250/tty/ttyS1
+N: ttyS1
+E: DEVNAME=/dev/ttyS1
+E: DEVPATH=/devices/platform/serial8250/tty/ttyS1
+E: MAJOR=4
+E: MINOR=65
+E: SUBSYSTEM=tty
+
+P: /devices/pci0000:00/0000:00:06.0/usb1/1-2/1-2:1.0/tty/ttyACM0
+N: ttyACM0
+S: serial/by-id/usb-Arduino__www.arduino.cc__0043_752303138333518011C1-if00
+S: serial/by-path/pci-0000:00:06.0-usb-0:2:1.0
+E: DEVLINKS=/dev/serial/by-path/pci-0000:00:06.0-usb-0:2:1.0 /dev/serial/by-id/usb-Arduino__www.arduino.cc__0043_752303138333518011C1-if00
+E: DEVNAME=/dev/ttyACM0
+E: DEVPATH=/devices/pci0000:00/0000:00:06.0/usb1/1-2/1-2:1.0/tty/ttyACM0
+E: ID_BUS=usb
+E: ID_MM_CANDIDATE=1
+E: ID_MODEL=0043
+E: ID_MODEL_ENC=0043
+E: ID_MODEL_FROM_DATABASE=Uno R3 (CDC ACM)
+E: ID_MODEL_ID=0043
+E: ID_PATH=pci-0000:00:06.0-usb-0:2:1.0
+E: ID_PATH_TAG=pci-0000_00_06_0-usb-0_2_1_0
+E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
+E: ID_PCI_INTERFACE_FROM_DATABASE=OHCI
+E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
+E: ID_REVISION=0001
+E: ID_SERIAL=Arduino__www.arduino.cc__0043_752303138333518011C1
+E: ID_SERIAL_SHORT=752303138333518011C1
+E: ID_TYPE=generic
+E: ID_USB_CLASS_FROM_DATABASE=Communications
+E: ID_USB_DRIVER=cdc_acm
+E: ID_USB_INTERFACES=:020201:0a0000:
+E: ID_USB_INTERFACE_NUM=00
+E: ID_VENDOR=Arduino__www.arduino.cc_
+E: ID_VENDOR_ENC=Arduino\x20\x28www.arduino.cc\x29
+E: ID_VENDOR_FROM_DATABASE=Arduino SA
+E: ID_VENDOR_ID=2341
+E: MAJOR=166
+E: MINOR=0
+E: SUBSYSTEM=tty
+E: TAGS=:systemd:
+E: USEC_INITIALIZED=2219936602
+
+P: /devices/unknown
+N: ttyAMA_im_a_programmer
+E: DEVNAME=/dev/ttyAMA_im_a_programmer
+E: DEVLINKS=/dev/serial/by-id/pci-NATA_Siolynx2_C8T6VI1F-if00-port0 /dev/serial/by-path/pci-0000:00:14.0-usb-0:2:1.0-port0
+
+P: /devices/unknown
+N: ttyMFD0
+E: DEVNAME=/dev/ttyMFD0
+E: ID_VENDOR_ID=0x2343
+E: ID_MODEL_ID=0043
+E: ID_MODEL_ENC=some device made by someone
+
+P: /devices/unknown
+N: rfcomm4
+E: DEVNAME=/dev/rfcomm4
+
+P: /devices/unknown
+N: ttyNOTASERIALPORT
+`
+
+const portOutput = [
+  {
+    comName: '/dev/ttyS0',
+  },
+  {
+    comName: '/dev/ttyS1',
+  },
+  {
+    comName: '/dev/ttyACM0',
+    manufacturer: 'Arduino (www.arduino.cc)',
+    serialNumber: '752303138333518011C1',
+    productId: '0043',
+    vendorId: '2341',
+    pnpId: 'usb-Arduino__www.arduino.cc__0043_752303138333518011C1-if00',
+  },
+  {
+    comName: '/dev/ttyAMA_im_a_programmer',
+    pnpId: 'pci-NATA_Siolynx2_C8T6VI1F-if00-port0',
+  },
+  {
+    comName: '/dev/ttyMFD0',
+    vendorId: '2343',
+    productId: '0043',
+  },
+  {
+    comName: '/dev/rfcomm4',
+  },
+]
+
+describe('listLinux', () => {
+  beforeEach(() => {
+    listLinux.reset()
+  })
+
+  it('lists available serialports', () => {
+    listLinux.setPorts(ports)
+    return listLinux().then(ports => {
+      assert.containSubset(ports, portOutput)
+    })
+  })
+})
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/linux-list.js b/input_devices/mag/node_modules/@serialport/bindings/lib/linux-list.js
new file mode 100644
index 00000000..52fa5be9
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/linux-list.js
@@ -0,0 +1,99 @@
+const childProcess = require('child_process')
+const Readline = require('@serialport/parser-readline')
+
+// get only serial port names
+function checkPathOfDevice(path) {
+  return /(tty(S|ACM|USB|AMA|MFD|O)|rfcomm)/.test(path) && path
+}
+
+function propName(name) {
+  return {
+    DEVNAME: 'comName',
+    ID_VENDOR_ENC: 'manufacturer',
+    ID_SERIAL_SHORT: 'serialNumber',
+    ID_VENDOR_ID: 'vendorId',
+    ID_MODEL_ID: 'productId',
+    DEVLINKS: 'pnpId',
+  }[name.toUpperCase()]
+}
+
+function decodeHexEscape(str) {
+  return str.replace(/\\x([a-fA-F0-9]{2})/g, (a, b) => {
+    return String.fromCharCode(parseInt(b, 16))
+  })
+}
+
+function propVal(name, val) {
+  if (name === 'pnpId') {
+    const match = val.match(/\/by-id\/([^\s]+)/)
+    return (match && match[1]) || undefined
+  }
+  if (name === 'manufacturer') {
+    return decodeHexEscape(val)
+  }
+  if (/^0x/.test(val)) {
+    return val.substr(2)
+  }
+  return val
+}
+
+function listLinux() {
+  return new Promise((resolve, reject) => {
+    const ports = []
+    const ude = childProcess.spawn('udevadm', ['info', '-e'])
+    const lines = ude.stdout.pipe(new Readline())
+    ude.on('error', reject)
+    lines.on('error', reject)
+
+    let port = {}
+    let skipPort = false
+    lines.on('data', line => {
+      const lineType = line.slice(0, 1)
+      const data = line.slice(3)
+      // new port entry
+      if (lineType === 'P') {
+        port = {
+          manufacturer: undefined,
+          serialNumber: undefined,
+          pnpId: undefined,
+          locationId: undefined,
+          vendorId: undefined,
+          productId: undefined,
+        }
+        skipPort = false
+        return
+      }
+
+      if (skipPort) {
+        return
+      }
+
+      // Check dev name and save port if it matches flag to skip the rest of the data if not
+      if (lineType === 'N') {
+        if (checkPathOfDevice(data)) {
+          ports.push(port)
+        } else {
+          skipPort = true
+        }
+        return
+      }
+
+      // parse data about each port
+      if (lineType === 'E') {
+        const keyValue = data.match(/^(.+)=(.*)/)
+        if (!keyValue) {
+          return
+        }
+        const key = propName(keyValue[1])
+        if (!key) {
+          return
+        }
+        port[key] = propVal(key, keyValue[2])
+      }
+    })
+
+    lines.on('finish', () => resolve(ports))
+  })
+}
+
+module.exports = listLinux
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/linux.js b/input_devices/mag/node_modules/@serialport/bindings/lib/linux.js
new file mode 100644
index 00000000..f80322ee
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/linux.js
@@ -0,0 +1,111 @@
+const binding = require('bindings')('bindings.node')
+const AbstractBinding = require('@serialport/binding-abstract')
+const linuxList = require('./linux-list')
+const Poller = require('./poller')
+const promisify = require('./util').promisify
+const unixRead = require('./unix-read')
+const unixWrite = require('./unix-write')
+
+const defaultBindingOptions = Object.freeze({
+  vmin: 1,
+  vtime: 0,
+})
+/**
+ * The linux binding layer
+ */
+class LinuxBinding extends AbstractBinding {
+  static list() {
+    return linuxList()
+  }
+
+  constructor(opt) {
+    super(opt)
+    this.bindingOptions = Object.assign(
+      {},
+      defaultBindingOptions,
+      opt.bindingOptions || {}
+    )
+    this.fd = null
+    this.writeOperation = null
+  }
+
+  get isOpen() {
+    return this.fd !== null
+  }
+
+  open(path, options) {
+    return super
+      .open(path, options)
+      .then(() => {
+        this.openOptions = Object.assign({}, this.bindingOptions, options)
+        return promisify(binding.open)(path, this.openOptions)
+      })
+      .then(fd => {
+        this.fd = fd
+        this.poller = new Poller(fd)
+      })
+  }
+
+  close() {
+    return super.close().then(() => {
+      const fd = this.fd
+      this.poller.stop()
+      this.poller.destroy()
+      this.poller = null
+      this.openOptions = null
+      this.fd = null
+      return promisify(binding.close)(fd)
+    })
+  }
+
+  read(buffer, offset, length) {
+    return super
+      .read(buffer, offset, length)
+      .then(() => unixRead.call(this, buffer, offset, length))
+  }
+
+  write(buffer) {
+    this.writeOperation = super
+      .write(buffer)
+      .then(() => unixWrite.call(this, buffer))
+      .then(() => {
+        this.writeOperation = null
+      })
+    return this.writeOperation
+  }
+
+  update(options) {
+    return super
+      .update(options)
+      .then(() => promisify(binding.update)(this.fd, options))
+  }
+
+  set(options) {
+    return super
+      .set(options)
+      .then(() => promisify(binding.set)(this.fd, options))
+  }
+
+  get() {
+    return super.get().then(() => promisify(binding.get)(this.fd))
+  }
+
+  getBaudRate() {
+    return super
+      .getBaudRate()
+      .then(() => promisify(binding.getBaudRate)(this.fd))
+  }
+
+  drain() {
+    return super
+      .drain()
+      .then(() => Promise.resolve(this.writeOperation))
+      .then(() => promisify(binding.drain)(this.fd))
+  }
+
+  flush() {
+    return super.flush().then(() => promisify(binding.flush)(this.fd))
+  }
+}
+
+module.exports = LinuxBinding
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/poller.js b/input_devices/mag/node_modules/@serialport/bindings/lib/poller.js
new file mode 100644
index 00000000..4a54ca0f
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/poller.js
@@ -0,0 +1,111 @@
+const debug = require('debug')
+const logger = debug('@serialport/bindings:poller')
+const EventEmitter = require('events')
+const FDPoller = require('bindings')('bindings.node').Poller
+
+const EVENTS = {
+  UV_READABLE: 1,
+  UV_WRITABLE: 2,
+  UV_DISCONNECT: 4,
+}
+
+function handleEvent(error, eventFlag) {
+  if (error) {
+    logger('error', error)
+    this.emit('readable', error)
+    this.emit('writable', error)
+    this.emit('disconnect', error)
+    return
+  }
+  if (eventFlag & EVENTS.UV_READABLE) {
+    logger('received "readable"')
+    this.emit('readable', null)
+  }
+  if (eventFlag & EVENTS.UV_WRITABLE) {
+    logger('received "writable"')
+    this.emit('writable', null)
+  }
+  if (eventFlag & EVENTS.UV_DISCONNECT) {
+    logger('received "disconnect"')
+    this.emit('disconnect', null)
+  }
+}
+
+/**
+ * Polls unix systems for readable or writable states of a file or serialport
+ */
+class Poller extends EventEmitter {
+  constructor(fd) {
+    logger('Creating poller')
+    super()
+    this.poller = new FDPoller(fd, handleEvent.bind(this))
+  }
+  /**
+   * Wait for the next event to occur
+   * @param {string} event ('readable'|'writable'|'disconnect')
+   * @returns {Poller} returns itself
+   */
+  once(event) {
+    switch (event) {
+      case 'readable':
+        this.poll(EVENTS.UV_READABLE)
+        break
+      case 'writable':
+        this.poll(EVENTS.UV_WRITABLE)
+        break
+      case 'disconnect':
+        this.poll(EVENTS.UV_DISCONNECT)
+        break
+    }
+    return EventEmitter.prototype.once.apply(this, arguments)
+  }
+
+  /**
+   * Ask the bindings to listen for an event, it is recommend to use `.once()` for easy use
+   * @param {EVENTS} eventFlag polls for an event or group of events based upon a flag.
+   * @returns {undefined}
+   */
+  poll(eventFlag) {
+    eventFlag = eventFlag || 0
+
+    if (eventFlag & EVENTS.UV_READABLE) {
+      logger('Polling for "readable"')
+    }
+    if (eventFlag & EVENTS.UV_WRITABLE) {
+      logger('Polling for "writable"')
+    }
+    if (eventFlag & EVENTS.UV_DISCONNECT) {
+      logger('Polling for "disconnect"')
+    }
+
+    this.poller.poll(eventFlag)
+  }
+
+  /**
+   * Stop listening for events and cancel all outstanding listening with an error
+   * @returns {undefined}
+   */
+  stop() {
+    logger('Stopping poller')
+    this.poller.stop()
+    this.emitCanceled()
+  }
+
+  destroy() {
+    logger('Destroying poller')
+    this.poller.destroy()
+    this.emitCanceled()
+  }
+
+  emitCanceled() {
+    const err = new Error('Canceled')
+    err.canceled = true
+    this.emit('readable', err)
+    this.emit('writable', err)
+    this.emit('disconnect', err)
+  }
+}
+
+Poller.EVENTS = EVENTS
+
+module.exports = Poller
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/unix-read.js b/input_devices/mag/node_modules/@serialport/bindings/lib/unix-read.js
new file mode 100644
index 00000000..af8958ad
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/unix-read.js
@@ -0,0 +1,56 @@
+const fs = require('fs')
+const debug = require('debug')
+const logger = debug('@serialport/bindings:unixRead')
+
+module.exports = function unixRead(buffer, offset, length) {
+  logger('Starting read')
+  if (!this.isOpen) {
+    return Promise.reject(new Error('Port is not open'))
+  }
+  return new Promise((resolve, reject) => {
+    fs.read(this.fd, buffer, offset, length, null, (err, bytesRead) => {
+      if (
+        err &&
+        (err.code === 'EAGAIN' ||
+          err.code === 'EWOULDBLOCK' ||
+          err.code === 'EINTR')
+      ) {
+        if (!this.isOpen) {
+          return reject(new Error('Port is not open'))
+        }
+        logger('waiting for readable because of code:', err.code)
+        this.poller.once('readable', err => {
+          if (err) {
+            return reject(err)
+          }
+          resolve(this.read(buffer, offset, length))
+        })
+        return
+      }
+
+      const disconnectError =
+        err &&
+        (err.code === 'EBADF' || // Bad file number means we got closed
+        err.code === 'ENXIO' || // No such device or address probably usb disconnect
+          err.code === 'UNKNOWN' ||
+          err.errno === -1) // generic error
+
+      if (disconnectError) {
+        err.disconnect = true
+        logger('disconnecting', err)
+      }
+
+      if (err) {
+        return reject(err)
+      }
+
+      if (bytesRead === 0) {
+        resolve(this.read(buffer, offset, length))
+        return
+      }
+
+      logger('Finished read', bytesRead, 'bytes')
+      resolve(bytesRead)
+    })
+  })
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/unix-write.js b/input_devices/mag/node_modules/@serialport/bindings/lib/unix-write.js
new file mode 100644
index 00000000..d00dbd36
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/unix-write.js
@@ -0,0 +1,70 @@
+const fs = require('fs')
+const debug = require('debug')
+const logger = debug('@serialport/bindings:unixWrite')
+
+module.exports = function unixWrite(buffer, offset) {
+  offset = offset || 0
+  const bytesToWrite = buffer.length - offset
+  logger(
+    'Starting write',
+    buffer.length,
+    'bytes offset',
+    offset,
+    'bytesToWrite',
+    bytesToWrite
+  )
+  if (!this.isOpen) {
+    return Promise.reject(new Error('Port is not open'))
+  }
+  return new Promise((resolve, reject) => {
+    fs.write(this.fd, buffer, offset, bytesToWrite, (err, bytesWritten) => {
+      logger('write returned', err, bytesWritten)
+      if (
+        err &&
+        (err.code === 'EAGAIN' ||
+          err.code === 'EWOULDBLOCK' ||
+          err.code === 'EINTR')
+      ) {
+        if (!this.isOpen) {
+          return reject(new Error('Port is not open'))
+        }
+        logger('waiting for writable because of code:', err.code)
+        this.poller.once('writable', err => {
+          if (err) {
+            return reject(err)
+          }
+          resolve(unixWrite.call(this, buffer, offset))
+        })
+        return
+      }
+
+      const disconnectError =
+        err &&
+        (err.code === 'EBADF' || // Bad file number means we got closed
+        err.code === 'ENXIO' || // No such device or address probably usb disconnect
+          err.code === 'UNKNOWN' ||
+          err.errno === -1) // generic error
+
+      if (disconnectError) {
+        err.disconnect = true
+        logger('disconnecting', err)
+      }
+
+      if (err) {
+        logger('error', err)
+        return reject(err)
+      }
+
+      logger('wrote', bytesWritten, 'bytes')
+      if (bytesWritten + offset < buffer.length) {
+        if (!this.isOpen) {
+          return reject(new Error('Port is not open'))
+        }
+        return resolve(unixWrite.call(this, buffer, bytesWritten + offset))
+      }
+
+      logger('Finished writing', bytesWritten + offset, 'bytes')
+      resolve()
+    })
+  })
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/util.js b/input_devices/mag/node_modules/@serialport/bindings/lib/util.js
new file mode 100644
index 00000000..04bea6f4
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/util.js
@@ -0,0 +1,20 @@
+function promisify(func) {
+  if (typeof func !== 'function') {
+    throw new Error('"func" must be a function')
+  }
+  return function(...args) {
+    return new Promise((resolve, reject) => {
+      args.push((err, data) => {
+        if (err) {
+          return reject(err)
+        }
+        resolve(data)
+      })
+      func(...args)
+    })
+  }
+}
+
+module.exports = {
+  promisify,
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/win32-sn-parser.js b/input_devices/mag/node_modules/@serialport/bindings/lib/win32-sn-parser.js
new file mode 100644
index 00000000..cf8c12b1
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/win32-sn-parser.js
@@ -0,0 +1,15 @@
+const PARSERS = [/USB\\(?:.+)\\(.+)/, /FTDIBUS\\(?:.+)\+(.+?)A?\\.+/]
+
+module.exports = function(pnpId) {
+  if (!pnpId) {
+    return null
+  }
+  for (let index = 0; index < PARSERS.length; index++) {
+    const parser = PARSERS[index]
+    const sn = pnpId.match(parser)
+    if (sn) {
+      return sn[1]
+    }
+  }
+  return null
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/lib/win32.js b/input_devices/mag/node_modules/@serialport/bindings/lib/win32.js
new file mode 100644
index 00000000..1001b8d6
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/lib/win32.js
@@ -0,0 +1,110 @@
+const binding = require('bindings')('bindings.node')
+const AbstractBinding = require('@serialport/binding-abstract')
+const promisify = require('./util').promisify
+const serialNumParser = require('./win32-sn-parser')
+
+/**
+ * The Windows binding layer
+ */
+class WindowsBinding extends AbstractBinding {
+  static list() {
+    return promisify(binding.list)().then(ports => {
+      // Grab the serial number from the pnp id
+      ports.forEach(port => {
+        if (port.pnpId && !port.serialNumber) {
+          const serialNumber = serialNumParser(port.pnpId)
+          if (serialNumber) {
+            port.serialNumber = serialNumber
+          }
+        }
+      })
+      return ports
+    })
+  }
+
+  constructor(opt) {
+    super(opt)
+    this.bindingOptions = Object.assign({}, opt.bindingOptions || {})
+    this.fd = null
+    this.writeOperation = null
+  }
+
+  get isOpen() {
+    return this.fd !== null
+  }
+
+  open(path, options) {
+    return super
+      .open(path, options)
+      .then(() => {
+        this.openOptions = Object.assign({}, this.bindingOptions, options)
+        return promisify(binding.open)(path, this.openOptions)
+      })
+      .then(fd => {
+        this.fd = fd
+      })
+  }
+
+  close() {
+    return super.close().then(() => {
+      const fd = this.fd
+      this.fd = null
+      return promisify(binding.close)(fd)
+    })
+  }
+
+  read(buffer, offset, length) {
+    return super
+      .read(buffer, offset, length)
+      .then(() => promisify(binding.read)(this.fd, buffer, offset, length))
+      .catch(err => {
+        if (!this.isOpen) {
+          err.canceled = true
+        }
+        throw err
+      })
+  }
+
+  write(buffer) {
+    this.writeOperation = super
+      .write(buffer)
+      .then(() => promisify(binding.write)(this.fd, buffer))
+      .then(() => {
+        this.writeOperation = null
+      })
+    return this.writeOperation
+  }
+
+  update(options) {
+    return super
+      .update(options)
+      .then(() => promisify(binding.update)(this.fd, options))
+  }
+
+  set(options) {
+    return super
+      .set(options)
+      .then(() => promisify(binding.set)(this.fd, options))
+  }
+
+  get() {
+    return super.get().then(() => promisify(binding.get)(this.fd))
+  }
+
+  getBaudRate() {
+    return super.get().then(() => promisify(binding.getBaudRate)(this.fd))
+  }
+
+  drain() {
+    return super
+      .drain()
+      .then(() => Promise.resolve(this.writeOperation))
+      .then(() => promisify(binding.drain)(this.fd))
+  }
+
+  flush() {
+    return super.flush().then(() => promisify(binding.flush)(this.fd))
+  }
+}
+
+module.exports = WindowsBinding
diff --git a/input_devices/mag/node_modules/@serialport/bindings/package.json b/input_devices/mag/node_modules/@serialport/bindings/package.json
new file mode 100644
index 00000000..65e887c1
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "@serialport/bindings@^2.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/bindings@>=2.0.2 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/bindings@2.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/bindings",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/bindings_2.0.2_1535514355119_0.9260097609171571"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/bindings",
+    "raw": "@serialport/bindings@^2.0.2",
+    "rawSpec": "^2.0.2",
+    "scope": "@serialport",
+    "spec": ">=2.0.2 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-2.0.2.tgz",
+  "_shasum": "64416a51043b1b0a4b7e4f25f8d5d8c93124e79b",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/bindings@^2.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "cc": {
+    "files": [
+      "src/*.cpp",
+      "src/*.h"
+    ],
+    "filter": [
+      "build/include",
+      "legal/copyright"
+    ],
+    "linelength": "120"
+  },
+  "dependencies": {
+    "@serialport/binding-abstract": "^2.0.1",
+    "@serialport/parser-readline": "^2.0.1",
+    "bindings": "^1.3.0",
+    "debug": "^3.1.0",
+    "nan": "^2.9.2",
+    "prebuild-install": "^5.1.0"
+  },
+  "description": "This package does some neat stuff.",
+  "devDependencies": {
+    "@serialport/binding-mock": "^2.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 30,
+    "integrity": "sha512-MrGma+SfOBUQWhjOAsCBjXExI2C5pCAFTQeGE43zpuZikHw1dZQ35kV4hVDPw2mSzsXBR14OuvDonEVrr9vysg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhbzCRA9TVsSAnZWagAAYx8QAJHZbZf3X/LPn2pYtU20\nYlougP1cW2C27TAZrhsmir9vqAdNMLyFO67KQtUKl8kHQZp91GwYNtSjs5c7\nVjXjrfJMNauTmKgw1fR7IcFm/ZufDXmUxWnWmmcWKQrrV+nsEpuwCl5WZv3U\nLP9kWpNhH8hjPaQQc/u/nu9fXis5MluQug++6Sl14UlWcN/Iw3u1cxojLBmj\n4cK1b/l1SrI5u4GN9w8Qcm8GWTfiAjmWIG+QL94T2oH0ikThu6MaYSVKD8WZ\nqt/e1COFXe+yNEcevvQc6jpZMesy8brMxmVX7Lg+L9F1Eu+RE3mMuifgtN0c\nZ1I5pK6iH4bl+9+0xB6TwvN3+0D6smYs4E9g/4pwkqTkd3VlTEQPSQqn1iN7\nTRA4zY1nAUjBYiXkn3nP/G1dQpAKpkui+49bzuLAKsaRq2ASp6rtGp5l3wi8\nrisNaaMe6XlrSVKkTleWjy6jrWctZGfgb24JjDbZlJ+fnpyHZJe406BAWrLF\nPLjHeYpPL0hFOIBeZh218eslLaW3RfcCDhKHO3QiEPKQ/qhaq325lkbNNsPy\nRa+GkKp+sF9ttYemlR/WfzE7KclbTMaXkmsu3wJTY2VFGCkoot8a+HYxiIr1\nGsTDSGE1LCmzG/yuMS1bD7QDITL7aQBN9+p/gOAzVsWjFW4bxzfdoy+JoMb4\nnoPH\r\n=bX5a\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "64416a51043b1b0a4b7e4f25f8d5d8c93124e79b",
+    "tarball": "https://registry.npmjs.org/@serialport/bindings/-/bindings-2.0.2.tgz",
+    "unpackedSize": 122027
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "4017f61620a845713f711576ba05bd47ae7601b6",
+  "gypfile": true,
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "lib",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/bindings",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "scripts": {
+    "install": "prebuild-install --tag-prefix @serialport/bindings@ || node-gyp rebuild",
+    "lint": "cc --verbose",
+    "prebuild": "prebuild --all --force --strip --verbose --tag-prefix @serialport/bindings@",
+    "rebuild": "node-gyp rebuild"
+  },
+  "version": "2.0.2"
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.cpp b/input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.cpp
new file mode 100644
index 00000000..5aeaadfd
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.cpp
@@ -0,0 +1,359 @@
+#include "./darwin_list.h"
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/serial/IOSerialKeys.h>
+
+#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
+#include <sys/ioctl.h>
+#include <IOKit/serial/ioss.h>
+#endif
+
+#include <string>
+#include <list>
+
+uv_mutex_t list_mutex;
+Boolean lockInitialised = FALSE;
+
+NAN_METHOD(List) {
+  // callback
+  if (!info[0]->IsFunction()) {
+    Nan::ThrowTypeError("First argument must be a function");
+    return;
+  }
+
+  ListBaton* baton = new ListBaton();
+  snprintf(baton->errorString, sizeof(baton->errorString), "");
+  baton->callback.Reset(info[0].As<v8::Function>());
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_List, (uv_after_work_cb)EIO_AfterList);
+}
+
+void setIfNotEmpty(v8::Local<v8::Object> item, std::string key, const char *value) {
+  v8::Local<v8::String> v8key = Nan::New<v8::String>(key).ToLocalChecked();
+  if (strlen(value) > 0) {
+    Nan::Set(item, v8key, Nan::New<v8::String>(value).ToLocalChecked());
+  } else {
+    Nan::Set(item, v8key, Nan::Undefined());
+  }
+}
+
+
+// Function prototypes
+static kern_return_t FindModems(io_iterator_t *matchingServices);
+static io_service_t GetUsbDevice(io_service_t service);
+static stDeviceListItem* GetSerialDevices();
+
+
+static kern_return_t FindModems(io_iterator_t *matchingServices) {
+    kern_return_t     kernResult;
+    CFMutableDictionaryRef  classesToMatch;
+    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
+    if (classesToMatch != NULL) {
+        CFDictionarySetValue(classesToMatch,
+                             CFSTR(kIOSerialBSDTypeKey),
+                             CFSTR(kIOSerialBSDAllTypes));
+    }
+
+    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
+
+    return kernResult;
+}
+
+static io_service_t GetUsbDevice(io_service_t service) {
+  IOReturn status;
+  io_iterator_t   iterator = 0;
+  io_service_t    device = 0;
+
+  if (!service) {
+    return device;
+  }
+
+  status = IORegistryEntryCreateIterator(service,
+                                         kIOServicePlane,
+                                         (kIORegistryIterateParents | kIORegistryIterateRecursively),
+                                         &iterator);
+
+  if (status == kIOReturnSuccess) {
+    io_service_t currentService;
+    while ((currentService = IOIteratorNext(iterator)) && device == 0) {
+      io_name_t serviceName;
+      status = IORegistryEntryGetNameInPlane(currentService, kIOServicePlane, serviceName);
+      if (status == kIOReturnSuccess && IOObjectConformsTo(currentService, kIOUSBDeviceClassName)) {
+        device = currentService;
+      } else {
+        // Release the service object which is no longer needed
+        (void) IOObjectRelease(currentService);
+      }
+    }
+
+    // Release the iterator
+    (void) IOObjectRelease(iterator);
+  }
+
+  return device;
+}
+
+static void ExtractUsbInformation(stSerialDevice *serialDevice, IOUSBDeviceInterface  **deviceInterface) {
+  kern_return_t kernResult;
+  UInt32 locationID;
+  kernResult = (*deviceInterface)->GetLocationID(deviceInterface, &locationID);
+  if (KERN_SUCCESS == kernResult) {
+    snprintf(serialDevice->locationId, sizeof(serialDevice->locationId), "%08x", locationID);
+  }
+
+  UInt16 vendorID;
+  kernResult = (*deviceInterface)->GetDeviceVendor(deviceInterface, &vendorID);
+  if (KERN_SUCCESS == kernResult) {
+    snprintf(serialDevice->vendorId, sizeof(serialDevice->vendorId), "%04x", vendorID);
+  }
+
+  UInt16 productID;
+  kernResult = (*deviceInterface)->GetDeviceProduct(deviceInterface, &productID);
+  if (KERN_SUCCESS == kernResult) {
+    snprintf(serialDevice->productId, sizeof(serialDevice->productId), "%04x", productID);
+  }
+}
+
+static stDeviceListItem* GetSerialDevices() {
+  char bsdPath[MAXPATHLEN];
+
+  io_iterator_t serialPortIterator;
+  FindModems(&serialPortIterator);
+
+  kern_return_t kernResult = KERN_FAILURE;
+  Boolean modemFound = false;
+
+  // Initialize the returned path
+  *bsdPath = '\0';
+
+  stDeviceListItem* devices = NULL;
+  stDeviceListItem* lastDevice = NULL;
+  int length = 0;
+
+  io_service_t modemService;
+  while ((modemService = IOIteratorNext(serialPortIterator))) {
+    CFTypeRef bsdPathAsCFString;
+    bsdPathAsCFString = IORegistryEntrySearchCFProperty(
+      modemService,
+      kIOServicePlane,
+      CFSTR(kIODialinDeviceKey),
+      kCFAllocatorDefault,
+      kIORegistryIterateRecursively);
+
+    if (bsdPathAsCFString) {
+      Boolean result;
+
+      // Convert the path from a CFString to a C (NUL-terminated)
+      result = CFStringGetCString((CFStringRef) bsdPathAsCFString,
+                    bsdPath,
+                    sizeof(bsdPath),
+                    kCFStringEncodingUTF8);
+      CFRelease(bsdPathAsCFString);
+
+      if (result) {
+        stDeviceListItem *deviceListItem = reinterpret_cast<stDeviceListItem*>( malloc(sizeof(stDeviceListItem)));
+        stSerialDevice *serialDevice = &(deviceListItem->value);
+        snprintf(serialDevice->port, sizeof(serialDevice->port), "%s", bsdPath);
+        memset(serialDevice->locationId, 0, sizeof(serialDevice->locationId));
+        memset(serialDevice->vendorId, 0, sizeof(serialDevice->vendorId));
+        memset(serialDevice->productId, 0, sizeof(serialDevice->productId));
+        serialDevice->manufacturer[0] = '\0';
+        serialDevice->serialNumber[0] = '\0';
+        deviceListItem->next = NULL;
+        deviceListItem->length = &length;
+
+        if (devices == NULL) {
+          devices = deviceListItem;
+        } else {
+          lastDevice->next = deviceListItem;
+        }
+
+        lastDevice = deviceListItem;
+        length++;
+
+        modemFound = true;
+        kernResult = KERN_SUCCESS;
+
+        uv_mutex_lock(&list_mutex);
+
+        io_service_t device = GetUsbDevice(modemService);
+
+        if (device) {
+          CFStringRef manufacturerAsCFString = (CFStringRef) IORegistryEntryCreateCFProperty(device,
+                      CFSTR(kUSBVendorString),
+                      kCFAllocatorDefault,
+                      0);
+
+          if (manufacturerAsCFString) {
+            Boolean result;
+            char    manufacturer[MAXPATHLEN];
+
+            // Convert from a CFString to a C (NUL-terminated)
+            result = CFStringGetCString(manufacturerAsCFString,
+                          manufacturer,
+                          sizeof(manufacturer),
+                          kCFStringEncodingUTF8);
+
+            if (result) {
+              snprintf(serialDevice->manufacturer, sizeof(serialDevice->manufacturer), "%s", manufacturer);
+            }
+
+            CFRelease(manufacturerAsCFString);
+          }
+
+          CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device,
+                      kIOServicePlane,
+                      CFSTR(kUSBSerialNumberString),
+                      kCFAllocatorDefault,
+                      kIORegistryIterateRecursively);
+
+          if (serialNumberAsCFString) {
+            Boolean result;
+            char    serialNumber[MAXPATHLEN];
+
+            // Convert from a CFString to a C (NUL-terminated)
+            result = CFStringGetCString(serialNumberAsCFString,
+                          serialNumber,
+                          sizeof(serialNumber),
+                          kCFStringEncodingUTF8);
+
+            if (result) {
+              snprintf(serialDevice->serialNumber, sizeof(serialDevice->serialNumber), "%s", serialNumber);
+            }
+
+            CFRelease(serialNumberAsCFString);
+          }
+
+          IOCFPlugInInterface **plugInInterface = NULL;
+          SInt32        score;
+          HRESULT       res;
+
+          IOUSBDeviceInterface  **deviceInterface = NULL;
+
+          kernResult = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
+                               &plugInInterface, &score);
+
+          if ((kIOReturnSuccess != kernResult) || !plugInInterface) {
+            continue;
+          }
+
+          // Use the plugin interface to retrieve the device interface.
+          res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
+                               reinterpret_cast<LPVOID*> (&deviceInterface));
+
+          // Now done with the plugin interface.
+          (*plugInInterface)->Release(plugInInterface);
+
+          if (res || deviceInterface == NULL) {
+            continue;
+          }
+
+          // Extract the desired Information
+          ExtractUsbInformation(serialDevice, deviceInterface);
+
+          // Release the Interface
+          (*deviceInterface)->Release(deviceInterface);
+
+          // Release the device
+          (void) IOObjectRelease(device);
+        }
+
+        uv_mutex_unlock(&list_mutex);
+      }
+    }
+
+    // Release the io_service_t now that we are done with it.
+    (void) IOObjectRelease(modemService);
+  }
+
+  IOObjectRelease(serialPortIterator);  // Release the iterator.
+
+  return devices;
+}
+
+void EIO_List(uv_work_t* req) {
+  ListBaton* data = static_cast<ListBaton*>(req->data);
+
+  if (!lockInitialised) {
+    uv_mutex_init(&list_mutex);
+    lockInitialised = TRUE;
+  }
+
+  stDeviceListItem* devices = GetSerialDevices();
+  if (devices != NULL && *(devices->length) > 0) {
+    stDeviceListItem* next = devices;
+
+    for (int i = 0, len = *(devices->length); i < len; i++) {
+      stSerialDevice device = (* next).value;
+
+      ListResultItem* resultItem = new ListResultItem();
+      resultItem->comName = device.port;
+
+      if (*device.locationId) {
+        resultItem->locationId = device.locationId;
+      }
+      if (*device.vendorId) {
+        resultItem->vendorId = device.vendorId;
+      }
+      if (*device.productId) {
+        resultItem->productId = device.productId;
+      }
+      if (*device.manufacturer) {
+        resultItem->manufacturer = device.manufacturer;
+      }
+      if (*device.serialNumber) {
+        resultItem->serialNumber = device.serialNumber;
+      }
+      data->results.push_back(resultItem);
+
+      stDeviceListItem* current = next;
+
+      if (next->next != NULL) {
+        next = next->next;
+      }
+
+      free(current);
+    }
+  }
+}
+
+void EIO_AfterList(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  ListBaton* data = static_cast<ListBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[2];
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+    argv[1] = Nan::Undefined();
+  } else {
+    v8::Local<v8::Array> results = Nan::New<v8::Array>();
+    int i = 0;
+    for (std::list<ListResultItem*>::iterator it = data->results.begin(); it != data->results.end(); ++it, i++) {
+      v8::Local<v8::Object> item = Nan::New<v8::Object>();
+
+      setIfNotEmpty(item, "comName", (*it)->comName.c_str());
+      setIfNotEmpty(item, "manufacturer", (*it)->manufacturer.c_str());
+      setIfNotEmpty(item, "serialNumber", (*it)->serialNumber.c_str());
+      setIfNotEmpty(item, "pnpId", (*it)->pnpId.c_str());
+      setIfNotEmpty(item, "locationId", (*it)->locationId.c_str());
+      setIfNotEmpty(item, "vendorId", (*it)->vendorId.c_str());
+      setIfNotEmpty(item, "productId", (*it)->productId.c_str());
+
+      Nan::Set(results, i, item);
+    }
+    argv[0] = Nan::Null();
+    argv[1] = results;
+  }
+  data->callback.Call(2, argv);
+
+  for (std::list<ListResultItem*>::iterator it = data->results.begin(); it != data->results.end(); ++it) {
+    delete *it;
+  }
+  delete data;
+  delete req;
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.h b/input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.h
new file mode 100644
index 00000000..d1514b48
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/darwin_list.h
@@ -0,0 +1,45 @@
+#ifndef PACKAGES_SERIALPORT_SRC_DARWIN_LIST_H_
+#define PACKAGES_SERIALPORT_SRC_DARWIN_LIST_H_
+#include <sys/param.h>  // For MAXPATHLEN
+#include <nan.h>
+#include <list>
+#include <string>
+
+#define ERROR_STRING_SIZE 1024
+
+NAN_METHOD(List);
+void EIO_List(uv_work_t* req);
+void EIO_AfterList(uv_work_t* req);
+
+struct ListResultItem {
+  std::string comName;
+  std::string manufacturer;
+  std::string serialNumber;
+  std::string pnpId;
+  std::string locationId;
+  std::string vendorId;
+  std::string productId;
+};
+
+struct ListBaton {
+  Nan::Callback callback;
+  std::list<ListResultItem*> results;
+  char errorString[ERROR_STRING_SIZE];
+};
+
+typedef struct SerialDevice {
+    char port[MAXPATHLEN];
+    char locationId[MAXPATHLEN];
+    char vendorId[MAXPATHLEN];
+    char productId[MAXPATHLEN];
+    char manufacturer[MAXPATHLEN];
+    char serialNumber[MAXPATHLEN];
+} stSerialDevice;
+
+typedef struct DeviceListItem {
+    struct SerialDevice value;
+    struct DeviceListItem *next;
+    int* length;
+} stDeviceListItem;
+
+#endif  // PACKAGES_SERIALPORT_SRC_DARWIN_LIST_H_
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/poller.cpp b/input_devices/mag/node_modules/@serialport/bindings/src/poller.cpp
new file mode 100644
index 00000000..68f83add
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/poller.cpp
@@ -0,0 +1,135 @@
+#include <nan.h>
+#include "./poller.h"
+
+Poller::Poller(int fd) {
+  Nan::HandleScope scope;
+  this->fd = fd;
+  this->poll_handle = new uv_poll_t();
+  memset(this->poll_handle, 0, sizeof(uv_poll_t));
+  poll_handle->data = this;
+  int status = uv_poll_init(uv_default_loop(), poll_handle, fd);
+  if (0 != status) {
+    Nan::ThrowError(uv_strerror(status));
+    return;
+  }
+  uv_poll_init_success = true;
+}
+
+Poller::~Poller() {
+  // if we call uv_poll_stop after uv_poll_init failed we segfault
+  if (uv_poll_init_success) {
+    uv_poll_stop(poll_handle);
+    uv_close(reinterpret_cast<uv_handle_t*> (poll_handle), Poller::onClose);
+  } else {
+    delete poll_handle;
+  }
+}
+
+void Poller::onClose(uv_handle_t* poll_handle) {
+  // fprintf(stdout, "~Poller is closed\n");
+  delete poll_handle;
+}
+
+// Events can be UV_READABLE | UV_WRITABLE | UV_DISCONNECT
+void Poller::poll(int events) {
+  // fprintf(stdout, "Poller:poll for %d\n", events);
+  this->events = this->events | events;
+  int status = uv_poll_start(poll_handle, events, Poller::onData);
+  if (0 != status) {
+    Nan::ThrowTypeError(uv_strerror(status));
+    return;
+  }
+}
+
+void Poller::stop() {
+  int status = uv_poll_stop(poll_handle);
+  if (0 != status) {
+    Nan::ThrowTypeError(uv_strerror(status));
+    return;
+  }
+}
+
+void Poller::onData(uv_poll_t* handle, int status, int events) {
+  Nan::HandleScope scope;
+  Poller* obj = static_cast<Poller*>(handle->data);
+  v8::Local<v8::Value> argv[2];
+  if (0 != status) {
+    // fprintf(stdout, "OnData Error status=%s events=%d\n", uv_strerror(status), events);
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(uv_strerror(status)).ToLocalChecked());
+    argv[1] = Nan::Undefined();
+  } else {
+    // fprintf(stdout, "OnData status=%d events=%d\n", status, events);
+    argv[0] = Nan::Null();
+    argv[1] = Nan::New<v8::Integer>(events);
+  }
+  // remove triggered events from the poll
+  int newEvents = obj->events & ~events;
+  obj->poll(newEvents);
+
+  obj->callback.Call(2, argv);
+}
+
+NAN_MODULE_INIT(Poller::Init) {
+  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
+  tpl->SetClassName(Nan::New("Poller").ToLocalChecked());
+  tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+  Nan::SetPrototypeMethod(tpl, "poll", poll);
+  Nan::SetPrototypeMethod(tpl, "stop", stop);
+  Nan::SetPrototypeMethod(tpl, "destroy", destroy);
+
+  constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
+  Nan::Set(target, Nan::New("Poller").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());
+}
+
+NAN_METHOD(Poller::New) {
+  if (!info.IsConstructCall()) {
+    const int argc = 2;
+    v8::Local<v8::Value> argv[argc] = {info[0], info[1]};
+    v8::Local<v8::Function> cons = Nan::New(constructor());
+    info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
+    return;
+  }
+
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("fd must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  if (!info[1]->IsFunction()) {
+    Nan::ThrowTypeError("cb must be a function");
+    return;
+  }
+
+  Poller *obj = new Poller(fd);
+  obj->callback.Reset(info[1].As<v8::Function>());
+  obj->Wrap(info.This());
+  info.GetReturnValue().Set(info.This());
+}
+
+NAN_METHOD(Poller::poll) {
+  Poller* obj = Nan::ObjectWrap::Unwrap<Poller>(info.Holder());
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("events must be an int");
+    return;
+  }
+  int events = Nan::To<int>(info[0]).FromJust();
+  obj->poll(events);
+}
+
+NAN_METHOD(Poller::stop) {
+  Poller* obj = Nan::ObjectWrap::Unwrap<Poller>(info.Holder());
+  obj->stop();
+}
+
+NAN_METHOD(Poller::destroy) {
+  Poller* obj = Nan::ObjectWrap::Unwrap<Poller>(info.Holder());
+  obj->persistent().Reset();
+  delete obj;
+}
+
+inline Nan::Persistent<v8::Function> & Poller::constructor() {
+  static Nan::Persistent<v8::Function> my_constructor;
+  return my_constructor;
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/poller.h b/input_devices/mag/node_modules/@serialport/bindings/src/poller.h
new file mode 100644
index 00000000..1bcaf63e
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/poller.h
@@ -0,0 +1,33 @@
+#ifndef PACKAGES_SERIALPORT_SRC_POLLER_H_
+#define PACKAGES_SERIALPORT_SRC_POLLER_H_
+
+#include <nan.h>
+
+class Poller : public Nan::ObjectWrap {
+ public:
+  static NAN_MODULE_INIT(Init);
+  static void onData(uv_poll_t* handle, int status, int events);
+  static void onClose(uv_handle_t* poll_handle);
+
+ private:
+  int fd;
+  uv_poll_t* poll_handle;
+  Nan::Callback callback;
+  bool uv_poll_init_success = false;
+
+  // can this be read off of poll_handle?
+  int events = 0;
+
+  explicit Poller(int fd);
+  ~Poller();
+  void poll(int events);
+  void stop();
+
+  static NAN_METHOD(New);
+  static NAN_METHOD(poll);
+  static NAN_METHOD(stop);
+  static NAN_METHOD(destroy);
+  static inline Nan::Persistent<v8::Function> & constructor();
+};
+
+#endif  // PACKAGES_SERIALPORT_SRC_POLLER_H_
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport.cpp b/input_devices/mag/node_modules/@serialport/bindings/src/serialport.cpp
new file mode 100644
index 00000000..d6c7ddcb
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport.cpp
@@ -0,0 +1,485 @@
+#include "./serialport.h"
+
+#ifdef __APPLE__
+  #include "./darwin_list.h"
+#endif
+
+#ifdef WIN32
+  #define strncasecmp strnicmp
+  #include "./serialport_win.h"
+#else
+  #include "./poller.h"
+#endif
+
+v8::Local<v8::Value> getValueFromObject(v8::Local<v8::Object> options, std::string key) {
+  v8::Local<v8::String> v8str = Nan::New<v8::String>(key).ToLocalChecked();
+  return Nan::Get(options, v8str).ToLocalChecked();
+}
+
+int getIntFromObject(v8::Local<v8::Object> options, std::string key) {
+  return Nan::To<v8::Int32>(getValueFromObject(options, key)).ToLocalChecked()->Value();
+}
+
+bool getBoolFromObject(v8::Local<v8::Object> options, std::string key) {
+  return Nan::To<v8::Boolean>(getValueFromObject(options, key)).ToLocalChecked()->Value();
+}
+
+v8::Local<v8::String> getStringFromObj(v8::Local<v8::Object> options, std::string key) {
+  return Nan::To<v8::String>(getValueFromObject(options, key)).ToLocalChecked();
+}
+
+double getDoubleFromObject(v8::Local<v8::Object> options, std::string key) {
+  return Nan::To<double>(getValueFromObject(options, key)).FromMaybe(0);
+}
+
+NAN_METHOD(Open) {
+  // path
+  if (!info[0]->IsString()) {
+    Nan::ThrowTypeError("First argument must be a string");
+    return;
+  }
+  v8::String::Utf8Value path(info[0]->ToString());
+
+  // options
+  if (!info[1]->IsObject()) {
+    Nan::ThrowTypeError("Second argument must be an object");
+    return;
+  }
+  v8::Local<v8::Object> options = info[1]->ToObject();
+
+  // callback
+  if (!info[2]->IsFunction()) {
+    Nan::ThrowTypeError("Third argument must be a function");
+    return;
+  }
+
+  OpenBaton* baton = new OpenBaton();
+  snprintf(baton->path, sizeof(baton->path), "%s", *path);
+  baton->baudRate = getIntFromObject(options, "baudRate");
+  baton->dataBits = getIntFromObject(options, "dataBits");
+  baton->parity = ToParityEnum(getStringFromObj(options, "parity"));
+  baton->stopBits = ToStopBitEnum(getDoubleFromObject(options, "stopBits"));
+  baton->rtscts = getBoolFromObject(options, "rtscts");
+  baton->xon = getBoolFromObject(options, "xon");
+  baton->xoff = getBoolFromObject(options, "xoff");
+  baton->xany = getBoolFromObject(options, "xany");
+  baton->hupcl = getBoolFromObject(options, "hupcl");
+  baton->lock = getBoolFromObject(options, "lock");
+  baton->callback.Reset(info[2].As<v8::Function>());
+
+  #ifndef WIN32
+    baton->vmin = getIntFromObject(options, "vmin");
+    baton->vtime = getIntFromObject(options, "vtime");
+  #endif
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+
+  uv_queue_work(uv_default_loop(), req, EIO_Open, (uv_after_work_cb)EIO_AfterOpen);
+}
+
+void EIO_AfterOpen(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  OpenBaton* data = static_cast<OpenBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[2];
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+    argv[1] = Nan::Undefined();
+  } else {
+    argv[0] = Nan::Null();
+    argv[1] = Nan::New<v8::Int32>(data->result);
+  }
+
+  data->callback.Call(2, argv);
+  delete data;
+  delete req;
+}
+
+NAN_METHOD(Update) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // options
+  if (!info[1]->IsObject()) {
+    Nan::ThrowTypeError("Second argument must be an object");
+    return;
+  }
+  v8::Local<v8::Object> options = info[1]->ToObject();
+
+  if (!Nan::Has(options, Nan::New<v8::String>("baudRate").ToLocalChecked()).FromMaybe(false)) {
+    Nan::ThrowTypeError("\"baudRate\" must be set on options object");
+    return;
+  }
+
+  // callback
+  if (!info[2]->IsFunction()) {
+    Nan::ThrowTypeError("Third argument must be a function");
+    return;
+  }
+
+  ConnectionOptionsBaton* baton = new ConnectionOptionsBaton();
+
+  baton->fd = fd;
+  baton->baudRate = getIntFromObject(options, "baudRate");
+  baton->callback.Reset(info[2].As<v8::Function>());
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+
+  uv_queue_work(uv_default_loop(), req, EIO_Update, (uv_after_work_cb)EIO_AfterUpdate);
+}
+
+void EIO_AfterUpdate(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  ConnectionOptionsBaton* data = static_cast<ConnectionOptionsBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[1];
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+  } else {
+    argv[0] = Nan::Null();
+  }
+
+  data->callback.Call(1, argv);
+
+  delete data;
+  delete req;
+}
+
+NAN_METHOD(Close) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+
+  // callback
+  if (!info[1]->IsFunction()) {
+    Nan::ThrowTypeError("Second argument must be a function");
+    return;
+  }
+
+  VoidBaton* baton = new VoidBaton();
+  baton->fd = Nan::To<v8::Int32>(info[0]).ToLocalChecked()->Value();
+  baton->callback.Reset(info[1].As<v8::Function>());
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_Close, (uv_after_work_cb)EIO_AfterClose);
+}
+
+void EIO_AfterClose(uv_work_t* req) {
+  Nan::HandleScope scope;
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[1];
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+  } else {
+    argv[0] = Nan::Null();
+  }
+  data->callback.Call(1, argv);
+
+  delete data;
+  delete req;
+}
+
+NAN_METHOD(Flush) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // callback
+  if (!info[1]->IsFunction()) {
+    Nan::ThrowTypeError("Second argument must be a function");
+    return;
+  }
+  v8::Local<v8::Function> callback = info[1].As<v8::Function>();
+
+  VoidBaton* baton = new VoidBaton();
+  baton->fd = fd;
+  baton->callback.Reset(callback);
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_Flush, (uv_after_work_cb)EIO_AfterFlush);
+}
+
+void EIO_AfterFlush(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[1];
+
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+  } else {
+    argv[0] = Nan::Null();
+  }
+
+  data->callback.Call(1, argv);
+
+  delete data;
+  delete req;
+}
+
+NAN_METHOD(Set) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // options
+  if (!info[1]->IsObject()) {
+    Nan::ThrowTypeError("Second argument must be an object");
+    return;
+  }
+  v8::Local<v8::Object> options = info[1]->ToObject();
+
+  // callback
+  if (!info[2]->IsFunction()) {
+    Nan::ThrowTypeError("Third argument must be a function");
+    return;
+  }
+  v8::Local<v8::Function> callback = info[2].As<v8::Function>();
+
+  SetBaton* baton = new SetBaton();
+  baton->fd = fd;
+  baton->callback.Reset(callback);
+  baton->brk = getBoolFromObject(options, "brk");
+  baton->rts = getBoolFromObject(options, "rts");
+  baton->cts = getBoolFromObject(options, "cts");
+  baton->dtr = getBoolFromObject(options, "dtr");
+  baton->dsr = getBoolFromObject(options, "dsr");
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_Set, (uv_after_work_cb)EIO_AfterSet);
+}
+
+void EIO_AfterSet(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  SetBaton* data = static_cast<SetBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[1];
+
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+  } else {
+    argv[0] = Nan::Null();
+  }
+  data->callback.Call(1, argv);
+
+  delete data;
+  delete req;
+}
+
+NAN_METHOD(Get) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // callback
+  if (!info[1]->IsFunction()) {
+    Nan::ThrowTypeError("Second argument must be a function");
+    return;
+  }
+
+  GetBaton* baton = new GetBaton();
+  baton->fd = fd;
+  baton->cts = false;
+  baton->dsr = false;
+  baton->dcd = false;
+  baton->callback.Reset(info[1].As<v8::Function>());
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_Get, (uv_after_work_cb)EIO_AfterGet);
+}
+
+void EIO_AfterGet(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  GetBaton* data = static_cast<GetBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[2];
+
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+    argv[1] = Nan::Undefined();
+  } else {
+    v8::Local<v8::Object> results = Nan::New<v8::Object>();
+    results->Set(Nan::New<v8::String>("cts").ToLocalChecked(), Nan::New<v8::Boolean>(data->cts));
+    results->Set(Nan::New<v8::String>("dsr").ToLocalChecked(), Nan::New<v8::Boolean>(data->dsr));
+    results->Set(Nan::New<v8::String>("dcd").ToLocalChecked(), Nan::New<v8::Boolean>(data->dcd));
+
+    argv[0] = Nan::Null();
+    argv[1] = results;
+  }
+  data->callback.Call(2, argv);
+
+  delete data;
+  delete req;
+}
+
+NAN_METHOD(GetBaudRate) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // callback
+  if (!info[1]->IsFunction()) {
+    Nan::ThrowTypeError("Second argument must be a function");
+    return;
+  }
+
+  GetBaudRateBaton* baton = new GetBaudRateBaton();
+  baton->fd = fd;
+  baton->baudRate = 0;
+  baton->callback.Reset(info[1].As<v8::Function>());
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_GetBaudRate, (uv_after_work_cb)EIO_AfterGetBaudRate);
+}
+
+void EIO_AfterGetBaudRate(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  GetBaudRateBaton* data = static_cast<GetBaudRateBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[2];
+
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+    argv[1] = Nan::Undefined();
+  } else {
+    v8::Local<v8::Object> results = Nan::New<v8::Object>();
+    results->Set(Nan::New<v8::String>("baudRate").ToLocalChecked(), Nan::New<v8::Integer>(data->baudRate));
+
+    argv[0] = Nan::Null();
+    argv[1] = results;
+  }
+  data->callback.Call(2, argv);
+
+  delete data;
+  delete req;
+}
+
+NAN_METHOD(Drain) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // callback
+  if (!info[1]->IsFunction()) {
+    Nan::ThrowTypeError("Second argument must be a function");
+    return;
+  }
+
+  VoidBaton* baton = new VoidBaton();
+  baton->fd = fd;
+  baton->callback.Reset(info[1].As<v8::Function>());
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_Drain, (uv_after_work_cb)EIO_AfterDrain);
+}
+
+void EIO_AfterDrain(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[1];
+
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+  } else {
+    argv[0] = Nan::Null();
+  }
+  data->callback.Call(1, argv);
+
+  delete data;
+  delete req;
+}
+
+SerialPortParity NAN_INLINE(ToParityEnum(const v8::Local<v8::String>& v8str)) {
+  Nan::HandleScope scope;
+  Nan::Utf8String str(v8str);
+  size_t count = strlen(*str);
+  SerialPortParity parity = SERIALPORT_PARITY_NONE;
+  if (!strncasecmp(*str, "none", count)) {
+    parity = SERIALPORT_PARITY_NONE;
+  } else if (!strncasecmp(*str, "even", count)) {
+    parity = SERIALPORT_PARITY_EVEN;
+  } else if (!strncasecmp(*str, "mark", count)) {
+    parity = SERIALPORT_PARITY_MARK;
+  } else if (!strncasecmp(*str, "odd", count)) {
+    parity = SERIALPORT_PARITY_ODD;
+  } else if (!strncasecmp(*str, "space", count)) {
+    parity = SERIALPORT_PARITY_SPACE;
+  }
+  return parity;
+}
+
+SerialPortStopBits NAN_INLINE(ToStopBitEnum(double stopBits)) {
+  if (stopBits > 1.4 && stopBits < 1.6) {
+    return SERIALPORT_STOPBITS_ONE_FIVE;
+  }
+  if (stopBits == 2) {
+    return SERIALPORT_STOPBITS_TWO;
+  }
+  return SERIALPORT_STOPBITS_ONE;
+}
+
+extern "C" {
+  void init(v8::Handle<v8::Object> target) {
+    Nan::HandleScope scope;
+    Nan::SetMethod(target, "set", Set);
+    Nan::SetMethod(target, "get", Get);
+    Nan::SetMethod(target, "getBaudRate", GetBaudRate);
+    Nan::SetMethod(target, "open", Open);
+    Nan::SetMethod(target, "update", Update);
+    Nan::SetMethod(target, "close", Close);
+    Nan::SetMethod(target, "flush", Flush);
+    Nan::SetMethod(target, "drain", Drain);
+
+    #ifdef __APPLE__
+    Nan::SetMethod(target, "list", List);
+    #endif
+
+    #ifdef WIN32
+    Nan::SetMethod(target, "write", Write);
+    Nan::SetMethod(target, "read", Read);
+    Nan::SetMethod(target, "list", List);
+    #else
+    Poller::Init(target);
+    #endif
+  }
+}
+
+NODE_MODULE(serialport, init);
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport.h b/input_devices/mag/node_modules/@serialport/bindings/src/serialport.h
new file mode 100644
index 00000000..e25d29c4
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport.h
@@ -0,0 +1,126 @@
+#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_H_
+#define PACKAGES_SERIALPORT_SRC_SERIALPORT_H_
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <nan.h>
+#include <string>
+
+#define ERROR_STRING_SIZE 1024
+
+NAN_METHOD(Open);
+void EIO_Open(uv_work_t* req);
+void EIO_AfterOpen(uv_work_t* req);
+
+NAN_METHOD(Update);
+void EIO_Update(uv_work_t* req);
+void EIO_AfterUpdate(uv_work_t* req);
+
+NAN_METHOD(Close);
+void EIO_Close(uv_work_t* req);
+void EIO_AfterClose(uv_work_t* req);
+
+NAN_METHOD(Flush);
+void EIO_Flush(uv_work_t* req);
+void EIO_AfterFlush(uv_work_t* req);
+
+NAN_METHOD(Set);
+void EIO_Set(uv_work_t* req);
+void EIO_AfterSet(uv_work_t* req);
+
+NAN_METHOD(Get);
+void EIO_Get(uv_work_t* req);
+void EIO_AfterGet(uv_work_t* req);
+
+NAN_METHOD(GetBaudRate);
+void EIO_GetBaudRate(uv_work_t* req);
+void EIO_AfterGetBaudRate(uv_work_t* req);
+
+NAN_METHOD(Drain);
+void EIO_Drain(uv_work_t* req);
+void EIO_AfterDrain(uv_work_t* req);
+
+enum SerialPortParity {
+  SERIALPORT_PARITY_NONE  = 1,
+  SERIALPORT_PARITY_MARK  = 2,
+  SERIALPORT_PARITY_EVEN  = 3,
+  SERIALPORT_PARITY_ODD   = 4,
+  SERIALPORT_PARITY_SPACE = 5
+};
+
+enum SerialPortStopBits {
+  SERIALPORT_STOPBITS_ONE      = 1,
+  SERIALPORT_STOPBITS_ONE_FIVE = 2,
+  SERIALPORT_STOPBITS_TWO      = 3
+};
+
+SerialPortParity ToParityEnum(const v8::Local<v8::String>& str);
+SerialPortStopBits ToStopBitEnum(double stopBits);
+
+struct OpenBaton {
+  char errorString[ERROR_STRING_SIZE];
+  Nan::Callback callback;
+  char path[1024];
+  int fd;
+  int result;
+  int baudRate;
+  int dataBits;
+  bool rtscts;
+  bool xon;
+  bool xoff;
+  bool xany;
+  bool dsrdtr;
+  bool hupcl;
+  bool lock;
+  SerialPortParity parity;
+  SerialPortStopBits stopBits;
+#ifndef WIN32
+  uint8_t vmin;
+  uint8_t vtime;
+#endif
+};
+
+struct ConnectionOptionsBaton {
+  char errorString[ERROR_STRING_SIZE];
+  Nan::Callback callback;
+  int fd;
+  int baudRate;
+};
+
+struct SetBaton {
+  int fd;
+  Nan::Callback callback;
+  int result;
+  char errorString[ERROR_STRING_SIZE];
+  bool rts;
+  bool cts;
+  bool dtr;
+  bool dsr;
+  bool brk;
+};
+
+struct GetBaton {
+  int fd;
+  Nan::Callback callback;
+  char errorString[ERROR_STRING_SIZE];
+  bool cts;
+  bool dsr;
+  bool dcd;
+};
+
+struct GetBaudRateBaton {
+  int fd;
+  Nan::Callback callback;
+  char errorString[ERROR_STRING_SIZE];
+  int baudRate;
+};
+
+struct VoidBaton {
+  int fd;
+  Nan::Callback callback;
+  char errorString[ERROR_STRING_SIZE];
+};
+
+int setup(int fd, OpenBaton *data);
+int setBaudRate(ConnectionOptionsBaton *data);
+#endif  // PACKAGES_SERIALPORT_SRC_SERIALPORT_H_
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.cpp b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.cpp
new file mode 100755
index 00000000..c87f6a5b
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.cpp
@@ -0,0 +1,39 @@
+#if defined(__linux__)
+
+#include <sys/ioctl.h>
+#include <asm/ioctls.h>
+#include <asm/termbits.h>
+
+// Uses the termios2 interface to set nonstandard baud rates
+int linuxSetCustomBaudRate(const int fd, const unsigned int baudrate) {
+    struct termios2 t;
+
+    if (ioctl(fd, TCGETS2, &t)) {
+      return -1;
+    }
+
+    t.c_cflag &= ~CBAUD;
+    t.c_cflag |= BOTHER;
+    t.c_ospeed = t.c_ispeed = baudrate;
+
+    if (ioctl(fd, TCSETS2, &t)) {
+      return -2;
+    }
+
+    return 0;
+}
+
+// Uses termios2 interface to retrieve system reported baud rate
+int linuxGetSystemBaudRate(const int fd, int* const outbaud) {
+  struct termios2 t;
+
+  if (ioctl(fd, TCGETS2, &t)) {
+    return -1;
+  }
+
+  *outbaud = static_cast<int>(t.c_ospeed);
+
+  return 0;
+}
+
+#endif
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.h b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.h
new file mode 100755
index 00000000..dc38b068
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_linux.h
@@ -0,0 +1,8 @@
+#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_LINUX_H_
+#define PACKAGES_SERIALPORT_SRC_SERIALPORT_LINUX_H_
+
+int linuxSetCustomBaudRate(const int fd, const unsigned int baudrate);
+int linuxGetSystemBaudRate(const int fd, int* const outbaud);
+
+#endif  // PACKAGES_SERIALPORT_SRC_SERIALPORT_LINUX_H_
+
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.cpp b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.cpp
new file mode 100644
index 00000000..b8979959
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.cpp
@@ -0,0 +1,403 @@
+#include "serialport_unix.h"
+#include "serialport.h"
+
+#include <sys/file.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+
+#ifdef __APPLE__
+#include <AvailabilityMacros.h>
+#include <sys/param.h>
+#endif
+
+#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
+#include <sys/ioctl.h>
+#include <IOKit/serial/ioss.h>
+
+#elif defined(__OpenBSD__)
+#include <sys/ioctl.h>
+
+#elif defined(__linux__)
+#include <sys/ioctl.h>
+#include <linux/serial.h>
+#include "serialport_linux.h"
+#endif
+
+int ToStopBitsConstant(SerialPortStopBits stopBits);
+
+int ToBaudConstant(int baudRate) {
+  switch (baudRate) {
+    case 0: return B0;
+    case 50: return B50;
+    case 75: return B75;
+    case 110: return B110;
+    case 134: return B134;
+    case 150: return B150;
+    case 200: return B200;
+    case 300: return B300;
+    case 600: return B600;
+    case 1200: return B1200;
+    case 1800: return B1800;
+    case 2400: return B2400;
+    case 4800: return B4800;
+    case 9600: return B9600;
+    case 19200: return B19200;
+    case 38400: return B38400;
+    case 57600: return B57600;
+    case 115200: return B115200;
+    case 230400: return B230400;
+#if defined(__linux__)
+    case 460800: return B460800;
+    case 500000: return B500000;
+    case 576000: return B576000;
+    case 921600: return B921600;
+    case 1000000: return B1000000;
+    case 1152000: return B1152000;
+    case 1500000: return B1500000;
+    case 2000000: return B2000000;
+    case 2500000: return B2500000;
+    case 3000000: return B3000000;
+    case 3500000: return B3500000;
+    case 4000000: return B4000000;
+#endif
+  }
+  return -1;
+}
+
+int ToDataBitsConstant(int dataBits) {
+  switch (dataBits) {
+    case 8: default: return CS8;
+    case 7: return CS7;
+    case 6: return CS6;
+    case 5: return CS5;
+  }
+  return -1;
+}
+
+void EIO_Open(uv_work_t* req) {
+  OpenBaton* data = static_cast<OpenBaton*>(req->data);
+
+  int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC | O_SYNC);
+  int fd = open(data->path, flags);
+
+  if (-1 == fd) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot open %s", strerror(errno), data->path);
+    return;
+  }
+
+  if (-1 == setup(fd, data)) {
+    close(fd);
+    return;
+  }
+
+  data->result = fd;
+}
+
+int setBaudRate(ConnectionOptionsBaton *data) {
+  // lookup the standard baudrates from the table
+  int baudRate = ToBaudConstant(data->baudRate);
+  int fd = data->fd;
+
+  // get port options
+  struct termios options;
+  if (-1 == tcgetattr(fd, &options)) {
+    snprintf(data->errorString, sizeof(data->errorString),
+             "Error: %s setting custom baud rate of %d", strerror(errno), data->baudRate);
+    return -1;
+  }
+
+  // If there is a custom baud rate on linux you can do the following trick with B38400
+  #if defined(__linux__) && defined(ASYNC_SPD_CUST)
+    if (baudRate == -1) {
+      int err = linuxSetCustomBaudRate(fd, data->baudRate);
+
+      if (err == -1) {
+        snprintf(data->errorString, sizeof(data->errorString),
+                 "Error: %s || while retrieving termios2 info", strerror(errno));
+        return -1;
+      } else if (err == -2) {
+        snprintf(data->errorString, sizeof(data->errorString),
+                 "Error: %s || while setting custom baud rate of %d", strerror(errno), data->baudRate);
+        return -1;
+      }
+
+      return 1;
+    }
+  #endif
+
+  // On OS X, starting with Tiger, we can set a custom baud rate with ioctl
+  #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
+    if (-1 == baudRate) {
+      speed_t speed = data->baudRate;
+      if (-1 == ioctl(fd, IOSSIOSPEED, &speed)) {
+        snprintf(data->errorString, sizeof(data->errorString),
+                 "Error: %s calling ioctl(.., IOSSIOSPEED, %ld )", strerror(errno), speed);
+        return -1;
+      } else {
+        tcflush(fd, TCIOFLUSH);
+        return 1;
+      }
+    }
+  #endif
+
+  if (-1 == baudRate) {
+    snprintf(data->errorString, sizeof(data->errorString),
+             "Error baud rate of %d is not supported on your platform", data->baudRate);
+    return -1;
+  }
+
+  // If we have a good baud rate set it and lets go
+  cfsetospeed(&options, baudRate);
+  cfsetispeed(&options, baudRate);
+  // throw away all the buffered data
+  tcflush(fd, TCIOFLUSH);
+  // make the changes now
+  tcsetattr(fd, TCSANOW, &options);
+  return 1;
+}
+
+void EIO_Update(uv_work_t* req) {
+  ConnectionOptionsBaton* data = static_cast<ConnectionOptionsBaton*>(req->data);
+  setBaudRate(data);
+}
+
+int setup(int fd, OpenBaton *data) {
+  int dataBits = ToDataBitsConstant(data->dataBits);
+  if (-1 == dataBits) {
+    snprintf(data->errorString, sizeof(data->errorString),
+             "Invalid data bits setting %d", data->dataBits);
+    return -1;
+  }
+
+  // Snow Leopard doesn't have O_CLOEXEC
+  if (-1 == fcntl(fd, F_SETFD, FD_CLOEXEC)) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot open %s", strerror(errno), data->path);
+    return -1;
+  }
+
+  // Get port configuration for modification
+  struct termios options;
+  tcgetattr(fd, &options);
+
+  // IGNPAR: ignore bytes with parity errors
+  options.c_iflag = IGNPAR;
+
+  // ICRNL: map CR to NL (otherwise a CR input on the other computer will not terminate input)
+  // Future potential option
+  // options.c_iflag = ICRNL;
+  // otherwise make device raw (no other input processing)
+
+  // Specify data bits
+  options.c_cflag &= ~CSIZE;
+  options.c_cflag |= dataBits;
+
+  options.c_cflag &= ~(CRTSCTS);
+
+  if (data->rtscts) {
+    options.c_cflag |= CRTSCTS;
+    // evaluate specific flow control options
+  }
+
+  options.c_iflag &= ~(IXON | IXOFF | IXANY);
+
+  if (data->xon) {
+    options.c_iflag |= IXON;
+  }
+
+  if (data->xoff) {
+    options.c_iflag |= IXOFF;
+  }
+
+  if (data->xany) {
+    options.c_iflag |= IXANY;
+  }
+
+  switch (data->parity) {
+  case SERIALPORT_PARITY_NONE:
+    options.c_cflag &= ~PARENB;
+    // options.c_cflag &= ~CSTOPB;
+    // options.c_cflag &= ~CSIZE;
+    // options.c_cflag |= CS8;
+    break;
+  case SERIALPORT_PARITY_ODD:
+    options.c_cflag |= PARENB;
+    options.c_cflag |= PARODD;
+    // options.c_cflag &= ~CSTOPB;
+    // options.c_cflag &= ~CSIZE;
+    // options.c_cflag |= CS7;
+    break;
+  case SERIALPORT_PARITY_EVEN:
+    options.c_cflag |= PARENB;
+    options.c_cflag &= ~PARODD;
+    // options.c_cflag &= ~CSTOPB;
+    // options.c_cflag &= ~CSIZE;
+    // options.c_cflag |= CS7;
+    break;
+  default:
+    snprintf(data->errorString, sizeof(data->errorString), "Invalid parity setting %d", data->parity);
+    return -1;
+  }
+
+  switch (data->stopBits) {
+  case SERIALPORT_STOPBITS_ONE:
+    options.c_cflag &= ~CSTOPB;
+    break;
+  case SERIALPORT_STOPBITS_TWO:
+    options.c_cflag |= CSTOPB;
+    break;
+  default:
+    snprintf(data->errorString, sizeof(data->errorString), "Invalid stop bits setting %d", data->stopBits);
+    return -1;
+  }
+
+  options.c_cflag |= CLOCAL;  // ignore status lines
+  options.c_cflag |= CREAD;   // enable receiver
+  if (data->hupcl) {
+    options.c_cflag |= HUPCL;  // drop DTR (i.e. hangup) on close
+  }
+
+  // Raw output
+  options.c_oflag = 0;
+
+  // ICANON makes partial lines not readable. It should be optional.
+  // It works with ICRNL.
+  options.c_lflag = 0;  // ICANON;
+  options.c_cc[VMIN]= data->vmin;
+  options.c_cc[VTIME]= data->vtime;
+
+  // Note that tcsetattr() returns success if any of the requested changes could be successfully carried out.
+  // Therefore, when making multiple changes it may be necessary to follow this call with a further call to
+  // tcgetattr() to check that all changes have been performed successfully.
+  // This also fails on OSX
+  tcsetattr(fd, TCSANOW, &options);
+
+  if (data->lock) {
+    if (-1 == flock(fd, LOCK_EX | LOCK_NB)) {
+      snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot lock port", strerror(errno));
+      return -1;
+    }
+  }
+
+  // Copy the connection options into the ConnectionOptionsBaton to set the baud rate
+  ConnectionOptionsBaton* connectionOptions = new ConnectionOptionsBaton();
+  connectionOptions->fd = fd;
+  connectionOptions->baudRate = data->baudRate;
+
+  if (-1 == setBaudRate(connectionOptions)) {
+    strncpy(data->errorString, connectionOptions->errorString, sizeof(data->errorString));
+    delete(connectionOptions);
+    return -1;
+  }
+  delete(connectionOptions);
+
+  // flush all unread and wrote data up to this point because it could have been received or sent with bad settings
+  // Not needed since setBaudRate does this for us
+  // tcflush(fd, TCIOFLUSH);
+
+  return 1;
+}
+
+void EIO_Close(uv_work_t* req) {
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  if (-1 == close(data->fd)) {
+    snprintf(data->errorString, sizeof(data->errorString),
+             "Error: %s, unable to close fd %d", strerror(errno), data->fd);
+  }
+}
+
+void EIO_Set(uv_work_t* req) {
+  SetBaton* data = static_cast<SetBaton*>(req->data);
+
+  int bits;
+  ioctl(data->fd, TIOCMGET, &bits);
+
+  bits &= ~(TIOCM_RTS | TIOCM_CTS | TIOCM_DTR | TIOCM_DSR);
+
+  if (data->rts) {
+    bits |= TIOCM_RTS;
+  }
+
+  if (data->cts) {
+    bits |= TIOCM_CTS;
+  }
+
+  if (data->dtr) {
+    bits |= TIOCM_DTR;
+  }
+
+  if (data->dsr) {
+    bits |= TIOCM_DSR;
+  }
+
+  int result = 0;
+  if (data->brk) {
+    result = ioctl(data->fd, TIOCSBRK, NULL);
+  } else {
+    result = ioctl(data->fd, TIOCCBRK, NULL);
+  }
+
+  if (-1 == result) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot set", strerror(errno));
+    return;
+  }
+
+  if (-1 == ioctl(data->fd, TIOCMSET, &bits)) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot set", strerror(errno));
+    return;
+  }
+}
+
+void EIO_Get(uv_work_t* req) {
+  GetBaton* data = static_cast<GetBaton*>(req->data);
+
+  int bits;
+  if (-1 == ioctl(data->fd, TIOCMGET, &bits)) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot get", strerror(errno));
+    return;
+  }
+
+  data->cts = bits & TIOCM_CTS;
+  data->dsr = bits & TIOCM_DSR;
+  data->dcd = bits & TIOCM_CD;
+}
+
+void EIO_GetBaudRate(uv_work_t* req) {
+  GetBaudRateBaton* data = static_cast<GetBaudRateBaton*>(req->data);
+  int outbaud;
+
+  #if defined(__linux__) && defined(ASYNC_SPD_CUST)
+  if (-1 == linuxGetSystemBaudRate(data->fd, &outbaud)) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot get baud rate", strerror(errno));
+    return;
+  }
+  #endif
+
+  // TODO(Fumon) implement on mac
+  #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
+  snprintf(data->errorString, sizeof(data->errorString), "Error: System baud rate check not implemented on darwin");
+  return;
+  #endif
+
+  data->baudRate = outbaud;
+}
+
+void EIO_Flush(uv_work_t* req) {
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  if (-1 == tcflush(data->fd, TCIOFLUSH)) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot flush", strerror(errno));
+    return;
+  }
+}
+
+void EIO_Drain(uv_work_t* req) {
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  if (-1 == tcdrain(data->fd)) {
+    snprintf(data->errorString, sizeof(data->errorString), "Error: %s, cannot drain", strerror(errno));
+    return;
+  }
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.h b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.h
new file mode 100644
index 00000000..08b11e0c
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_unix.h
@@ -0,0 +1,7 @@
+#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_UNIX_H_
+#define PACKAGES_SERIALPORT_SRC_SERIALPORT_UNIX_H_
+
+int ToBaudConstant(int baudRate);
+int ToDataBitsConstant(int dataBits);
+
+#endif  // PACKAGES_SERIALPORT_SRC_SERIALPORT_UNIX_H_
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.cpp b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.cpp
new file mode 100644
index 00000000..24247478
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.cpp
@@ -0,0 +1,948 @@
+#include "./serialport.h"
+#include "./serialport_win.h"
+#include <nan.h>
+#include <list>
+#include <vector>
+#include <string.h>
+#include <windows.h>
+#include <Setupapi.h>
+#include <initguid.h>
+#include <devpkey.h>
+#include <devguid.h>
+#pragma comment(lib, "setupapi.lib")
+
+#define ARRAY_SIZE(arr)     (sizeof(arr)/sizeof(arr[0]))
+
+#define MAX_BUFFER_SIZE 1000
+
+// As per https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
+#define MAX_REGISTRY_KEY_SIZE 255
+
+// Declare type of pointer to CancelIoEx function
+typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
+
+std::list<int> g_closingHandles;
+
+void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) {
+  switch (errorCode) {
+  case ERROR_FILE_NOT_FOUND:
+    _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: File not found", prefix);
+    break;
+  case ERROR_INVALID_HANDLE:
+    _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Invalid handle", prefix);
+    break;
+  case ERROR_ACCESS_DENIED:
+    _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Access denied", prefix);
+    break;
+  case ERROR_OPERATION_ABORTED:
+    _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Operation aborted", prefix);
+    break;
+  case ERROR_INVALID_PARAMETER:
+    _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: The parameter is incorrect", prefix);
+    break;
+  default:
+    _snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Unknown error code %d", prefix, errorCode);
+    break;
+  }
+}
+
+void AsyncCloseCallback(uv_handle_t* handle) {
+  uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);
+  delete async;
+}
+
+void EIO_Open(uv_work_t* req) {
+  OpenBaton* data = static_cast<OpenBaton*>(req->data);
+
+  char originalPath[1024];
+  strncpy_s(originalPath, sizeof(originalPath), data->path, _TRUNCATE);
+  // data->path is char[1024] but on Windows it has the form "COMx\0" or "COMxx\0"
+  // We want to prepend "\\\\.\\" to it before we call CreateFile
+  strncpy(data->path + 20, data->path, 10);
+  strncpy(data->path, "\\\\.\\", 4);
+  strncpy(data->path + 4, data->path + 20, 10);
+
+  int shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+  if (data->lock) {
+    shareMode = 0;
+  }
+
+  HANDLE file = CreateFile(
+    data->path,
+    GENERIC_READ | GENERIC_WRITE,
+    shareMode,  // dwShareMode 0 Prevents other processes from opening if they request delete, read, or write access
+    NULL,
+    OPEN_EXISTING,
+    FILE_FLAG_OVERLAPPED,  // allows for reading and writing at the same time and sets the handle for asynchronous I/O
+    NULL);
+
+  if (file == INVALID_HANDLE_VALUE) {
+    DWORD errorCode = GetLastError();
+    char temp[100];
+    _snprintf_s(temp, sizeof(temp), _TRUNCATE, "Opening %s", originalPath);
+    ErrorCodeToString(temp, errorCode, data->errorString);
+    return;
+  }
+
+  DCB dcb = { 0 };
+  SecureZeroMemory(&dcb, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+
+  if (!GetCommState(file, &dcb)) {
+    ErrorCodeToString("Open (GetCommState)", GetLastError(), data->errorString);
+    CloseHandle(file);
+    return;
+  }
+
+  if (data->hupcl) {
+    dcb.fDtrControl = DTR_CONTROL_ENABLE;
+  } else {
+    dcb.fDtrControl = DTR_CONTROL_DISABLE;  // disable DTR to avoid reset
+  }
+
+  dcb.Parity = NOPARITY;
+  dcb.ByteSize = 8;
+  dcb.StopBits = ONESTOPBIT;
+
+
+  dcb.fOutxDsrFlow = FALSE;
+  dcb.fOutxCtsFlow = FALSE;
+
+  if (data->xon) {
+    dcb.fOutX = TRUE;
+  } else {
+    dcb.fOutX = FALSE;
+  }
+
+  if (data->xoff) {
+    dcb.fInX = TRUE;
+  } else {
+    dcb.fInX = FALSE;
+  }
+
+  if (data->rtscts) {
+    dcb.fRtsControl = RTS_CONTROL_ENABLE;
+  } else {
+    dcb.fRtsControl = RTS_CONTROL_DISABLE;
+  }
+
+  dcb.fBinary = true;
+  dcb.BaudRate = data->baudRate;
+  dcb.ByteSize = data->dataBits;
+
+  switch (data->parity) {
+  case SERIALPORT_PARITY_NONE:
+    dcb.Parity = NOPARITY;
+    break;
+  case SERIALPORT_PARITY_MARK:
+    dcb.Parity = MARKPARITY;
+    break;
+  case SERIALPORT_PARITY_EVEN:
+    dcb.Parity = EVENPARITY;
+    break;
+  case SERIALPORT_PARITY_ODD:
+    dcb.Parity = ODDPARITY;
+    break;
+  case SERIALPORT_PARITY_SPACE:
+    dcb.Parity = SPACEPARITY;
+    break;
+  }
+
+  switch (data->stopBits) {
+  case SERIALPORT_STOPBITS_ONE:
+    dcb.StopBits = ONESTOPBIT;
+    break;
+  case SERIALPORT_STOPBITS_ONE_FIVE:
+    dcb.StopBits = ONE5STOPBITS;
+    break;
+  case SERIALPORT_STOPBITS_TWO:
+    dcb.StopBits = TWOSTOPBITS;
+    break;
+  }
+
+  if (!SetCommState(file, &dcb)) {
+    ErrorCodeToString("Open (SetCommState)", GetLastError(), data->errorString);
+    CloseHandle(file);
+    return;
+  }
+
+  // Set the timeouts for read and write operations.
+  // Read operation will wait for at least 1 byte to be received.
+  COMMTIMEOUTS commTimeouts = {};
+  commTimeouts.ReadIntervalTimeout = 0;          // Never timeout, always wait for data.
+  commTimeouts.ReadTotalTimeoutMultiplier = 0;   // Do not allow big read timeout when big read buffer used
+  commTimeouts.ReadTotalTimeoutConstant = 0;     // Total read timeout (period of read loop)
+  commTimeouts.WriteTotalTimeoutConstant = 0;    // Const part of write timeout
+  commTimeouts.WriteTotalTimeoutMultiplier = 0;  // Variable part of write timeout (per byte)
+
+  if (!SetCommTimeouts(file, &commTimeouts)) {
+    ErrorCodeToString("Open (SetCommTimeouts)", GetLastError(), data->errorString);
+    CloseHandle(file);
+    return;
+  }
+
+  // Remove garbage data in RX/TX queues
+  PurgeComm(file, PURGE_RXCLEAR);
+  PurgeComm(file, PURGE_TXCLEAR);
+
+  data->result = (int)file;  // NOLINT
+}
+
+void EIO_Update(uv_work_t* req) {
+  ConnectionOptionsBaton* data = static_cast<ConnectionOptionsBaton*>(req->data);
+
+  DCB dcb = { 0 };
+  SecureZeroMemory(&dcb, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+
+  if (!GetCommState((HANDLE)data->fd, &dcb)) {
+    ErrorCodeToString("Update (GetCommState)", GetLastError(), data->errorString);
+    return;
+  }
+
+  dcb.BaudRate = data->baudRate;
+
+  if (!SetCommState((HANDLE)data->fd, &dcb)) {
+    ErrorCodeToString("Update (SetCommState)", GetLastError(), data->errorString);
+    return;
+  }
+}
+
+void EIO_Set(uv_work_t* req) {
+  SetBaton* data = static_cast<SetBaton*>(req->data);
+
+  if (data->rts) {
+    EscapeCommFunction((HANDLE)data->fd, SETRTS);
+  } else {
+    EscapeCommFunction((HANDLE)data->fd, CLRRTS);
+  }
+
+  if (data->dtr) {
+    EscapeCommFunction((HANDLE)data->fd, SETDTR);
+  } else {
+    EscapeCommFunction((HANDLE)data->fd, CLRDTR);
+  }
+
+  if (data->brk) {
+    EscapeCommFunction((HANDLE)data->fd, SETBREAK);
+  } else {
+    EscapeCommFunction((HANDLE)data->fd, CLRBREAK);
+  }
+
+  DWORD bits = 0;
+
+  GetCommMask((HANDLE)data->fd, &bits);
+
+  bits &= ~(EV_CTS | EV_DSR);
+
+  if (data->cts) {
+    bits |= EV_CTS;
+  }
+
+  if (data->dsr) {
+    bits |= EV_DSR;
+  }
+
+  if (!SetCommMask((HANDLE)data->fd, bits)) {
+    ErrorCodeToString("Setting options on COM port (SetCommMask)", GetLastError(), data->errorString);
+    return;
+  }
+}
+
+void EIO_Get(uv_work_t* req) {
+  GetBaton* data = static_cast<GetBaton*>(req->data);
+
+  DWORD bits = 0;
+  if (!GetCommModemStatus((HANDLE)data->fd, &bits)) {
+    ErrorCodeToString("Getting control settings on COM port (GetCommModemStatus)", GetLastError(), data->errorString);
+    return;
+  }
+
+  data->cts = bits & MS_CTS_ON;
+  data->dsr = bits & MS_DSR_ON;
+  data->dcd = bits & MS_RLSD_ON;
+}
+
+void EIO_GetBaudRate(uv_work_t* req) {
+  GetBaudRateBaton* data = static_cast<GetBaudRateBaton*>(req->data);
+
+  DCB dcb = { 0 };
+  SecureZeroMemory(&dcb, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+
+  if (!GetCommState((HANDLE)data->fd, &dcb)) {
+    ErrorCodeToString("Getting baud rate (GetCommState)", GetLastError(), data->errorString);
+    return;
+  }
+
+  data->baudRate = static_cast<int>(dcb.BaudRate);
+}
+
+bool IsClosingHandle(int fd) {
+  for (std::list<int>::iterator it = g_closingHandles.begin(); it != g_closingHandles.end(); ++it) {
+    if (fd == *it) {
+      g_closingHandles.remove(fd);
+      return true;
+    }
+  }
+  return false;
+}
+
+NAN_METHOD(Write) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be an int");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // buffer
+  if (!info[1]->IsObject() || !node::Buffer::HasInstance(info[1])) {
+    Nan::ThrowTypeError("Second argument must be a buffer");
+    return;
+  }
+  v8::Local<v8::Object> buffer = info[1]->ToObject();
+  char* bufferData = node::Buffer::Data(buffer);
+  size_t bufferLength = node::Buffer::Length(buffer);
+
+  // callback
+  if (!info[2]->IsFunction()) {
+    Nan::ThrowTypeError("Third argument must be a function");
+    return;
+  }
+
+  WriteBaton* baton = new WriteBaton();
+  baton->fd = fd;
+  baton->buffer.Reset(buffer);
+  baton->bufferData = bufferData;
+  baton->bufferLength = bufferLength;
+  baton->offset = 0;
+  baton->callback.Reset(info[2].As<v8::Function>());
+  baton->complete = false;
+
+  uv_async_t* async = new uv_async_t;
+  uv_async_init(uv_default_loop(), async, EIO_AfterWrite);
+  async->data = baton;
+  // WriteFileEx requires a thread that can block. Create a new thread to
+  // run the write operation, saving the handle so it can be deallocated later.
+  baton->hThread = CreateThread(NULL, 0, WriteThread, async, 0, NULL);
+}
+
+void __stdcall WriteIOCompletion(DWORD errorCode, DWORD bytesTransferred, OVERLAPPED* ov) {
+  WriteBaton* baton = static_cast<WriteBaton*>(ov->hEvent);
+  DWORD bytesWritten;
+  if (!GetOverlappedResult((HANDLE)baton->fd, ov, &bytesWritten, TRUE)) {
+    errorCode = GetLastError();
+    ErrorCodeToString("Writing to COM port (GetOverlappedResult)", errorCode, baton->errorString);
+    baton->complete = true;
+    return;
+  }
+  if (bytesWritten) {
+    baton->offset += bytesWritten;
+    if (baton->offset >= baton->bufferLength) {
+      baton->complete = true;
+    }
+  }
+}
+
+DWORD __stdcall WriteThread(LPVOID param) {
+  uv_async_t* async = static_cast<uv_async_t*>(param);
+  WriteBaton* baton = static_cast<WriteBaton*>(async->data);
+
+  OVERLAPPED* ov = new OVERLAPPED;
+  memset(ov, 0, sizeof(OVERLAPPED));
+  ov->hEvent = static_cast<void*>(baton);
+
+  while (!baton->complete) {
+    char* offsetPtr = baton->bufferData + baton->offset;
+    // WriteFileEx requires calling GetLastError even upon success. Clear the error beforehand.
+    SetLastError(0);
+    WriteFileEx((HANDLE)baton->fd, offsetPtr,
+                static_cast<DWORD>(baton->bufferLength - baton->offset), ov, WriteIOCompletion);
+    // Error codes when call is successful, such as ERROR_MORE_DATA.
+    DWORD lastError = GetLastError();
+    if (lastError != ERROR_SUCCESS) {
+      ErrorCodeToString("Writing to COM port (WriteFileEx)", lastError, baton->errorString);
+      break;
+    }
+    // IOCompletion routine is only called once this thread is in an alertable wait state.
+    SleepEx(INFINITE, TRUE);
+  }
+  delete ov;
+  // Signal the main thread to run the callback.
+  uv_async_send(async);
+  ExitThread(0);
+}
+
+void EIO_AfterWrite(uv_async_t* req) {
+  Nan::HandleScope scope;
+  WriteBaton* baton = static_cast<WriteBaton*>(req->data);
+  WaitForSingleObject(baton->hThread, INFINITE);
+  CloseHandle(baton->hThread);
+  uv_close(reinterpret_cast<uv_handle_t*>(req), AsyncCloseCallback);
+
+  v8::Local<v8::Value> argv[1];
+  if (baton->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(baton->errorString).ToLocalChecked());
+  } else {
+    argv[0] = Nan::Null();
+  }
+  baton->callback.Call(1, argv);
+  baton->buffer.Reset();
+  delete baton;
+}
+
+NAN_METHOD(Read) {
+  // file descriptor
+  if (!info[0]->IsInt32()) {
+    Nan::ThrowTypeError("First argument must be a fd");
+    return;
+  }
+  int fd = Nan::To<int>(info[0]).FromJust();
+
+  // buffer
+  if (!info[1]->IsObject() || !node::Buffer::HasInstance(info[1])) {
+    Nan::ThrowTypeError("Second argument must be a buffer");
+    return;
+  }
+  v8::Local<v8::Object> buffer = info[1]->ToObject();
+  size_t bufferLength = node::Buffer::Length(buffer);
+
+  // offset
+  if (!info[2]->IsInt32()) {
+    Nan::ThrowTypeError("Third argument must be an int");
+    return;
+  }
+  int offset = Nan::To<v8::Int32>(info[2]).ToLocalChecked()->Value();
+
+  // bytes to read
+  if (!info[3]->IsInt32()) {
+    Nan::ThrowTypeError("Fourth argument must be an int");
+    return;
+  }
+  size_t bytesToRead = Nan::To<v8::Int32>(info[3]).ToLocalChecked()->Value();
+
+  if ((bytesToRead + offset) > bufferLength) {
+    Nan::ThrowTypeError("'bytesToRead' + 'offset' cannot be larger than the buffer's length");
+    return;
+  }
+
+  // callback
+  if (!info[4]->IsFunction()) {
+    Nan::ThrowTypeError("Fifth argument must be a function");
+    return;
+  }
+
+  ReadBaton* baton = new ReadBaton();
+  baton->fd = fd;
+  baton->offset = offset;
+  baton->bytesToRead = bytesToRead;
+  baton->bufferLength = bufferLength;
+  baton->bufferData = node::Buffer::Data(buffer);
+  baton->callback.Reset(info[4].As<v8::Function>());
+  baton->complete = false;
+
+  uv_async_t* async = new uv_async_t;
+  uv_async_init(uv_default_loop(), async, EIO_AfterRead);
+  async->data = baton;
+  // ReadFileEx requires a thread that can block. Create a new thread to
+  // run the read operation, saving the handle so it can be deallocated later.
+  baton->hThread = CreateThread(NULL, 0, ReadThread, async, 0, NULL);
+}
+
+void __stdcall ReadIOCompletion(DWORD errorCode, DWORD bytesTransferred, OVERLAPPED* ov) {
+  ReadBaton* baton = static_cast<ReadBaton*>(ov->hEvent);
+
+  if (errorCode) {
+    ErrorCodeToString("Reading from COM port (ReadIOCompletion)", errorCode, baton->errorString);
+    baton->complete = true;
+    return;
+  }
+
+  DWORD lastError;
+  if (!GetOverlappedResult((HANDLE)baton->fd, ov, &bytesTransferred, TRUE)) {
+    lastError = GetLastError();
+    ErrorCodeToString("Reading from COM port (GetOverlappedResult)", lastError, baton->errorString);
+    baton->complete = true;
+    return;
+  }
+  if (bytesTransferred) {
+    baton->bytesToRead -= bytesTransferred;
+    baton->bytesRead += bytesTransferred;
+    baton->offset += bytesTransferred;
+  }
+
+  // ReadFileEx and GetOverlappedResult retrieved only 1 byte. Read any additional data in the input
+  // buffer. Set the timeout to MAXDWORD in order to disable timeouts, so the read operation will
+  // return immediately no matter how much data is available.
+  COMMTIMEOUTS commTimeouts = {};
+  commTimeouts.ReadIntervalTimeout = MAXDWORD;
+  if (!SetCommTimeouts((HANDLE)baton->fd, &commTimeouts)) {
+    lastError = GetLastError();
+    ErrorCodeToString("Setting COM timeout (SetCommTimeouts)", lastError, baton->errorString);
+    baton->complete = true;
+    return;
+  }
+
+  // Store additional data after whatever data has already been read.
+  char* offsetPtr = baton->bufferData + baton->offset;
+
+  // ReadFile, unlike ReadFileEx, needs an event in the overlapped structure.
+  memset(ov, 0, sizeof(OVERLAPPED));
+  ov->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+  if (!ReadFile((HANDLE)baton->fd, offsetPtr, baton->bytesToRead, &bytesTransferred, ov)) {
+    errorCode = GetLastError();
+
+    if (errorCode != ERROR_IO_PENDING) {
+      ErrorCodeToString("Reading from COM port (ReadFile)", errorCode, baton->errorString);
+      baton->complete = true;
+      CloseHandle(ov->hEvent);
+      return;
+    }
+
+    if (!GetOverlappedResult((HANDLE)baton->fd, ov, &bytesTransferred, TRUE)) {
+      lastError = GetLastError();
+      ErrorCodeToString("Reading from COM port (GetOverlappedResult)", lastError, baton->errorString);
+      baton->complete = true;
+      CloseHandle(ov->hEvent);
+      return;
+    }
+  }
+  CloseHandle(ov->hEvent);
+
+  baton->bytesToRead -= bytesTransferred;
+  baton->bytesRead += bytesTransferred;
+  baton->complete = true;
+}
+
+DWORD __stdcall ReadThread(LPVOID param) {
+  uv_async_t* async = static_cast<uv_async_t*>(param);
+  ReadBaton* baton = static_cast<ReadBaton*>(async->data);
+  DWORD lastError;
+
+  OVERLAPPED* ov = new OVERLAPPED;
+  memset(ov, 0, sizeof(OVERLAPPED));
+  ov->hEvent = static_cast<void*>(baton);
+
+  while (!baton->complete) {
+    // Reset the read timeout to 0, so that it will block until more data arrives.
+    COMMTIMEOUTS commTimeouts = {};
+    commTimeouts.ReadIntervalTimeout = 0;
+    if (!SetCommTimeouts((HANDLE)baton->fd, &commTimeouts)) {
+      lastError = GetLastError();
+      ErrorCodeToString("Setting COM timeout (SetCommTimeouts)", lastError, baton->errorString);
+      break;
+    }
+    // ReadFileEx doesn't use overlapped's hEvent, so it is reserved for user data.
+    ov->hEvent = static_cast<HANDLE>(baton);
+    char* offsetPtr = baton->bufferData + baton->offset;
+    // ReadFileEx requires calling GetLastError even upon success. Clear the error beforehand.
+    SetLastError(0);
+    // Only read 1 byte, so that the callback will be triggered once any data arrives.
+    ReadFileEx((HANDLE)baton->fd, offsetPtr, 1, ov, ReadIOCompletion);
+    // Error codes when call is successful, such as ERROR_MORE_DATA.
+    lastError = GetLastError();
+    if (lastError != ERROR_SUCCESS) {
+      ErrorCodeToString("Reading from COM port (ReadFileEx)", lastError, baton->errorString);
+      break;
+    }
+    // IOCompletion routine is only called once this thread is in an alertable wait state.
+    SleepEx(INFINITE, TRUE);
+  }
+  delete ov;
+  // Signal the main thread to run the callback.
+  uv_async_send(async);
+  ExitThread(0);
+}
+
+void EIO_AfterRead(uv_async_t* req) {
+  Nan::HandleScope scope;
+  ReadBaton* baton = static_cast<ReadBaton*>(req->data);
+  WaitForSingleObject(baton->hThread, INFINITE);
+  CloseHandle(baton->hThread);
+  uv_close(reinterpret_cast<uv_handle_t*>(req), AsyncCloseCallback);
+
+  v8::Local<v8::Value> argv[2];
+  if (baton->errorString[0]) {
+    argv[0] = Nan::Error(baton->errorString);
+    argv[1] = Nan::Undefined();
+  } else {
+    argv[0] = Nan::Null();
+    argv[1] = Nan::New<v8::Integer>(static_cast<int>(baton->bytesRead));
+  }
+
+  baton->callback.Call(2, argv);
+  delete baton;
+}
+
+void EIO_Close(uv_work_t* req) {
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  g_closingHandles.push_back(data->fd);
+
+  HMODULE hKernel32 = LoadLibrary("kernel32.dll");
+  // Look up function address
+  CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
+  // Do something with it
+  if (pCancelIoEx) {
+    // Function exists so call it
+    // Cancel all pending IO Requests for the current device
+    pCancelIoEx((HANDLE)data->fd, NULL);
+  }
+  if (!CloseHandle((HANDLE)data->fd)) {
+    ErrorCodeToString("Closing connection (CloseHandle)", GetLastError(), data->errorString);
+    return;
+  }
+}
+
+char *copySubstring(char *someString, int n) {
+  char *new_ = reinterpret_cast<char*>(malloc(sizeof(char)*n + 1));
+  strncpy_s(new_, n + 1, someString, n);
+  new_[n] = '\0';
+  return new_;
+}
+
+NAN_METHOD(List) {
+  // callback
+  if (!info[0]->IsFunction()) {
+    Nan::ThrowTypeError("First argument must be a function");
+    return;
+  }
+
+  ListBaton* baton = new ListBaton();
+  snprintf(baton->errorString, sizeof(baton->errorString), "");
+  baton->callback.Reset(info[0].As<v8::Function>());
+
+  uv_work_t* req = new uv_work_t();
+  req->data = baton;
+  uv_queue_work(uv_default_loop(), req, EIO_List, (uv_after_work_cb)EIO_AfterList);
+}
+
+// It's possible that the s/n is a construct and not the s/n of the parent USB
+// composite device. This performs some convoluted registry lookups to fetch the USB s/n.
+void getSerialNumber(const char *vid,
+                     const char *pid,
+                     const HDEVINFO hDevInfo,
+                     SP_DEVINFO_DATA deviceInfoData,
+                     const unsigned int maxSerialNumberLength,
+                     char* serialNumber) {
+  _snprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, "");
+  if (vid == NULL || pid == NULL) {
+    return;
+  }
+
+  DWORD dwSize;
+  WCHAR szWUuidBuffer[MAX_BUFFER_SIZE];
+  WCHAR containerUuid[MAX_BUFFER_SIZE];
+
+
+  // Fetch the "Container ID" for this device node. In USB context, this "Container
+  // ID" refers to the composite USB device, i.e. the USB device as a whole, not
+  // just one of its interfaces with a serial port driver attached.
+
+  // From https://stackoverflow.com/questions/3438366/setupdigetdeviceproperty-usage-example:
+  // Because this is not compiled with UNICODE defined, the call to SetupDiGetDevicePropertyW
+  // has to be setup manually.
+  DEVPROPTYPE ulPropertyType;
+  typedef BOOL (WINAPI *FN_SetupDiGetDevicePropertyW)(
+    __in       HDEVINFO DeviceInfoSet,
+    __in       PSP_DEVINFO_DATA DeviceInfoData,
+    __in       const DEVPROPKEY *PropertyKey,
+    __out      DEVPROPTYPE *PropertyType,
+    __out_opt  PBYTE PropertyBuffer,
+    __in       DWORD PropertyBufferSize,
+    __out_opt  PDWORD RequiredSize,
+    __in       DWORD Flags);
+
+  FN_SetupDiGetDevicePropertyW fn_SetupDiGetDevicePropertyW = (FN_SetupDiGetDevicePropertyW)
+        GetProcAddress(GetModuleHandle(TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyW");
+
+  if (fn_SetupDiGetDevicePropertyW (
+        hDevInfo,
+        &deviceInfoData,
+        &DEVPKEY_Device_ContainerId,
+        &ulPropertyType,
+        reinterpret_cast<BYTE*>(szWUuidBuffer),
+        sizeof(szWUuidBuffer),
+        &dwSize,
+        0)) {
+    szWUuidBuffer[dwSize] = '\0';
+
+    // Given the UUID bytes, build up a (widechar) string from it. There's some mangling
+    // going on.
+    StringFromGUID2((REFGUID)szWUuidBuffer, containerUuid, ARRAY_SIZE(containerUuid));
+  } else {
+    // Container UUID could not be fetched, return empty serial number.
+    return;
+  }
+
+  // NOTE: Devices might have a containerUuid like {00000000-0000-0000-FFFF-FFFFFFFFFFFF}
+  // This means they're non-removable, and are not handled (yet).
+  // Maybe they should inherit the s/n from somewhere else.
+
+  // Sanitize input - for whatever reason, StringFromGUID2() returns a WCHAR* but
+  // the comparisons later need a plain old char*, in lowercase ASCII.
+  char wantedUuid[MAX_BUFFER_SIZE];
+  _snprintf_s(wantedUuid, MAX_BUFFER_SIZE, _TRUNCATE, "%ws", containerUuid);
+  strlwr(wantedUuid);
+
+  // Iterate through all the USB devices with the given VendorID/ProductID
+
+  HKEY vendorProductHKey;
+  DWORD retCode;
+  char hkeyPath[MAX_BUFFER_SIZE];
+
+  _snprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE, "SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%s&PID_%s", vid, pid);
+
+  retCode = RegOpenKeyEx(
+    HKEY_LOCAL_MACHINE,
+    hkeyPath,
+    0,
+    KEY_READ,
+    &vendorProductHKey);
+
+  if (retCode == ERROR_SUCCESS) {
+    DWORD    serialNumbersCount = 0;       // number of subkeys
+
+    // Fetch how many subkeys there are for this VendorID/ProductID pair.
+    // That's the number of devices for this VendorID/ProductID known to this machine.
+
+    retCode = RegQueryInfoKey(
+        vendorProductHKey,    // hkey handle
+        NULL,      // buffer for class name
+        NULL,      // size of class string
+        NULL,      // reserved
+        &serialNumbersCount,  // number of subkeys
+        NULL,      // longest subkey size
+        NULL,      // longest class string
+        NULL,      // number of values for this key
+        NULL,      // longest value name
+        NULL,      // longest value data
+        NULL,      // security descriptor
+        NULL);     // last write time
+
+    if (retCode == ERROR_SUCCESS && serialNumbersCount > 0) {
+        for (unsigned int i=0; i < serialNumbersCount; i++) {
+          // Each of the subkeys here is the serial number of a USB device with the
+          // given VendorId/ProductId. Now fetch the string for the S/N.
+          DWORD serialNumberLength = maxSerialNumberLength;
+          retCode = RegEnumKeyEx(vendorProductHKey,
+                                  i,
+                                  serialNumber,
+                                  &serialNumberLength,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL);
+
+          if (retCode == ERROR_SUCCESS) {
+            // Lookup info for VID_(vendorId)&PID_(productId)\(serialnumber)
+
+            _snprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE,
+                        "SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%s&PID_%s\\%s",
+                        vid, pid, serialNumber);
+
+            HKEY deviceHKey;
+
+            if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, hkeyPath, 0, KEY_READ, &deviceHKey) == ERROR_SUCCESS) {
+                char readUuid[MAX_BUFFER_SIZE];
+                DWORD readSize = sizeof(readUuid);
+
+                // Query VID_(vendorId)&PID_(productId)\(serialnumber)\ContainerID
+                DWORD retCode = RegQueryValueEx(deviceHKey, "ContainerID", NULL, NULL, (LPBYTE)&readUuid, &readSize);
+                if (retCode == ERROR_SUCCESS) {
+                    readUuid[readSize] = '\0';
+                    if (strcmp(wantedUuid, readUuid) == 0) {
+                        // The ContainerID UUIDs match, return now that serialNumber has
+                        // the right value.
+                        RegCloseKey(deviceHKey);
+                        RegCloseKey(vendorProductHKey);
+                        return;
+                    }
+                }
+            }
+            RegCloseKey(deviceHKey);
+          }
+       }
+    }
+
+    /* In case we did not obtain the path, for whatever reason, we close the key and return an empty string. */
+    RegCloseKey(vendorProductHKey);
+  }
+
+  _snprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, "");
+  return;
+}
+
+void EIO_List(uv_work_t* req) {
+  ListBaton* data = static_cast<ListBaton*>(req->data);
+
+  GUID *guidDev = (GUID*)& GUID_DEVCLASS_PORTS;  // NOLINT
+  HDEVINFO hDevInfo = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
+  SP_DEVINFO_DATA deviceInfoData;
+
+  int memberIndex = 0;
+  DWORD dwSize, dwPropertyRegDataType;
+  char szBuffer[MAX_BUFFER_SIZE];
+  char *pnpId;
+  char *vendorId;
+  char *productId;
+  char *name;
+  char *manufacturer;
+  char *locationId;
+  char serialNumber[MAX_REGISTRY_KEY_SIZE];
+  bool isCom;
+  while (true) {
+    pnpId = NULL;
+    vendorId = NULL;
+    productId = NULL;
+    name = NULL;
+    manufacturer = NULL;
+    locationId = NULL;
+
+    ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
+    deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+
+    if (SetupDiEnumDeviceInfo(hDevInfo, memberIndex, &deviceInfoData) == FALSE) {
+      if (GetLastError() == ERROR_NO_MORE_ITEMS) {
+        break;
+      }
+    }
+
+    dwSize = sizeof(szBuffer);
+    SetupDiGetDeviceInstanceId(hDevInfo, &deviceInfoData, szBuffer, dwSize, &dwSize);
+    szBuffer[dwSize] = '\0';
+    pnpId = strdup(szBuffer);
+
+    vendorId = strstr(szBuffer, "VID_");
+    if (vendorId) {
+      vendorId += 4;
+      vendorId = copySubstring(vendorId, 4);
+    }
+    productId = strstr(szBuffer, "PID_");
+    if (productId) {
+      productId += 4;
+      productId = copySubstring(productId, 4);
+    }
+
+    getSerialNumber(vendorId, productId, hDevInfo, deviceInfoData, MAX_REGISTRY_KEY_SIZE, serialNumber);
+
+    if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData,
+                                         SPDRP_LOCATION_INFORMATION, &dwPropertyRegDataType,
+                                         reinterpret_cast<BYTE*>(szBuffer),
+                                         sizeof(szBuffer), &dwSize)) {
+      locationId = strdup(szBuffer);
+    }
+    if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData,
+                                         SPDRP_MFG, &dwPropertyRegDataType,
+                                         reinterpret_cast<BYTE*>(szBuffer),
+                                         sizeof(szBuffer), &dwSize)) {
+      manufacturer = strdup(szBuffer);
+    }
+
+    HKEY hkey = SetupDiOpenDevRegKey(hDevInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
+    if (hkey != INVALID_HANDLE_VALUE) {
+      dwSize = sizeof(szBuffer);
+      if (RegQueryValueEx(hkey, "PortName", NULL, NULL, (LPBYTE)&szBuffer, &dwSize) == ERROR_SUCCESS) {
+        szBuffer[dwSize] = '\0';
+        name = strdup(szBuffer);
+        isCom = strstr(szBuffer, "COM") != NULL;
+      }
+    }
+    if (isCom) {
+      ListResultItem* resultItem = new ListResultItem();
+      resultItem->comName = name;
+      resultItem->manufacturer = manufacturer;
+      resultItem->pnpId = pnpId;
+      if (vendorId) {
+        resultItem->vendorId = vendorId;
+      }
+      if (productId) {
+        resultItem->productId = productId;
+      }
+      resultItem->serialNumber = serialNumber;
+      if (locationId) {
+        resultItem->locationId = locationId;
+      }
+      data->results.push_back(resultItem);
+    }
+    free(pnpId);
+    free(vendorId);
+    free(productId);
+    free(locationId);
+    free(manufacturer);
+    free(name);
+
+    RegCloseKey(hkey);
+    memberIndex++;
+  }
+  if (hDevInfo) {
+    SetupDiDestroyDeviceInfoList(hDevInfo);
+  }
+}
+
+void setIfNotEmpty(v8::Local<v8::Object> item, std::string key, const char *value) {
+  v8::Local<v8::String> v8key = Nan::New<v8::String>(key).ToLocalChecked();
+  if (strlen(value) > 0) {
+    Nan::Set(item, v8key, Nan::New<v8::String>(value).ToLocalChecked());
+  } else {
+    Nan::Set(item, v8key, Nan::Undefined());
+  }
+}
+
+void EIO_AfterList(uv_work_t* req) {
+  Nan::HandleScope scope;
+
+  ListBaton* data = static_cast<ListBaton*>(req->data);
+
+  v8::Local<v8::Value> argv[2];
+  if (data->errorString[0]) {
+    argv[0] = v8::Exception::Error(Nan::New<v8::String>(data->errorString).ToLocalChecked());
+    argv[1] = Nan::Undefined();
+  } else {
+    v8::Local<v8::Array> results = Nan::New<v8::Array>();
+    int i = 0;
+    for (std::list<ListResultItem*>::iterator it = data->results.begin(); it != data->results.end(); ++it, i++) {
+      v8::Local<v8::Object> item = Nan::New<v8::Object>();
+
+      setIfNotEmpty(item, "comName", (*it)->comName.c_str());
+      setIfNotEmpty(item, "manufacturer", (*it)->manufacturer.c_str());
+      setIfNotEmpty(item, "serialNumber", (*it)->serialNumber.c_str());
+      setIfNotEmpty(item, "pnpId", (*it)->pnpId.c_str());
+      setIfNotEmpty(item, "locationId", (*it)->locationId.c_str());
+      setIfNotEmpty(item, "vendorId", (*it)->vendorId.c_str());
+      setIfNotEmpty(item, "productId", (*it)->productId.c_str());
+
+      Nan::Set(results, i, item);
+    }
+    argv[0] = Nan::Null();
+    argv[1] = results;
+  }
+  data->callback.Call(2, argv);
+
+  for (std::list<ListResultItem*>::iterator it = data->results.begin(); it != data->results.end(); ++it) {
+    delete *it;
+  }
+  delete data;
+  delete req;
+}
+
+
+void EIO_Flush(uv_work_t* req) {
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  DWORD purge_all = PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR;
+  if (!PurgeComm((HANDLE)data->fd, purge_all)) {
+    ErrorCodeToString("Flushing connection (PurgeComm)", GetLastError(), data->errorString);
+    return;
+  }
+}
+
+void EIO_Drain(uv_work_t* req) {
+  VoidBaton* data = static_cast<VoidBaton*>(req->data);
+
+  if (!FlushFileBuffers((HANDLE)data->fd)) {
+    ErrorCodeToString("Draining connection (FlushFileBuffers)", GetLastError(), data->errorString);
+    return;
+  }
+}
diff --git a/input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.h b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.h
new file mode 100644
index 00000000..a385b77a
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/bindings/src/serialport_win.h
@@ -0,0 +1,71 @@
+#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_WIN_H_
+#define PACKAGES_SERIALPORT_SRC_SERIALPORT_WIN_H_
+// #include <stdio.h>
+// #include <stdlib.h>
+// #include <string.h>
+#include <nan.h>
+#include <list>
+#include <string>
+
+#define ERROR_STRING_SIZE 1024
+
+struct WriteBaton {
+  int fd;
+  char* bufferData;
+  size_t bufferLength;
+  size_t offset;
+  size_t bytesWritten;
+  void* hThread;
+  bool complete;
+  Nan::Persistent<v8::Object> buffer;
+  Nan::Callback callback;
+  int result;
+  char errorString[ERROR_STRING_SIZE];
+};
+
+NAN_METHOD(Write);
+void EIO_Write(uv_work_t* req);
+void EIO_AfterWrite(uv_async_t* req);
+DWORD __stdcall WriteThread(LPVOID param);
+
+
+struct ReadBaton {
+  int fd;
+  char* bufferData;
+  size_t bufferLength;
+  size_t bytesRead;
+  size_t bytesToRead;
+  size_t offset;
+  void* hThread;
+  bool complete;
+  char errorString[ERROR_STRING_SIZE];
+  Nan::Callback callback;
+};
+
+NAN_METHOD(Read);
+void EIO_Read(uv_work_t* req);
+void EIO_AfterRead(uv_async_t* req);
+DWORD __stdcall ReadThread(LPVOID param);
+
+
+NAN_METHOD(List);
+void EIO_List(uv_work_t* req);
+void EIO_AfterList(uv_work_t* req);
+
+struct ListResultItem {
+  std::string comName;
+  std::string manufacturer;
+  std::string serialNumber;
+  std::string pnpId;
+  std::string locationId;
+  std::string vendorId;
+  std::string productId;
+};
+
+struct ListBaton {
+  Nan::Callback callback;
+  std::list<ListResultItem*> results;
+  char errorString[ERROR_STRING_SIZE];
+};
+
+#endif  // PACKAGES_SERIALPORT_SRC_SERIALPORT_WIN_H_
diff --git a/input_devices/mag/node_modules/@serialport/parser-byte-length/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/parser-byte-length/CHANGELOG.md
new file mode 100644
index 00000000..700a4775
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-byte-length/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/parser-byte-length@2.0.0...@serialport/parser-byte-length@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/parser-byte-length
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/parser-byte-length
diff --git a/input_devices/mag/node_modules/@serialport/parser-byte-length/LICENSE b/input_devices/mag/node_modules/@serialport/parser-byte-length/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-byte-length/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/parser-byte-length/README.md b/input_devices/mag/node_modules/@serialport/parser-byte-length/README.md
new file mode 100644
index 00000000..60bd35fd
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-byte-length/README.md
@@ -0,0 +1 @@
+See our api docs https://node-serialport.github.io/node-serialport/ByteLengthParser.html
diff --git a/input_devices/mag/node_modules/@serialport/parser-byte-length/byte-length.js b/input_devices/mag/node_modules/@serialport/parser-byte-length/byte-length.js
new file mode 100644
index 00000000..803bb445
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-byte-length/byte-length.js
@@ -0,0 +1,55 @@
+const Transform = require('stream').Transform
+
+/**
+ * Emit data every number of bytes
+ * @extends Transform
+ * @param {Object} options parser options object
+ * @param {Number} options.length the number of bytes on each data event
+ * @summary A transform stream that emits data as a buffer after a specific number of bytes are received. Runs in O(n) time.
+ * @example
+const SerialPort = require('serialport')
+const ByteLength = require('@serialport/parser-byte-length')
+const port = new SerialPort('/dev/tty-usbserial1')
+const parser = port.pipe(new ByteLength({length: 8}))
+parser.on('data', console.log) // will have 8 bytes per data event
+ */
+class ByteLengthParser extends Transform {
+  constructor(options = {}) {
+    super(options)
+
+    if (typeof options.length !== 'number') {
+      throw new TypeError('"length" is not a number')
+    }
+
+    if (options.length < 1) {
+      throw new TypeError('"length" is not greater than 0')
+    }
+
+    this.length = options.length
+    this.position = 0
+    this.buffer = Buffer.alloc(this.length)
+  }
+
+  _transform(chunk, encoding, cb) {
+    let cursor = 0
+    while (cursor < chunk.length) {
+      this.buffer[this.position] = chunk[cursor]
+      cursor++
+      this.position++
+      if (this.position === this.length) {
+        this.push(this.buffer)
+        this.buffer = Buffer.alloc(this.length)
+        this.position = 0
+      }
+    }
+    cb()
+  }
+
+  _flush(cb) {
+    this.push(this.buffer.slice(0, this.position))
+    this.buffer = Buffer.alloc(this.length)
+    cb()
+  }
+}
+
+module.exports = ByteLengthParser
diff --git a/input_devices/mag/node_modules/@serialport/parser-byte-length/package.json b/input_devices/mag/node_modules/@serialport/parser-byte-length/package.json
new file mode 100644
index 00000000..54b07cec
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-byte-length/package.json
@@ -0,0 +1,81 @@
+{
+  "_args": [
+    [
+      "@serialport/parser-byte-length@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/parser-byte-length@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/parser-byte-length@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/parser-byte-length",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/parser-byte-length_2.0.1_1535513343603_0.01535684631932499"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/parser-byte-length",
+    "raw": "@serialport/parser-byte-length@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-2.0.1.tgz",
+  "_shasum": "d3b5d41e77208e3361bd048d78e6c53546c7ea2c",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/parser-byte-length@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {},
+  "description": "See our api docs https://node-serialport.github.io/node-serialport/ByteLengthParser.html",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-5eqSWfVSqnPexbwi+pL+DY0/KBMV4zNhxl+vNCZ23FztKwqpfzDVNwHFEIZn+olK5z0Ht6jz4EVo19uum7yE2Q==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMACRA9TVsSAnZWagAA9EkQAKKFMEgQmQyPL3u/UHz2\nbXOJ9EChZ/VOPW23NycEpaNPPz3GMY17TlDXbBxd3yyzp1XKWDzE+9o/VcQ/\nl2MkWEUIEqe3f0bMiremucyJTtg1yxwMyFEUiaNTHeeYvwAalrvBnOeQr93X\n9tGAklsy77533M4VKr6UoVwV6uqyxD9fjOorWI85L7iphrCkJIKJvacbqN4w\nNdZMspySIXEnmQklcblr9L7y7f584ThiSyULtzrVNANVN0kbbc7tgh7D3m4X\nc/6TGFxDNqoeEQJmkkEFIDGj+iK4rOUp8YDQl6GYuEWmy2QXQN55DcxDJKrY\nBGW8mfM8vhLD9bKpUDRDpWeF4089W6SXDuz3yLk/hwzzcPQBlTtMzxPRLXQO\nvtFTZ5nGkRS0k05wlQZgQwZOv3Kiv5lWLhGsAQGySA0aWZWku+N2jOyyrp08\niV+pLG6HyyggEBjDtM1FjRZt8jjGhKz9WvOe/4Ng3wdLKra96g8D4D4bhtep\nqgUdZZlnbF30sCQItUxcEezMINjfR+s0L1R+q1O2NnC6rWsaK8vl5cRw9iw7\npIc9fAaKiDoAPoQmbdDApdPCwsldARV2kjvfOYqFX3RKO+18w+zsV6D+rswN\ndAHv1Bbh0KdCFpwLfvWaAqrsY1BEZpXeZMNr64CNmXsH3yS09FK1sBoe0BPb\nefi1\r\n=2bSu\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "d3b5d41e77208e3361bd048d78e6c53546c7ea2c",
+    "tarball": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-2.0.1.tgz",
+    "unpackedSize": 3665
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "byte-length.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/parser-byte-length",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/parser-cctalk/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/parser-cctalk/CHANGELOG.md
new file mode 100644
index 00000000..0cae58dc
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-cctalk/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/parser-cctalk@2.0.0...@serialport/parser-cctalk@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/parser-cctalk
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/parser-cctalk
diff --git a/input_devices/mag/node_modules/@serialport/parser-cctalk/LICENSE b/input_devices/mag/node_modules/@serialport/parser-cctalk/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-cctalk/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/parser-cctalk/README.md b/input_devices/mag/node_modules/@serialport/parser-cctalk/README.md
new file mode 100644
index 00000000..a6bb54a8
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-cctalk/README.md
@@ -0,0 +1 @@
+See our api docs https://node-serialport.github.io/node-serialport/CCTalkParser.html
diff --git a/input_devices/mag/node_modules/@serialport/parser-cctalk/cctalk.js b/input_devices/mag/node_modules/@serialport/parser-cctalk/cctalk.js
new file mode 100644
index 00000000..d3e1642f
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-cctalk/cctalk.js
@@ -0,0 +1,41 @@
+const Transform = require('stream').Transform
+
+/**
+ * Parse the CCTalk protocol
+ * @extends Transform
+ * @summary A transform stream that emits CCTalk packets as they are received.
+ * @example
+const SerialPort = require('serialport')
+const CCTalk = require('@serialport/parser-cctalk')
+const port = new SerialPort('/dev/ttyUSB0')
+const parser = port.pipe(new CCtalk())
+parser.on('data', console.log)
+ */
+class CCTalkParser extends Transform {
+  constructor() {
+    super()
+    this.array = []
+    this.cursor = 0
+  }
+  _transform(buffer, _, cb) {
+    this.cursor += buffer.length
+    // TODO: Better Faster es7 no supported by node 4
+    // ES7 allows directly push [...buffer]
+    // this.array = this.array.concat(Array.from(buffer)) //Slower ?!?
+    Array.from(buffer).map(byte => this.array.push(byte))
+    while (this.cursor > 1 && this.cursor >= this.array[1] + 5) {
+      // full frame accumulated
+      // copy command from the array
+      const FullMsgLength = this.array[1] + 5
+
+      const frame = Buffer.from(this.array.slice(0, FullMsgLength))
+      // Preserve Extra Data
+      this.array = this.array.slice(frame.length, this.array.length)
+      this.cursor -= FullMsgLength
+      this.push(frame)
+    }
+    cb()
+  }
+}
+
+module.exports = CCTalkParser
diff --git a/input_devices/mag/node_modules/@serialport/parser-cctalk/package.json b/input_devices/mag/node_modules/@serialport/parser-cctalk/package.json
new file mode 100644
index 00000000..e0f27b02
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-cctalk/package.json
@@ -0,0 +1,81 @@
+{
+  "_args": [
+    [
+      "@serialport/parser-cctalk@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/parser-cctalk@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/parser-cctalk@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/parser-cctalk",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/parser-cctalk_2.0.1_1535513343611_0.07852743186893751"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/parser-cctalk",
+    "raw": "@serialport/parser-cctalk@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-2.0.1.tgz",
+  "_shasum": "d2395adc0472a3399cd6f26a5fdcf86560341aba",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/parser-cctalk@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {},
+  "description": "See our api docs https://node-serialport.github.io/node-serialport/CCTalkParser.html",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-gZpM4ViS48xTiHTC+xV54lcBYzhII1250dwBmdX+8ZjKGb8n99S9LreQRisexhcWvXhIT6f45xya6xBk5aHQIw==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMACRA9TVsSAnZWagAAbFIQAJ5Asr4fkFtjAq06464g\nr1utODUsuLgcrKlT7iTwnE4pV/QaXes0fBd8l4wXWbyEq+htigAiUdLyumZB\nWdNShqjSjGDHkMEBo2m/g0evirbej093uFjWM4MQEbv9xgr1M9KjAcbH+p7a\nGgRj/M6xv75fklyeVMzKsPxNOTWRh5wOIdt+4IEEwrYx3Jx2O2o+lrcRpZrC\nJ+Yg+Hi02L9e0v+Sp3mbyZTnTXW+ZijFEPi0M+dsUr46VaowWZFs/iOjZrTG\nhBEsrNe3c5fkqZku7EvlONOpw6Z+zLZgkv3u5f+z2gyuNP9obVxJv1TCQaZ/\nPwkTq8CJatlRwnaWCZCZFId8yFOSUtc4LW4vBZ2G8u6vlLDSaxZR6YyHhdox\n8CnqysLXXw8s+mEBNex71/EyFpyQFvIliOopuBNUGBvjxHI1z8pvbFeekSj8\n/UHRP08YtfySWtw1uJRCEnO5B3IuspMlzdMvWGm27iyvNYR63SFNj3g2r/Oz\nczBqNdElI8ab27IarUE6J7WOY1JM0R9f60h1GEMU0pU4MrQKgfwjQOeCw8D2\nzkGpHSlBnT0mC2VK5XEjMwCOZdZzdy9sr6q+CoQu31TbXZyS5fdA5bNRnCQ9\nCPFAbzaHAwc83GDa2+I9pjUufn4546Tj+joqv0D18MgM+FWyKzkz5jJHehA8\nr9pf\r\n=9Pu3\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "d2395adc0472a3399cd6f26a5fdcf86560341aba",
+    "tarball": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-2.0.1.tgz",
+    "unpackedSize": 3337
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "cctalk.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/parser-cctalk",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/parser-delimiter/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/parser-delimiter/CHANGELOG.md
new file mode 100644
index 00000000..82001040
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-delimiter/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/parser-delimiter@2.0.0...@serialport/parser-delimiter@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/parser-delimiter
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/parser-delimiter
diff --git a/input_devices/mag/node_modules/@serialport/parser-delimiter/LICENSE b/input_devices/mag/node_modules/@serialport/parser-delimiter/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-delimiter/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/parser-delimiter/README.md b/input_devices/mag/node_modules/@serialport/parser-delimiter/README.md
new file mode 100644
index 00000000..622f8525
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-delimiter/README.md
@@ -0,0 +1 @@
+See our api docs https://node-serialport.github.io/node-serialport/DelimiterParser.html
diff --git a/input_devices/mag/node_modules/@serialport/parser-delimiter/delimiter.js b/input_devices/mag/node_modules/@serialport/parser-delimiter/delimiter.js
new file mode 100644
index 00000000..651e1d08
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-delimiter/delimiter.js
@@ -0,0 +1,55 @@
+const Transform = require('stream').Transform
+
+/**
+ * A transform stream that emits data each time a byte sequence is received.
+ * @extends Transform
+ * @summary To use the `Delimiter` parser, provide a delimiter as a string, buffer, or array of bytes. Runs in O(n) time.
+ * @example
+const SerialPort = require('serialport')
+const Delimiter = require('@serialport/parser-delimiter')
+const port = new SerialPort('/dev/tty-usbserial1')
+const parser = port.pipe(new Delimiter({ delimiter: '\n' }))
+parser.on('data', console.log)
+ */
+class DelimiterParser extends Transform {
+  constructor(options = {}) {
+    super(options)
+
+    if (options.delimiter === undefined) {
+      throw new TypeError('"delimiter" is not a bufferable object')
+    }
+
+    if (options.delimiter.length === 0) {
+      throw new TypeError('"delimiter" has a 0 or undefined length')
+    }
+
+    this.includeDelimiter =
+      options.includeDelimiter !== undefined ? options.includeDelimiter : false
+    this.delimiter = Buffer.from(options.delimiter)
+    this.buffer = Buffer.alloc(0)
+  }
+
+  _transform(chunk, encoding, cb) {
+    let data = Buffer.concat([this.buffer, chunk])
+    let position
+    while ((position = data.indexOf(this.delimiter)) !== -1) {
+      this.push(
+        data.slice(
+          0,
+          position + (this.includeDelimiter ? this.delimiter.length : 0)
+        )
+      )
+      data = data.slice(position + this.delimiter.length)
+    }
+    this.buffer = data
+    cb()
+  }
+
+  _flush(cb) {
+    this.push(this.buffer)
+    this.buffer = Buffer.alloc(0)
+    cb()
+  }
+}
+
+module.exports = DelimiterParser
diff --git a/input_devices/mag/node_modules/@serialport/parser-delimiter/package.json b/input_devices/mag/node_modules/@serialport/parser-delimiter/package.json
new file mode 100644
index 00000000..155a6115
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-delimiter/package.json
@@ -0,0 +1,82 @@
+{
+  "_args": [
+    [
+      "@serialport/parser-delimiter@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/parser-delimiter@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/parser-delimiter@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/parser-delimiter",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/parser-delimiter_2.0.1_1535513343648_0.8708043219163069"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/parser-delimiter",
+    "raw": "@serialport/parser-delimiter@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/parser-readline",
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-2.0.1.tgz",
+  "_shasum": "5aeb60579a8f8fb47d095a66c7bea9f861ca1728",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/parser-delimiter@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {},
+  "description": "See our api docs https://node-serialport.github.io/node-serialport/DelimiterParser.html",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-y7m6Rn3Y93DnZtS5jhFNbzRFP9E2mVcn6Lu9j6RQmHJeCK/q/6dOKURWRQ4vat+S7QWtYlaEOchF1hEvmoOmLQ==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMACRA9TVsSAnZWagAA/ZYP/ikjFVjFnyr2cdhK4/JG\nuje0H1lTdTtA9mc5NdVGO0gjwJuZMuNHoiJimr9P+aACQVNjK41MFFtrZqNk\n93Cofo2gFuUc0bQ1s5/qqwujfILEsq4IT748c89DRUNfqSy5AXGpklo3U7ku\nE40xg06uUQOq6s56G8FvooWj63Jz3pJOfNOsPrQCpvFkIylunjh6bzP68uos\nZu0xNw83COMZywKFdIRqTAHQzRXtTkGh5UmzWzikOIA/2US3JQPqmAbRbiFt\nPIlbxe7sncPJpLroNXK4xVFrFxFU+kk0qRlzyufkoOS7/5jD1suu90BAmjO6\nSIaxx74tZYbcYCDl0QXvCiebi1Fc25VzfKYdTTu93bDTKEY0vieRfp2fRPMN\nTqxDSyAqSK+0Dp1JQPyHCmOci0U6W+gtfYjIUIBpwvcSXB5TjUUGKYP5JJA/\nP6UKnrnHJYwdD7Ri6WvI6qp3ompvmlIcXq882FBk4gDatt5hv9+P+5jVppKK\n/BKWxA48dX899tGCwizB8MOK2XzVgUCnbL7e/VhLFBLnSTKF8e6EKoWcUP8B\nOyRalev7IhJL3NBPb8lW8RWdciV3EAnZyR5hMpgVEAdr3QHrx1i2H81d+U6g\nla4Rdv7uZ9XkFkHeqsiQh5NvKmAtLgoVDjxeAvIJJAK5MGmNJkerm45QVN54\nSkrO\r\n=oXGG\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "5aeb60579a8f8fb47d095a66c7bea9f861ca1728",
+    "tarball": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-2.0.1.tgz",
+    "unpackedSize": 3684
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "delimiter.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/parser-delimiter",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/parser-readline/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/parser-readline/CHANGELOG.md
new file mode 100644
index 00000000..8dbc0348
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-readline/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/parser-readline@2.0.0...@serialport/parser-readline@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/parser-readline
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/parser-readline
diff --git a/input_devices/mag/node_modules/@serialport/parser-readline/LICENSE b/input_devices/mag/node_modules/@serialport/parser-readline/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-readline/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/parser-readline/README.md b/input_devices/mag/node_modules/@serialport/parser-readline/README.md
new file mode 100644
index 00000000..0c057224
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-readline/README.md
@@ -0,0 +1 @@
+See our api docs https://node-serialport.github.io/node-serialport/ReadLineParser.html
diff --git a/input_devices/mag/node_modules/@serialport/parser-readline/package.json b/input_devices/mag/node_modules/@serialport/parser-readline/package.json
new file mode 100644
index 00000000..973907d1
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-readline/package.json
@@ -0,0 +1,84 @@
+{
+  "_args": [
+    [
+      "@serialport/parser-readline@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/parser-readline@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/parser-readline@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/parser-readline",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/parser-readline_2.0.1_1535513359215_0.652056595557603"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/parser-readline",
+    "raw": "@serialport/parser-readline@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/bindings",
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-2.0.1.tgz",
+  "_shasum": "e491bdf432b4f96f31fd8206b49feb03776a201b",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/parser-readline@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {
+    "@serialport/parser-delimiter": "^2.0.1"
+  },
+  "description": "See our api docs https://node-serialport.github.io/node-serialport/ReadLineParser.html",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-EOsuBkmYuUrWZ7X2aPvpE1NeLHk3wmLJDrxsfTHbErTajk3AcsZfq28yNQcSPN5v7902VXgMJom94TruWyOTzw==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMPCRA9TVsSAnZWagAAv/QQAJmjlxaMk9tu3UXjxJoZ\nVe/+RFl0ReV6Pc5vbjrxytZ8GNQ3s+lqYzPi6CtoXjcxHm3TiLr8zn+fpqdR\nvIKMmOZud2yMMcCx94fRPXr2vf2SFvkhRNmV6UGLFgNpsuH4pxuKkSVYPi3k\nDZm44VqKt8YCPC943hv/HYBTXUSiCxqODio5l1gfiddkX66stSP3NgmDglpR\nkfaskwlBnJW9S4qqaxdsAtdeRdpb+9oBJlE7eWC4u/CPzJBSDaREVCuz9KHU\nJqHMcbJlKPdU7U78FremamijqLYuST0Rj03PP15v10OGNH60O4qJn2B2MPCN\nEFCpJwTa3a14dpCsNrtLTXdIgFoQSpu9Ei07FAkdKghviL/KlreueY0+xoNS\n6vH3dnBqfB+v55d43RGJTnNqnhBZvazBuhOUVs6Y/h3Ic1Y4nfSPtvh49xXz\nufgyroRAkJQHOriUuC7Ov0QcR5VihUmElMyqpGZ/sb4cOngrDshupjW/ODnS\nonIQIF7LwQiVN2xo29vKPI24UBPZJblX2fdVcTvOLIEaGsMIiUfG0HcrOvqX\npelG3D9MN9jJ01fvtEejNq30cmJ/FJMqt1sf0rWv9JKvlIUg+AzBJMI4GMkO\nYDDGAcT+fYg80UqrXv32rMIknGkuxhPt/sDvlyWDCpuVf/6iqQaCJPNTQ/dl\nlUhU\r\n=sAtM\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "e491bdf432b4f96f31fd8206b49feb03776a201b",
+    "tarball": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-2.0.1.tgz",
+    "unpackedSize": 3143
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "readline.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/parser-readline",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/parser-readline/readline.js b/input_devices/mag/node_modules/@serialport/parser-readline/readline.js
new file mode 100644
index 00000000..24189c38
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-readline/readline.js
@@ -0,0 +1,32 @@
+const DelimiterParser = require('@serialport/parser-delimiter')
+
+/**
+ *  A transform stream that emits data after a newline delimiter is received.
+ * @summary To use the `Readline` parser, provide a delimiter (defaults to `\n`). Data is emitted as string controllable by the `encoding` option (defaults to `utf8`).
+ * @extends DelimiterParser
+ * @example
+const SerialPort = require('serialport')
+const Readline = require('@serialport/parser-readline')
+const port = new SerialPort('/dev/tty-usbserial1')
+const parser = port.pipe(new Readline({ delimiter: '\r\n' }))
+parser.on('data', console.log)
+*/
+class ReadLineParser extends DelimiterParser {
+  constructor(options) {
+    const opts = Object.assign(
+      {
+        delimiter: Buffer.from('\n', 'utf8'),
+        encoding: 'utf8',
+      },
+      options
+    )
+
+    if (typeof opts.delimiter === 'string') {
+      opts.delimiter = Buffer.from(opts.delimiter, opts.encoding)
+    }
+
+    super(opts)
+  }
+}
+
+module.exports = ReadLineParser
diff --git a/input_devices/mag/node_modules/@serialport/parser-ready/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/parser-ready/CHANGELOG.md
new file mode 100644
index 00000000..7b563f62
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-ready/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/parser-ready@2.0.0...@serialport/parser-ready@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/parser-ready
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/parser-ready
diff --git a/input_devices/mag/node_modules/@serialport/parser-ready/LICENSE b/input_devices/mag/node_modules/@serialport/parser-ready/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-ready/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/parser-ready/README.md b/input_devices/mag/node_modules/@serialport/parser-ready/README.md
new file mode 100644
index 00000000..9d356d01
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-ready/README.md
@@ -0,0 +1 @@
+See our api docs https://node-serialport.github.io/node-serialport/ReadyParser.html
diff --git a/input_devices/mag/node_modules/@serialport/parser-ready/package.json b/input_devices/mag/node_modules/@serialport/parser-ready/package.json
new file mode 100644
index 00000000..772f9d7b
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-ready/package.json
@@ -0,0 +1,81 @@
+{
+  "_args": [
+    [
+      "@serialport/parser-ready@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/parser-ready@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/parser-ready@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/parser-ready",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/parser-ready_2.0.1_1535513349677_0.1263589862297403"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/parser-ready",
+    "raw": "@serialport/parser-ready@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-2.0.1.tgz",
+  "_shasum": "e8be565959b00dcae61a2ba888f82382bd1a5754",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/parser-ready@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {},
+  "description": "See our api docs https://node-serialport.github.io/node-serialport/ReadyParser.html",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-Rdsiru1HHmwcENGyJ+bC7x8aKbbki1vOwp/eQ26LCuIq2Hbq61wKHq2lNwvlp48tmWsB8cRbMuYMjh6zU/1zbA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMGCRA9TVsSAnZWagAAqqcP/RB8MTuxDoUz6FwIU97I\nt6ojt/eC5re2jq9GeRdC4Qz5OeouAEVclSZfoObtONwmVxOn2kFGANk5RVS+\nbC52RoGQBQ80/LZezXdmGWutxS8A92DmWBO0J05l85ecxDs5gDjVZrR3PkHC\negBxCRrkRnDTdEsCY/BdpQDZW56+RphPzAythGcMQ+zSzhLnX6YUDPP26Vyj\n6FvC1tZgBFnBVHyqTfDoBYklQT9XAar1FFMERtGNMEJP0XKcECbzePtI2IsX\nIvIyu0ZLP1RO3Bz3PUkfY/jnurgtB+1wbn71SR5nTi5CUbk9PP6vtJkuQ/Ss\nwYdl/ObgXiflIE7OthzIfIsGVmRda8+JY0C1vy/3FyrQUtmjhe82vsZ74+4i\nFemlnRjVHTwpaNDDZkJo3M8hecZjSGPQUrxUKHzUuogLOzioMysQY7IcC0BV\n0gmg8Qt/uO8I7qsSSG4wv/dTmS2Vf72orHyIcseEMXeCz9vDmuiUXo+niEGg\nvWzb3PKFafJtfO3BeXPqIeI3iRJxvw4yP8T5o2LpIRCYW4yGcwjfcrtyC2I1\npC3Gpkd+BjlrkbCEu/NMMZ6vhVcxTrEq1YHBkdBGo//YY8dnngxJmi5KgDo6\neFgKSIu8RQxVAw6009yHXx5crOPmlBzhPQ4VXXlYm9J1K/9OVfVudUPiUfby\nW5Nz\r\n=+l9r\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "e8be565959b00dcae61a2ba888f82382bd1a5754",
+    "tarball": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-2.0.1.tgz",
+    "unpackedSize": 4056
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "ready.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/parser-ready",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/parser-ready/ready.js b/input_devices/mag/node_modules/@serialport/parser-ready/ready.js
new file mode 100644
index 00000000..29b94d92
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-ready/ready.js
@@ -0,0 +1,63 @@
+const Transform = require('stream').Transform
+
+/**
+ * A transform stream that waits for a sequence of "ready" bytes before emitting a ready event and emitting data events
+ * @summary To use the `Ready` parser provide a byte start sequence. After the bytes have been received a ready event is fired and data events are passed through.
+ * @extends Transform
+ * @example
+const SerialPort = require('serialport')
+const Ready = require('@serialport/parser-ready')
+const port = new SerialPort('/dev/tty-usbserial1')
+const parser = port.pipe(new Ready({ delimiter: 'READY' }))
+parser.on('ready', () => console.log('the ready byte sequence has been received'))
+parser.on('data', console.log) // all data after READY is received
+ */
+class ReadyParser extends Transform {
+  /**
+   *
+   * @param {object} options options for the parser
+   * @param {string|Buffer|array} options.delimiter data to look for before emitted "ready"
+   */
+  constructor(options = {}) {
+    if (options.delimiter === undefined) {
+      throw new TypeError('"delimiter" is not a bufferable object')
+    }
+
+    if (options.delimiter.length === 0) {
+      throw new TypeError('"delimiter" has a 0 or undefined length')
+    }
+
+    super(options)
+    this.delimiter = Buffer.from(options.delimiter)
+    this.readOffset = 0
+    this.ready = false
+  }
+
+  _transform(chunk, encoding, cb) {
+    if (this.ready) {
+      this.push(chunk)
+      return cb()
+    }
+    const delimiter = this.delimiter
+    let chunkOffset = 0
+    while (this.readOffset < delimiter.length && chunkOffset < chunk.length) {
+      if (delimiter[this.readOffset] === chunk[chunkOffset]) {
+        this.readOffset++
+      } else {
+        this.readOffset = 0
+      }
+      chunkOffset++
+    }
+    if (this.readOffset === delimiter.length) {
+      this.ready = true
+      this.emit('ready')
+      const chunkRest = chunk.slice(chunkOffset)
+      if (chunkRest.length > 0) {
+        this.push(chunkRest)
+      }
+    }
+    cb()
+  }
+}
+
+module.exports = ReadyParser
diff --git a/input_devices/mag/node_modules/@serialport/parser-regex/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/parser-regex/CHANGELOG.md
new file mode 100644
index 00000000..d0643353
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-regex/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/parser-regex@2.0.0...@serialport/parser-regex@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/parser-regex
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/parser-regex
diff --git a/input_devices/mag/node_modules/@serialport/parser-regex/LICENSE b/input_devices/mag/node_modules/@serialport/parser-regex/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-regex/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/parser-regex/README.md b/input_devices/mag/node_modules/@serialport/parser-regex/README.md
new file mode 100644
index 00000000..e7287ec9
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-regex/README.md
@@ -0,0 +1 @@
+See our api docs https://node-serialport.github.io/node-serialport/RegexParser.html
diff --git a/input_devices/mag/node_modules/@serialport/parser-regex/package.json b/input_devices/mag/node_modules/@serialport/parser-regex/package.json
new file mode 100644
index 00000000..0d9ac3dc
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-regex/package.json
@@ -0,0 +1,81 @@
+{
+  "_args": [
+    [
+      "@serialport/parser-regex@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/parser-regex@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/parser-regex@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/parser-regex",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/parser-regex_2.0.1_1535513349736_0.8780974871898808"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/parser-regex",
+    "raw": "@serialport/parser-regex@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-2.0.1.tgz",
+  "_shasum": "29e87248601f482ba892596adad8f22a0658279c",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/parser-regex@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {},
+  "description": "See our api docs https://node-serialport.github.io/node-serialport/RegexParser.html",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-Dg9BAVrYfJG2IBA4BjWEE3GShZLPW9iT4PJ7fHFPZItw4Ljzwo86rXva18lx5auegE+6w3t9OwG3rIsImqk9sg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMGCRA9TVsSAnZWagAAuGIP/AuHrRFZn+1gaYTH566t\nCGB5L32dI8E43z7y4OxeGIrFDiuC5NDY7J345N7CDCEzC+3pxXRIBGIip/+s\nOUvps37NAT7Zmsb/5V8K0+swBVLHYWyyY1mEcef+8AZlEANZH0e9W3m1uV00\npfy646JtQetjh22g+6WiXvBMNlczz6kOhYkZwBgeOYklAqDWqA27fri0oIuT\n3WLzXYdnrBMyBp5nOynyXZ2F8au9tk3prp3eYsDaRQ6To3fuf240ZrpiSobA\nI5U2DYh27VqneN4TnT4p051GlMTAxS/3OuGpWE1j3g4ci+ajlAg/SqN0qJHu\nGKJu/aox6tLZKL0CnYZ0oa2cuUnrOdf081kkpwg3OVoua6fc6ed102Y2Il37\nzx8VrsIzeH6Umprbfz8rfhFmtHdDz44s+R93ASpicr21KwrwjzsLoqPoPXt5\nvdBY7eifs9NTpColoPFXvk0bPVlUSckdMA2DQEo+sTQqf18llNicw2sF/7tS\nWUxeUKKOfRqIp9QuVXJ/yw5kdWaiMMi6y4w/OgU4pBN+U0JDFTMX42OnPN9e\nFKqjGwIT95cwG/I2v8W7B9nRQXxNbS18UmCYMmi5bHDUi/s02gX+ttn+V/wZ\nniLRbidr8hbHMghP1m15xxKo5ie5WrINW4z0OXW/yESY+/p9ODOe6AnsHYIK\nf4um\r\n=J7mG\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "29e87248601f482ba892596adad8f22a0658279c",
+    "tarball": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-2.0.1.tgz",
+    "unpackedSize": 3437
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "regex.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/parser-regex",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/parser-regex/regex.js b/input_devices/mag/node_modules/@serialport/parser-regex/regex.js
new file mode 100644
index 00000000..48d0a3eb
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/parser-regex/regex.js
@@ -0,0 +1,57 @@
+const Transform = require('stream').Transform
+
+/**
+ * A transform stream that uses a regular expression to split the incoming text upon.
+ *
+ * To use the `Regex` parser provide a regular expression to split the incoming text upon. Data is emitted as string controllable by the `encoding` option (defaults to `utf8`).
+ * @extends Transform
+ * @example
+const SerialPort = require('serialport')
+const Regex = require('@serialport/parser-regex')
+const port = new SerialPort('/dev/tty-usbserial1')
+const parser = port.pipe(new Regex({ regex: /[\r\n]+/ }))
+parser.on('data', console.log)
+ */
+class RegexParser extends Transform {
+  constructor(options) {
+    const opts = Object.assign(
+      {
+        encoding: 'utf8',
+      },
+      options
+    )
+
+    if (opts.regex === undefined) {
+      throw new TypeError(
+        '"options.regex" must be a regular expression pattern or object'
+      )
+    }
+
+    if (!(opts.regex instanceof RegExp)) {
+      opts.regex = new RegExp(opts.regex)
+    }
+    super(opts)
+
+    this.regex = opts.regex
+    this.data = ''
+  }
+
+  _transform(chunk, encoding, cb) {
+    const data = this.data + chunk
+    const parts = data.split(this.regex)
+    this.data = parts.pop()
+
+    parts.forEach(part => {
+      this.push(part)
+    })
+    cb()
+  }
+
+  _flush(cb) {
+    this.push(this.data)
+    this.data = ''
+    cb()
+  }
+}
+
+module.exports = RegexParser
diff --git a/input_devices/mag/node_modules/@serialport/stream/CHANGELOG.md b/input_devices/mag/node_modules/@serialport/stream/CHANGELOG.md
new file mode 100644
index 00000000..a1d40bf4
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/stream/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="2.0.1"></a>
+## [2.0.1](https://github.com/node-serialport/node-serialport/compare/@serialport/stream@2.0.0...@serialport/stream@2.0.1) (2018-08-29)
+
+**Note:** Version bump only for package @serialport/stream
+
+
+
+
+
+<a name="2.0.0"></a>
+# 2.0.0 (2018-08-26)
+
+**Note:** Version bump only for package @serialport/stream
diff --git a/input_devices/mag/node_modules/@serialport/stream/LICENSE b/input_devices/mag/node_modules/@serialport/stream/LICENSE
new file mode 100644
index 00000000..800d7767
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/stream/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
+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/input_devices/mag/node_modules/@serialport/stream/README.md b/input_devices/mag/node_modules/@serialport/stream/README.md
new file mode 100644
index 00000000..ff7d2bf0
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/stream/README.md
@@ -0,0 +1,14 @@
+# @serialport/Stream
+
+The serialport stream interface. This package requires bindings to work.
+
+You'd use this if you want to keep your package size down by requiring only the parts of serialport that you want to use. It is used internally in the `serialport` package.
+
+This is how you use it.
+```js
+
+const SerialPort = require('@serialport/stream')
+const Binding = require('@serialport/bindings')
+SerialPort.Binding = Binding
+const port = new Serialport('/dev/ttyay')
+```
diff --git a/input_devices/mag/node_modules/@serialport/stream/package.json b/input_devices/mag/node_modules/@serialport/stream/package.json
new file mode 100644
index 00000000..d332797f
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/stream/package.json
@@ -0,0 +1,84 @@
+{
+  "_args": [
+    [
+      "@serialport/stream@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "@serialport/stream@>=2.0.1 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "@serialport/stream@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/@serialport/stream",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/stream_2.0.1_1535513363610_0.5446042396240458"
+  },
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
+  },
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "@serialport/stream",
+    "raw": "@serialport/stream@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": "@serialport",
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-2.0.1.tgz",
+  "_shasum": "a48ac2e72d4963816550cd71c2852d3799d3a1e3",
+  "_shrinkwrap": null,
+  "_spec": "@serialport/stream@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
+  },
+  "dependencies": {
+    "@serialport/binding-mock": "^2.0.1",
+    "debug": "^3.1.0"
+  },
+  "description": "The serialport stream interface. This package requires bindings to work.",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-/m+TLQyCWLm4QczjHu1VEjM2LkFhN6f9O3BlMh/AK55I8vOJ9vZycZAVLSFF2ybqB5wFCHfZD2fbbWfyeA28bA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhMUCRA9TVsSAnZWagAA2iYP/jNIg9fgxGv5MzqOCtff\nr2nC0sAcXrJ9nSV1OCzEw9yTRag4TLm+DGuugrkXdt2drjqHmZLG3Vh88zvn\n/YoG6Sf583IEU7q8mmwDR38VOPF2biK4/WYQjsaqY/C66/XTnyDgRFyeumcT\nYNvMs+O0VFjraAWitTat2uohEFnPPeV6sSsl8oD67NIPgEbrkn7TVM6DGQ7T\nWwMt2MotteKLmxzUVp1imhhdmQoYXjLQM/ZTvPK20GqbSv9fcssGJANbl57d\nBy0iRJFeLf2bfvqeCUJbUoJx3My6ifixNfHn4terus7dudsuiwhhw+0ST/Tn\nIeGFV1KjU+Dzedufd+v76A3Eb0/npwjLirQAF3e/Ce8BikASCKQUwRZFlaoe\nmlyiUQ9kOQrra8YFf3BTrArAk0sJsoxwmNJa2Wr4HPLBeqPsUjN4Uc5+uh14\n7YzPe1yHMyrifX3CpnlhU/2SPoSaqKBU3t36xG4z9FcvN7C3k4QgtjDgMf3c\nrdZD308GvsRWYaQ65jztch40aiw9vl7dzVBxPcX0cKrjrWwq3/mkSsYVNDiO\n8IEuTV2oLgEvfCKmD94Q7AwD9JBHVAiYzQyQv0JjQsNCoAP8S4GAosWTTAno\nXKPGGls1HQg8X7TF+053T0xHsji6HlqiXVcHiOPtwi8minQZS16C9JIejI1U\nWrsh\r\n=/4ZO\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "a48ac2e72d4963816550cd71c2852d3799d3a1e3",
+    "tarball": "https://registry.npmjs.org/@serialport/stream/-/stream-2.0.1.tgz",
+    "unpackedSize": 27263
+  },
+  "engines": {
+    "node": ">=6.0.0"
+  },
+  "gitHead": "40a06fb71d659940ed5058316b594b9da9957c2f",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "license": "MIT",
+  "main": "stream.js",
+  "maintainers": [
+    {
+      "name": "reconbot",
+      "email": "wizard@roborooter.com"
+    }
+  ],
+  "name": "@serialport/stream",
+  "optionalDependencies": {},
+  "publishConfig": {
+    "access": "public"
+  },
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/@serialport/stream/stream.js b/input_devices/mag/node_modules/@serialport/stream/stream.js
new file mode 100644
index 00000000..988bcc3e
--- /dev/null
+++ b/input_devices/mag/node_modules/@serialport/stream/stream.js
@@ -0,0 +1,676 @@
+const stream = require('stream')
+const util = require('util')
+const debug = require('debug')('@serialport/stream')
+
+//  VALIDATION
+const DATABITS = Object.freeze([5, 6, 7, 8])
+const STOPBITS = Object.freeze([1, 1.5, 2])
+const PARITY = Object.freeze(['none', 'even', 'mark', 'odd', 'space'])
+const FLOWCONTROLS = Object.freeze(['xon', 'xoff', 'xany', 'rtscts'])
+
+const defaultSettings = Object.freeze({
+  autoOpen: true,
+  baudRate: 9600,
+  dataBits: 8,
+  hupcl: true,
+  lock: true,
+  parity: 'none',
+  rtscts: false,
+  stopBits: 1,
+  xany: false,
+  xoff: false,
+  xon: false,
+  highWaterMark: 64 * 1024,
+})
+
+const defaultSetFlags = Object.freeze({
+  brk: false,
+  cts: false,
+  dtr: true,
+  dts: false,
+  rts: true,
+})
+
+function allocNewReadPool(poolSize) {
+  const pool = Buffer.allocUnsafe(poolSize)
+  pool.used = 0
+  return pool
+}
+
+/**
+ * A callback called with an error or null.
+ * @typedef {function} errorCallback
+ * @param {?error} error
+ */
+
+/**
+ * A callback called with an error or an object with the modem line values (cts, dsr, dcd).
+ * @typedef {function} modemBitsCallback
+ * @param {?error} error
+ * @param {?object} status
+ * @param {boolean} [status.cts=false]
+ * @param {boolean} [status.dsr=false]
+ * @param {boolean} [status.dcd=false]
+ */
+
+/**
+ * @typedef {Object} openOptions
+ * @property {boolean} [autoOpen=true] Automatically opens the port on `nextTick`.
+ * @property {number=} [baudRate=9600] The baud rate of the port to be opened. This should match one of the commonly available baud rates, such as 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, or 115200. Custom rates are supported best effort per platform. The device connected to the serial port is not guaranteed to support the requested baud rate, even if the port itself supports that baud rate.
+ * @property {number} [dataBits=8] Must be one of these: 8, 7, 6, or 5.
+ * @property {number} [highWaterMark=65536] The size of the read and write buffers defaults to 64k.
+ * @property {boolean} [lock=true] Prevent other processes from opening the port. Windows does not currently support `false`.
+ * @property {number} [stopBits=1] Must be one of these: 1 or 2.
+ * @property {string} [parity=none] Must be one of these: 'none', 'even', 'mark', 'odd', 'space'.
+ * @property {boolean} [rtscts=false] flow control setting
+ * @property {boolean} [xon=false] flow control setting
+ * @property {boolean} [xoff=false] flow control setting
+ * @property {boolean} [xany=false] flow control setting
+ * @property {object=} bindingOptions sets binding-specific options
+ * @property {Binding=} Binding The hardware access binding. `Bindings` are how Node-Serialport talks to the underlying system. By default we auto detect Windows (`WindowsBinding`), Linux (`LinuxBinding`) and OS X (`DarwinBinding`) and load the appropriate module for your system.
+ * @property {number} [bindingOptions.vmin=1] see [`man termios`](http://linux.die.net/man/3/termios) LinuxBinding and DarwinBinding
+ * @property {number} [bindingOptions.vtime=0] see [`man termios`](http://linux.die.net/man/3/termios) LinuxBinding and DarwinBinding
+ */
+
+/**
+ * Create a new serial port object for the `path`. In the case of invalid arguments or invalid options, when constructing a new SerialPort it will throw an error. The port will open automatically by default, which is the equivalent of calling `port.open(openCallback)` in the next tick. You can disable this by setting the option `autoOpen` to `false`.
+ * @class SerialPort
+ * @param {string} path - The system path of the serial port you want to open. For example, `/dev/tty.XXX` on Mac/Linux, or `COM1` on Windows.
+ * @param {openOptions=} options - Port configuration options
+ * @param {errorCallback=} openCallback - Called after a connection is opened. If this is not provided and an error occurs, it will be emitted on the port's `error` event. The callback will NOT be called if `autoOpen` is set to `false` in the `openOptions` as the open will not be performed.
+ * @property {number} baudRate The port's baudRate. Use `.update` to change it. Read-only.
+ * @property {object} binding The binding object backing the port. Read-only.
+ * @property {boolean} isOpen `true` if the port is open, `false` otherwise. Read-only. (`since 5.0.0`)
+ * @property {string} path The system path or name of the serial port. Read-only.
+ * @throws {TypeError} When given invalid arguments, a `TypeError` will be thrown.
+ * @emits open
+ * @emits data
+ * @emits close
+ * @emits error
+ * @alias module:serialport
+ */
+function SerialPort(path, options, openCallback) {
+  if (!(this instanceof SerialPort)) {
+    return new SerialPort(path, options, openCallback)
+  }
+
+  if (options instanceof Function) {
+    openCallback = options
+    options = {}
+  }
+
+  const settings = Object.assign({}, defaultSettings, options)
+
+  stream.Duplex.call(this, {
+    highWaterMark: settings.highWaterMark,
+  })
+
+  const Binding = settings.binding || SerialPort.Binding
+
+  if (!Binding) {
+    throw new TypeError(
+      '"Bindings" is invalid pass it as `options.binding` or set it on `SerialPort.Binding`'
+    )
+  }
+
+  if (!path) {
+    throw new TypeError(`"path" is not defined: ${path}`)
+  }
+
+  if (settings.baudrate) {
+    throw new TypeError(
+      `"baudrate" is an unknown option, did you mean "baudRate"?`
+    )
+  }
+
+  if (typeof settings.baudRate !== 'number') {
+    throw new TypeError(`"baudRate" must be a number: ${settings.baudRate}`)
+  }
+
+  if (DATABITS.indexOf(settings.dataBits) === -1) {
+    throw new TypeError(`"databits" is invalid: ${settings.dataBits}`)
+  }
+
+  if (STOPBITS.indexOf(settings.stopBits) === -1) {
+    throw new TypeError(`"stopbits" is invalid: ${settings.stopbits}`)
+  }
+
+  if (PARITY.indexOf(settings.parity) === -1) {
+    throw new TypeError(`"parity" is invalid: ${settings.parity}`)
+  }
+
+  FLOWCONTROLS.forEach(control => {
+    if (typeof settings[control] !== 'boolean') {
+      throw new TypeError(`"${control}" is not boolean: ${settings[control]}`)
+    }
+  })
+
+  const binding = new Binding({
+    bindingOptions: settings.bindingOptions,
+  })
+
+  Object.defineProperties(this, {
+    binding: {
+      enumerable: true,
+      value: binding,
+    },
+    path: {
+      enumerable: true,
+      value: path,
+    },
+    settings: {
+      enumerable: true,
+      value: settings,
+    },
+  })
+
+  this.opening = false
+  this.closing = false
+  this._pool = allocNewReadPool(this.settings.highWaterMark)
+  this._kMinPoolSpace = 128
+
+  if (this.settings.autoOpen) {
+    this.open(openCallback)
+  }
+}
+
+util.inherits(SerialPort, stream.Duplex)
+
+Object.defineProperties(SerialPort.prototype, {
+  isOpen: {
+    enumerable: true,
+    get() {
+      return this.binding.isOpen && !this.closing
+    },
+  },
+  baudRate: {
+    enumerable: true,
+    get() {
+      return this.settings.baudRate
+    },
+  },
+})
+
+/**
+ * The `error` event's callback is called with an error object whenever there is an error.
+ * @event error
+ */
+
+SerialPort.prototype._error = function(error, callback) {
+  if (callback) {
+    callback.call(this, error)
+  } else {
+    this.emit('error', error)
+  }
+}
+
+SerialPort.prototype._asyncError = function(error, callback) {
+  process.nextTick(() => this._error(error, callback))
+}
+
+/**
+ * The `open` event's callback is called with no arguments when the port is opened and ready for writing. This happens if you have the constructor open immediately (which opens in the next tick) or if you open the port manually with `open()`. See [Useage/Opening a Port](#opening-a-port) for more information.
+ * @event open
+ */
+
+/**
+ * Opens a connection to the given serial port.
+ * @param {errorCallback=} openCallback - Called after a connection is opened. If this is not provided and an error occurs, it will be emitted on the port's `error` event.
+ * @emits open
+ * @returns {undefined}
+ */
+SerialPort.prototype.open = function(openCallback) {
+  if (this.isOpen) {
+    return this._asyncError(new Error('Port is already open'), openCallback)
+  }
+
+  if (this.opening) {
+    return this._asyncError(new Error('Port is opening'), openCallback)
+  }
+
+  this.opening = true
+  debug('opening', `path: ${this.path}`)
+  this.binding.open(this.path, this.settings).then(
+    () => {
+      debug('opened', `path: ${this.path}`)
+      this.opening = false
+      this.emit('open')
+      if (openCallback) {
+        openCallback.call(this, null)
+      }
+    },
+    err => {
+      this.opening = false
+      debug('Binding #open had an error', err)
+      this._error(err, openCallback)
+    }
+  )
+}
+
+/**
+ * Changes the baud rate for an open port. Throws if you provide a bad argument. Emits an error or calls the callback if the baud rate isn't supported.
+ * @param {object=} options Only supports `baudRate`.
+ * @param {number=} [options.baudRate] The baud rate of the port to be opened. This should match one of the commonly available baud rates, such as 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, or 115200. Custom rates are supported best effort per platform. The device connected to the serial port is not guaranteed to support the requested baud rate, even if the port itself supports that baud rate.
+ * @param {errorCallback=} [callback] Called once the port's baud rate changes. If `.update` is called without a callback, and there is an error, an error event is emitted.
+ * @returns {undefined}
+ */
+SerialPort.prototype.update = function(options, callback) {
+  if (typeof options !== 'object') {
+    throw TypeError('"options" is not an object')
+  }
+
+  if (!this.isOpen) {
+    debug('update attempted, but port is not open')
+    return this._asyncError(new Error('Port is not open'), callback)
+  }
+
+  const settings = Object.assign({}, defaultSettings, options)
+  this.settings.baudRate = settings.baudRate
+
+  debug('update', `baudRate: ${settings.baudRate}`)
+  this.binding.update(this.settings).then(
+    () => {
+      debug('binding.update', 'finished')
+      if (callback) {
+        callback.call(this, null)
+      }
+    },
+    err => {
+      debug('binding.update', 'error', err)
+      return this._error(err, callback)
+    }
+  )
+}
+
+/**
+ * Writes data to the given serial port. Buffers written data if the port is not open.
+
+The write operation is non-blocking. When it returns, data might still not have been written to the serial port. See `drain()`.
+
+Some devices, like the Arduino, reset when you open a connection to them. In such cases, immediately writing to the device will cause lost data as they wont be ready to receive the data. This is often worked around by having the Arduino send a "ready" byte that your Node program waits for before writing. You can also often get away with waiting around 400ms.
+
+If a port is disconnected during a write, the write will error in addition to the `close` event.
+
+From the [stream docs](https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback) write errors don't always provide the error in the callback, sometimes they use the error event.
+> If an error occurs, the callback may or may not be called with the error as its first argument. To reliably detect write errors, add a listener for the 'error' event.
+
+In addition to the usual `stream.write` arguments (`String` and `Buffer`), `write()` can accept arrays of bytes (positive numbers under 256) which is passed to `Buffer.from([])` for conversion. This extra functionality is pretty sweet.
+ * @method SerialPort.prototype.write
+ * @param  {(string|array|buffer)} data Accepts a [`Buffer` ](http://nodejs.org/api/buffer.html) object, or a type that is accepted by the `Buffer` constructor (e.g. an array of bytes or a string).
+ * @param  {string=} encoding The encoding, if chunk is a string. Defaults to `'utf8'`. Also accepts `'ascii'`, `'base64'`, `'binary'`, and `'hex'` See [Buffers and Character Encodings](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) for all available options.
+ * @param  {function=} callback Called once the write operation finishes. Data may not yet be flushed to the underlying port. No arguments.
+ * @returns {boolean} `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
+ * @since 5.0.0
+ */
+const superWrite = SerialPort.prototype.write
+SerialPort.prototype.write = function(data, encoding, callback) {
+  if (Array.isArray(data)) {
+    data = Buffer.from(data)
+  }
+  return superWrite.call(this, data, encoding, callback)
+}
+
+SerialPort.prototype._write = function(data, encoding, callback) {
+  if (!this.isOpen) {
+    return this.once('open', function afterOpenWrite() {
+      this._write(data, encoding, callback)
+    })
+  }
+  debug('_write', `${data.length} bytes of data`)
+  this.binding.write(data).then(
+    () => {
+      debug('binding.write', 'write finished')
+      callback(null)
+    },
+    err => {
+      debug('binding.write', 'error', err)
+      if (!err.canceled) {
+        this._disconnected(err)
+      }
+      callback(err)
+    }
+  )
+}
+
+SerialPort.prototype._writev = function(data, callback) {
+  debug('_writev', `${data.length} chunks of data`)
+  const dataV = data.map(write => write.chunk)
+  this._write(Buffer.concat(dataV), null, callback)
+}
+
+/**
+ * Request a number of bytes from the SerialPort. The `read()` method pulls some data out of the internal buffer and returns it. If no data is available to be read, null is returned. By default, the data is returned as a `Buffer` object unless an encoding has been specified using the `.setEncoding()` method.
+ * @method SerialPort.prototype.read
+ * @param {number=} size Specify how many bytes of data to return, if available
+ * @returns {(string|Buffer|null)} The data from internal buffers
+ * @since 5.0.0
+ */
+
+/**
+ * Listening for the `data` event puts the port in flowing mode. Data is emitted as soon as it's received. Data is a `Buffer` object with a varying amount of data in it. The `readLine` parser converts the data into string lines. See the [parsers](https://node-serialport.github.io/node-serialport/global.html#Parsers) section for more information on parsers, and the [Node.js stream documentation](https://nodejs.org/api/stream.html#stream_event_data) for more information on the data event.
+ * @event data
+ */
+
+SerialPort.prototype._read = function(bytesToRead) {
+  if (!this.isOpen) {
+    debug('_read', 'queueing _read for after open')
+    this.once('open', () => {
+      this._read(bytesToRead)
+    })
+    return
+  }
+
+  if (
+    !this._pool ||
+    this._pool.length - this._pool.used < this._kMinPoolSpace
+  ) {
+    debug('_read', 'discarding the read buffer pool')
+    this._pool = allocNewReadPool(this.settings.highWaterMark)
+  }
+
+  // Grab another reference to the pool in the case that while we're
+  // in the thread pool another read() finishes up the pool, and
+  // allocates a new one.
+  const pool = this._pool
+  // Read the smaller of rest of the pool or however many bytes we want
+  const toRead = Math.min(pool.length - pool.used, bytesToRead)
+  const start = pool.used
+
+  // the actual read.
+  debug('_read', `reading`)
+  this.binding.read(pool, start, toRead).then(
+    bytesRead => {
+      debug('binding.read', `finished`)
+      // zero bytes means read means we've hit EOF? Maybe this should be an error
+      if (bytesRead === 0) {
+        debug('binding.read', 'Zero bytes read closing readable stream')
+        this.push(null)
+        return
+      }
+      pool.used += bytesRead
+      this.push(pool.slice(start, start + bytesRead))
+    },
+    err => {
+      debug('binding.read', `error`, err)
+      if (!err.canceled) {
+        this._disconnected(err)
+      }
+      this._read(bytesToRead) // prime to read more once we're reconnected
+    }
+  )
+}
+
+SerialPort.prototype._disconnected = function(err) {
+  if (!this.isOpen) {
+    debug('disconnected aborted because already closed', err)
+    return
+  }
+  debug('disconnected', err)
+  err.disconnected = true
+  this.close(null, err)
+}
+
+/**
+ * The `close` event's callback is called with no arguments when the port is closed. In the case of a disconnect it will be called with a Disconnect Error object (`err.disconnected == true`). In the event of a close error (unlikely), an error event is triggered.
+ * @event close
+ */
+
+/**
+ * Closes an open connection.
+ *
+ * If there are in progress writes when the port is closed the writes will error.
+ * @param {errorCallback} callback Called once a connection is closed.
+ * @param {Error} disconnectError used internally to propagate a disconnect error
+ * @emits close
+ * @returns {undefined}
+ */
+SerialPort.prototype.close = function(callback, disconnectError) {
+  disconnectError = disconnectError || null
+
+  if (!this.isOpen) {
+    debug('close attempted, but port is not open')
+    return this._asyncError(new Error('Port is not open'), callback)
+  }
+
+  this.closing = true
+  debug('#close')
+  this.binding.close().then(
+    () => {
+      this.closing = false
+      debug('binding.close', 'finished')
+      this.emit('close', disconnectError)
+      if (callback) {
+        callback.call(this, disconnectError)
+      }
+    },
+    err => {
+      this.closing = false
+      debug('binding.close', 'had an error', err)
+      return this._error(err, callback)
+    }
+  )
+}
+
+/**
+ * Set control flags on an open port. Uses [`SetCommMask`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363257(v=vs.85).aspx) for Windows and [`ioctl`](http://linux.die.net/man/4/tty_ioctl) for OS X and Linux.
+ * @param {object=} options All options are operating system default when the port is opened. Every flag is set on each call to the provided or default values. If options isn't provided default options is used.
+ * @param {Boolean} [options.brk=false] sets the brk flag
+ * @param {Boolean} [options.cts=false] sets the cts flag
+ * @param {Boolean} [options.dsr=false] sets the dsr flag
+ * @param {Boolean} [options.dtr=true] sets the dtr flag
+ * @param {Boolean} [options.rts=true] sets the rts flag
+ * @param {errorCallback=} callback Called once the port's flags have been set.
+ * @since 5.0.0
+ * @returns {undefined}
+ */
+SerialPort.prototype.set = function(options, callback) {
+  if (typeof options !== 'object') {
+    throw TypeError('"options" is not an object')
+  }
+
+  if (!this.isOpen) {
+    debug('set attempted, but port is not open')
+    return this._asyncError(new Error('Port is not open'), callback)
+  }
+
+  const settings = Object.assign({}, defaultSetFlags, options)
+  debug('#set', settings)
+  this.binding.set(settings).then(
+    () => {
+      debug('binding.set', 'finished')
+      if (callback) {
+        callback.call(this, null)
+      }
+    },
+    err => {
+      debug('binding.set', 'had an error', err)
+      return this._error(err, callback)
+    }
+  )
+}
+
+/**
+ * Returns the control flags (CTS, DSR, DCD) on the open port.
+ * Uses [`GetCommModemStatus`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363258(v=vs.85).aspx) for Windows and [`ioctl`](http://linux.die.net/man/4/tty_ioctl) for mac and linux.
+ * @param {modemBitsCallback=} callback Called once the modem bits are retrieved.
+ * @returns {undefined}
+ */
+SerialPort.prototype.get = function(callback) {
+  if (!this.isOpen) {
+    debug('get attempted, but port is not open')
+    return this._asyncError(new Error('Port is not open'), callback)
+  }
+
+  debug('#get')
+  this.binding.get().then(
+    status => {
+      debug('binding.get', 'finished')
+      if (callback) {
+        callback.call(this, null, status)
+      }
+    },
+    err => {
+      debug('binding.get', 'had an error', err)
+      return this._error(err, callback)
+    }
+  )
+}
+
+/**
+ * Flush discards data received but not read, and written but not transmitted by the operating system. For more technical details, see [`tcflush(fd, TCIOFLUSH)`](http://linux.die.net/man/3/tcflush) for Mac/Linux and [`FlushFileBuffers`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa364439) for Windows.
+ * @param  {errorCallback=} callback Called once the flush operation finishes.
+ * @returns {undefined}
+ */
+SerialPort.prototype.flush = function(callback) {
+  if (!this.isOpen) {
+    debug('flush attempted, but port is not open')
+    return this._asyncError(new Error('Port is not open'), callback)
+  }
+
+  debug('#flush')
+  this.binding.flush().then(
+    () => {
+      debug('binding.flush', 'finished')
+      if (callback) {
+        callback.call(this, null)
+      }
+    },
+    err => {
+      debug('binding.flush', 'had an error', err)
+      return this._error(err, callback)
+    }
+  )
+}
+
+/**
+ * Waits until all output data is transmitted to the serial port. After any pending write has completed it calls [`tcdrain()`](http://linux.die.net/man/3/tcdrain) or [FlushFileBuffers()](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364439(v=vs.85).aspx) to ensure it has been written to the device.
+ * @param {errorCallback=} callback Called once the drain operation returns.
+ * @returns {undefined}
+ * @example
+Write the `data` and wait until it has finished transmitting to the target serial port before calling the callback. This will queue until the port is open and writes are finished.
+
+```js
+function writeAndDrain (data, callback) {
+  port.write(data);
+  port.drain(callback);
+}
+```
+ */
+SerialPort.prototype.drain = function(callback) {
+  debug('drain')
+  if (!this.isOpen) {
+    debug('drain queuing on port open')
+    return this.once('open', () => {
+      this.drain(callback)
+    })
+  }
+  this.binding.drain().then(
+    () => {
+      debug('binding.drain', 'finished')
+      if (callback) {
+        callback.call(this, null)
+      }
+    },
+    err => {
+      debug('binding.drain', 'had an error', err)
+      return this._error(err, callback)
+    }
+  )
+}
+
+/**
+ * The `pause()` method causes a stream in flowing mode to stop emitting 'data' events, switching out of flowing mode. Any data that becomes available remains in the internal buffer.
+ * @method SerialPort.prototype.pause
+ * @see resume
+ * @since 5.0.0
+ * @returns `this`
+ */
+
+/**
+ * The `resume()` method causes an explicitly paused, `Readable` stream to resume emitting 'data' events, switching the stream into flowing mode.
+ * @method SerialPort.prototype.resume
+ * @see pause
+ * @since 5.0.0
+ * @returns `this`
+ */
+
+/**
+ * This callback type is called `requestCallback`.
+ * @callback listCallback
+ * @param {?error} error
+ * @param {array} ports an array of objects with port info
+ */
+
+/**
+ * Retrieves a list of available serial ports with metadata. Only the `comName` is guaranteed. If unavailable the other fields will be undefined. The `comName` is either the path or an identifier (eg `COM1`) used to open the SerialPort.
+ *
+ * We make an effort to identify the hardware attached and have consistent results between systems. Linux and OS X are mostly consistent. Windows relies on 3rd party device drivers for the information and is unable to guarantee the information. On windows If you have a USB connected device can we provide a serial number otherwise it will be `undefined`. The `pnpId` and `locationId` are not the same or present on all systems. The examples below were run with the same Arduino Uno.
+ * @type {function}
+ * @param {listCallback=} callback Called with a list of available serial ports.
+ * @returns {Promise} Resolves with the list of available serial ports.
+ * @example
+```js
+// OSX example port
+{
+  comName: '/dev/tty.usbmodem1421',
+  manufacturer: 'Arduino (www.arduino.cc)',
+  serialNumber: '752303138333518011C1',
+  pnpId: undefined,
+  locationId: '14500000',
+  productId: '0043',
+  vendorId: '2341'
+}
+
+// Linux example port
+{
+  comName: '/dev/ttyACM0',
+  manufacturer: 'Arduino (www.arduino.cc)',
+  serialNumber: '752303138333518011C1',
+  pnpId: 'usb-Arduino__www.arduino.cc__0043_752303138333518011C1-if00',
+  locationId: undefined,
+  productId: '0043',
+  vendorId: '2341'
+}
+
+// Windows example port
+{
+  comName: 'COM3',
+  manufacturer: 'Arduino LLC (www.arduino.cc)',
+  serialNumber: '752303138333518011C1',
+  pnpId: 'USB\\VID_2341&PID_0043\\752303138333518011C1',
+  locationId: 'Port_#0003.Hub_#0001',
+  productId: '0043',
+  vendorId: '2341'
+}
+```
+
+```js
+var SerialPort = require('serialport');
+// callback approach
+SerialPort.list(function (err, ports) {
+  ports.forEach(function(port) {
+    console.log(port.comName);
+    console.log(port.pnpId);
+    console.log(port.manufacturer);
+  });
+});
+
+// promise approach
+SerialPort.list()
+  .then(ports) {...});
+  .catch(err) {...});
+```
+ */
+SerialPort.list = function(callback) {
+  if (!SerialPort.Binding) {
+    throw new TypeError('No Binding set on `SerialPort.Binding`')
+  }
+  debug('.list')
+  const promise = SerialPort.Binding.list()
+  if (typeof callback === 'function') {
+    promise.then(ports => callback(null, ports), err => callback(err))
+  }
+  return promise
+}
+
+module.exports = SerialPort
diff --git a/input_devices/mag/node_modules/ansi-bgblack/LICENSE b/input_devices/mag/node_modules/ansi-bgblack/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblack/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bgblack/README.md b/input_devices/mag/node_modules/ansi-bgblack/README.md
new file mode 100644
index 00000000..21782e22
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblack/README.md
@@ -0,0 +1,74 @@
+# ansi-bgblack [![NPM version](https://badge.fury.io/js/ansi-bgblack.svg)](http://badge.fury.io/js/ansi-bgblack)
+
+> The color bgblack, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bgblack --save
+```
+
+## Usage
+
+```js
+var bgblack = require('ansi-bgblack');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bgblack/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bgblack/index.js b/input_devices/mag/node_modules/ansi-bgblack/index.js
new file mode 100644
index 00000000..639488fc
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblack/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bgblack <https://github.com/jonschlinkert/ansi-bgblack>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bgblack(message) {
+  return wrap(40, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bgblack/package.json b/input_devices/mag/node_modules/ansi-bgblack/package.json
new file mode 100644
index 00000000..c0c84be1
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblack/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bgblack@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bgblack@>=0.1.1 <0.2.0",
+  "_id": "ansi-bgblack@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bgblack",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bgblack",
+    "raw": "ansi-bgblack@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bgblack/-/ansi-bgblack-0.1.1.tgz",
+  "_shasum": "a68ba5007887701b6aafbe3fa0dadfdfa8ee3ca2",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bgblack@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bgblack/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bgblack, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a68ba5007887701b6aafbe3fa0dadfdfa8ee3ca2",
+    "tarball": "https://registry.npmjs.org/ansi-bgblack/-/ansi-bgblack-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bgblack",
+  "keywords": [
+    "256",
+    "ansi",
+    "bgblack",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bgblack",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bgblack.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bgblue/LICENSE b/input_devices/mag/node_modules/ansi-bgblue/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblue/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bgblue/index.js b/input_devices/mag/node_modules/ansi-bgblue/index.js
new file mode 100644
index 00000000..495add2d
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblue/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bgblue <https://github.com/jonschlinkert/ansi-bgblue>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bgblue(message) {
+  return wrap(44, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bgblue/package.json b/input_devices/mag/node_modules/ansi-bgblue/package.json
new file mode 100644
index 00000000..213e5a20
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblue/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bgblue@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bgblue@>=0.1.1 <0.2.0",
+  "_id": "ansi-bgblue@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bgblue",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bgblue",
+    "raw": "ansi-bgblue@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bgblue/-/ansi-bgblue-0.1.1.tgz",
+  "_shasum": "67bdc04edc9b9b5278969da196dea3d75c8c3613",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bgblue@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bgblue/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bgblue, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "67bdc04edc9b9b5278969da196dea3d75c8c3613",
+    "tarball": "https://registry.npmjs.org/ansi-bgblue/-/ansi-bgblue-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bgblue",
+  "keywords": [
+    "256",
+    "ansi",
+    "bgblue",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bgblue",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bgblue.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bgblue/readme.md b/input_devices/mag/node_modules/ansi-bgblue/readme.md
new file mode 100644
index 00000000..cb94c137
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgblue/readme.md
@@ -0,0 +1,74 @@
+# ansi-bgblue [![NPM version](https://badge.fury.io/js/ansi-bgblue.svg)](http://badge.fury.io/js/ansi-bgblue)
+
+> The color bgblue, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bgblue --save
+```
+
+## Usage
+
+```js
+var bgblue = require('ansi-bgblue');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bgblue/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bgcyan/LICENSE b/input_devices/mag/node_modules/ansi-bgcyan/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgcyan/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bgcyan/index.js b/input_devices/mag/node_modules/ansi-bgcyan/index.js
new file mode 100644
index 00000000..b5c116d6
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgcyan/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bgcyan <https://github.com/jonschlinkert/ansi-bgcyan>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bgcyan(message) {
+  return wrap(46, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bgcyan/package.json b/input_devices/mag/node_modules/ansi-bgcyan/package.json
new file mode 100644
index 00000000..395aedfd
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgcyan/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bgcyan@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bgcyan@>=0.1.1 <0.2.0",
+  "_id": "ansi-bgcyan@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bgcyan",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bgcyan",
+    "raw": "ansi-bgcyan@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bgcyan/-/ansi-bgcyan-0.1.1.tgz",
+  "_shasum": "58489425600bde9f5507068dd969ebfdb50fe768",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bgcyan@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bgcyan/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bgcyan, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "58489425600bde9f5507068dd969ebfdb50fe768",
+    "tarball": "https://registry.npmjs.org/ansi-bgcyan/-/ansi-bgcyan-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bgcyan",
+  "keywords": [
+    "256",
+    "ansi",
+    "bgcyan",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bgcyan",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bgcyan.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bgcyan/readme.md b/input_devices/mag/node_modules/ansi-bgcyan/readme.md
new file mode 100644
index 00000000..a841ad55
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgcyan/readme.md
@@ -0,0 +1,74 @@
+# ansi-bgcyan [![NPM version](https://badge.fury.io/js/ansi-bgcyan.svg)](http://badge.fury.io/js/ansi-bgcyan)
+
+> The color bgcyan, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bgcyan --save
+```
+
+## Usage
+
+```js
+var bgcyan = require('ansi-bgcyan');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bgcyan/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bggreen/LICENSE b/input_devices/mag/node_modules/ansi-bggreen/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bggreen/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bggreen/index.js b/input_devices/mag/node_modules/ansi-bggreen/index.js
new file mode 100644
index 00000000..e933981e
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bggreen/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bggreen <https://github.com/jonschlinkert/ansi-bggreen>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bggreen(message) {
+  return wrap(42, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bggreen/package.json b/input_devices/mag/node_modules/ansi-bggreen/package.json
new file mode 100644
index 00000000..7b6b5691
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bggreen/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bggreen@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bggreen@>=0.1.1 <0.2.0",
+  "_id": "ansi-bggreen@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bggreen",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bggreen",
+    "raw": "ansi-bggreen@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bggreen/-/ansi-bggreen-0.1.1.tgz",
+  "_shasum": "4e3191248529943f4321e96bf131d1c13816af49",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bggreen@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bggreen/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bggreen, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "4e3191248529943f4321e96bf131d1c13816af49",
+    "tarball": "https://registry.npmjs.org/ansi-bggreen/-/ansi-bggreen-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bggreen",
+  "keywords": [
+    "256",
+    "ansi",
+    "bggreen",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bggreen",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bggreen.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bggreen/readme.md b/input_devices/mag/node_modules/ansi-bggreen/readme.md
new file mode 100644
index 00000000..48cb4973
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bggreen/readme.md
@@ -0,0 +1,74 @@
+# ansi-bggreen [![NPM version](https://badge.fury.io/js/ansi-bggreen.svg)](http://badge.fury.io/js/ansi-bggreen)
+
+> The color bggreen, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bggreen --save
+```
+
+## Usage
+
+```js
+var bggreen = require('ansi-bggreen');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bggreen/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bgmagenta/LICENSE b/input_devices/mag/node_modules/ansi-bgmagenta/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgmagenta/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bgmagenta/index.js b/input_devices/mag/node_modules/ansi-bgmagenta/index.js
new file mode 100644
index 00000000..2d125e63
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgmagenta/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bgmagenta <https://github.com/jonschlinkert/ansi-bgmagenta>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bgmagenta(message) {
+  return wrap(45, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bgmagenta/package.json b/input_devices/mag/node_modules/ansi-bgmagenta/package.json
new file mode 100644
index 00000000..01c03b5c
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgmagenta/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bgmagenta@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bgmagenta@>=0.1.1 <0.2.0",
+  "_id": "ansi-bgmagenta@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bgmagenta",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bgmagenta",
+    "raw": "ansi-bgmagenta@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bgmagenta/-/ansi-bgmagenta-0.1.1.tgz",
+  "_shasum": "9b28432c076eaa999418672a3efbe19391c2c7a1",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bgmagenta@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bgmagenta/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bgmagenta, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "9b28432c076eaa999418672a3efbe19391c2c7a1",
+    "tarball": "https://registry.npmjs.org/ansi-bgmagenta/-/ansi-bgmagenta-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bgmagenta",
+  "keywords": [
+    "256",
+    "ansi",
+    "bgmagenta",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bgmagenta",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bgmagenta.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bgmagenta/readme.md b/input_devices/mag/node_modules/ansi-bgmagenta/readme.md
new file mode 100644
index 00000000..e2d9513f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgmagenta/readme.md
@@ -0,0 +1,74 @@
+# ansi-bgmagenta [![NPM version](https://badge.fury.io/js/ansi-bgmagenta.svg)](http://badge.fury.io/js/ansi-bgmagenta)
+
+> The color bgmagenta, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bgmagenta --save
+```
+
+## Usage
+
+```js
+var bgmagenta = require('ansi-bgmagenta');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bgmagenta/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bgred/LICENSE b/input_devices/mag/node_modules/ansi-bgred/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgred/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bgred/index.js b/input_devices/mag/node_modules/ansi-bgred/index.js
new file mode 100644
index 00000000..81bd715b
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgred/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bgred <https://github.com/jonschlinkert/ansi-bgred>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bgred(message) {
+  return wrap(41, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bgred/package.json b/input_devices/mag/node_modules/ansi-bgred/package.json
new file mode 100644
index 00000000..20cc1746
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgred/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bgred@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bgred@>=0.1.1 <0.2.0",
+  "_id": "ansi-bgred@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bgred",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bgred",
+    "raw": "ansi-bgred@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bgred/-/ansi-bgred-0.1.1.tgz",
+  "_shasum": "a76f92838382ba43290a6c1778424f984d6f1041",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bgred@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bgred/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bgred, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a76f92838382ba43290a6c1778424f984d6f1041",
+    "tarball": "https://registry.npmjs.org/ansi-bgred/-/ansi-bgred-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bgred",
+  "keywords": [
+    "256",
+    "ansi",
+    "bgred",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bgred",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bgred.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bgred/readme.md b/input_devices/mag/node_modules/ansi-bgred/readme.md
new file mode 100644
index 00000000..fb4e5533
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgred/readme.md
@@ -0,0 +1,74 @@
+# ansi-bgred [![NPM version](https://badge.fury.io/js/ansi-bgred.svg)](http://badge.fury.io/js/ansi-bgred)
+
+> The color bgred, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bgred --save
+```
+
+## Usage
+
+```js
+var bgred = require('ansi-bgred');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bgred/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bgwhite/LICENSE b/input_devices/mag/node_modules/ansi-bgwhite/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgwhite/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bgwhite/index.js b/input_devices/mag/node_modules/ansi-bgwhite/index.js
new file mode 100644
index 00000000..a9ff8328
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgwhite/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bgwhite <https://github.com/jonschlinkert/ansi-bgwhite>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bgwhite(message) {
+  return wrap(47, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bgwhite/package.json b/input_devices/mag/node_modules/ansi-bgwhite/package.json
new file mode 100644
index 00000000..29386621
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgwhite/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bgwhite@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bgwhite@>=0.1.1 <0.2.0",
+  "_id": "ansi-bgwhite@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bgwhite",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bgwhite",
+    "raw": "ansi-bgwhite@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bgwhite/-/ansi-bgwhite-0.1.1.tgz",
+  "_shasum": "6504651377a58a6ececd0331994e480258e11ba8",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bgwhite@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bgwhite/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bgwhite, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "6504651377a58a6ececd0331994e480258e11ba8",
+    "tarball": "https://registry.npmjs.org/ansi-bgwhite/-/ansi-bgwhite-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bgwhite",
+  "keywords": [
+    "256",
+    "ansi",
+    "bgwhite",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bgwhite",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bgwhite.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bgwhite/readme.md b/input_devices/mag/node_modules/ansi-bgwhite/readme.md
new file mode 100644
index 00000000..85f5b0e7
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgwhite/readme.md
@@ -0,0 +1,74 @@
+# ansi-bgwhite [![NPM version](https://badge.fury.io/js/ansi-bgwhite.svg)](http://badge.fury.io/js/ansi-bgwhite)
+
+> The color bgwhite, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bgwhite --save
+```
+
+## Usage
+
+```js
+var bgwhite = require('ansi-bgwhite');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bgwhite/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bgyellow/LICENSE b/input_devices/mag/node_modules/ansi-bgyellow/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgyellow/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bgyellow/index.js b/input_devices/mag/node_modules/ansi-bgyellow/index.js
new file mode 100644
index 00000000..fc3b7eef
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgyellow/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bgyellow <https://github.com/jonschlinkert/ansi-bgyellow>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bgyellow(message) {
+  return wrap(43, 49, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bgyellow/package.json b/input_devices/mag/node_modules/ansi-bgyellow/package.json
new file mode 100644
index 00000000..a0299463
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgyellow/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bgyellow@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bgyellow@>=0.1.1 <0.2.0",
+  "_id": "ansi-bgyellow@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bgyellow",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bgyellow",
+    "raw": "ansi-bgyellow@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bgyellow/-/ansi-bgyellow-0.1.1.tgz",
+  "_shasum": "c3fe2eb08cd476648029e6874d15a0b38f61d44f",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bgyellow@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bgyellow/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bgyellow, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "c3fe2eb08cd476648029e6874d15a0b38f61d44f",
+    "tarball": "https://registry.npmjs.org/ansi-bgyellow/-/ansi-bgyellow-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bgyellow",
+  "keywords": [
+    "256",
+    "ansi",
+    "bgyellow",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bgyellow",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bgyellow.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bgyellow/readme.md b/input_devices/mag/node_modules/ansi-bgyellow/readme.md
new file mode 100644
index 00000000..74d531d2
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bgyellow/readme.md
@@ -0,0 +1,74 @@
+# ansi-bgyellow [![NPM version](https://badge.fury.io/js/ansi-bgyellow.svg)](http://badge.fury.io/js/ansi-bgyellow)
+
+> The color bgyellow, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bgyellow --save
+```
+
+## Usage
+
+```js
+var bgyellow = require('ansi-bgyellow');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bgyellow/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-black/LICENSE b/input_devices/mag/node_modules/ansi-black/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-black/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-black/index.js b/input_devices/mag/node_modules/ansi-black/index.js
new file mode 100644
index 00000000..9b3c92ed
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-black/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-black <https://github.com/jonschlinkert/ansi-black>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function black(message) {
+  return wrap(30, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-black/package.json b/input_devices/mag/node_modules/ansi-black/package.json
new file mode 100644
index 00000000..e73ec966
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-black/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-black@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-black@>=0.1.1 <0.2.0",
+  "_id": "ansi-black@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-black",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-black",
+    "raw": "ansi-black@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-black/-/ansi-black-0.1.1.tgz",
+  "_shasum": "f6185e889360b2545a1ec50c0bf063fc43032453",
+  "_shrinkwrap": null,
+  "_spec": "ansi-black@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-black/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color black, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "f6185e889360b2545a1ec50c0bf063fc43032453",
+    "tarball": "https://registry.npmjs.org/ansi-black/-/ansi-black-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-black",
+  "keywords": [
+    "256",
+    "ansi",
+    "black",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-black",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-black.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-black/readme.md b/input_devices/mag/node_modules/ansi-black/readme.md
new file mode 100644
index 00000000..a175e2e1
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-black/readme.md
@@ -0,0 +1,74 @@
+# ansi-black [![NPM version](https://badge.fury.io/js/ansi-black.svg)](http://badge.fury.io/js/ansi-black)
+
+> The color black, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-black --save
+```
+
+## Usage
+
+```js
+var black = require('ansi-black');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-black/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-blue/LICENSE b/input_devices/mag/node_modules/ansi-blue/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-blue/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-blue/index.js b/input_devices/mag/node_modules/ansi-blue/index.js
new file mode 100644
index 00000000..0a4e349d
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-blue/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-blue <https://github.com/jonschlinkert/ansi-blue>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function blue(message) {
+  return wrap(34, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-blue/package.json b/input_devices/mag/node_modules/ansi-blue/package.json
new file mode 100644
index 00000000..f082e7b8
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-blue/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-blue@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-blue@>=0.1.1 <0.2.0",
+  "_id": "ansi-blue@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-blue",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-blue",
+    "raw": "ansi-blue@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-blue/-/ansi-blue-0.1.1.tgz",
+  "_shasum": "15b804990e92fc9ca8c5476ce8f699777c21edbf",
+  "_shrinkwrap": null,
+  "_spec": "ansi-blue@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-blue/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color blue, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "15b804990e92fc9ca8c5476ce8f699777c21edbf",
+    "tarball": "https://registry.npmjs.org/ansi-blue/-/ansi-blue-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-blue",
+  "keywords": [
+    "256",
+    "ansi",
+    "blue",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-blue",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-blue.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-blue/readme.md b/input_devices/mag/node_modules/ansi-blue/readme.md
new file mode 100644
index 00000000..8fc3b046
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-blue/readme.md
@@ -0,0 +1,74 @@
+# ansi-blue [![NPM version](https://badge.fury.io/js/ansi-blue.svg)](http://badge.fury.io/js/ansi-blue)
+
+> The color blue, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-blue --save
+```
+
+## Usage
+
+```js
+var blue = require('ansi-blue');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-blue/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-bold/LICENSE b/input_devices/mag/node_modules/ansi-bold/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bold/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-bold/index.js b/input_devices/mag/node_modules/ansi-bold/index.js
new file mode 100644
index 00000000..a56a16dc
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bold/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-bold <https://github.com/jonschlinkert/ansi-bold>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function bold(message) {
+  return wrap(1, 22, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-bold/package.json b/input_devices/mag/node_modules/ansi-bold/package.json
new file mode 100644
index 00000000..e5ae27e5
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bold/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-bold@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-bold@>=0.1.1 <0.2.0",
+  "_id": "ansi-bold@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-bold",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-bold",
+    "raw": "ansi-bold@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-bold/-/ansi-bold-0.1.1.tgz",
+  "_shasum": "3e63950af5acc2ae2e670e6f67deb115d1a5f505",
+  "_shrinkwrap": null,
+  "_spec": "ansi-bold@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-bold/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color bold, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "3e63950af5acc2ae2e670e6f67deb115d1a5f505",
+    "tarball": "https://registry.npmjs.org/ansi-bold/-/ansi-bold-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-bold",
+  "keywords": [
+    "256",
+    "ansi",
+    "bold",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-bold",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-bold.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-bold/readme.md b/input_devices/mag/node_modules/ansi-bold/readme.md
new file mode 100644
index 00000000..e06c0ebf
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-bold/readme.md
@@ -0,0 +1,74 @@
+# ansi-bold [![NPM version](https://badge.fury.io/js/ansi-bold.svg)](http://badge.fury.io/js/ansi-bold)
+
+> The color bold, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-bold --save
+```
+
+## Usage
+
+```js
+var bold = require('ansi-bold');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-bold/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-colors/LICENSE b/input_devices/mag/node_modules/ansi-colors/LICENSE
new file mode 100644
index 00000000..5b613fed
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-colors/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Brian Woodward.
+
+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/input_devices/mag/node_modules/ansi-colors/README.md b/input_devices/mag/node_modules/ansi-colors/README.md
new file mode 100644
index 00000000..7e0a6ba3
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-colors/README.md
@@ -0,0 +1,94 @@
+# ansi-colors [![NPM version](https://img.shields.io/npm/v/ansi-colors.svg?style=flat)](https://www.npmjs.com/package/ansi-colors) [![NPM downloads](https://img.shields.io/npm/dm/ansi-colors.svg?style=flat)](https://npmjs.org/package/ansi-colors) [![Build Status](https://img.shields.io/travis/doowb/ansi-colors.svg?style=flat)](https://travis-ci.org/doowb/ansi-colors)
+
+Collection of ansi colors and styles.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save ansi-colors
+```
+
+This module was created to make it easy to allow color configuration through options.
+
+If your application will always one or two specific colors, we recommend directly requiring only [the necessary modules](#related-projects).
+
+If your application uses **more than 10 colors**, we recommend using [chalk](https://github.com/chalk/chalk) for faster require times (since chalk loads everything at once). However, when using less than 10 colors this module will be more efficient due to lazy caching the [underlying modules](#related-projects).
+
+## Usage
+
+```js
+var colors = require('ansi-colors');
+```
+
+## About
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [ansi-bgblack](https://www.npmjs.com/package/ansi-bgblack): The color bgblack, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bgblack "The color bgblack, in ansi.")
+* [ansi-bgblue](https://www.npmjs.com/package/ansi-bgblue): The color bgblue, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bgblue "The color bgblue, in ansi.")
+* [ansi-bgcyan](https://www.npmjs.com/package/ansi-bgcyan): The color bgcyan, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bgcyan "The color bgcyan, in ansi.")
+* [ansi-bggreen](https://www.npmjs.com/package/ansi-bggreen): The color bggreen, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bggreen "The color bggreen, in ansi.")
+* [ansi-bgmagenta](https://www.npmjs.com/package/ansi-bgmagenta): The color bgmagenta, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bgmagenta "The color bgmagenta, in ansi.")
+* [ansi-bgred](https://www.npmjs.com/package/ansi-bgred): The color bgred, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bgred "The color bgred, in ansi.")
+* [ansi-bgwhite](https://www.npmjs.com/package/ansi-bgwhite): The color bgwhite, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bgwhite "The color bgwhite, in ansi.")
+* [ansi-bgyellow](https://www.npmjs.com/package/ansi-bgyellow): The color bgyellow, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bgyellow "The color bgyellow, in ansi.")
+* [ansi-black](https://www.npmjs.com/package/ansi-black): The color black, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-black "The color black, in ansi.")
+* [ansi-blue](https://www.npmjs.com/package/ansi-blue): The color blue, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-blue "The color blue, in ansi.")
+* [ansi-bold](https://www.npmjs.com/package/ansi-bold): The color bold, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bold "The color bold, in ansi.")
+* [ansi-cyan](https://www.npmjs.com/package/ansi-cyan): The color cyan, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-cyan "The color cyan, in ansi.")
+* [ansi-dim](https://www.npmjs.com/package/ansi-dim): The color dim, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-dim "The color dim, in ansi.")
+* [ansi-gray](https://www.npmjs.com/package/ansi-gray): The color gray, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-gray "The color gray, in ansi.")
+* [ansi-green](https://www.npmjs.com/package/ansi-green): The color green, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-green "The color green, in ansi.")
+* [ansi-grey](https://www.npmjs.com/package/ansi-grey): The color grey, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-grey "The color grey, in ansi.")
+* [ansi-hidden](https://www.npmjs.com/package/ansi-hidden): The color hidden, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-hidden "The color hidden, in ansi.")
+* [ansi-inverse](https://www.npmjs.com/package/ansi-inverse): The color inverse, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-inverse "The color inverse, in ansi.")
+* [ansi-italic](https://www.npmjs.com/package/ansi-italic): The color italic, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-italic "The color italic, in ansi.")
+* [ansi-magenta](https://www.npmjs.com/package/ansi-magenta): The color magenta, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-magenta "The color magenta, in ansi.")
+* [ansi-red](https://www.npmjs.com/package/ansi-red): The color red, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-red "The color red, in ansi.")
+* [ansi-reset](https://www.npmjs.com/package/ansi-reset): The color reset, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-reset "The color reset, in ansi.")
+* [ansi-strikethrough](https://www.npmjs.com/package/ansi-strikethrough): The color strikethrough, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-strikethrough "The color strikethrough, in ansi.")
+* [ansi-underline](https://www.npmjs.com/package/ansi-underline): The color underline, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-underline "The color underline, in ansi.")
+* [ansi-white](https://www.npmjs.com/package/ansi-white): The color white, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-white "The color white, in ansi.")
+* [ansi-yellow](https://www.npmjs.com/package/ansi-yellow): The color yellow, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-yellow "The color yellow, in ansi.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This document was generated by [verb-readme-generator](https://github.com/verbose/verb-readme-generator) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
+
+Generate readme and API documentation with [verb](https://github.com/verbose/verb):
+
+```sh
+$ npm install -g verb verb-readme-generator && verb
+```
+
+### Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm install -d && npm test
+```
+
+### Author
+
+**Brian Woodward**
+
+* [github/doowb](https://github.com/doowb)
+* [twitter/doowb](http://twitter.com/doowb)
+
+### License
+
+Copyright © 2016, [Brian Woodward](https://github.com/doowb).
+Released under the [MIT license](https://github.com/doowb/ansi-colors/blob/master/LICENSE).
+
+***
+
+_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on July 11, 2016._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-colors/index.js b/input_devices/mag/node_modules/ansi-colors/index.js
new file mode 100644
index 00000000..5adfcdcc
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-colors/index.js
@@ -0,0 +1,434 @@
+/*!
+ * ansi-colors <https://github.com/doowb/ansi-colors>
+ *
+ * Copyright (c) 2015, Brian Woodward.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+/**
+ * Module dependencies
+ */
+
+var colors = require('lazy-cache')(require);
+
+/**
+ * Temporarily re-assign `require` to trick browserify and
+ * webpack into reconizing lazy dependencies.
+ *
+ * This tiny bit of ugliness has the huge dual advantage of
+ * only loading modules that are actually called at some
+ * point in the lifecycle of the application, whilst also
+ * allowing browserify and webpack to find modules that
+ * are depended on but never actually called.
+ */
+
+var fn = require;
+require = colors;
+
+/**
+ * Lazily required module dependencies
+ */
+
+/**
+ * Wrap a string with ansi codes to create a black background.
+ *
+ * ```js
+ * console.log(colors.bgblack('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bgblack
+ */
+
+require('ansi-bgblack', 'bgblack');
+
+/**
+ * Wrap a string with ansi codes to create a blue background.
+ *
+ * ```js
+ * console.log(colors.bgblue('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bgblue
+ */
+
+require('ansi-bgblue', 'bgblue');
+
+/**
+ * Wrap a string with ansi codes to create a cyan background.
+ *
+ * ```js
+ * console.log(colors.bgcyan('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bgcyan
+ */
+
+require('ansi-bgcyan', 'bgcyan');
+
+/**
+ * Wrap a string with ansi codes to create a green background.
+ *
+ * ```js
+ * console.log(colors.bggreen('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bggreen
+ */
+
+require('ansi-bggreen', 'bggreen');
+
+/**
+ * Wrap a string with ansi codes to create a magenta background.
+ *
+ * ```js
+ * console.log(colors.bgmagenta('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bgmagenta
+ */
+
+require('ansi-bgmagenta', 'bgmagenta');
+
+/**
+ * Wrap a string with ansi codes to create a red background.
+ *
+ * ```js
+ * console.log(colors.bgred('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bgred
+ */
+
+require('ansi-bgred', 'bgred');
+
+/**
+ * Wrap a string with ansi codes to create a white background.
+ *
+ * ```js
+ * console.log(colors.bgwhite('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bgwhite
+ */
+
+require('ansi-bgwhite', 'bgwhite');
+
+/**
+ * Wrap a string with ansi codes to create a yellow background.
+ *
+ * ```js
+ * console.log(colors.bgyellow('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bgyellow
+ */
+
+require('ansi-bgyellow', 'bgyellow');
+
+/**
+ * Wrap a string with ansi codes to create black text.
+ *
+ * ```js
+ * console.log(colors.black('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  black
+ */
+
+require('ansi-black', 'black');
+
+/**
+ * Wrap a string with ansi codes to create blue text.
+ *
+ * ```js
+ * console.log(colors.blue('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  blue
+ */
+
+require('ansi-blue', 'blue');
+
+/**
+ * Wrap a string with ansi codes to create bold text.
+ *
+ * ```js
+ * console.log(colors.bold('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  bold
+ */
+
+require('ansi-bold', 'bold');
+
+/**
+ * Wrap a string with ansi codes to create cyan text.
+ *
+ * ```js
+ * console.log(colors.cyan('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  cyan
+ */
+
+require('ansi-cyan', 'cyan');
+
+/**
+ * Wrap a string with ansi codes to create dim text.
+ *
+ * ```js
+ * console.log(colors.dim('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  dim
+ */
+
+require('ansi-dim', 'dim');
+
+/**
+ * Wrap a string with ansi codes to create gray text.
+ *
+ * ```js
+ * console.log(colors.gray('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  gray
+ */
+
+require('ansi-gray', 'gray');
+
+/**
+ * Wrap a string with ansi codes to create green text.
+ *
+ * ```js
+ * console.log(colors.green('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  green
+ */
+
+require('ansi-green', 'green');
+
+/**
+ * Wrap a string with ansi codes to create grey text.
+ *
+ * ```js
+ * console.log(colors.grey('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  grey
+ */
+
+require('ansi-grey', 'grey');
+
+/**
+ * Wrap a string with ansi codes to create hidden text.
+ *
+ * ```js
+ * console.log(colors.hidden('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  hidden
+ */
+
+require('ansi-hidden', 'hidden');
+
+/**
+ * Wrap a string with ansi codes to create inverse text.
+ *
+ * ```js
+ * console.log(colors.inverse('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  inverse
+ */
+
+require('ansi-inverse', 'inverse');
+
+/**
+ * Wrap a string with ansi codes to create italic text.
+ *
+ * ```js
+ * console.log(colors.italic('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  italic
+ */
+
+require('ansi-italic', 'italic');
+
+/**
+ * Wrap a string with ansi codes to create magenta text.
+ *
+ * ```js
+ * console.log(colors.magenta('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  magenta
+ */
+
+require('ansi-magenta', 'magenta');
+
+/**
+ * Wrap a string with ansi codes to create red text.
+ *
+ * ```js
+ * console.log(colors.red('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  red
+ */
+
+require('ansi-red', 'red');
+
+/**
+ * Wrap a string with ansi codes to reset ansi colors currently on the string.
+ *
+ * ```js
+ * console.log(colors.reset('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  reset
+ */
+
+require('ansi-reset', 'reset');
+
+/**
+ * Wrap a string with ansi codes to add a strikethrough to the text.
+ *
+ * ```js
+ * console.log(colors.strikethrough('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  strikethrough
+ */
+
+require('ansi-strikethrough', 'strikethrough');
+
+/**
+ * Wrap a string with ansi codes to underline the text.
+ *
+ * ```js
+ * console.log(colors.underline('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  underline
+ */
+
+require('ansi-underline', 'underline');
+
+/**
+ * Wrap a string with ansi codes to create white text.
+ *
+ * ```js
+ * console.log(colors.white('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  white
+ */
+
+require('ansi-white', 'white');
+
+/**
+ * Wrap a string with ansi codes to create yellow text.
+ *
+ * ```js
+ * console.log(colors.yellow('some string'));
+ * ```
+ *
+ * @param  {String} `str` String to wrap with ansi codes.
+ * @return {String} Wrapped string
+ * @api public
+ * @name  yellow
+ */
+
+require('ansi-yellow', 'yellow');
+
+/**
+ * Restore `require`
+ */
+
+require = fn;
+
+/**
+ * Expose `colors` modules
+ */
+
+module.exports = colors;
diff --git a/input_devices/mag/node_modules/ansi-colors/package.json b/input_devices/mag/node_modules/ansi-colors/package.json
new file mode 100644
index 00000000..cafa35e9
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-colors/package.json
@@ -0,0 +1,188 @@
+{
+  "_args": [
+    [
+      "ansi-colors@^0.2.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils"
+    ]
+  ],
+  "_from": "ansi-colors@>=0.2.0 <0.3.0",
+  "_id": "ansi-colors@0.2.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-colors",
+  "_nodeVersion": "6.2.0",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/ansi-colors-0.2.0.tgz_1468242571540_0.2293846202082932"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.8.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-colors",
+    "raw": "ansi-colors@^0.2.0",
+    "rawSpec": "^0.2.0",
+    "scope": null,
+    "spec": ">=0.2.0 <0.3.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/log-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz",
+  "_shasum": "72c31de2a0d9a2ccd0cac30cc9823eeb2f6434b5",
+  "_shrinkwrap": null,
+  "_spec": "ansi-colors@^0.2.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils",
+  "author": {
+    "name": "Brian Woodward",
+    "url": "https://github.com/doowb"
+  },
+  "bugs": {
+    "url": "https://github.com/doowb/ansi-colors/issues"
+  },
+  "dependencies": {
+    "ansi-bgblack": "^0.1.1",
+    "ansi-bgblue": "^0.1.1",
+    "ansi-bgcyan": "^0.1.1",
+    "ansi-bggreen": "^0.1.1",
+    "ansi-bgmagenta": "^0.1.1",
+    "ansi-bgred": "^0.1.1",
+    "ansi-bgwhite": "^0.1.1",
+    "ansi-bgyellow": "^0.1.1",
+    "ansi-black": "^0.1.1",
+    "ansi-blue": "^0.1.1",
+    "ansi-bold": "^0.1.1",
+    "ansi-cyan": "^0.1.1",
+    "ansi-dim": "^0.1.1",
+    "ansi-gray": "^0.1.1",
+    "ansi-green": "^0.1.1",
+    "ansi-grey": "^0.1.1",
+    "ansi-hidden": "^0.1.1",
+    "ansi-inverse": "^0.1.1",
+    "ansi-italic": "^0.1.1",
+    "ansi-magenta": "^0.1.1",
+    "ansi-red": "^0.1.1",
+    "ansi-reset": "^0.1.1",
+    "ansi-strikethrough": "^0.1.1",
+    "ansi-underline": "^0.1.1",
+    "ansi-white": "^0.1.1",
+    "ansi-yellow": "^0.1.1",
+    "lazy-cache": "^2.0.1"
+  },
+  "description": "Collection of ansi colors and styles.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.9",
+    "mocha": "^2.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "72c31de2a0d9a2ccd0cac30cc9823eeb2f6434b5",
+    "tarball": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "06cdbc9d6e290992ec4ce70f261c7866fa6524c4",
+  "homepage": "https://github.com/doowb/ansi-colors",
+  "keywords": [
+    "ansi-bgblack",
+    "ansi-bgblue",
+    "ansi-bgcyan",
+    "ansi-bggreen",
+    "ansi-bgmagenta",
+    "ansi-bgred",
+    "ansi-bgwhite",
+    "ansi-bgyellow",
+    "ansi-black",
+    "ansi-blue",
+    "ansi-bold",
+    "ansi-cyan",
+    "ansi-dim",
+    "ansi-gray",
+    "ansi-green",
+    "ansi-grey",
+    "ansi-hidden",
+    "ansi-inverse",
+    "ansi-italic",
+    "ansi-magenta",
+    "ansi-red",
+    "ansi-reset",
+    "ansi-strikethrough",
+    "ansi-underline",
+    "ansi-white",
+    "ansi-yellow",
+    "bgblack",
+    "bgblue",
+    "bgcyan",
+    "bggreen",
+    "bgmagenta",
+    "bgred",
+    "bgwhite",
+    "bgyellow",
+    "black",
+    "blue",
+    "bold",
+    "cyan",
+    "dim",
+    "gray",
+    "green",
+    "grey",
+    "hidden",
+    "inverse",
+    "italic",
+    "magenta",
+    "red",
+    "reset",
+    "strikethrough",
+    "underline",
+    "white",
+    "yellow"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-colors",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/doowb/ansi-colors.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-readme-generator"
+    ],
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.2.0"
+}
diff --git a/input_devices/mag/node_modules/ansi-cyan/LICENSE b/input_devices/mag/node_modules/ansi-cyan/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-cyan/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-cyan/index.js b/input_devices/mag/node_modules/ansi-cyan/index.js
new file mode 100644
index 00000000..b1e12c54
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-cyan/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-cyan <https://github.com/jonschlinkert/ansi-cyan>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function cyan(message) {
+  return wrap(36, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-cyan/package.json b/input_devices/mag/node_modules/ansi-cyan/package.json
new file mode 100644
index 00000000..dfe7608f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-cyan/package.json
@@ -0,0 +1,110 @@
+{
+  "_args": [
+    [
+      "ansi-cyan@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-list"
+    ]
+  ],
+  "_from": "ansi-cyan@>=0.1.1 <0.2.0",
+  "_id": "ansi-cyan@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-cyan",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-cyan",
+    "raw": "ansi-cyan@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors",
+    "/prompt-checkbox",
+    "/prompt-list"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz",
+  "_shasum": "538ae528af8982f28ae30d86f2f17456d2609873",
+  "_shrinkwrap": null,
+  "_spec": "ansi-cyan@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-list",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-cyan/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color cyan, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "538ae528af8982f28ae30d86f2f17456d2609873",
+    "tarball": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-cyan",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "cyan",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-cyan",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-cyan.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-cyan/readme.md b/input_devices/mag/node_modules/ansi-cyan/readme.md
new file mode 100644
index 00000000..7b0c2148
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-cyan/readme.md
@@ -0,0 +1,74 @@
+# ansi-cyan [![NPM version](https://badge.fury.io/js/ansi-cyan.svg)](http://badge.fury.io/js/ansi-cyan)
+
+> The color cyan, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-cyan --save
+```
+
+## Usage
+
+```js
+var cyan = require('ansi-cyan');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-cyan/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-dim/LICENSE b/input_devices/mag/node_modules/ansi-dim/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-dim/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-dim/index.js b/input_devices/mag/node_modules/ansi-dim/index.js
new file mode 100644
index 00000000..441d7ffa
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-dim/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-dim <https://github.com/jonschlinkert/ansi-dim>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function dim(message) {
+  return wrap(2, 22, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-dim/package.json b/input_devices/mag/node_modules/ansi-dim/package.json
new file mode 100644
index 00000000..7dd18095
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-dim/package.json
@@ -0,0 +1,110 @@
+{
+  "_args": [
+    [
+      "ansi-dim@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-list"
+    ]
+  ],
+  "_from": "ansi-dim@>=0.1.1 <0.2.0",
+  "_id": "ansi-dim@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-dim",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-dim",
+    "raw": "ansi-dim@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors",
+    "/choices-separator",
+    "/prompt-list"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-dim/-/ansi-dim-0.1.1.tgz",
+  "_shasum": "40de4c603aa8086d8e7a86b8ff998d5c36eefd6c",
+  "_shrinkwrap": null,
+  "_spec": "ansi-dim@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-list",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-dim/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color dim, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "40de4c603aa8086d8e7a86b8ff998d5c36eefd6c",
+    "tarball": "https://registry.npmjs.org/ansi-dim/-/ansi-dim-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-dim",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "dim",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-dim",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-dim.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-dim/readme.md b/input_devices/mag/node_modules/ansi-dim/readme.md
new file mode 100644
index 00000000..d8038ae8
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-dim/readme.md
@@ -0,0 +1,74 @@
+# ansi-dim [![NPM version](https://badge.fury.io/js/ansi-dim.svg)](http://badge.fury.io/js/ansi-dim)
+
+> The color dim, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-dim --save
+```
+
+## Usage
+
+```js
+var dim = require('ansi-dim');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-dim/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-gray/LICENSE b/input_devices/mag/node_modules/ansi-gray/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-gray/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-gray/index.js b/input_devices/mag/node_modules/ansi-gray/index.js
new file mode 100644
index 00000000..c22176a3
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-gray/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-gray <https://github.com/jonschlinkert/ansi-gray>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function gray(message) {
+  return wrap(90, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-gray/package.json b/input_devices/mag/node_modules/ansi-gray/package.json
new file mode 100644
index 00000000..86aab942
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-gray/package.json
@@ -0,0 +1,109 @@
+{
+  "_args": [
+    [
+      "ansi-gray@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-gray@>=0.1.1 <0.2.0",
+  "_id": "ansi-gray@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-gray",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-gray",
+    "raw": "ansi-gray@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors",
+    "/radio-symbol"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
+  "_shasum": "2962cf54ec9792c48510a3deb524436861ef7251",
+  "_shrinkwrap": null,
+  "_spec": "ansi-gray@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-gray/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color gray, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "2962cf54ec9792c48510a3deb524436861ef7251",
+    "tarball": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-gray",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "gray",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-gray",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-gray.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-gray/readme.md b/input_devices/mag/node_modules/ansi-gray/readme.md
new file mode 100644
index 00000000..9b59a29a
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-gray/readme.md
@@ -0,0 +1,74 @@
+# ansi-gray [![NPM version](https://badge.fury.io/js/ansi-gray.svg)](http://badge.fury.io/js/ansi-gray)
+
+> The color gray, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-gray --save
+```
+
+## Usage
+
+```js
+var gray = require('ansi-gray');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-gray/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-green/LICENSE b/input_devices/mag/node_modules/ansi-green/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-green/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-green/index.js b/input_devices/mag/node_modules/ansi-green/index.js
new file mode 100644
index 00000000..1a741e58
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-green/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-green <https://github.com/jonschlinkert/ansi-green>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function green(message) {
+  return wrap(32, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-green/package.json b/input_devices/mag/node_modules/ansi-green/package.json
new file mode 100644
index 00000000..ae774b4b
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-green/package.json
@@ -0,0 +1,110 @@
+{
+  "_args": [
+    [
+      "ansi-green@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-green@>=0.1.1 <0.2.0",
+  "_id": "ansi-green@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-green",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-green",
+    "raw": "ansi-green@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors",
+    "/log-ok",
+    "/radio-symbol"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-green/-/ansi-green-0.1.1.tgz",
+  "_shasum": "8a5d9a979e458d57c40e33580b37390b8e10d0f7",
+  "_shrinkwrap": null,
+  "_spec": "ansi-green@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-green/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color green, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "8a5d9a979e458d57c40e33580b37390b8e10d0f7",
+    "tarball": "https://registry.npmjs.org/ansi-green/-/ansi-green-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-green",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "green",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-green",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-green.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-green/readme.md b/input_devices/mag/node_modules/ansi-green/readme.md
new file mode 100644
index 00000000..4b9c7ab9
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-green/readme.md
@@ -0,0 +1,74 @@
+# ansi-green [![NPM version](https://badge.fury.io/js/ansi-green.svg)](http://badge.fury.io/js/ansi-green)
+
+> The color green, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-green --save
+```
+
+## Usage
+
+```js
+var green = require('ansi-green');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-green/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-grey/LICENSE b/input_devices/mag/node_modules/ansi-grey/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-grey/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-grey/index.js b/input_devices/mag/node_modules/ansi-grey/index.js
new file mode 100644
index 00000000..45e73022
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-grey/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-grey <https://github.com/jonschlinkert/ansi-grey>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function grey(message) {
+  return wrap(90, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-grey/package.json b/input_devices/mag/node_modules/ansi-grey/package.json
new file mode 100644
index 00000000..12349d2b
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-grey/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-grey@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-grey@>=0.1.1 <0.2.0",
+  "_id": "ansi-grey@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-grey",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-grey",
+    "raw": "ansi-grey@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-grey/-/ansi-grey-0.1.1.tgz",
+  "_shasum": "59d98b6ac2ba19f8a51798e9853fba78339a33c1",
+  "_shrinkwrap": null,
+  "_spec": "ansi-grey@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-grey/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color grey, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "59d98b6ac2ba19f8a51798e9853fba78339a33c1",
+    "tarball": "https://registry.npmjs.org/ansi-grey/-/ansi-grey-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-grey",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "grey",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-grey",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-grey.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-grey/readme.md b/input_devices/mag/node_modules/ansi-grey/readme.md
new file mode 100644
index 00000000..1d270180
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-grey/readme.md
@@ -0,0 +1,74 @@
+# ansi-grey [![NPM version](https://badge.fury.io/js/ansi-grey.svg)](http://badge.fury.io/js/ansi-grey)
+
+> The color grey, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-grey --save
+```
+
+## Usage
+
+```js
+var grey = require('ansi-grey');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-grey/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-hidden/LICENSE b/input_devices/mag/node_modules/ansi-hidden/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-hidden/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-hidden/index.js b/input_devices/mag/node_modules/ansi-hidden/index.js
new file mode 100644
index 00000000..e220a9cc
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-hidden/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-hidden <https://github.com/jonschlinkert/ansi-hidden>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function hidden(message) {
+  return wrap(8, 28, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-hidden/package.json b/input_devices/mag/node_modules/ansi-hidden/package.json
new file mode 100644
index 00000000..21820391
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-hidden/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-hidden@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-hidden@>=0.1.1 <0.2.0",
+  "_id": "ansi-hidden@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-hidden",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-hidden",
+    "raw": "ansi-hidden@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-hidden/-/ansi-hidden-0.1.1.tgz",
+  "_shasum": "ed6a4c498d2bb7cbb289dbf2a8d1dcc8567fae0f",
+  "_shrinkwrap": null,
+  "_spec": "ansi-hidden@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-hidden/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color hidden, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "ed6a4c498d2bb7cbb289dbf2a8d1dcc8567fae0f",
+    "tarball": "https://registry.npmjs.org/ansi-hidden/-/ansi-hidden-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-hidden",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "hidden",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-hidden",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-hidden.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-hidden/readme.md b/input_devices/mag/node_modules/ansi-hidden/readme.md
new file mode 100644
index 00000000..e646072c
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-hidden/readme.md
@@ -0,0 +1,74 @@
+# ansi-hidden [![NPM version](https://badge.fury.io/js/ansi-hidden.svg)](http://badge.fury.io/js/ansi-hidden)
+
+> The color hidden, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-hidden --save
+```
+
+## Usage
+
+```js
+var hidden = require('ansi-hidden');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-hidden/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-inverse/LICENSE b/input_devices/mag/node_modules/ansi-inverse/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-inverse/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-inverse/index.js b/input_devices/mag/node_modules/ansi-inverse/index.js
new file mode 100644
index 00000000..2db93ada
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-inverse/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-inverse <https://github.com/jonschlinkert/ansi-inverse>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function inverse(message) {
+  return wrap(7, 27, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-inverse/package.json b/input_devices/mag/node_modules/ansi-inverse/package.json
new file mode 100644
index 00000000..68a9844d
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-inverse/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-inverse@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-inverse@>=0.1.1 <0.2.0",
+  "_id": "ansi-inverse@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-inverse",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-inverse",
+    "raw": "ansi-inverse@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-inverse/-/ansi-inverse-0.1.1.tgz",
+  "_shasum": "b6af45826fe826bfb528a6c79885794355ccd269",
+  "_shrinkwrap": null,
+  "_spec": "ansi-inverse@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-inverse/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color inverse, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "b6af45826fe826bfb528a6c79885794355ccd269",
+    "tarball": "https://registry.npmjs.org/ansi-inverse/-/ansi-inverse-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-inverse",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "inverse",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-inverse",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-inverse.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-inverse/readme.md b/input_devices/mag/node_modules/ansi-inverse/readme.md
new file mode 100644
index 00000000..3cc6cf23
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-inverse/readme.md
@@ -0,0 +1,74 @@
+# ansi-inverse [![NPM version](https://badge.fury.io/js/ansi-inverse.svg)](http://badge.fury.io/js/ansi-inverse)
+
+> The color inverse, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-inverse --save
+```
+
+## Usage
+
+```js
+var inverse = require('ansi-inverse');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-inverse/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-italic/LICENSE b/input_devices/mag/node_modules/ansi-italic/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-italic/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-italic/index.js b/input_devices/mag/node_modules/ansi-italic/index.js
new file mode 100644
index 00000000..90e01163
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-italic/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-italic <https://github.com/jonschlinkert/ansi-italic>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function italic(message) {
+  return wrap(3, 23, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-italic/package.json b/input_devices/mag/node_modules/ansi-italic/package.json
new file mode 100644
index 00000000..6b909ab4
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-italic/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-italic@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-italic@>=0.1.1 <0.2.0",
+  "_id": "ansi-italic@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-italic",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-italic",
+    "raw": "ansi-italic@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-italic/-/ansi-italic-0.1.1.tgz",
+  "_shasum": "104743463f625c142a036739cf85eda688986f23",
+  "_shrinkwrap": null,
+  "_spec": "ansi-italic@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-italic/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color italic, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "104743463f625c142a036739cf85eda688986f23",
+    "tarball": "https://registry.npmjs.org/ansi-italic/-/ansi-italic-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-italic",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "italic",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-italic",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-italic.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-italic/readme.md b/input_devices/mag/node_modules/ansi-italic/readme.md
new file mode 100644
index 00000000..17e7450f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-italic/readme.md
@@ -0,0 +1,74 @@
+# ansi-italic [![NPM version](https://badge.fury.io/js/ansi-italic.svg)](http://badge.fury.io/js/ansi-italic)
+
+> The color italic, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-italic --save
+```
+
+## Usage
+
+```js
+var italic = require('ansi-italic');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-italic/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-magenta/LICENSE b/input_devices/mag/node_modules/ansi-magenta/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-magenta/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-magenta/index.js b/input_devices/mag/node_modules/ansi-magenta/index.js
new file mode 100644
index 00000000..bbce5e0b
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-magenta/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-magenta <https://github.com/jonschlinkert/ansi-magenta>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function magenta(message) {
+  return wrap(35, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-magenta/package.json b/input_devices/mag/node_modules/ansi-magenta/package.json
new file mode 100644
index 00000000..7998e565
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-magenta/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-magenta@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-magenta@>=0.1.1 <0.2.0",
+  "_id": "ansi-magenta@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-magenta",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-magenta",
+    "raw": "ansi-magenta@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-magenta/-/ansi-magenta-0.1.1.tgz",
+  "_shasum": "063b5ba16fb3f23e1cfda2b07c0a89de11e430ae",
+  "_shrinkwrap": null,
+  "_spec": "ansi-magenta@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-magenta/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color magenta, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "063b5ba16fb3f23e1cfda2b07c0a89de11e430ae",
+    "tarball": "https://registry.npmjs.org/ansi-magenta/-/ansi-magenta-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-magenta",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "magenta",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-magenta",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-magenta.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-magenta/readme.md b/input_devices/mag/node_modules/ansi-magenta/readme.md
new file mode 100644
index 00000000..5ef9e678
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-magenta/readme.md
@@ -0,0 +1,74 @@
+# ansi-magenta [![NPM version](https://badge.fury.io/js/ansi-magenta.svg)](http://badge.fury.io/js/ansi-magenta)
+
+> The color magenta, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-magenta --save
+```
+
+## Usage
+
+```js
+var magenta = require('ansi-magenta');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-magenta/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-red/LICENSE b/input_devices/mag/node_modules/ansi-red/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-red/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-red/index.js b/input_devices/mag/node_modules/ansi-red/index.js
new file mode 100644
index 00000000..00ea3028
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-red/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-red <https://github.com/jonschlinkert/ansi-red>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function red(message) {
+  return wrap(31, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-red/package.json b/input_devices/mag/node_modules/ansi-red/package.json
new file mode 100644
index 00000000..9abb53a1
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-red/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-red@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-red@>=0.1.1 <0.2.0",
+  "_id": "ansi-red@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-red",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-red",
+    "raw": "ansi-red@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
+  "_shasum": "8c638f9d1080800a353c9c28c8a81ca4705d946c",
+  "_shrinkwrap": null,
+  "_spec": "ansi-red@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-red/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color red, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "8c638f9d1080800a353c9c28c8a81ca4705d946c",
+    "tarball": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-red",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "red",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-red",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-red.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-red/readme.md b/input_devices/mag/node_modules/ansi-red/readme.md
new file mode 100644
index 00000000..e09e77b3
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-red/readme.md
@@ -0,0 +1,74 @@
+# ansi-red [![NPM version](https://badge.fury.io/js/ansi-red.svg)](http://badge.fury.io/js/ansi-red)
+
+> The color red, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-red --save
+```
+
+## Usage
+
+```js
+var red = require('ansi-red');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-red/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-regex/index.js b/input_devices/mag/node_modules/ansi-regex/index.js
new file mode 100644
index 00000000..b9574ed7
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-regex/index.js
@@ -0,0 +1,4 @@
+'use strict';
+module.exports = function () {
+	return /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]/g;
+};
diff --git a/input_devices/mag/node_modules/ansi-regex/license b/input_devices/mag/node_modules/ansi-regex/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-regex/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/ansi-regex/package.json b/input_devices/mag/node_modules/ansi-regex/package.json
new file mode 100644
index 00000000..d41e1ab2
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-regex/package.json
@@ -0,0 +1,123 @@
+{
+  "_args": [
+    [
+      "ansi-regex@^2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/strip-ansi"
+    ]
+  ],
+  "_from": "ansi-regex@>=2.0.0 <3.0.0",
+  "_id": "ansi-regex@2.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-regex",
+  "_nodeVersion": "0.10.32",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/ansi-regex-2.1.1.tgz_1484363378013_0.4482989883981645"
+  },
+  "_npmUser": {
+    "email": "i.am.qix@gmail.com",
+    "name": "qix"
+  },
+  "_npmVersion": "2.14.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-regex",
+    "raw": "ansi-regex@^2.0.0",
+    "rawSpec": "^2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/strip-ansi"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+  "_shasum": "c3b33ab5ee360d86e0e628f0468ae7ef27d654df",
+  "_shrinkwrap": null,
+  "_spec": "ansi-regex@^2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/strip-ansi",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/chalk/ansi-regex/issues"
+  },
+  "dependencies": {},
+  "description": "Regular expression for matching ANSI escape codes",
+  "devDependencies": {
+    "ava": "0.17.0",
+    "xo": "0.16.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "c3b33ab5ee360d86e0e628f0468ae7ef27d654df",
+    "tarball": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "7c908e7b4eb6cd82bfe1295e33fdf6d166c7ed85",
+  "homepage": "https://github.com/chalk/ansi-regex#readme",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command-line",
+    "console",
+    "escape",
+    "find",
+    "formatting",
+    "match",
+    "pattern",
+    "re",
+    "regex",
+    "regexp",
+    "rgb",
+    "shell",
+    "string",
+    "styles",
+    "terminal",
+    "test",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "qix",
+      "email": "i.am.qix@gmail.com"
+    },
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "ansi-regex",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/chalk/ansi-regex.git"
+  },
+  "scripts": {
+    "test": "xo && ava --verbose",
+    "view-supported": "node fixtures/view-codes.js"
+  },
+  "version": "2.1.1",
+  "xo": {
+    "rules": {
+      "guard-for-in": 0,
+      "no-loop-func": 0
+    }
+  }
+}
diff --git a/input_devices/mag/node_modules/ansi-regex/readme.md b/input_devices/mag/node_modules/ansi-regex/readme.md
new file mode 100644
index 00000000..6a928edf
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-regex/readme.md
@@ -0,0 +1,39 @@
+# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)
+
+> Regular expression for matching [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code)
+
+
+## Install
+
+```
+$ npm install --save ansi-regex
+```
+
+
+## Usage
+
+```js
+const ansiRegex = require('ansi-regex');
+
+ansiRegex().test('\u001b[4mcake\u001b[0m');
+//=> true
+
+ansiRegex().test('cake');
+//=> false
+
+'\u001b[4mcake\u001b[0m'.match(ansiRegex());
+//=> ['\u001b[4m', '\u001b[0m']
+```
+
+## FAQ
+
+### Why do you test for codes not in the ECMA 48 standard?
+
+Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. If I recall correctly, we test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
+
+On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
+
+
+## License
+
+MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/ansi-reset/LICENSE b/input_devices/mag/node_modules/ansi-reset/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-reset/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-reset/index.js b/input_devices/mag/node_modules/ansi-reset/index.js
new file mode 100644
index 00000000..808b00f0
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-reset/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-reset <https://github.com/jonschlinkert/ansi-reset>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function reset(message) {
+  return wrap(0, 0, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-reset/package.json b/input_devices/mag/node_modules/ansi-reset/package.json
new file mode 100644
index 00000000..78280e9b
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-reset/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-reset@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-reset@>=0.1.1 <0.2.0",
+  "_id": "ansi-reset@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-reset",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-reset",
+    "raw": "ansi-reset@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-reset/-/ansi-reset-0.1.1.tgz",
+  "_shasum": "e7e71292c3c7ddcd4d62ef4a6c7c05980911c3b7",
+  "_shrinkwrap": null,
+  "_spec": "ansi-reset@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-reset/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color reset, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "e7e71292c3c7ddcd4d62ef4a6c7c05980911c3b7",
+    "tarball": "https://registry.npmjs.org/ansi-reset/-/ansi-reset-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-reset",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "reset",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-reset",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-reset.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-reset/readme.md b/input_devices/mag/node_modules/ansi-reset/readme.md
new file mode 100644
index 00000000..992ba57a
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-reset/readme.md
@@ -0,0 +1,74 @@
+# ansi-reset [![NPM version](https://badge.fury.io/js/ansi-reset.svg)](http://badge.fury.io/js/ansi-reset)
+
+> The color reset, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-reset --save
+```
+
+## Usage
+
+```js
+var reset = require('ansi-reset');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-reset/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-strikethrough/LICENSE b/input_devices/mag/node_modules/ansi-strikethrough/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-strikethrough/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-strikethrough/index.js b/input_devices/mag/node_modules/ansi-strikethrough/index.js
new file mode 100644
index 00000000..39df3cc5
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-strikethrough/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-strikethrough <https://github.com/jonschlinkert/ansi-strikethrough>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function strikethrough(message) {
+  return wrap(9, 29, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-strikethrough/package.json b/input_devices/mag/node_modules/ansi-strikethrough/package.json
new file mode 100644
index 00000000..0d4608c0
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-strikethrough/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-strikethrough@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-strikethrough@>=0.1.1 <0.2.0",
+  "_id": "ansi-strikethrough@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-strikethrough",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-strikethrough",
+    "raw": "ansi-strikethrough@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-strikethrough/-/ansi-strikethrough-0.1.1.tgz",
+  "_shasum": "d84877140b2cff07d1c93ebce69904f68885e568",
+  "_shrinkwrap": null,
+  "_spec": "ansi-strikethrough@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-strikethrough/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color strikethrough, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "d84877140b2cff07d1c93ebce69904f68885e568",
+    "tarball": "https://registry.npmjs.org/ansi-strikethrough/-/ansi-strikethrough-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-strikethrough",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "strikethrough",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-strikethrough",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-strikethrough.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-strikethrough/readme.md b/input_devices/mag/node_modules/ansi-strikethrough/readme.md
new file mode 100644
index 00000000..78f63c00
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-strikethrough/readme.md
@@ -0,0 +1,74 @@
+# ansi-strikethrough [![NPM version](https://badge.fury.io/js/ansi-strikethrough.svg)](http://badge.fury.io/js/ansi-strikethrough)
+
+> The color strikethrough, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-strikethrough --save
+```
+
+## Usage
+
+```js
+var strikethrough = require('ansi-strikethrough');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-strikethrough/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-underline/LICENSE b/input_devices/mag/node_modules/ansi-underline/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-underline/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-underline/index.js b/input_devices/mag/node_modules/ansi-underline/index.js
new file mode 100644
index 00000000..40842b16
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-underline/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-underline <https://github.com/jonschlinkert/ansi-underline>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function underline(message) {
+  return wrap(4, 24, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-underline/package.json b/input_devices/mag/node_modules/ansi-underline/package.json
new file mode 100644
index 00000000..6c57752b
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-underline/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-underline@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-underline@>=0.1.1 <0.2.0",
+  "_id": "ansi-underline@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-underline",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-underline",
+    "raw": "ansi-underline@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-underline/-/ansi-underline-0.1.1.tgz",
+  "_shasum": "dfc920f4c97b5977ea162df8ffb988308aaa71a4",
+  "_shrinkwrap": null,
+  "_spec": "ansi-underline@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-underline/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color underline, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "dfc920f4c97b5977ea162df8ffb988308aaa71a4",
+    "tarball": "https://registry.npmjs.org/ansi-underline/-/ansi-underline-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-underline",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "underline",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-underline",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-underline.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-underline/readme.md b/input_devices/mag/node_modules/ansi-underline/readme.md
new file mode 100644
index 00000000..ad279c94
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-underline/readme.md
@@ -0,0 +1,74 @@
+# ansi-underline [![NPM version](https://badge.fury.io/js/ansi-underline.svg)](http://badge.fury.io/js/ansi-underline)
+
+> The color underline, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-underline --save
+```
+
+## Usage
+
+```js
+var underline = require('ansi-underline');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-underline/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-white/LICENSE b/input_devices/mag/node_modules/ansi-white/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-white/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-white/index.js b/input_devices/mag/node_modules/ansi-white/index.js
new file mode 100644
index 00000000..f262a33e
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-white/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-white <https://github.com/jonschlinkert/ansi-white>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function white(message) {
+  return wrap(37, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-white/package.json b/input_devices/mag/node_modules/ansi-white/package.json
new file mode 100644
index 00000000..34278505
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-white/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-white@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-white@>=0.1.1 <0.2.0",
+  "_id": "ansi-white@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-white",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-white",
+    "raw": "ansi-white@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-white/-/ansi-white-0.1.1.tgz",
+  "_shasum": "9c77b7c193c5ee992e6011d36ec4c921b4578944",
+  "_shrinkwrap": null,
+  "_spec": "ansi-white@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-white/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color white, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "9c77b7c193c5ee992e6011d36ec4c921b4578944",
+    "tarball": "https://registry.npmjs.org/ansi-white/-/ansi-white-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-white",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "white",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-white",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-white.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-white/readme.md b/input_devices/mag/node_modules/ansi-white/readme.md
new file mode 100644
index 00000000..ce1aa5db
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-white/readme.md
@@ -0,0 +1,74 @@
+# ansi-white [![NPM version](https://badge.fury.io/js/ansi-white.svg)](http://badge.fury.io/js/ansi-white)
+
+> The color white, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-white --save
+```
+
+## Usage
+
+```js
+var white = require('ansi-white');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-white/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-wrap/LICENSE b/input_devices/mag/node_modules/ansi-wrap/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-wrap/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-wrap/README.md b/input_devices/mag/node_modules/ansi-wrap/README.md
new file mode 100644
index 00000000..032c1e6b
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-wrap/README.md
@@ -0,0 +1,89 @@
+# ansi-wrap [![NPM version](https://badge.fury.io/js/ansi-wrap.svg)](http://badge.fury.io/js/ansi-wrap)
+
+> Create ansi colors by passing the open and close codes.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-wrap --save
+```
+
+## Usage
+
+```js
+var wrap = require('ansi-wrap');
+```
+
+**Example**
+
+Pass codes for [ansi magenta background](https://github.com/jonschlinkert/ansi-bgmagenta):
+
+```js
+console.log(wrap(45, 49, 'This is a message...'));
+//=> '\u001b[45mfoo\u001b[49m'
+```
+
+Which prints out...
+
+[![screen shot 2015-05-21 at 8 28 32 pm](https://cloud.githubusercontent.com/assets/383994/7761769/12488afa-fff8-11e4-9cc1-71a8a6ec14a4.png)](https://www.npmjs.com/)
+
+## Related projects
+
+This is used in these projects:
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-wrap/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ansi-wrap/index.js b/input_devices/mag/node_modules/ansi-wrap/index.js
new file mode 100644
index 00000000..ffc52d75
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-wrap/index.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = function(a, b, msg) {
+  return '\u001b['+ a + 'm' + msg + '\u001b[' + b + 'm';
+};
diff --git a/input_devices/mag/node_modules/ansi-wrap/package.json b/input_devices/mag/node_modules/ansi-wrap/package.json
new file mode 100644
index 00000000..63b35042
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-wrap/package.json
@@ -0,0 +1,106 @@
+{
+  "_args": [
+    [
+      "ansi-wrap@0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-cyan"
+    ]
+  ],
+  "_from": "ansi-wrap@0.1.0",
+  "_id": "ansi-wrap@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-wrap",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-wrap",
+    "raw": "ansi-wrap@0.1.0",
+    "rawSpec": "0.1.0",
+    "scope": null,
+    "spec": "0.1.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/ansi-bgblack",
+    "/ansi-bgblue",
+    "/ansi-bgcyan",
+    "/ansi-bggreen",
+    "/ansi-bgmagenta",
+    "/ansi-bgred",
+    "/ansi-bgwhite",
+    "/ansi-bgyellow",
+    "/ansi-black",
+    "/ansi-blue",
+    "/ansi-bold",
+    "/ansi-cyan",
+    "/ansi-dim",
+    "/ansi-gray",
+    "/ansi-green",
+    "/ansi-grey",
+    "/ansi-hidden",
+    "/ansi-inverse",
+    "/ansi-italic",
+    "/ansi-magenta",
+    "/ansi-red",
+    "/ansi-reset",
+    "/ansi-strikethrough",
+    "/ansi-underline",
+    "/ansi-white",
+    "/ansi-yellow"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
+  "_shasum": "a82250ddb0015e9a27ca82e82ea603bbfa45efaf",
+  "_shrinkwrap": null,
+  "_spec": "ansi-wrap@0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-cyan",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-wrap/issues"
+  },
+  "dependencies": {},
+  "description": "Create ansi colors by passing the open and close codes.",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "shasum": "a82250ddb0015e9a27ca82e82ea603bbfa45efaf",
+    "tarball": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-wrap",
+  "keywords": [],
+  "license": {
+    "type": "MIT",
+    "url": "https://github.com/jonschlinkert/ansi-wrap/blob/master/LICENSE"
+  },
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-wrap",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-wrap.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/ansi-yellow/LICENSE b/input_devices/mag/node_modules/ansi-yellow/LICENSE
new file mode 100644
index 00000000..41283c9f
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-yellow/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= year() %>, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/ansi-yellow/index.js b/input_devices/mag/node_modules/ansi-yellow/index.js
new file mode 100644
index 00000000..53999c78
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-yellow/index.js
@@ -0,0 +1,14 @@
+/*!
+ * ansi-yellow <https://github.com/jonschlinkert/ansi-yellow>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var wrap = require('ansi-wrap');
+
+module.exports = function yellow(message) {
+  return wrap(33, 39, message);
+};
diff --git a/input_devices/mag/node_modules/ansi-yellow/package.json b/input_devices/mag/node_modules/ansi-yellow/package.json
new file mode 100644
index 00000000..680b99f2
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-yellow/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "ansi-yellow@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "ansi-yellow@>=0.1.1 <0.2.0",
+  "_id": "ansi-yellow@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ansi-yellow",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-yellow",
+    "raw": "ansi-yellow@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-yellow/-/ansi-yellow-0.1.1.tgz",
+  "_shasum": "cb9356f2f46c732f0e3199e6102955a77da83c1d",
+  "_shrinkwrap": null,
+  "_spec": "ansi-yellow@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/ansi-yellow/issues"
+  },
+  "dependencies": {
+    "ansi-wrap": "0.1.0"
+  },
+  "description": "The color yellow, in ansi.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "cb9356f2f46c732f0e3199e6102955a77da83c1d",
+    "tarball": "https://registry.npmjs.org/ansi-yellow/-/ansi-yellow-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/ansi-yellow",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "tty",
+    "xterm",
+    "yellow"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "ansi-yellow",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/ansi-yellow.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/ansi-yellow/readme.md b/input_devices/mag/node_modules/ansi-yellow/readme.md
new file mode 100644
index 00000000..f3fa43e0
--- /dev/null
+++ b/input_devices/mag/node_modules/ansi-yellow/readme.md
@@ -0,0 +1,74 @@
+# ansi-yellow [![NPM version](https://badge.fury.io/js/ansi-yellow.svg)](http://badge.fury.io/js/ansi-yellow)
+
+> The color yellow, in ansi.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i ansi-yellow --save
+```
+
+## Usage
+
+```js
+var yellow = require('ansi-yellow');
+```
+
+## Related projects
+
+* [ansi-reset](https://github.com/jonschlinkert/ansi-reset)
+* [ansi-bold](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-dim](https://github.com/jonschlinkert/ansi-dim)
+* [ansi-italic](https://github.com/jonschlinkert/ansi-italic)
+* [ansi-underline](https://github.com/jonschlinkert/ansi-underline)
+* [ansi-inverse](https://github.com/jonschlinkert/ansi-inverse)
+* [ansi-hidden](https://github.com/jonschlinkert/ansi-hidden)
+* [ansi-strikethrough](https://github.com/jonschlinkert/ansi-strikethrough)
+* [ansi-black](https://github.com/jonschlinkert/ansi-black)
+* [ansi-red](https://github.com/jonschlinkert/ansi-red)
+* [ansi-green](https://github.com/jonschlinkert/ansi-green)
+* [ansi-yellow](https://github.com/jonschlinkert/ansi-yellow)
+* [ansi-blue](https://github.com/jonschlinkert/ansi-blue)
+* [ansi-magenta](https://github.com/jonschlinkert/ansi-magenta)
+* [ansi-cyan](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-white](https://github.com/jonschlinkert/ansi-white)
+* [ansi-gray](https://github.com/jonschlinkert/ansi-gray)
+* [ansi-grey](https://github.com/jonschlinkert/ansi-grey)
+* [ansi-bgblack](https://github.com/jonschlinkert/ansi-bgblack)
+* [ansi-bgred](https://github.com/jonschlinkert/ansi-bgred)
+* [ansi-bggreen](https://github.com/jonschlinkert/ansi-bggreen)
+* [ansi-bgyellow](https://github.com/jonschlinkert/ansi-bgyellow)
+* [ansi-bgblue](https://github.com/jonschlinkert/ansi-bgblue)
+* [ansi-bgmagenta](https://github.com/jonschlinkert/ansi-bgmagenta)
+* [ansi-bgcyan](https://github.com/jonschlinkert/ansi-bgcyan)
+* [ansi-bgwhite](https://github.com/jonschlinkert/ansi-bgwhite)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/ansi-yellow/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 21, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/aproba/LICENSE b/input_devices/mag/node_modules/aproba/LICENSE
new file mode 100644
index 00000000..f4be44d8
--- /dev/null
+++ b/input_devices/mag/node_modules/aproba/LICENSE
@@ -0,0 +1,14 @@
+Copyright (c) 2015, Rebecca Turner <me@re-becca.org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/input_devices/mag/node_modules/aproba/README.md b/input_devices/mag/node_modules/aproba/README.md
new file mode 100644
index 00000000..0bfc594c
--- /dev/null
+++ b/input_devices/mag/node_modules/aproba/README.md
@@ -0,0 +1,94 @@
+aproba
+======
+
+A ridiculously light-weight function argument validator
+
+```
+var validate = require("aproba")
+
+function myfunc(a, b, c) {
+  // `a` must be a string, `b` a number, `c` a function
+  validate('SNF', arguments) // [a,b,c] is also valid
+}
+
+myfunc('test', 23, function () {}) // ok
+myfunc(123, 23, function () {}) // type error
+myfunc('test', 23) // missing arg error
+myfunc('test', 23, function () {}, true) // too many args error
+
+```
+
+Valid types are:
+
+| type | description
+| :--: | :----------
+| *    | matches any type
+| A    | `Array.isArray` OR an `arguments` object
+| S    | typeof == string
+| N    | typeof == number
+| F    | typeof == function
+| O    | typeof == object and not type A and not type E
+| B    | typeof == boolean
+| E    | `instanceof Error` OR `null` **(special: see below)**
+| Z    | == `null`
+
+Validation failures throw one of three exception types, distinguished by a
+`code` property of `EMISSINGARG`, `EINVALIDTYPE` or `ETOOMANYARGS`.
+
+If you pass in an invalid type then it will throw with a code of
+`EUNKNOWNTYPE`.
+
+If an **error** argument is found and is not null then the remaining
+arguments are optional.  That is, if you say `ESO` then that's like using a
+non-magical `E` in: `E|ESO|ZSO`.
+
+### But I have optional arguments?!
+
+You can provide more than one signature by separating them with pipes `|`.
+If any signature matches the arguments then they'll be considered valid.
+
+So for example, say you wanted to write a signature for
+`fs.createWriteStream`.  The docs for it describe it thusly:
+
+```
+fs.createWriteStream(path[, options])
+```
+
+This would be a signature of `SO|S`.  That is, a string and and object, or
+just a string.
+
+Now, if you read the full `fs` docs, you'll see that actually path can ALSO
+be a buffer.  And options can be a string, that is:
+```
+path <String> | <Buffer>
+options <String> | <Object>
+```
+
+To reproduce this you have to fully enumerate all of the possible
+combinations and that implies a signature of `SO|SS|OO|OS|S|O`.  The
+awkwardness is a feature: It reminds you of the complexity you're adding to
+your API when you do this sort of thing.
+
+
+### Browser support
+
+This has no dependencies and should work in browsers, though you'll have
+noisier stack traces.
+
+### Why this exists
+
+I wanted a very simple argument validator. It needed to do two things:
+
+1. Be more concise and easier to use than assertions
+
+2. Not encourage an infinite bikeshed of DSLs
+
+This is why types are specified by a single character and there's no such
+thing as an optional argument. 
+
+This is not intended to validate user data. This is specifically about
+asserting the interface of your functions.
+
+If you need greater validation, I encourage you to write them by hand or
+look elsewhere.
+
diff --git a/input_devices/mag/node_modules/aproba/index.js b/input_devices/mag/node_modules/aproba/index.js
new file mode 100644
index 00000000..6f3f797c
--- /dev/null
+++ b/input_devices/mag/node_modules/aproba/index.js
@@ -0,0 +1,105 @@
+'use strict'
+
+function isArguments (thingy) {
+  return thingy != null && typeof thingy === 'object' && thingy.hasOwnProperty('callee')
+}
+
+var types = {
+  '*': {label: 'any', check: function () { return true }},
+  A: {label: 'array', check: function (thingy) { return Array.isArray(thingy) || isArguments(thingy) }},
+  S: {label: 'string', check: function (thingy) { return typeof thingy === 'string' }},
+  N: {label: 'number', check: function (thingy) { return typeof thingy === 'number' }},
+  F: {label: 'function', check: function (thingy) { return typeof thingy === 'function' }},
+  O: {label: 'object', check: function (thingy) { return typeof thingy === 'object' && thingy != null && !types.A.check(thingy) && !types.E.check(thingy) }},
+  B: {label: 'boolean', check: function (thingy) { return typeof thingy === 'boolean' }},
+  E: {label: 'error', check: function (thingy) { return thingy instanceof Error }},
+  Z: {label: 'null', check: function (thingy) { return thingy == null }}
+}
+
+function addSchema (schema, arity) {
+  var group = arity[schema.length] = arity[schema.length] || []
+  if (group.indexOf(schema) === -1) group.push(schema)
+}
+
+var validate = module.exports = function (rawSchemas, args) {
+  if (arguments.length !== 2) throw wrongNumberOfArgs(['SA'], arguments.length)
+  if (!rawSchemas) throw missingRequiredArg(0, 'rawSchemas')
+  if (!args) throw missingRequiredArg(1, 'args')
+  if (!types.S.check(rawSchemas)) throw invalidType(0, ['string'], rawSchemas)
+  if (!types.A.check(args)) throw invalidType(1, ['array'], args)
+  var schemas = rawSchemas.split('|')
+  var arity = {}
+
+  schemas.forEach(function (schema) {
+    for (var ii = 0; ii < schema.length; ++ii) {
+      var type = schema[ii]
+      if (!types[type]) throw unknownType(ii, type)
+    }
+    if (/E.*E/.test(schema)) throw moreThanOneError(schema)
+    addSchema(schema, arity)
+    if (/E/.test(schema)) {
+      addSchema(schema.replace(/E.*$/, 'E'), arity)
+      addSchema(schema.replace(/E/, 'Z'), arity)
+      if (schema.length === 1) addSchema('', arity)
+    }
+  })
+  var matching = arity[args.length]
+  if (!matching) {
+    throw wrongNumberOfArgs(Object.keys(arity), args.length)
+  }
+  for (var ii = 0; ii < args.length; ++ii) {
+    var newMatching = matching.filter(function (schema) {
+      var type = schema[ii]
+      var typeCheck = types[type].check
+      return typeCheck(args[ii])
+    })
+    if (!newMatching.length) {
+      var labels = matching.map(function (schema) {
+        return types[schema[ii]].label
+      }).filter(function (schema) { return schema != null })
+      throw invalidType(ii, labels, args[ii])
+    }
+    matching = newMatching
+  }
+}
+
+function missingRequiredArg (num) {
+  return newException('EMISSINGARG', 'Missing required argument #' + (num + 1))
+}
+
+function unknownType (num, type) {
+  return newException('EUNKNOWNTYPE', 'Unknown type ' + type + ' in argument #' + (num + 1))
+}
+
+function invalidType (num, expectedTypes, value) {
+  var valueType
+  Object.keys(types).forEach(function (typeCode) {
+    if (types[typeCode].check(value)) valueType = types[typeCode].label
+  })
+  return newException('EINVALIDTYPE', 'Argument #' + (num + 1) + ': Expected ' +
+    englishList(expectedTypes) + ' but got ' + valueType)
+}
+
+function englishList (list) {
+  return list.join(', ').replace(/, ([^,]+)$/, ' or $1')
+}
+
+function wrongNumberOfArgs (expected, got) {
+  var english = englishList(expected)
+  var args = expected.every(function (ex) { return ex.length === 1 })
+    ? 'argument'
+    : 'arguments'
+  return newException('EWRONGARGCOUNT', 'Expected ' + english + ' ' + args + ' but got ' + got)
+}
+
+function moreThanOneError (schema) {
+  return newException('ETOOMANYERRORTYPES',
+    'Only one error type per argument signature is allowed, more than one found in "' + schema + '"')
+}
+
+function newException (code, msg) {
+  var e = new Error(msg)
+  e.code = code
+  if (Error.captureStackTrace) Error.captureStackTrace(e, validate)
+  return e
+}
diff --git a/input_devices/mag/node_modules/aproba/package.json b/input_devices/mag/node_modules/aproba/package.json
new file mode 100644
index 00000000..c83770c7
--- /dev/null
+++ b/input_devices/mag/node_modules/aproba/package.json
@@ -0,0 +1,89 @@
+{
+  "_args": [
+    [
+      "aproba@^1.0.3",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge"
+    ]
+  ],
+  "_from": "aproba@>=1.0.3 <2.0.0",
+  "_id": "aproba@1.2.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/aproba",
+  "_nodeVersion": "8.5.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/aproba-1.2.0.tgz_1505861292502_0.3447994305752218"
+  },
+  "_npmUser": {
+    "email": "me@re-becca.org",
+    "name": "iarna"
+  },
+  "_npmVersion": "5.4.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "aproba",
+    "raw": "aproba@^1.0.3",
+    "rawSpec": "^1.0.3",
+    "scope": null,
+    "spec": ">=1.0.3 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge"
+  ],
+  "_resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+  "_shasum": "6802e6264efd18c790a1b0d517f0f2627bf2c94a",
+  "_shrinkwrap": null,
+  "_spec": "aproba@^1.0.3",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge",
+  "author": {
+    "email": "me@re-becca.org",
+    "name": "Rebecca Turner"
+  },
+  "bugs": {
+    "url": "https://github.com/iarna/aproba/issues"
+  },
+  "dependencies": {},
+  "description": "A ridiculously light-weight argument validator (now browser friendly)",
+  "devDependencies": {
+    "standard": "^10.0.3",
+    "tap": "^10.0.2"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "dist": {
+    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+    "shasum": "6802e6264efd18c790a1b0d517f0f2627bf2c94a",
+    "tarball": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ee43ce68c9992e8f9d0d925dc2b1f2e1e5c976de",
+  "homepage": "https://github.com/iarna/aproba",
+  "keywords": [
+    "argument",
+    "validate"
+  ],
+  "license": "ISC",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    }
+  ],
+  "name": "aproba",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/iarna/aproba.git"
+  },
+  "scripts": {
+    "test": "standard && tap -j3 test/*.js"
+  },
+  "version": "1.2.0"
+}
diff --git a/input_devices/mag/node_modules/are-we-there-yet/CHANGES.md b/input_devices/mag/node_modules/are-we-there-yet/CHANGES.md
new file mode 100644
index 00000000..21f3b1c1
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/CHANGES.md
@@ -0,0 +1,37 @@
+Hi, figured we could actually use a changelog now:
+
+## 1.1.5 2018-05-24
+
+* [#92](https://github.com/iarna/are-we-there-yet/pull/92) Fix bug where
+  `finish` would throw errors when including `TrackerStream` objects in
+  `TrackerGroup` collections.  (@brianloveswords)
+
+## 1.1.4 2017-04-21
+
+* Fix typo in package.json
+
+## 1.1.3 2017-04-21
+
+* Improve documentation and limit files included in the distribution.
+
+## 1.1.2 2016-03-15
+
+* Add tracker group cycle detection and tests for it
+
+## 1.1.1 2016-01-29
+
+* Fix a typo in stream completion tracker
+
+## 1.1.0 2016-01-29
+
+* Rewrote completion percent computation to be low impact– no more walking a
+  tree of completion groups every time we need this info.  Previously, with
+  medium sized tree of completion groups, even a relatively modest number of
+  calls to the top level `completed()` method would result in absurd numbers
+  of calls overall as it walked down the tree. We now, instead, keep track as
+  we bubble up changes, so the computation is limited to when data changes and
+  to the depth of that one branch, instead of _every_ node. (Plus, we were already
+  incurring _this_ cost, since we already bubbled out changes.)
+* Moved different tracker types out to their own files.
+* Made tests test for TOO MANY events too.
+* Standarized the source code formatting
diff --git a/input_devices/mag/node_modules/are-we-there-yet/LICENSE b/input_devices/mag/node_modules/are-we-there-yet/LICENSE
new file mode 100644
index 00000000..af458806
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/LICENSE
@@ -0,0 +1,5 @@
+Copyright (c) 2015, Rebecca Turner
+
+Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/are-we-there-yet/README.md b/input_devices/mag/node_modules/are-we-there-yet/README.md
new file mode 100644
index 00000000..7e2b42d8
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/README.md
@@ -0,0 +1,195 @@
+are-we-there-yet
+----------------
+
+Track complex hiearchies of asynchronous task completion statuses.  This is
+intended to give you a way of recording and reporting the progress of the big
+recursive fan-out and gather type workflows that are so common in async.
+
+What you do with this completion data is up to you, but the most common use case is to
+feed it to one of the many progress bar modules.
+
+Most progress bar modules include a rudamentary version of this, but my
+needs were more complex.
+
+Usage
+=====
+
+```javascript
+var TrackerGroup = require("are-we-there-yet").TrackerGroup
+
+var top = new TrackerGroup("program")
+
+var single = top.newItem("one thing", 100)
+single.completeWork(20)
+
+console.log(top.completed()) // 0.2
+
+fs.stat("file", function(er, stat) {
+  if (er) throw er  
+  var stream = top.newStream("file", stat.size)
+  console.log(top.completed()) // now 0.1 as single is 50% of the job and is 20% complete
+                              // and 50% * 20% == 10%
+  fs.createReadStream("file").pipe(stream).on("data", function (chunk) {
+    // do stuff with chunk
+  })
+  top.on("change", function (name) {
+    // called each time a chunk is read from "file"
+    // top.completed() will start at 0.1 and fill up to 0.6 as the file is read
+  })
+})
+```
+
+Shared Methods
+==============
+
+* var completed = tracker.completed()
+
+Implemented in: `Tracker`, `TrackerGroup`, `TrackerStream`
+
+Returns the ratio of completed work to work to be done. Range of 0 to 1.
+
+* tracker.finish()
+
+Implemented in: `Tracker`, `TrackerGroup`
+
+Marks the tracker as completed. With a TrackerGroup this marks all of its
+components as completed.
+
+Marks all of the components of this tracker as finished, which in turn means
+that `tracker.completed()` for this will now be 1.
+
+This will result in one or more `change` events being emitted.
+
+Events
+======
+
+All tracker objects emit `change` events with the following arguments:
+
+```
+function (name, completed, tracker)
+```
+
+`name` is the name of the tracker that originally emitted the event,
+or if it didn't have one, the first containing tracker group that had one.
+
+`completed` is the percent complete (as returned by `tracker.completed()` method).
+
+`tracker` is the tracker object that you are listening for events on.
+
+TrackerGroup
+============
+
+* var tracker = new TrackerGroup(**name**)
+
+  * **name** *(optional)* - The name of this tracker group, used in change
+    notifications if the component updating didn't have a name. Defaults to undefined.
+
+Creates a new empty tracker aggregation group. These are trackers whose
+completion status is determined by the completion status of other trackers.
+
+* tracker.addUnit(**otherTracker**, **weight**)
+
+  * **otherTracker** - Any of the other are-we-there-yet tracker objects
+  * **weight** *(optional)* - The weight to give the tracker, defaults to 1.
+
+Adds the **otherTracker** to this aggregation group. The weight determines
+how long you expect this tracker to take to complete in proportion to other
+units.  So for instance, if you add one tracker with a weight of 1 and
+another with a weight of 2, you're saying the second will take twice as long
+to complete as the first.  As such, the first will account for 33% of the
+completion of this tracker and the second will account for the other 67%.
+
+Returns **otherTracker**.
+
+* var subGroup = tracker.newGroup(**name**, **weight**)
+
+The above is exactly equivalent to:
+
+```javascript
+  var subGroup = tracker.addUnit(new TrackerGroup(name), weight)
+```
+
+* var subItem = tracker.newItem(**name**, **todo**, **weight**)
+
+The above is exactly equivalent to:
+
+```javascript
+  var subItem = tracker.addUnit(new Tracker(name, todo), weight)
+```
+
+* var subStream = tracker.newStream(**name**, **todo**, **weight**)
+
+The above is exactly equivalent to:
+
+```javascript
+  var subStream = tracker.addUnit(new TrackerStream(name, todo), weight)
+```
+
+* console.log( tracker.debug() )
+
+Returns a tree showing the completion of this tracker group and all of its
+children, including recursively entering all of the children.
+
+Tracker
+=======
+
+* var tracker = new Tracker(**name**, **todo**)
+
+  * **name** *(optional)* The name of this counter to report in change
+    events.  Defaults to undefined.
+  * **todo** *(optional)* The amount of work todo (a number). Defaults to 0.
+
+Ordinarily these are constructed as a part of a tracker group (via
+`newItem`).
+
+* var completed = tracker.completed()
+
+Returns the ratio of completed work to work to be done. Range of 0 to 1. If
+total work to be done is 0 then it will return 0.
+
+* tracker.addWork(**todo**)
+
+  * **todo** A number to add to the amount of work to be done.
+
+Increases the amount of work to be done, thus decreasing the completion
+percentage.  Triggers a `change` event.
+
+* tracker.completeWork(**completed**)
+
+  * **completed** A number to add to the work complete
+
+Increase the amount of work complete, thus increasing the completion percentage.
+Will never increase the work completed past the amount of work todo. That is,
+percentages > 100% are not allowed. Triggers a `change` event.
+
+* tracker.finish()
+
+Marks this tracker as finished, tracker.completed() will now be 1. Triggers
+a `change` event.
+
+TrackerStream
+=============
+
+* var tracker = new TrackerStream(**name**, **size**, **options**)
+
+  * **name** *(optional)* The name of this counter to report in change
+    events.  Defaults to undefined.
+  * **size** *(optional)* The number of bytes being sent through this stream.
+  * **options** *(optional)* A hash of stream options
+
+The tracker stream object is a pass through stream that updates an internal
+tracker object each time a block passes through.  It's intended to track
+downloads, file extraction and other related activities. You use it by piping
+your data source into it and then using it as your data source.
+
+If your data has a length attribute then that's used as the amount of work
+completed when the chunk is passed through.  If it does not (eg, object
+streams) then each chunk counts as completing 1 unit of work, so your size
+should be the total number of objects being streamed.
+
+* tracker.addWork(**todo**)
+
+  * **todo** Increase the expected overall size by **todo** bytes.
+
+Increases the amount of work to be done, thus decreasing the completion
+percentage.  Triggers a `change` event.
diff --git a/input_devices/mag/node_modules/are-we-there-yet/index.js b/input_devices/mag/node_modules/are-we-there-yet/index.js
new file mode 100644
index 00000000..57d8743f
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/index.js
@@ -0,0 +1,4 @@
+'use strict'
+exports.TrackerGroup = require('./tracker-group.js')
+exports.Tracker = require('./tracker.js')
+exports.TrackerStream = require('./tracker-stream.js')
diff --git a/input_devices/mag/node_modules/are-we-there-yet/package.json b/input_devices/mag/node_modules/are-we-there-yet/package.json
new file mode 100644
index 00000000..26040657
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/package.json
@@ -0,0 +1,94 @@
+{
+  "_args": [
+    [
+      "are-we-there-yet@~1.1.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog"
+    ]
+  ],
+  "_from": "are-we-there-yet@>=1.1.2 <1.2.0",
+  "_id": "are-we-there-yet@1.1.5",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/are-we-there-yet",
+  "_nodeVersion": "9.3.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/are-we-there-yet_1.1.5_1527199680706_0.2972836172536619"
+  },
+  "_npmUser": {
+    "email": "me@re-becca.org",
+    "name": "iarna"
+  },
+  "_npmVersion": "6.1.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "are-we-there-yet",
+    "raw": "are-we-there-yet@~1.1.2",
+    "rawSpec": "~1.1.2",
+    "scope": null,
+    "spec": ">=1.1.2 <1.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/npmlog"
+  ],
+  "_resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+  "_shasum": "4b35c2944f062a8bfcda66410760350fe9ddfc21",
+  "_shrinkwrap": null,
+  "_spec": "are-we-there-yet@~1.1.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog",
+  "author": {
+    "name": "Rebecca Turner",
+    "url": "http://re-becca.org"
+  },
+  "bugs": {
+    "url": "https://github.com/iarna/are-we-there-yet/issues"
+  },
+  "dependencies": {
+    "delegates": "^1.0.0",
+    "readable-stream": "^2.0.6"
+  },
+  "description": "Keep track of the overall completion of many disparate processes",
+  "devDependencies": {
+    "standard": "^11.0.1",
+    "tap": "^12.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 9,
+    "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbBzfBCRA9TVsSAnZWagAAtR4QAJuFZqCyX+bkCwSGz/DJ\nAXAnaUYip2Hd8sb2u28miiJwM6aE/yuu126iXLIKj4ov+LEVyiFSXNtkRc8H\nSgDvyh5WZZ8m06o78GA/0FGOxDuJHbBtTPvIFkVM9Wud3NuJ8M08mlRnZGMo\nyLzjUEOejLt5o/JjQfiftVsN9cUXt0UkfP9ZkDuqg8HrVC8k1GS0qte15sKm\nISytjUl4atLw9d6oBsWCwc7xyUSv6wSER+Fqf5vo/4+IIeOdcWFmTGrtvWdo\n8KtHUik4bmo5EE3Z3XlFfEadOd/HSkUfizFOxRaauFWpJMF24+zt1wkrZ26R\nZWc6hyIg/1xrYKgJ0uOuBhPMxcOaUZNO5h3BeQ5J/Rdzg4rAZXSA26GVe+zL\n7sZbWASLSyjquh+jiZ94ztYdS8FhfuCa12TfoHBLOu9yp3xkFHrD89FHg915\nltEo3hERMxHyQdL7Fx/V7ewNH0Y7jL0PSQyEg5Fq1F7YS2AYskAI86FCCm41\nZXP1MveV1c39oqJxpwXhr22z5ga5GDxwVr4cNT0q6hOzMJ0Yigrht+YQZLFc\n0mG6h177j8U+6Q68wK69NcGEiosZCnmMRihGvJxZ6Keq9YvGEZNcnUGdfSPJ\nxu7tGhwr78HDOPTvLzCE9H4nBsBNTMMqJkMAcqjN3u90KGPIMyl/K0S3rfnv\nIiix\r\n=Mjkz\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "4b35c2944f062a8bfcda66410760350fe9ddfc21",
+    "tarball": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+    "unpackedSize": 14650
+  },
+  "files": [
+    "CHANGES.md",
+    "index.js",
+    "tracker-base.js",
+    "tracker-group.js",
+    "tracker-stream.js",
+    "tracker.js"
+  ],
+  "gitHead": "b4d023b8b754b9d2d540c9db21cc7edf2962ea63",
+  "homepage": "https://github.com/iarna/are-we-there-yet",
+  "license": "ISC",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    }
+  ],
+  "name": "are-we-there-yet",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/iarna/are-we-there-yet.git"
+  },
+  "scripts": {
+    "test": "standard && tap test/*.js"
+  },
+  "version": "1.1.5"
+}
diff --git a/input_devices/mag/node_modules/are-we-there-yet/tracker-base.js b/input_devices/mag/node_modules/are-we-there-yet/tracker-base.js
new file mode 100644
index 00000000..6f436875
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/tracker-base.js
@@ -0,0 +1,11 @@
+'use strict'
+var EventEmitter = require('events').EventEmitter
+var util = require('util')
+
+var trackerId = 0
+var TrackerBase = module.exports = function (name) {
+  EventEmitter.call(this)
+  this.id = ++trackerId
+  this.name = name
+}
+util.inherits(TrackerBase, EventEmitter)
diff --git a/input_devices/mag/node_modules/are-we-there-yet/tracker-group.js b/input_devices/mag/node_modules/are-we-there-yet/tracker-group.js
new file mode 100644
index 00000000..9759e122
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/tracker-group.js
@@ -0,0 +1,107 @@
+'use strict'
+var util = require('util')
+var TrackerBase = require('./tracker-base.js')
+var Tracker = require('./tracker.js')
+var TrackerStream = require('./tracker-stream.js')
+
+var TrackerGroup = module.exports = function (name) {
+  TrackerBase.call(this, name)
+  this.parentGroup = null
+  this.trackers = []
+  this.completion = {}
+  this.weight = {}
+  this.totalWeight = 0
+  this.finished = false
+  this.bubbleChange = bubbleChange(this)
+}
+util.inherits(TrackerGroup, TrackerBase)
+
+function bubbleChange (trackerGroup) {
+  return function (name, completed, tracker) {
+    trackerGroup.completion[tracker.id] = completed
+    if (trackerGroup.finished) return
+    trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup)
+  }
+}
+
+TrackerGroup.prototype.nameInTree = function () {
+  var names = []
+  var from = this
+  while (from) {
+    names.unshift(from.name)
+    from = from.parentGroup
+  }
+  return names.join('/')
+}
+
+TrackerGroup.prototype.addUnit = function (unit, weight) {
+  if (unit.addUnit) {
+    var toTest = this
+    while (toTest) {
+      if (unit === toTest) {
+        throw new Error(
+          'Attempted to add tracker group ' +
+          unit.name + ' to tree that already includes it ' +
+          this.nameInTree(this))
+      }
+      toTest = toTest.parentGroup
+    }
+    unit.parentGroup = this
+  }
+  this.weight[unit.id] = weight || 1
+  this.totalWeight += this.weight[unit.id]
+  this.trackers.push(unit)
+  this.completion[unit.id] = unit.completed()
+  unit.on('change', this.bubbleChange)
+  if (!this.finished) this.emit('change', unit.name, this.completion[unit.id], unit)
+  return unit
+}
+
+TrackerGroup.prototype.completed = function () {
+  if (this.trackers.length === 0) return 0
+  var valPerWeight = 1 / this.totalWeight
+  var completed = 0
+  for (var ii = 0; ii < this.trackers.length; ii++) {
+    var trackerId = this.trackers[ii].id
+    completed += valPerWeight * this.weight[trackerId] * this.completion[trackerId]
+  }
+  return completed
+}
+
+TrackerGroup.prototype.newGroup = function (name, weight) {
+  return this.addUnit(new TrackerGroup(name), weight)
+}
+
+TrackerGroup.prototype.newItem = function (name, todo, weight) {
+  return this.addUnit(new Tracker(name, todo), weight)
+}
+
+TrackerGroup.prototype.newStream = function (name, todo, weight) {
+  return this.addUnit(new TrackerStream(name, todo), weight)
+}
+
+TrackerGroup.prototype.finish = function () {
+  this.finished = true
+  if (!this.trackers.length) this.addUnit(new Tracker(), 1, true)
+  for (var ii = 0; ii < this.trackers.length; ii++) {
+    var tracker = this.trackers[ii]
+    tracker.finish()
+    tracker.removeListener('change', this.bubbleChange)
+  }
+  this.emit('change', this.name, 1, this)
+}
+
+var buffer = '                                  '
+TrackerGroup.prototype.debug = function (depth) {
+  depth = depth || 0
+  var indent = depth ? buffer.substr(0, depth) : ''
+  var output = indent + (this.name || 'top') + ': ' + this.completed() + '\n'
+  this.trackers.forEach(function (tracker) {
+    if (tracker instanceof TrackerGroup) {
+      output += tracker.debug(depth + 1)
+    } else {
+      output += indent + ' ' + tracker.name + ': ' + tracker.completed() + '\n'
+    }
+  })
+  return output
+}
diff --git a/input_devices/mag/node_modules/are-we-there-yet/tracker-stream.js b/input_devices/mag/node_modules/are-we-there-yet/tracker-stream.js
new file mode 100644
index 00000000..e1cf8505
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/tracker-stream.js
@@ -0,0 +1,36 @@
+'use strict'
+var util = require('util')
+var stream = require('readable-stream')
+var delegate = require('delegates')
+var Tracker = require('./tracker.js')
+
+var TrackerStream = module.exports = function (name, size, options) {
+  stream.Transform.call(this, options)
+  this.tracker = new Tracker(name, size)
+  this.name = name
+  this.id = this.tracker.id
+  this.tracker.on('change', delegateChange(this))
+}
+util.inherits(TrackerStream, stream.Transform)
+
+function delegateChange (trackerStream) {
+  return function (name, completion, tracker) {
+    trackerStream.emit('change', name, completion, trackerStream)
+  }
+}
+
+TrackerStream.prototype._transform = function (data, encoding, cb) {
+  this.tracker.completeWork(data.length ? data.length : 1)
+  this.push(data)
+  cb()
+}
+
+TrackerStream.prototype._flush = function (cb) {
+  this.tracker.finish()
+  cb()
+}
+
+delegate(TrackerStream.prototype, 'tracker')
+  .method('completed')
+  .method('addWork')
+  .method('finish')
diff --git a/input_devices/mag/node_modules/are-we-there-yet/tracker.js b/input_devices/mag/node_modules/are-we-there-yet/tracker.js
new file mode 100644
index 00000000..68c2339b
--- /dev/null
+++ b/input_devices/mag/node_modules/are-we-there-yet/tracker.js
@@ -0,0 +1,30 @@
+'use strict'
+var util = require('util')
+var TrackerBase = require('./tracker-base.js')
+
+var Tracker = module.exports = function (name, todo) {
+  TrackerBase.call(this, name)
+  this.workDone = 0
+  this.workTodo = todo || 0
+}
+util.inherits(Tracker, TrackerBase)
+
+Tracker.prototype.completed = function () {
+  return this.workTodo === 0 ? 0 : this.workDone / this.workTodo
+}
+
+Tracker.prototype.addWork = function (work) {
+  this.workTodo += work
+  this.emit('change', this.name, this.completed(), this)
+}
+
+Tracker.prototype.completeWork = function (work) {
+  this.workDone += work
+  if (this.workDone > this.workTodo) this.workDone = this.workTodo
+  this.emit('change', this.name, this.completed(), this)
+}
+
+Tracker.prototype.finish = function () {
+  this.workTodo = this.workDone = 1
+  this.emit('change', this.name, 1, this)
+}
diff --git a/input_devices/mag/node_modules/arr-flatten/LICENSE b/input_devices/mag/node_modules/arr-flatten/LICENSE
new file mode 100755
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-flatten/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/arr-flatten/README.md b/input_devices/mag/node_modules/arr-flatten/README.md
new file mode 100755
index 00000000..7dc7a974
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-flatten/README.md
@@ -0,0 +1,86 @@
+# arr-flatten [![NPM version](https://img.shields.io/npm/v/arr-flatten.svg?style=flat)](https://www.npmjs.com/package/arr-flatten) [![NPM monthly downloads](https://img.shields.io/npm/dm/arr-flatten.svg?style=flat)](https://npmjs.org/package/arr-flatten) [![NPM total downloads](https://img.shields.io/npm/dt/arr-flatten.svg?style=flat)](https://npmjs.org/package/arr-flatten) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/arr-flatten.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/arr-flatten) [![Windows Build Status](https://img.shields.io/appveyor/ci/jonschlinkert/arr-flatten.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/jonschlinkert/arr-flatten)
+
+> Recursively flatten an array or arrays.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save arr-flatten
+```
+
+## Install
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install arr-flatten --save
+```
+
+## Usage
+
+```js
+var flatten = require('arr-flatten');
+
+flatten(['a', ['b', ['c']], 'd', ['e']]);
+//=> ['a', 'b', 'c', 'd', 'e']
+```
+
+## Why another flatten utility?
+
+I wanted the fastest implementation I could find, with implementation choices that should work for 95% of use cases, but no cruft to cover the other 5%.
+
+## About
+
+### Related projects
+
+* [arr-filter](https://www.npmjs.com/package/arr-filter): Faster alternative to javascript's native filter method. | [homepage](https://github.com/jonschlinkert/arr-filter "Faster alternative to javascript's native filter method.")
+* [arr-union](https://www.npmjs.com/package/arr-union): Combines a list of arrays, returning a single array with unique values, using strict equality… [more](https://github.com/jonschlinkert/arr-union) | [homepage](https://github.com/jonschlinkert/arr-union "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.")
+* [array-each](https://www.npmjs.com/package/array-each): Loop over each item in an array and call the given function on every element. | [homepage](https://github.com/jonschlinkert/array-each "Loop over each item in an array and call the given function on every element.")
+* [array-unique](https://www.npmjs.com/package/array-unique): Remove duplicate values from an array. Fastest ES5 implementation. | [homepage](https://github.com/jonschlinkert/array-unique "Remove duplicate values from an array. Fastest ES5 implementation.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 20 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [lukeed](https://github.com/lukeed) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 05, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/arr-flatten/index.js b/input_devices/mag/node_modules/arr-flatten/index.js
new file mode 100644
index 00000000..0cb4ea4e
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-flatten/index.js
@@ -0,0 +1,22 @@
+/*!
+ * arr-flatten <https://github.com/jonschlinkert/arr-flatten>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+module.exports = function (arr) {
+  return flat(arr, []);
+};
+
+function flat(arr, res) {
+  var i = 0, cur;
+  var len = arr.length;
+  for (; i < len; i++) {
+    cur = arr[i];
+    Array.isArray(cur) ? flat(cur, res) : res.push(cur);
+  }
+  return res;
+}
diff --git a/input_devices/mag/node_modules/arr-flatten/package.json b/input_devices/mag/node_modules/arr-flatten/package.json
new file mode 100644
index 00000000..b9f71340
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-flatten/package.json
@@ -0,0 +1,143 @@
+{
+  "_args": [
+    [
+      "arr-flatten@^1.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "arr-flatten@>=1.1.0 <2.0.0",
+  "_id": "arr-flatten@1.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/arr-flatten",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/arr-flatten-1.1.0.tgz_1499280630530_0.4138362631201744"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.0.4",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "arr-flatten",
+    "raw": "arr-flatten@^1.1.0",
+    "rawSpec": "^1.1.0",
+    "scope": null,
+    "spec": ">=1.1.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices",
+    "/readline-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+  "_shasum": "36048bbff4e7b47e136644316c99669ea5ae91f1",
+  "_shrinkwrap": null,
+  "_spec": "arr-flatten@^1.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/arr-flatten/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Luke Edwards",
+      "url": "https://lukeed.com"
+    }
+  ],
+  "dependencies": {},
+  "description": "Recursively flatten an array or arrays.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "array-flatten": "^2.1.1",
+    "array-slice": "^1.0.0",
+    "benchmarked": "^1.0.0",
+    "compute-flatten": "^1.0.0",
+    "flatit": "^1.1.1",
+    "flatten": "^1.0.2",
+    "flatten-array": "^1.0.0",
+    "glob": "^7.1.1",
+    "gulp-format-md": "^0.1.12",
+    "just-flatten-it": "^1.1.23",
+    "lodash.flattendeep": "^4.4.0",
+    "m_flattened": "^1.0.1",
+    "mocha": "^3.2.0",
+    "utils-flatten": "^1.0.0",
+    "write": "^0.3.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+    "shasum": "36048bbff4e7b47e136644316c99669ea5ae91f1",
+    "tarball": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "76a1ae28b03fdb1cbe5d49fa521bc4807b9f94d3",
+  "homepage": "https://github.com/jonschlinkert/arr-flatten",
+  "keywords": [
+    "arr",
+    "array",
+    "elements",
+    "flat",
+    "flatten",
+    "nested",
+    "recurse",
+    "recursive",
+    "recursively"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "arr-flatten",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/arr-flatten.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "arr-filter",
+        "arr-union",
+        "array-each",
+        "array-unique"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.1.0"
+}
diff --git a/input_devices/mag/node_modules/arr-swap/LICENSE b/input_devices/mag/node_modules/arr-swap/LICENSE
new file mode 100644
index 00000000..9a1c8567
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/arr-swap/README.md b/input_devices/mag/node_modules/arr-swap/README.md
new file mode 100644
index 00000000..2cf85096
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/README.md
@@ -0,0 +1,85 @@
+# arr-swap [![NPM version](https://img.shields.io/npm/v/arr-swap.svg?style=flat)](https://www.npmjs.com/package/arr-swap) [![NPM monthly downloads](https://img.shields.io/npm/dm/arr-swap.svg?style=flat)](https://npmjs.org/package/arr-swap) [![NPM total downloads](https://img.shields.io/npm/dt/arr-swap.svg?style=flat)](https://npmjs.org/package/arr-swap) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/arr-swap.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/arr-swap)
+
+> Swap two items in an array. Does not modify the Array prototype.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save arr-swap
+```
+
+## Usage
+
+```js
+var swap = require('arr-swap');
+```
+
+**By index**
+
+Swap by array index:
+
+```js
+var arr = ['a', 'b', 'c'];
+console.log(swap(arr, 0, 1));
+//=> ['b', 'a', 'c'];
+```
+
+**By element**
+
+Swap by array elements:
+
+```js
+var arr = ['a', 'b', 'c'];
+console.log(swap(arr, 'a', 'b'));
+//=> ['b', 'a', 'c'];
+```
+
+## About
+
+### Related projects
+
+* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays.")
+* [arr-union](https://www.npmjs.com/package/arr-union): Combines a list of arrays, returning a single array with unique values, using strict equality… [more](https://github.com/jonschlinkert/arr-union) | [homepage](https://github.com/jonschlinkert/arr-union "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.")
+* [array-unique](https://www.npmjs.com/package/array-unique): Remove duplicate values from an array. Fastest ES5 implementation. | [homepage](https://github.com/jonschlinkert/array-unique "Remove duplicate values from an array. Fastest ES5 implementation.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 25, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/arr-swap/index.js b/input_devices/mag/node_modules/arr-swap/index.js
new file mode 100644
index 00000000..ff5d545f
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/index.js
@@ -0,0 +1,17 @@
+'use strict';
+
+var isNumber = require('is-number');
+
+module.exports = function(arr, a, b) {
+  if (!Array.isArray(arr)) {
+    throw new TypeError('expected an array');
+  }
+
+  var idxa = isNumber(a) ? a : arr.indexOf(a);
+  var idxb = isNumber(b) ? b : arr.indexOf(b);
+  var vala = arr[idxa];
+  var valb = arr[idxb];
+  arr[idxa] = valb;
+  arr[idxb] = vala;
+  return arr;
+};
diff --git a/input_devices/mag/node_modules/arr-swap/node_modules/is-number/LICENSE b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/LICENSE
new file mode 100644
index 00000000..842218cf
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2016, Jon Schlinkert
+
+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/input_devices/mag/node_modules/arr-swap/node_modules/is-number/README.md b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/README.md
new file mode 100644
index 00000000..281165dc
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/README.md
@@ -0,0 +1,115 @@
+# is-number [![NPM version](https://img.shields.io/npm/v/is-number.svg?style=flat)](https://www.npmjs.com/package/is-number) [![NPM downloads](https://img.shields.io/npm/dm/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-number.svg?style=flat)](https://travis-ci.org/jonschlinkert/is-number)
+
+> Returns true if the value is a number. comprehensive tests.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-number
+```
+
+## Usage
+
+To understand some of the rationale behind the decisions made in this library (and to learn about some oddities of number evaluation in JavaScript), [see this gist](https://gist.github.com/jonschlinkert/e30c70c713da325d0e81).
+
+```js
+var isNumber = require('is-number');
+```
+
+### true
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber(5e3)      //=> 'true'
+isNumber(0xff)     //=> 'true'
+isNumber(-1.1)     //=> 'true'
+isNumber(0)        //=> 'true'
+isNumber(1)        //=> 'true'
+isNumber(1.1)      //=> 'true'
+isNumber(10)       //=> 'true'
+isNumber(10.10)    //=> 'true'
+isNumber(100)      //=> 'true'
+isNumber('-1.1')   //=> 'true'
+isNumber('0')      //=> 'true'
+isNumber('012')    //=> 'true'
+isNumber('0xff')   //=> 'true'
+isNumber('1')      //=> 'true'
+isNumber('1.1')    //=> 'true'
+isNumber('10')     //=> 'true'
+isNumber('10.10')  //=> 'true'
+isNumber('100')    //=> 'true'
+isNumber('5e3')    //=> 'true'
+isNumber(parseInt('012'))   //=> 'true'
+isNumber(parseFloat('012')) //=> 'true'
+```
+
+### False
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber('foo')             //=> 'false'
+isNumber([1])               //=> 'false'
+isNumber([])                //=> 'false'
+isNumber(function () {})    //=> 'false'
+isNumber(Infinity)          //=> 'false'
+isNumber(NaN)               //=> 'false'
+isNumber(new Array('abc'))  //=> 'false'
+isNumber(new Array(2))      //=> 'false'
+isNumber(new Buffer('abc')) //=> 'false'
+isNumber(null)              //=> 'false'
+isNumber(undefined)         //=> 'false'
+isNumber({abc: 'abc'})      //=> 'false'
+```
+
+## About
+
+### Related projects
+
+* [even](https://www.npmjs.com/package/even): Get the even numbered items from an array. | [homepage](https://github.com/jonschlinkert/even "Get the even numbered items from an array.")
+* [is-even](https://www.npmjs.com/package/is-even): Return true if the given number is even. | [homepage](https://github.com/jonschlinkert/is-even "Return true if the given number is even.")
+* [is-odd](https://www.npmjs.com/package/is-odd): Returns true if the given number is odd. | [homepage](https://github.com/jonschlinkert/is-odd "Returns true if the given number is odd.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+* [odd](https://www.npmjs.com/package/odd): Get the odd numbered items from an array. | [homepage](https://github.com/jonschlinkert/odd "Get the odd numbered items from an array.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
+
+To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
+
+```sh
+$ npm install -g verb verb-generate-readme && verb
+```
+
+### Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm install -d && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT license](https://github.com/jonschlinkert/is-number/blob/master/LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.30, on September 10, 2016._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/arr-swap/node_modules/is-number/index.js b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/index.js
new file mode 100644
index 00000000..7a2a45be
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/index.js
@@ -0,0 +1,22 @@
+/*!
+ * is-number <https://github.com/jonschlinkert/is-number>
+ *
+ * Copyright (c) 2014-2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+module.exports = function isNumber(num) {
+  var type = typeOf(num);
+
+  if (type === 'string') {
+    if (!num.trim()) return false;
+  } else if (type !== 'number') {
+    return false;
+  }
+
+  return (num - num + 1) >= 0;
+};
diff --git a/input_devices/mag/node_modules/arr-swap/node_modules/is-number/package.json b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/package.json
new file mode 100644
index 00000000..68ccff59
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/node_modules/is-number/package.json
@@ -0,0 +1,152 @@
+{
+  "_args": [
+    [
+      "is-number@^3.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/arr-swap"
+    ]
+  ],
+  "_from": "is-number@>=3.0.0 <4.0.0",
+  "_id": "is-number@3.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/arr-swap/is-number",
+  "_nodeVersion": "6.3.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/is-number-3.0.0.tgz_1473555089490_0.21388969756662846"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.10.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-number",
+    "raw": "is-number@^3.0.0",
+    "rawSpec": "^3.0.0",
+    "scope": null,
+    "spec": ">=3.0.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/arr-swap"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+  "_shasum": "24fd6201a4782cf50561c810276afc7d12d71195",
+  "_shrinkwrap": null,
+  "_spec": "is-number@^3.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/arr-swap",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-number/issues"
+  },
+  "contributors": [
+    {
+      "name": "Charlike Mike Reagent",
+      "url": "http://www.tunnckocore.tk"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Returns true if the value is a number. comprehensive tests.",
+  "devDependencies": {
+    "benchmarked": "^0.2.5",
+    "chalk": "^1.1.3",
+    "gulp-format-md": "^0.1.10",
+    "mocha": "^3.0.2"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "24fd6201a4782cf50561c810276afc7d12d71195",
+    "tarball": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "af885e2e890b9ef0875edd2b117305119ee5bdc5",
+  "homepage": "https://github.com/jonschlinkert/is-number",
+  "keywords": [
+    "check",
+    "coerce",
+    "coercion",
+    "integer",
+    "is",
+    "is-nan",
+    "is-num",
+    "is-number",
+    "istype",
+    "kind",
+    "math",
+    "nan",
+    "num",
+    "number",
+    "numeric",
+    "test",
+    "type",
+    "typeof",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "is-number",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-number.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-generate-readme"
+    ],
+    "related": {
+      "list": [
+        "even",
+        "is-even",
+        "is-odd",
+        "is-primitive",
+        "kind-of",
+        "odd"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.0.0"
+}
diff --git a/input_devices/mag/node_modules/arr-swap/package.json b/input_devices/mag/node_modules/arr-swap/package.json
new file mode 100644
index 00000000..a6c04332
--- /dev/null
+++ b/input_devices/mag/node_modules/arr-swap/package.json
@@ -0,0 +1,114 @@
+{
+  "_args": [
+    [
+      "arr-swap@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "arr-swap@>=1.0.1 <2.0.0",
+  "_id": "arr-swap@1.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/arr-swap",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/arr-swap-1.0.1.tgz_1495764656459_0.23885946325026453"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.6.1",
+  "_phantomChildren": {
+    "kind-of": "3.2.2"
+  },
+  "_requested": {
+    "name": "arr-swap",
+    "raw": "arr-swap@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/arr-swap/-/arr-swap-1.0.1.tgz",
+  "_shasum": "147590ed65fc815bc07fef0997c2e5823d643534",
+  "_shrinkwrap": null,
+  "_spec": "arr-swap@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/arr-swap/issues"
+  },
+  "dependencies": {
+    "is-number": "^3.0.0"
+  },
+  "description": "Swap two items in an array. Does not modify the Array prototype.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.4.2"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "147590ed65fc815bc07fef0997c2e5823d643534",
+    "tarball": "https://registry.npmjs.org/arr-swap/-/arr-swap-1.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "b584f561681cb58839e55c8148faa43f23eb9e00",
+  "homepage": "https://github.com/jonschlinkert/arr-swap",
+  "keywords": [
+    "arr",
+    "array",
+    "swap"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "arr-swap",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/arr-swap.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "arr-flatten",
+        "arr-union",
+        "array-unique"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.1"
+}
diff --git a/input_devices/mag/node_modules/async-limiter/.travis.yml b/input_devices/mag/node_modules/async-limiter/.travis.yml
new file mode 100644
index 00000000..6cf4a7ad
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/.travis.yml
@@ -0,0 +1,7 @@
+language: node_js
+node_js:
+  - "6"
+  - "node"
+script: npm run travis
+cache:
+  yarn: true
diff --git a/input_devices/mag/node_modules/async-limiter/LICENSE b/input_devices/mag/node_modules/async-limiter/LICENSE
new file mode 100644
index 00000000..9c91fb26
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/LICENSE
@@ -0,0 +1,8 @@
+The MIT License (MIT)
+Copyright (c) 2017 Samuel Reed <samuel.trace.reed@gmail.com>
+
+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/input_devices/mag/node_modules/async-limiter/coverage/coverage.json b/input_devices/mag/node_modules/async-limiter/coverage/coverage.json
new file mode 100644
index 00000000..5b4a3584
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/coverage.json
@@ -0,0 +1 @@
+{"/Users/samuelreed/git/forks/async-throttle/index.js":{"path":"/Users/samuelreed/git/forks/async-throttle/index.js","s":{"1":1,"2":7,"3":1,"4":6,"5":6,"6":6,"7":6,"8":6,"9":6,"10":1,"11":1,"12":3,"13":13,"14":13,"15":13,"16":1,"17":19,"18":1,"19":45,"20":6,"21":39,"22":13,"23":13,"24":13,"25":13,"26":39,"27":18,"28":6,"29":6,"30":1,"31":6,"32":6,"33":6,"34":1,"35":13,"36":13,"37":1},"b":{"1":[1,6],"2":[6,5],"3":[6,5],"4":[6,39],"5":[13,26],"6":[18,21],"7":[6,0]},"f":{"1":7,"2":3,"3":13,"4":19,"5":45,"6":6,"7":13},"fnMap":{"1":{"name":"Queue","line":3,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":24}}},"2":{"name":"(anonymous_2)","line":22,"loc":{"start":{"line":22,"column":24},"end":{"line":22,"column":41}}},"3":{"name":"(anonymous_3)","line":23,"loc":{"start":{"line":23,"column":28},"end":{"line":23,"column":39}}},"4":{"name":"(anonymous_4)","line":31,"loc":{"start":{"line":31,"column":7},"end":{"line":31,"column":18}}},"5":{"name":"(anonymous_5)","line":36,"loc":{"start":{"line":36,"column":23},"end":{"line":36,"column":34}}},"6":{"name":"(anonymous_6)","line":55,"loc":{"start":{"line":55,"column":25},"end":{"line":55,"column":38}}},"7":{"name":"done","line":62,"loc":{"start":{"line":62,"column":0},"end":{"line":62,"column":16}}}},"statementMap":{"1":{"start":{"line":3,"column":0},"end":{"line":14,"column":1}},"2":{"start":{"line":4,"column":2},"end":{"line":6,"column":3}},"3":{"start":{"line":5,"column":4},"end":{"line":5,"column":30}},"4":{"start":{"line":8,"column":2},"end":{"line":8,"column":26}},"5":{"start":{"line":9,"column":2},"end":{"line":9,"column":53}},"6":{"start":{"line":10,"column":2},"end":{"line":10,"column":19}},"7":{"start":{"line":11,"column":2},"end":{"line":11,"column":17}},"8":{"start":{"line":12,"column":2},"end":{"line":12,"column":16}},"9":{"start":{"line":13,"column":2},"end":{"line":13,"column":31}},"10":{"start":{"line":16,"column":0},"end":{"line":20,"column":2}},"11":{"start":{"line":22,"column":0},"end":{"line":28,"column":3}},"12":{"start":{"line":23,"column":2},"end":{"line":27,"column":4}},"13":{"start":{"line":24,"column":4},"end":{"line":24,"column":75}},"14":{"start":{"line":25,"column":4},"end":{"line":25,"column":16}},"15":{"start":{"line":26,"column":4},"end":{"line":26,"column":24}},"16":{"start":{"line":30,"column":0},"end":{"line":34,"column":3}},"17":{"start":{"line":32,"column":4},"end":{"line":32,"column":43}},"18":{"start":{"line":36,"column":0},"end":{"line":53,"column":2}},"19":{"start":{"line":37,"column":2},"end":{"line":39,"column":3}},"20":{"start":{"line":38,"column":4},"end":{"line":38,"column":11}},"21":{"start":{"line":40,"column":2},"end":{"line":45,"column":3}},"22":{"start":{"line":41,"column":4},"end":{"line":41,"column":32}},"23":{"start":{"line":42,"column":4},"end":{"line":42,"column":19}},"24":{"start":{"line":43,"column":4},"end":{"line":43,"column":20}},"25":{"start":{"line":44,"column":4},"end":{"line":44,"column":16}},"26":{"start":{"line":47,"column":2},"end":{"line":52,"column":3}},"27":{"start":{"line":48,"column":4},"end":{"line":51,"column":5}},"28":{"start":{"line":49,"column":6},"end":{"line":49,"column":30}},"29":{"start":{"line":50,"column":6},"end":{"line":50,"column":27}},"30":{"start":{"line":55,"column":0},"end":{"line":60,"column":2}},"31":{"start":{"line":56,"column":2},"end":{"line":59,"column":3}},"32":{"start":{"line":57,"column":4},"end":{"line":57,"column":22}},"33":{"start":{"line":58,"column":4},"end":{"line":58,"column":16}},"34":{"start":{"line":62,"column":0},"end":{"line":65,"column":1}},"35":{"start":{"line":63,"column":2},"end":{"line":63,"column":17}},"36":{"start":{"line":64,"column":2},"end":{"line":64,"column":14}},"37":{"start":{"line":67,"column":0},"end":{"line":67,"column":23}}},"branchMap":{"1":{"line":4,"type":"if","locations":[{"start":{"line":4,"column":2},"end":{"line":4,"column":2}},{"start":{"line":4,"column":2},"end":{"line":4,"column":2}}]},"2":{"line":8,"type":"binary-expr","locations":[{"start":{"line":8,"column":12},"end":{"line":8,"column":19}},{"start":{"line":8,"column":23},"end":{"line":8,"column":25}}]},"3":{"line":9,"type":"binary-expr","locations":[{"start":{"line":9,"column":21},"end":{"line":9,"column":40}},{"start":{"line":9,"column":44},"end":{"line":9,"column":52}}]},"4":{"line":37,"type":"if","locations":[{"start":{"line":37,"column":2},"end":{"line":37,"column":2}},{"start":{"line":37,"column":2},"end":{"line":37,"column":2}}]},"5":{"line":40,"type":"if","locations":[{"start":{"line":40,"column":2},"end":{"line":40,"column":2}},{"start":{"line":40,"column":2},"end":{"line":40,"column":2}}]},"6":{"line":47,"type":"if","locations":[{"start":{"line":47,"column":2},"end":{"line":47,"column":2}},{"start":{"line":47,"column":2},"end":{"line":47,"column":2}}]},"7":{"line":56,"type":"if","locations":[{"start":{"line":56,"column":2},"end":{"line":56,"column":2}},{"start":{"line":56,"column":2},"end":{"line":56,"column":2}}]}}}}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html
new file mode 100644
index 00000000..198882b4
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Code coverage report for async-throttle/</title>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="../prettify.css">
+    <link rel="stylesheet" href="../base.css">
+    <style type='text/css'>
+        div.coverage-summary .sorter {
+            background-image: url(../sort-arrow-sprite.png);
+        }
+    </style>
+</head>
+<body>
+<div class="header high">
+    <h1>Code coverage report for <span class="entity">async-throttle/</span></h1>
+    <h2>
+        Statements: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Branches: <span class="metric">92.86% <small>(13 / 14)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Functions: <span class="metric">100% <small>(7 / 7)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Lines: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Ignored: <span class="metric"><span class="ignore-none">none</span></span> &nbsp;&nbsp;&nbsp;&nbsp;
+    </h2>
+    <div class="path"><a href="../index.html">All files</a> &#187; async-throttle/</div>
+</div>
+<div class="body">
+<div class="coverage-summary">
+<table>
+<thead>
+<tr>
+   <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
+   <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
+   <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
+   <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
+   <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
+   <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
+   <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
+</tr>
+</thead>
+<tbody><tr>
+	<td class="file high" data-value="index.js"><a href="index.js.html">index.js</a></td>
+	<td data-value="100" class="pic high"><span class="cover-fill cover-full" style="width: 100px;"></span><span class="cover-empty" style="width:0px;"></span></td>
+	<td data-value="100" class="pct high">100%</td>
+	<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
+	<td data-value="92.86" class="pct high">92.86%</td>
+	<td data-value="14" class="abs high">(13&nbsp;/&nbsp;14)</td>
+	<td data-value="100" class="pct high">100%</td>
+	<td data-value="7" class="abs high">(7&nbsp;/&nbsp;7)</td>
+	<td data-value="100" class="pct high">100%</td>
+	<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
+	</tr>
+
+</tbody>
+</table>
+</div>
+</div>
+<div class="footer">
+    <div class="meta">Generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Sep 11 2017 11:14:14 GMT-0500 (CDT)</div>
+</div>
+<script src="../prettify.js"></script>
+<script>
+window.onload = function () {
+        if (typeof prettyPrint === 'function') {
+            prettyPrint();
+        }
+};
+</script>
+<script src="../sorter.js"></script>
+</body>
+</html>
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html
new file mode 100644
index 00000000..adc030fd
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html
@@ -0,0 +1,246 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Code coverage report for async-throttle/index.js</title>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="../prettify.css">
+    <link rel="stylesheet" href="../base.css">
+    <style type='text/css'>
+        div.coverage-summary .sorter {
+            background-image: url(../sort-arrow-sprite.png);
+        }
+    </style>
+</head>
+<body>
+<div class="header high">
+    <h1>Code coverage report for <span class="entity">async-throttle/index.js</span></h1>
+    <h2>
+        Statements: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Branches: <span class="metric">92.86% <small>(13 / 14)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Functions: <span class="metric">100% <small>(7 / 7)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Lines: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Ignored: <span class="metric"><span class="ignore-none">none</span></span> &nbsp;&nbsp;&nbsp;&nbsp;
+    </h2>
+    <div class="path"><a href="../index.html">All files</a> &#187; <a href="index.html">async-throttle/</a> &#187; index.js</div>
+</div>
+<div class="body">
+<pre><table class="coverage">
+<tr><td class="line-count">1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68</td><td class="line-coverage"><span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-yes">7</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-yes">3</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">19</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-yes">45</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">39</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">39</span>
+<span class="cline-any cline-yes">18</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-yes">6</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-yes">13</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1</span>
+<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">'use strict';
+&nbsp;
+function Queue(options) {
+  if (!(this instanceof Queue)) {
+    return new Queue(options);
+  }
+&nbsp;
+  options = options || {};
+  this.concurrency = options.concurrency || Infinity;
+  this.pending = 0;
+  this.jobs = [];
+  this.cbs = [];
+  this._done = done.bind(this);
+}
+&nbsp;
+var arrayAddMethods = [
+  'push',
+  'unshift',
+  'splice'
+];
+&nbsp;
+arrayAddMethods.forEach(function(method) {
+  Queue.prototype[method] = function() {
+    var methodResult = Array.prototype[method].apply(this.jobs, arguments);
+    this._run();
+    return methodResult;
+  };
+});
+&nbsp;
+Object.defineProperty(Queue.prototype, 'length', {
+  get: function() {
+    return this.pending + this.jobs.length;
+  }
+});
+&nbsp;
+Queue.prototype._run = function() {
+  if (this.pending === this.concurrency) {
+    return;
+  }
+  if (this.jobs.length) {
+    var job = this.jobs.shift();
+    this.pending++;
+    job(this._done);
+    this._run();
+  }
+&nbsp;
+  if (this.pending === 0) {
+    while (this.cbs.length !== 0) {
+      var cb = this.cbs.pop();
+      process.nextTick(cb);
+    }
+  }
+};
+&nbsp;
+Queue.prototype.onDone = function(cb) {
+  <span class="missing-if-branch" title="else path not taken" >E</span>if (typeof cb === 'function') {
+    this.cbs.push(cb);
+    this._run();
+  }
+};
+&nbsp;
+function done() {
+  this.pending--;
+  this._run();
+}
+&nbsp;
+module.exports = Queue;
+&nbsp;</pre></td></tr>
+</table></pre>
+
+</div>
+<div class="footer">
+    <div class="meta">Generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Sep 11 2017 11:14:14 GMT-0500 (CDT)</div>
+</div>
+<script src="../prettify.js"></script>
+<script>
+window.onload = function () {
+        if (typeof prettyPrint === 'function') {
+            prettyPrint();
+        }
+};
+</script>
+<script src="../sorter.js"></script>
+</body>
+</html>
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/base.css b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/base.css
new file mode 100644
index 00000000..a6a2f328
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/base.css
@@ -0,0 +1,182 @@
+body, html {
+    margin:0; padding: 0;
+}
+body {
+    font-family: Helvetica Neue, Helvetica,Arial;
+    font-size: 10pt;
+}
+div.header, div.footer {
+    background: #eee;
+    padding: 1em;
+}
+div.header {
+    z-index: 100;
+    position: fixed;
+    top: 0;
+    border-bottom: 1px solid #666;
+    width: 100%;
+}
+div.footer {
+    border-top: 1px solid #666;
+}
+div.body {
+    margin-top: 10em;
+}
+div.meta {
+    font-size: 90%;
+    text-align: center;
+}
+h1, h2, h3 {
+    font-weight: normal;
+}
+h1 {
+    font-size: 12pt;
+}
+h2 {
+    font-size: 10pt;
+}
+pre {
+    font-family: Consolas, Menlo, Monaco, monospace;
+    margin: 0;
+    padding: 0;
+    line-height: 1.3;
+    font-size: 14px;
+    -moz-tab-size: 2;
+    -o-tab-size:  2;
+    tab-size: 2;
+}
+
+div.path { font-size: 110%; }
+div.path a:link, div.path a:visited { color: #000; }
+table.coverage { border-collapse: collapse; margin:0; padding: 0 }
+
+table.coverage td {
+    margin: 0;
+    padding: 0;
+    color: #111;
+    vertical-align: top;
+}
+table.coverage td.line-count {
+    width: 50px;
+    text-align: right;
+    padding-right: 5px;
+}
+table.coverage td.line-coverage {
+    color: #777 !important;
+    text-align: right;
+    border-left: 1px solid #666;
+    border-right: 1px solid #666;
+}
+
+table.coverage td.text {
+}
+
+table.coverage td span.cline-any {
+    display: inline-block;
+    padding: 0 5px;
+    width: 40px;
+}
+table.coverage td span.cline-neutral {
+    background: #eee;
+}
+table.coverage td span.cline-yes {
+    background: #b5d592;
+    color: #999;
+}
+table.coverage td span.cline-no {
+    background: #fc8c84;
+}
+
+.cstat-yes { color: #111; }
+.cstat-no { background: #fc8c84; color: #111; }
+.fstat-no { background: #ffc520; color: #111 !important; }
+.cbranch-no { background:  yellow !important; color: #111; }
+
+.cstat-skip { background: #ddd; color: #111; }
+.fstat-skip { background: #ddd; color: #111 !important; }
+.cbranch-skip { background: #ddd !important; color: #111; }
+
+.missing-if-branch {
+    display: inline-block;
+    margin-right: 10px;
+    position: relative;
+    padding: 0 4px;
+    background: black;
+    color: yellow;
+}
+
+.skip-if-branch {
+    display: none;
+    margin-right: 10px;
+    position: relative;
+    padding: 0 4px;
+    background: #ccc;
+    color: white;
+}
+
+.missing-if-branch .typ, .skip-if-branch .typ {
+    color: inherit !important;
+}
+
+.entity, .metric { font-weight: bold; }
+.metric { display: inline-block; border: 1px solid #333; padding: 0.3em; background: white; }
+.metric small { font-size: 80%; font-weight: normal; color: #666; }
+
+div.coverage-summary table { border-collapse: collapse; margin: 3em; font-size: 110%; }
+div.coverage-summary td, div.coverage-summary table  th { margin: 0; padding: 0.25em 1em; border-top: 1px solid #666; border-bottom: 1px solid #666; }
+div.coverage-summary th { text-align: left; border: 1px solid #666; background: #eee; font-weight: normal; }
+div.coverage-summary th.file { border-right: none !important; }
+div.coverage-summary th.pic { border-left: none !important; text-align: right; }
+div.coverage-summary th.pct { border-right: none !important; }
+div.coverage-summary th.abs { border-left: none !important; text-align: right; }
+div.coverage-summary td.pct { text-align: right; border-left: 1px solid #666; }
+div.coverage-summary td.abs { text-align: right; font-size: 90%; color: #444; border-right: 1px solid #666; }
+div.coverage-summary td.file { border-left: 1px solid #666; white-space: nowrap;  }
+div.coverage-summary td.pic { min-width: 120px !important;  }
+div.coverage-summary a:link { text-decoration: none; color: #000; }
+div.coverage-summary a:visited { text-decoration: none; color: #777; }
+div.coverage-summary a:hover { text-decoration: underline; }
+div.coverage-summary tfoot td { border-top: 1px solid #666; }
+
+div.coverage-summary .sorter {
+    height: 10px;
+    width: 7px;
+    display: inline-block;
+    margin-left: 0.5em;
+    background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
+}
+div.coverage-summary .sorted .sorter {
+    background-position: 0 -20px;
+}
+div.coverage-summary .sorted-desc .sorter {
+    background-position: 0 -10px;
+}
+
+.high { background: #b5d592 !important; }
+.medium { background: #ffe87c !important; }
+.low { background: #fc8c84 !important; }
+
+span.cover-fill, span.cover-empty {
+    display:inline-block;
+    border:1px solid #444;
+    background: white;
+    height: 12px;
+}
+span.cover-fill {
+    background: #ccc;
+    border-right: 1px solid #444;
+}
+span.cover-empty {
+    background: white;
+    border-left: none;
+}
+span.cover-full {
+    border-right: none !important;
+}
+pre.prettyprint {
+    border: none !important;
+    padding: 0 !important;
+    margin: 0 !important;
+}
+.com { color: #999 !important; }
+.ignore-none { color: #999; font-weight: normal; }
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/index.html b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/index.html
new file mode 100644
index 00000000..782a1cff
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/index.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Code coverage report for All files</title>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="prettify.css">
+    <link rel="stylesheet" href="base.css">
+    <style type='text/css'>
+        div.coverage-summary .sorter {
+            background-image: url(sort-arrow-sprite.png);
+        }
+    </style>
+</head>
+<body>
+<div class="header high">
+    <h1>Code coverage report for <span class="entity">All files</span></h1>
+    <h2>
+        Statements: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Branches: <span class="metric">92.86% <small>(13 / 14)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Functions: <span class="metric">100% <small>(7 / 7)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Lines: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
+        Ignored: <span class="metric"><span class="ignore-none">none</span></span> &nbsp;&nbsp;&nbsp;&nbsp;
+    </h2>
+    <div class="path"></div>
+</div>
+<div class="body">
+<div class="coverage-summary">
+<table>
+<thead>
+<tr>
+   <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
+   <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
+   <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
+   <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
+   <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
+   <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
+   <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
+</tr>
+</thead>
+<tbody><tr>
+	<td class="file high" data-value="async-throttle/"><a href="async-throttle/index.html">async-throttle/</a></td>
+	<td data-value="100" class="pic high"><span class="cover-fill cover-full" style="width: 100px;"></span><span class="cover-empty" style="width:0px;"></span></td>
+	<td data-value="100" class="pct high">100%</td>
+	<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
+	<td data-value="92.86" class="pct high">92.86%</td>
+	<td data-value="14" class="abs high">(13&nbsp;/&nbsp;14)</td>
+	<td data-value="100" class="pct high">100%</td>
+	<td data-value="7" class="abs high">(7&nbsp;/&nbsp;7)</td>
+	<td data-value="100" class="pct high">100%</td>
+	<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
+	</tr>
+
+</tbody>
+</table>
+</div>
+</div>
+<div class="footer">
+    <div class="meta">Generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Sep 11 2017 11:14:14 GMT-0500 (CDT)</div>
+</div>
+<script src="prettify.js"></script>
+<script>
+window.onload = function () {
+        if (typeof prettyPrint === 'function') {
+            prettyPrint();
+        }
+};
+</script>
+<script src="sorter.js"></script>
+</body>
+</html>
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.css b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.css
new file mode 100644
index 00000000..b317a7cd
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.css
@@ -0,0 +1 @@
+.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.js b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.js
new file mode 100644
index 00000000..ef51e038
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/prettify.js
@@ -0,0 +1 @@
+window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.ignoreCase){ac=true}else{if(/[a-z]/i.test(ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){S=true;ac=false;break}}}var Y={b:8,t:9,n:10,v:11,f:12,r:13};function ab(ah){var ag=ah.charCodeAt(0);if(ag!==92){return ag}var af=ah.charAt(1);ag=Y[af];if(ag){return ag}else{if("0"<=af&&af<="7"){return parseInt(ah.substring(1),8)}else{if(af==="u"||af==="x"){return parseInt(ah.substring(2),16)}else{return ah.charCodeAt(1)}}}}function T(af){if(af<32){return(af<16?"\\x0":"\\x")+af.toString(16)}var ag=String.fromCharCode(af);if(ag==="\\"||ag==="-"||ag==="["||ag==="]"){ag="\\"+ag}return ag}function X(am){var aq=am.substring(1,am.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));var ak=[];var af=[];var ao=aq[0]==="^";for(var ar=ao?1:0,aj=aq.length;ar<aj;++ar){var ah=aq[ar];if(/\\[bdsw]/i.test(ah)){ak.push(ah)}else{var ag=ab(ah);var al;if(ar+2<aj&&"-"===aq[ar+1]){al=ab(aq[ar+2]);ar+=2}else{al=ag}af.push([ag,al]);if(!(al<65||ag>122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;ar<af.length;++ar){var at=af[ar];if(at[0]<=ap[1]+1){ap[1]=Math.max(ap[1],at[1])}else{ai.push(ap=at)}}var an=["["];if(ao){an.push("^")}an.push.apply(an,ak);for(var ar=0;ar<ai.length;++ar){var at=ai[ar];an.push(T(at[0]));if(at[1]>at[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){an[af]=-1}}}}for(var ak=1;ak<an.length;++ak){if(-1===an[ak]){an[ak]=++ad}}for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am;if(an[am]===undefined){aj[ak]="(?:"}}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){aj[ak]="\\"+an[am]}}}}for(var ak=0,am=0;ak<ah;++ak){if("^"===aj[ak]&&"^"!==aj[ak+1]){aj[ak]=""}}if(al.ignoreCase&&S){for(var ak=0;ak<ah;++ak){var ag=aj[ak];var ai=ag.charAt(0);if(ag.length>=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.global||ae.multiline){throw new Error(""+ae)}aa.push("(?:"+W(ae)+")")}return new RegExp(aa.join("|"),ac?"gi":"g")}function a(V){var U=/(?:^|\s)nocode(?:\s|$)/;var X=[];var T=0;var Z=[];var W=0;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=document.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Y=S&&"pre"===S.substring(0,3);function aa(ab){switch(ab.nodeType){case 1:if(U.test(ab.className)){return}for(var ae=ab.firstChild;ae;ae=ae.nextSibling){aa(ae)}var ad=ab.nodeName;if("BR"===ad||"LI"===ad){X[W]="\n";Z[W<<1]=T++;Z[(W++<<1)|1]=ab}break;case 3:case 4:var ac=ab.nodeValue;if(ac.length){if(!Y){ac=ac.replace(/[ \t\r\n]+/g," ")}else{ac=ac.replace(/\r\n?/g,"\n")}X[W]=ac;Z[W<<1]=T;T+=ac.length;Z[(W++<<1)|1]=ab}break}}aa(V);return{sourceCode:X.join("").replace(/\n$/,""),spans:Z}}function B(S,U,W,T){if(!U){return}var V={sourceCode:U,basePos:S};W(V);T.push.apply(T,V.decorations)}var v=/\S/;function o(S){var V=undefined;for(var U=S.firstChild;U;U=U.nextSibling){var T=U.nodeType;V=(T===1)?(V?S:U):(T===3)?(v.test(U.nodeValue)?S:V):V}return V===S?undefined:V}function g(U,T){var S={};var V;(function(){var ad=U.concat(T);var ah=[];var ag={};for(var ab=0,Z=ad.length;ab<Z;++ab){var Y=ad[ab];var ac=Y[3];if(ac){for(var ae=ac.length;--ae>=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae<aq;++ae){var ag=an[ae];var ap=aj[ag];var ai=void 0;var am;if(typeof ap==="string"){am=false}else{var aa=S[ag.charAt(0)];if(aa){ai=ag.match(aa[1]);ap=aa[0]}else{for(var ao=0;ao<X;++ao){aa=T[ao];ai=ag.match(aa[1]);if(ai){ap=aa[0];break}}if(!ai){ap=F}}am=ap.length>=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y<W.length;++Y){ae(W[Y])}if(ag===(ag|0)){W[0].setAttribute("value",ag)}var aa=ac.createElement("OL");aa.className="linenums";var X=Math.max(0,((ag-1))|0)||0;for(var Y=0,T=W.length;Y<T;++Y){af=W[Y];af.className="L"+((Y+X)%10);if(!af.firstChild){af.appendChild(ac.createTextNode("\xA0"))}aa.appendChild(af)}V.appendChild(aa)}function D(ac){var aj=/\bMSIE\b/.test(navigator.userAgent);var am=/\n/g;var al=ac.sourceCode;var an=al.length;var V=0;var aa=ac.spans;var T=aa.length;var ah=0;var X=ac.decorations;var Y=X.length;var Z=0;X[Y]=an;var ar,aq;for(aq=ar=0;aq<Y;){if(X[aq]!==X[aq+2]){X[ar++]=X[aq++];X[ar++]=X[aq++]}else{aq+=2}}Y=ar;for(aq=ar=0;aq<Y;){var at=X[aq];var ab=X[aq+1];var W=aq+2;while(W+2<=Y&&X[W+1]===ab){W+=2}X[ar++]=at;X[ar++]=ab;aq=W}Y=X.length=ar;var ae=null;while(ah<T){var af=aa[ah];var S=aa[ah+2]||an;var ag=X[Z];var ap=X[Z+2]||an;var W=Math.min(S,ap);var ak=aa[ah+1];var U;if(ak.nodeType!==1&&(U=al.substring(V,W))){if(aj){U=U.replace(am,"\r")}ak.nodeValue=U;var ai=ak.ownerDocument;var ao=ai.createElement("SPAN");ao.className=X[Z+1];var ad=ak.parentNode;ad.replaceChild(ao,ak);ao.appendChild(ak);if(V<S){aa[ah+1]=ak=ai.createTextNode(al.substring(W,S));ad.insertBefore(ak,ao.nextSibling)}}V=W;if(V>=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*</.test(S)?"default-markup":"default-code"}return t[T]}c(K,["default-code"]);c(g([],[[F,/^[^<?]+/],[E,/^<!\w[^>]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa<ac.length;++aa){for(var Z=0,V=ac[aa].length;Z<V;++Z){T.push(ac[aa][Z])}}ac=null;var W=Date;if(!W.now){W={now:function(){return +(new Date)}}}var X=0;var S;var ab=/\blang(?:uage)?-([\w.]+)(?!\S)/;var ae=/\bprettyprint\b/;function U(){var ag=(window.PR_SHOULD_USE_CONTINUATION?W.now()+250:Infinity);for(;X<T.length&&W.now()<ag;X++){var aj=T[X];var ai=aj.className;if(ai.indexOf("prettyprint")>=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X<T.length){setTimeout(U,250)}else{if(ad){ad()}}}U()}window.prettyPrintOne=y;window.prettyPrint=b;window.PR={createSimpleLexer:g,registerLangHandler:c,sourceDecorator:i,PR_ATTRIB_NAME:P,PR_ATTRIB_VALUE:n,PR_COMMENT:j,PR_DECLARATION:E,PR_KEYWORD:z,PR_LITERAL:G,PR_NOCODE:N,PR_PLAIN:F,PR_PUNCTUATION:L,PR_SOURCE:J,PR_STRING:C,PR_TAG:m,PR_TYPE:O}})();PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^<script\b[^>]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]);
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png
new file mode 100644
index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3
GIT binary patch
literal 209
zcmeAS@N?(olHy`uVBq!ia0y~yU|?rpV36iuV_;y|;5OBmfq_A?#5JNMI6tkVJh3R1
z!7(L2DOJHUH!(dmC^a#qvhZZ84Fdy1v8Rh;NX4x^L5_R}6gZgo9r-{1!E6ba-5Xf%
zq(%$#UgEmqk>(b`*UOu}kTva^=&Iw!;$1E&JZ>w?H|n0Au|c|n>!5-}9?Ru)_M5)i
z{$aOvJ+j@Yq@>UB?#NPgp~xQ-r`mh`&j_2Ou*qSS^zwr5AKDq186tmJIF%>sbTBY5
OFnGH9xvX<aXaWF!+epL!

literal 0
HcmV?d00001

diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/sorter.js b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/sorter.js
new file mode 100644
index 00000000..6afb736c
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov-report/sorter.js
@@ -0,0 +1,156 @@
+var addSorting = (function () {
+    "use strict";
+    var cols,
+        currentSort = {
+            index: 0,
+            desc: false
+        };
+
+    // returns the summary table element
+    function getTable() { return document.querySelector('.coverage-summary table'); }
+    // returns the thead element of the summary table
+    function getTableHeader() { return getTable().querySelector('thead tr'); }
+    // returns the tbody element of the summary table
+    function getTableBody() { return getTable().querySelector('tbody'); }
+    // returns the th element for nth column
+    function getNthColumn(n) { return getTableHeader().querySelectorAll('th')[n]; }
+
+    // loads all columns
+    function loadColumns() {
+        var colNodes = getTableHeader().querySelectorAll('th'),
+            colNode,
+            cols = [],
+            col,
+            i;
+
+        for (i = 0; i < colNodes.length; i += 1) {
+            colNode = colNodes[i];
+            col = {
+                key: colNode.getAttribute('data-col'),
+                sortable: !colNode.getAttribute('data-nosort'),
+                type: colNode.getAttribute('data-type') || 'string'
+            };
+            cols.push(col);
+            if (col.sortable) {
+                col.defaultDescSort = col.type === 'number';
+                colNode.innerHTML = colNode.innerHTML + '<span class="sorter"></span>';
+            }
+        }
+        return cols;
+    }
+    // attaches a data attribute to every tr element with an object
+    // of data values keyed by column name
+    function loadRowData(tableRow) {
+        var tableCols = tableRow.querySelectorAll('td'),
+            colNode,
+            col,
+            data = {},
+            i,
+            val;
+        for (i = 0; i < tableCols.length; i += 1) {
+            colNode = tableCols[i];
+            col = cols[i];
+            val = colNode.getAttribute('data-value');
+            if (col.type === 'number') {
+                val = Number(val);
+            }
+            data[col.key] = val;
+        }
+        return data;
+    }
+    // loads all row data
+    function loadData() {
+        var rows = getTableBody().querySelectorAll('tr'),
+            i;
+
+        for (i = 0; i < rows.length; i += 1) {
+            rows[i].data = loadRowData(rows[i]);
+        }
+    }
+    // sorts the table using the data for the ith column
+    function sortByIndex(index, desc) {
+        var key = cols[index].key,
+            sorter = function (a, b) {
+                a = a.data[key];
+                b = b.data[key];
+                return a < b ? -1 : a > b ? 1 : 0;
+            },
+            finalSorter = sorter,
+            tableBody = document.querySelector('.coverage-summary tbody'),
+            rowNodes = tableBody.querySelectorAll('tr'),
+            rows = [],
+            i;
+
+        if (desc) {
+            finalSorter = function (a, b) {
+                return -1 * sorter(a, b);
+            };
+        }
+
+        for (i = 0; i < rowNodes.length; i += 1) {
+            rows.push(rowNodes[i]);
+            tableBody.removeChild(rowNodes[i]);
+        }
+
+        rows.sort(finalSorter);
+
+        for (i = 0; i < rows.length; i += 1) {
+            tableBody.appendChild(rows[i]);
+        }
+    }
+    // removes sort indicators for current column being sorted
+    function removeSortIndicators() {
+        var col = getNthColumn(currentSort.index),
+            cls = col.className;
+
+        cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
+        col.className = cls;
+    }
+    // adds sort indicators for current column being sorted
+    function addSortIndicators() {
+        getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted';
+    }
+    // adds event listeners for all sorter widgets
+    function enableUI() {
+        var i,
+            el,
+            ithSorter = function ithSorter(i) {
+                var col = cols[i];
+
+                return function () {
+                    var desc = col.defaultDescSort;
+
+                    if (currentSort.index === i) {
+                        desc = !currentSort.desc;
+                    }
+                    sortByIndex(i, desc);
+                    removeSortIndicators();
+                    currentSort.index = i;
+                    currentSort.desc = desc;
+                    addSortIndicators();
+                };
+            };
+        for (i =0 ; i < cols.length; i += 1) {
+            if (cols[i].sortable) {
+                el = getNthColumn(i).querySelector('.sorter');
+                if (el.addEventListener) {
+                    el.addEventListener('click', ithSorter(i));
+                } else {
+                    el.attachEvent('onclick', ithSorter(i));
+                }
+            }
+        }
+    }
+    // adds sorting functionality to the UI
+    return function () {
+        if (!getTable()) {
+            return;
+        }
+        cols = loadColumns();
+        loadData(cols);
+        addSortIndicators();
+        enableUI();
+    };
+})();
+
+window.addEventListener('load', addSorting);
diff --git a/input_devices/mag/node_modules/async-limiter/coverage/lcov.info b/input_devices/mag/node_modules/async-limiter/coverage/lcov.info
new file mode 100644
index 00000000..fbf36aab
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/coverage/lcov.info
@@ -0,0 +1,74 @@
+TN:
+SF:/Users/samuelreed/git/forks/async-throttle/index.js
+FN:3,Queue
+FN:22,(anonymous_2)
+FN:23,(anonymous_3)
+FN:31,(anonymous_4)
+FN:36,(anonymous_5)
+FN:55,(anonymous_6)
+FN:62,done
+FNF:7
+FNH:7
+FNDA:7,Queue
+FNDA:3,(anonymous_2)
+FNDA:13,(anonymous_3)
+FNDA:19,(anonymous_4)
+FNDA:45,(anonymous_5)
+FNDA:6,(anonymous_6)
+FNDA:13,done
+DA:3,1
+DA:4,7
+DA:5,1
+DA:8,6
+DA:9,6
+DA:10,6
+DA:11,6
+DA:12,6
+DA:13,6
+DA:16,1
+DA:22,1
+DA:23,3
+DA:24,13
+DA:25,13
+DA:26,13
+DA:30,1
+DA:32,19
+DA:36,1
+DA:37,45
+DA:38,6
+DA:40,39
+DA:41,13
+DA:42,13
+DA:43,13
+DA:44,13
+DA:47,39
+DA:48,18
+DA:49,6
+DA:50,6
+DA:55,1
+DA:56,6
+DA:57,6
+DA:58,6
+DA:62,1
+DA:63,13
+DA:64,13
+DA:67,1
+LF:37
+LH:37
+BRDA:4,1,0,1
+BRDA:4,1,1,6
+BRDA:8,2,0,6
+BRDA:8,2,1,5
+BRDA:9,3,0,6
+BRDA:9,3,1,5
+BRDA:37,4,0,6
+BRDA:37,4,1,39
+BRDA:40,5,0,13
+BRDA:40,5,1,26
+BRDA:47,6,0,18
+BRDA:47,6,1,21
+BRDA:56,7,0,6
+BRDA:56,7,1,0
+BRF:14
+BRH:13
+end_of_record
diff --git a/input_devices/mag/node_modules/async-limiter/index.js b/input_devices/mag/node_modules/async-limiter/index.js
new file mode 100644
index 00000000..c9bd2f97
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/index.js
@@ -0,0 +1,67 @@
+'use strict';
+
+function Queue(options) {
+  if (!(this instanceof Queue)) {
+    return new Queue(options);
+  }
+
+  options = options || {};
+  this.concurrency = options.concurrency || Infinity;
+  this.pending = 0;
+  this.jobs = [];
+  this.cbs = [];
+  this._done = done.bind(this);
+}
+
+var arrayAddMethods = [
+  'push',
+  'unshift',
+  'splice'
+];
+
+arrayAddMethods.forEach(function(method) {
+  Queue.prototype[method] = function() {
+    var methodResult = Array.prototype[method].apply(this.jobs, arguments);
+    this._run();
+    return methodResult;
+  };
+});
+
+Object.defineProperty(Queue.prototype, 'length', {
+  get: function() {
+    return this.pending + this.jobs.length;
+  }
+});
+
+Queue.prototype._run = function() {
+  if (this.pending === this.concurrency) {
+    return;
+  }
+  if (this.jobs.length) {
+    var job = this.jobs.shift();
+    this.pending++;
+    job(this._done);
+    this._run();
+  }
+
+  if (this.pending === 0) {
+    while (this.cbs.length !== 0) {
+      var cb = this.cbs.pop();
+      process.nextTick(cb);
+    }
+  }
+};
+
+Queue.prototype.onDone = function(cb) {
+  if (typeof cb === 'function') {
+    this.cbs.push(cb);
+    this._run();
+  }
+};
+
+function done() {
+  this.pending--;
+  this._run();
+}
+
+module.exports = Queue;
diff --git a/input_devices/mag/node_modules/async-limiter/package.json b/input_devices/mag/node_modules/async-limiter/package.json
new file mode 100644
index 00000000..a97fc1fe
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/package.json
@@ -0,0 +1,97 @@
+{
+  "_args": [
+    [
+      "async-limiter@~1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ws"
+    ]
+  ],
+  "_from": "async-limiter@>=1.0.0 <1.1.0",
+  "_id": "async-limiter@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/async-limiter",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/async-limiter-1.0.0.tgz_1505149068503_0.15003100014291704"
+  },
+  "_npmUser": {
+    "email": "samuel.trace.reed@gmail.com",
+    "name": "strml"
+  },
+  "_npmVersion": "5.4.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "async-limiter",
+    "raw": "async-limiter@~1.0.0",
+    "rawSpec": "~1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <1.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ws"
+  ],
+  "_resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+  "_shasum": "78faed8c3d074ab81f22b4e985d79e8738f720f8",
+  "_shrinkwrap": null,
+  "_spec": "async-limiter@~1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ws",
+  "author": {
+    "name": "Samuel Reed"
+  },
+  "bugs": {
+    "url": "https://github.com/strml/async-limiter/issues"
+  },
+  "dependencies": {},
+  "description": "asynchronous function queue with adjustable concurrency",
+  "devDependencies": {
+    "coveralls": "^2.11.2",
+    "eslint": "^4.6.1",
+    "eslint-plugin-mocha": "^4.11.0",
+    "intelli-espower-loader": "^1.0.1",
+    "istanbul": "^0.3.2",
+    "mocha": "^3.5.2",
+    "power-assert": "^1.4.4"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
+    "shasum": "78faed8c3d074ab81f22b4e985d79e8738f720f8",
+    "tarball": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz"
+  },
+  "gitHead": "02c8b498279dc7cc1ecc1c4f6fc9ca320c0ce39b",
+  "homepage": "https://github.com/strml/async-limiter#readme",
+  "keywords": [
+    "async",
+    "asynchronous",
+    "concurrency",
+    "concurrent",
+    "job",
+    "limiter",
+    "task",
+    "throttle"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "strml",
+      "email": "samuel.trace.reed@gmail.com"
+    }
+  ],
+  "name": "async-limiter",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/strml/async-limiter.git"
+  },
+  "scripts": {
+    "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls",
+    "example": "node example",
+    "lint": "eslint .",
+    "test": "mocha --R intelli-espower-loader test/",
+    "travis": "npm run lint && npm run coverage"
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/async-limiter/readme.md b/input_devices/mag/node_modules/async-limiter/readme.md
new file mode 100644
index 00000000..dcf4932f
--- /dev/null
+++ b/input_devices/mag/node_modules/async-limiter/readme.md
@@ -0,0 +1,132 @@
+# Async-Limiter
+
+A module for limiting concurrent asynchronous actions in flight. Forked from [queue](https://github.com/jessetane/queue).
+
+[![npm](http://img.shields.io/npm/v/async-limiter.svg?style=flat-square)](http://www.npmjs.org/async-limiter)
+[![tests](https://img.shields.io/travis/STRML/async-limiter.svg?style=flat-square&branch=master)](https://travis-ci.org/STRML/async-limiter)
+[![coverage](https://img.shields.io/coveralls/STRML/async-limiter.svg?style=flat-square&branch=master)](https://coveralls.io/r/STRML/async-limiter)
+
+This module exports a class `Limiter` that implements some of the `Array` API.
+Pass async functions (ones that accept a callback or return a promise) to an instance's additive array methods.
+
+## Motivation
+
+Certain functions, like `zlib`, have [undesirable behavior](https://github.com/nodejs/node/issues/8871#issuecomment-250915913) when
+run at infinite concurrency.
+
+In this case, it is actually faster, and takes far less memory, to limit concurrency.
+
+This module should do the absolute minimum work necessary to queue up functions. PRs are welcome that would
+make this module faster or lighter, but new functionality is not desired.
+
+Style should confirm to nodejs/node style.
+
+## Example
+
+``` javascript
+var Limiter = require('async-limiter')
+
+var t = new Limiter({concurrency: 2});
+var results = []
+
+// add jobs using the familiar Array API
+t.push(function (cb) {
+  results.push('two')
+  cb()
+})
+
+t.push(
+  function (cb) {
+    results.push('four')
+    cb()
+  },
+  function (cb) {
+    results.push('five')
+    cb()
+  }
+)
+
+t.unshift(function (cb) {
+  results.push('one')
+  cb()
+})
+
+t.splice(2, 0, function (cb) {
+  results.push('three')
+  cb()
+})
+
+// Jobs run automatically. If you want a callback when all are done,
+// call 'onDone()'.
+t.onDone(function () {
+  console.log('all done:', results)
+})
+```
+
+## Zlib Example
+
+```js
+const zlib = require('zlib');
+const Limiter = require('async-limiter');
+
+const message = {some: "data"};
+const payload = new Buffer(JSON.stringify(message));
+
+// Try with different concurrency values to see how this actually
+// slows significantly with higher concurrency!
+//
+// 5:        1398.607ms
+// 10:       1375.668ms
+// Infinity: 4423.300ms
+//
+const t = new Limiter({concurrency: 5});
+function deflate(payload, cb) {
+  t.push(function(done) {
+    zlib.deflate(payload, function(err, buffer) {
+      done();
+      cb(err, buffer);
+    });
+  });
+}
+
+console.time('deflate');
+for(let i = 0; i < 30000; ++i) {
+  deflate(payload, function (err, buffer) {});
+}
+q.onDone(function() {
+  console.timeEnd('deflate');
+});
+```
+
+## Install
+
+`npm install async-limiter`
+
+## Test
+
+`npm test`
+
+## API
+
+### `var t = new Limiter([opts])`
+Constructor. `opts` may contain inital values for:
+* `q.concurrency`
+
+## Instance methods
+
+### `q.onDone(fn)`
+`fn` will be called once and only once, when the queue is empty.
+
+## Instance methods mixed in from `Array`
+Mozilla has docs on how these methods work [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).
+### `q.push(element1, ..., elementN)`
+### `q.unshift(element1, ..., elementN)`
+### `q.splice(index , howMany[, element1[, ...[, elementN]]])`
+
+## Properties
+### `q.concurrency`
+Max number of jobs the queue should process concurrently, defaults to `Infinity`.
+
+### `q.length`
+Jobs pending + jobs to process (readonly).
+
diff --git a/input_devices/mag/node_modules/bindings/README.md b/input_devices/mag/node_modules/bindings/README.md
new file mode 100644
index 00000000..a1f0d225
--- /dev/null
+++ b/input_devices/mag/node_modules/bindings/README.md
@@ -0,0 +1,98 @@
+node-bindings
+=============
+### Helper module for loading your native module's .node file
+
+This is a helper module for authors of Node.js native addon modules.
+It is basically the "swiss army knife" of `require()`ing your native module's
+`.node` file.
+
+Throughout the course of Node's native addon history, addons have ended up being
+compiled in a variety of different places, depending on which build tool and which
+version of node was used. To make matters worse, now the _gyp_ build tool can
+produce either a _Release_ or _Debug_ build, each being built into different
+locations.
+
+This module checks _all_ the possible locations that a native addon would be built
+at, and returns the first one that loads successfully.
+
+
+Installation
+------------
+
+Install with `npm`:
+
+``` bash
+$ npm install bindings
+```
+
+Or add it to the `"dependencies"` section of your _package.json_ file.
+
+
+Example
+-------
+
+`require()`ing the proper bindings file for the current node version, platform
+and architecture is as simple as:
+
+``` js
+var bindings = require('bindings')('binding.node')
+
+// Use your bindings defined in your C files
+bindings.your_c_function()
+```
+
+
+Nice Error Output
+-----------------
+
+When the `.node` file could not be loaded, `node-bindings` throws an Error with
+a nice error message telling you exactly what was tried. You can also check the
+`err.tries` Array property.
+
+```
+Error: Could not load the bindings file. Tried:
+ → /Users/nrajlich/ref/build/binding.node
+ → /Users/nrajlich/ref/build/Debug/binding.node
+ → /Users/nrajlich/ref/build/Release/binding.node
+ → /Users/nrajlich/ref/out/Debug/binding.node
+ → /Users/nrajlich/ref/Debug/binding.node
+ → /Users/nrajlich/ref/out/Release/binding.node
+ → /Users/nrajlich/ref/Release/binding.node
+ → /Users/nrajlich/ref/build/default/binding.node
+ → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node
+    at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)
+    at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)
+    at Module._compile (module.js:449:26)
+    at Object.Module._extensions..js (module.js:467:10)
+    at Module.load (module.js:356:32)
+    at Function.Module._load (module.js:312:12)
+    ...
+```
+
+The searching for the `.node` file will originate from the first directory in which has a `package.json` file is found. 
+
+License
+-------
+
+(The MIT License)
+
+Copyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
+
+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/input_devices/mag/node_modules/bindings/bindings.js b/input_devices/mag/node_modules/bindings/bindings.js
new file mode 100644
index 00000000..9a497bf0
--- /dev/null
+++ b/input_devices/mag/node_modules/bindings/bindings.js
@@ -0,0 +1,171 @@
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , path = require('path')
+  , join = path.join
+  , dirname = path.dirname
+  , exists = ((fs.accessSync && function (path) { try { fs.accessSync(path); } catch (e) { return false; } return true; })
+      || fs.existsSync || path.existsSync)
+  , defaults = {
+        arrow: process.env.NODE_BINDINGS_ARROW || ' → '
+      , compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled'
+      , platform: process.platform
+      , arch: process.arch
+      , version: process.versions.node
+      , bindings: 'bindings.node'
+      , try: [
+          // node-gyp's linked version in the "build" dir
+          [ 'module_root', 'build', 'bindings' ]
+          // node-waf and gyp_addon (a.k.a node-gyp)
+        , [ 'module_root', 'build', 'Debug', 'bindings' ]
+        , [ 'module_root', 'build', 'Release', 'bindings' ]
+          // Debug files, for development (legacy behavior, remove for node v0.9)
+        , [ 'module_root', 'out', 'Debug', 'bindings' ]
+        , [ 'module_root', 'Debug', 'bindings' ]
+          // Release files, but manually compiled (legacy behavior, remove for node v0.9)
+        , [ 'module_root', 'out', 'Release', 'bindings' ]
+        , [ 'module_root', 'Release', 'bindings' ]
+          // Legacy from node-waf, node <= 0.4.x
+        , [ 'module_root', 'build', 'default', 'bindings' ]
+          // Production "Release" buildtype binary (meh...)
+        , [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ]
+        ]
+    }
+
+/**
+ * The main `bindings()` function loads the compiled bindings for a given module.
+ * It uses V8's Error API to determine the parent filename that this function is
+ * being invoked from, which is then used to find the root directory.
+ */
+
+function bindings (opts) {
+
+  // Argument surgery
+  if (typeof opts == 'string') {
+    opts = { bindings: opts }
+  } else if (!opts) {
+    opts = {}
+  }
+
+  // maps `defaults` onto `opts` object
+  Object.keys(defaults).map(function(i) {
+    if (!(i in opts)) opts[i] = defaults[i];
+  });
+
+  // Get the module root
+  if (!opts.module_root) {
+    opts.module_root = exports.getRoot(exports.getFileName())
+  }
+
+  // Ensure the given bindings name ends with .node
+  if (path.extname(opts.bindings) != '.node') {
+    opts.bindings += '.node'
+  }
+
+  var tries = []
+    , i = 0
+    , l = opts.try.length
+    , n
+    , b
+    , err
+
+  for (; i<l; i++) {
+    n = join.apply(null, opts.try[i].map(function (p) {
+      return opts[p] || p
+    }))
+    tries.push(n)
+    try {
+      b = opts.path ? require.resolve(n) : require(n)
+      if (!opts.path) {
+        b.path = n
+      }
+      return b
+    } catch (e) {
+      if (!/not find/i.test(e.message)) {
+        throw e
+      }
+    }
+  }
+
+  err = new Error('Could not locate the bindings file. Tried:\n'
+    + tries.map(function (a) { return opts.arrow + a }).join('\n'))
+  err.tries = tries
+  throw err
+}
+module.exports = exports = bindings
+
+
+/**
+ * Gets the filename of the JavaScript file that invokes this function.
+ * Used to help find the root directory of a module.
+ * Optionally accepts an filename argument to skip when searching for the invoking filename
+ */
+
+exports.getFileName = function getFileName (calling_file) {
+  var origPST = Error.prepareStackTrace
+    , origSTL = Error.stackTraceLimit
+    , dummy = {}
+    , fileName
+
+  Error.stackTraceLimit = 10
+
+  Error.prepareStackTrace = function (e, st) {
+    for (var i=0, l=st.length; i<l; i++) {
+      fileName = st[i].getFileName()
+      if (fileName !== __filename) {
+        if (calling_file) {
+            if (fileName !== calling_file) {
+              return
+            }
+        } else {
+          return
+        }
+      }
+    }
+  }
+
+  // run the 'prepareStackTrace' function above
+  Error.captureStackTrace(dummy)
+  dummy.stack
+
+  // cleanup
+  Error.prepareStackTrace = origPST
+  Error.stackTraceLimit = origSTL
+
+  return fileName
+}
+
+/**
+ * Gets the root directory of a module, given an arbitrary filename
+ * somewhere in the module tree. The "root directory" is the directory
+ * containing the `package.json` file.
+ *
+ *   In:  /home/nate/node-native-module/lib/index.js
+ *   Out: /home/nate/node-native-module
+ */
+
+exports.getRoot = function getRoot (file) {
+  var dir = dirname(file)
+    , prev
+  while (true) {
+    if (dir === '.') {
+      // Avoids an infinite loop in rare cases, like the REPL
+      dir = process.cwd()
+    }
+    if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
+      // Found the 'package.json' file or 'node_modules' dir; we're done
+      return dir
+    }
+    if (prev === dir) {
+      // Got to the top
+      throw new Error('Could not find module root given file: "' + file
+                    + '". Do you have a `package.json` file? ')
+    }
+    // Try the parent dir next
+    prev = dir
+    dir = join(dir, '..')
+  }
+}
diff --git a/input_devices/mag/node_modules/bindings/package.json b/input_devices/mag/node_modules/bindings/package.json
new file mode 100644
index 00000000..e5fecc64
--- /dev/null
+++ b/input_devices/mag/node_modules/bindings/package.json
@@ -0,0 +1,84 @@
+{
+  "_args": [
+    [
+      "bindings@^1.3.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/bindings"
+    ]
+  ],
+  "_from": "bindings@>=1.3.0 <2.0.0",
+  "_id": "bindings@1.3.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/bindings",
+  "_nodeVersion": "8.1.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/bindings-1.3.0.tgz_1500923768710_0.3334669852629304"
+  },
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "5.0.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "bindings",
+    "raw": "bindings@^1.3.0",
+    "rawSpec": "^1.3.0",
+    "scope": null,
+    "spec": ">=1.3.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/bindings"
+  ],
+  "_resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz",
+  "_shasum": "b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7",
+  "_shrinkwrap": null,
+  "_spec": "bindings@^1.3.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/bindings",
+  "author": {
+    "email": "nathan@tootallnate.net",
+    "name": "Nathan Rajlich",
+    "url": "http://tootallnate.net"
+  },
+  "bugs": {
+    "url": "https://github.com/TooTallNate/node-bindings/issues"
+  },
+  "dependencies": {},
+  "description": "Helper module for loading your native module's .node file",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==",
+    "shasum": "b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7",
+    "tarball": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz"
+  },
+  "gitHead": "7fd065ee85386ad3d074d2506e03abe8f9b1588b",
+  "homepage": "https://github.com/TooTallNate/node-bindings",
+  "keywords": [
+    "addon",
+    "bindings",
+    "c",
+    "c++",
+    "gyp",
+    "native",
+    "waf"
+  ],
+  "license": "MIT",
+  "main": "./bindings.js",
+  "maintainers": [
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    }
+  ],
+  "name": "bindings",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/TooTallNate/node-bindings.git"
+  },
+  "version": "1.3.0"
+}
diff --git a/input_devices/mag/node_modules/bl/.jshintrc b/input_devices/mag/node_modules/bl/.jshintrc
new file mode 100644
index 00000000..c8ef3ca4
--- /dev/null
+++ b/input_devices/mag/node_modules/bl/.jshintrc
@@ -0,0 +1,59 @@
+{
+    "predef": [ ]
+  , "bitwise": false
+  , "camelcase": false
+  , "curly": false
+  , "eqeqeq": false
+  , "forin": false
+  , "immed": false
+  , "latedef": false
+  , "noarg": true
+  , "noempty": true
+  , "nonew": true
+  , "plusplus": false
+  , "quotmark": true
+  , "regexp": false
+  , "undef": true
+  , "unused": true
+  , "strict": false
+  , "trailing": true
+  , "maxlen": 120
+  , "asi": true
+  , "boss": true
+  , "debug": true
+  , "eqnull": true
+  , "esnext": true
+  , "evil": true
+  , "expr": true
+  , "funcscope": false
+  , "globalstrict": false
+  , "iterator": false
+  , "lastsemic": true
+  , "laxbreak": true
+  , "laxcomma": true
+  , "loopfunc": true
+  , "multistr": false
+  , "onecase": false
+  , "proto": false
+  , "regexdash": false
+  , "scripturl": true
+  , "smarttabs": false
+  , "shadow": false
+  , "sub": true
+  , "supernew": false
+  , "validthis": true
+  , "browser": true
+  , "couch": false
+  , "devel": false
+  , "dojo": false
+  , "mootools": false
+  , "node": true
+  , "nonstandard": true
+  , "prototypejs": false
+  , "rhino": false
+  , "worker": true
+  , "wsh": false
+  , "nomen": false
+  , "onevar": false
+  , "passfail": false
+}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/bl/.travis.yml b/input_devices/mag/node_modules/bl/.travis.yml
new file mode 100644
index 00000000..373bb4a7
--- /dev/null
+++ b/input_devices/mag/node_modules/bl/.travis.yml
@@ -0,0 +1,16 @@
+sudo: false
+language: node_js
+node_js:
+  - '0.10'
+  - '0.12'
+  - '4'
+  - '6'
+  - '8'
+  - '9'
+branches:
+  only:
+    - master
+notifications:
+  email:
+    - rod@vagg.org
+    - matteo.collina@gmail.com
diff --git a/input_devices/mag/node_modules/bl/LICENSE.md b/input_devices/mag/node_modules/bl/LICENSE.md
new file mode 100644
index 00000000..ff35a347
--- /dev/null
+++ b/input_devices/mag/node_modules/bl/LICENSE.md
@@ -0,0 +1,13 @@
+The MIT License (MIT)
+=====================
+
+Copyright (c) 2013-2016 bl contributors
+----------------------------------
+
+*bl contributors listed at <https://github.com/rvagg/bl#contributors>*
+
+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/input_devices/mag/node_modules/bl/README.md b/input_devices/mag/node_modules/bl/README.md
new file mode 100644
index 00000000..9eebd88b
--- /dev/null
+++ b/input_devices/mag/node_modules/bl/README.md
@@ -0,0 +1,208 @@
+# bl *(BufferList)*
+
+[![Build Status](https://travis-ci.org/rvagg/bl.svg?branch=master)](https://travis-ci.org/rvagg/bl)
+
+**A Node.js Buffer list collector, reader and streamer thingy.**
+
+[![NPM](https://nodei.co/npm/bl.png?downloads=true&downloadRank=true)](https://nodei.co/npm/bl/)
+[![NPM](https://nodei.co/npm-dl/bl.png?months=6&height=3)](https://nodei.co/npm/bl/)
+
+**bl** is a storage object for collections of Node Buffers, exposing them with the main Buffer readable API. Also works as a duplex stream so you can collect buffers from a stream that emits them and emit buffers to a stream that consumes them!
+
+The original buffers are kept intact and copies are only done as necessary. Any reads that require the use of a single original buffer will return a slice of that buffer only (which references the same memory as the original buffer). Reads that span buffers perform concatenation as required and return the results transparently.
+
+```js
+const BufferList = require('bl')
+
+var bl = new BufferList()
+bl.append(new Buffer('abcd'))
+bl.append(new Buffer('efg'))
+bl.append('hi')                     // bl will also accept & convert Strings
+bl.append(new Buffer('j'))
+bl.append(new Buffer([ 0x3, 0x4 ]))
+
+console.log(bl.length) // 12
+
+console.log(bl.slice(0, 10).toString('ascii')) // 'abcdefghij'
+console.log(bl.slice(3, 10).toString('ascii')) // 'defghij'
+console.log(bl.slice(3, 6).toString('ascii'))  // 'def'
+console.log(bl.slice(3, 8).toString('ascii'))  // 'defgh'
+console.log(bl.slice(5, 10).toString('ascii')) // 'fghij'
+
+// or just use toString!
+console.log(bl.toString())               // 'abcdefghij\u0003\u0004'
+console.log(bl.toString('ascii', 3, 8))  // 'defgh'
+console.log(bl.toString('ascii', 5, 10)) // 'fghij'
+
+// other standard Buffer readables
+console.log(bl.readUInt16BE(10)) // 0x0304
+console.log(bl.readUInt16LE(10)) // 0x0403
+```
+
+Give it a callback in the constructor and use it just like **[concat-stream](https://github.com/maxogden/node-concat-stream)**:
+
+```js
+const bl = require('bl')
+    , fs = require('fs')
+
+fs.createReadStream('README.md')
+  .pipe(bl(function (err, data) { // note 'new' isn't strictly required
+    // `data` is a complete Buffer object containing the full data
+    console.log(data.toString())
+  }))
+```
+
+Note that when you use the *callback* method like this, the resulting `data` parameter is a concatenation of all `Buffer` objects in the list. If you want to avoid the overhead of this concatenation (in cases of extreme performance consciousness), then avoid the *callback* method and just listen to `'end'` instead, like a standard Stream.
+
+Or to fetch a URL using [hyperquest](https://github.com/substack/hyperquest) (should work with [request](http://github.com/mikeal/request) and even plain Node http too!):
+```js
+const hyperquest = require('hyperquest')
+    , bl         = require('bl')
+    , url        = 'https://raw.github.com/rvagg/bl/master/README.md'
+
+hyperquest(url).pipe(bl(function (err, data) {
+  console.log(data.toString())
+}))
+```
+
+Or, use it as a readable stream to recompose a list of Buffers to an output source:
+
+```js
+const BufferList = require('bl')
+    , fs         = require('fs')
+
+var bl = new BufferList()
+bl.append(new Buffer('abcd'))
+bl.append(new Buffer('efg'))
+bl.append(new Buffer('hi'))
+bl.append(new Buffer('j'))
+
+bl.pipe(fs.createWriteStream('gibberish.txt'))
+```
+
+## API
+
+  * <a href="#ctor"><code><b>new BufferList([ callback ])</b></code></a>
+  * <a href="#length"><code>bl.<b>length</b></code></a>
+  * <a href="#append"><code>bl.<b>append(buffer)</b></code></a>
+  * <a href="#get"><code>bl.<b>get(index)</b></code></a>
+  * <a href="#slice"><code>bl.<b>slice([ start[, end ] ])</b></code></a>
+  * <a href="#shallowSlice"><code>bl.<b>shallowSlice([ start[, end ] ])</b></code></a>
+  * <a href="#copy"><code>bl.<b>copy(dest, [ destStart, [ srcStart [, srcEnd ] ] ])</b></code></a>
+  * <a href="#duplicate"><code>bl.<b>duplicate()</b></code></a>
+  * <a href="#consume"><code>bl.<b>consume(bytes)</b></code></a>
+  * <a href="#toString"><code>bl.<b>toString([encoding, [ start, [ end ]]])</b></code></a>
+  * <a href="#readXX"><code>bl.<b>readDoubleBE()</b></code>, <code>bl.<b>readDoubleLE()</b></code>, <code>bl.<b>readFloatBE()</b></code>, <code>bl.<b>readFloatLE()</b></code>, <code>bl.<b>readInt32BE()</b></code>, <code>bl.<b>readInt32LE()</b></code>, <code>bl.<b>readUInt32BE()</b></code>, <code>bl.<b>readUInt32LE()</b></code>, <code>bl.<b>readInt16BE()</b></code>, <code>bl.<b>readInt16LE()</b></code>, <code>bl.<b>readUInt16BE()</b></code>, <code>bl.<b>readUInt16LE()</b></code>, <code>bl.<b>readInt8()</b></code>, <code>bl.<b>readUInt8()</b></code></a>
+  * <a href="#streams">Streams</a>
+
+--------------------------------------------------------
+<a name="ctor"></a>
+### new BufferList([ callback | Buffer | Buffer array | BufferList | BufferList array | String ])
+The constructor takes an optional callback, if supplied, the callback will be called with an error argument followed by a reference to the **bl** instance, when `bl.end()` is called (i.e. from a piped stream). This is a convenient method of collecting the entire contents of a stream, particularly when the stream is *chunky*, such as a network stream.
+
+Normally, no arguments are required for the constructor, but you can initialise the list by passing in a single `Buffer` object or an array of `Buffer` object.
+
+`new` is not strictly required, if you don't instantiate a new object, it will be done automatically for you so you can create a new instance simply with:
+
+```js
+var bl = require('bl')
+var myinstance = bl()
+
+// equivalent to:
+
+var BufferList = require('bl')
+var myinstance = new BufferList()
+```
+
+--------------------------------------------------------
+<a name="length"></a>
+### bl.length
+Get the length of the list in bytes. This is the sum of the lengths of all of the buffers contained in the list, minus any initial offset for a semi-consumed buffer at the beginning. Should accurately represent the total number of bytes that can be read from the list.
+
+--------------------------------------------------------
+<a name="append"></a>
+### bl.append(Buffer | Buffer array | BufferList | BufferList array | String)
+`append(buffer)` adds an additional buffer or BufferList to the internal list. `this` is returned so it can be chained.
+
+--------------------------------------------------------
+<a name="get"></a>
+### bl.get(index)
+`get()` will return the byte at the specified index.
+
+--------------------------------------------------------
+<a name="slice"></a>
+### bl.slice([ start, [ end ] ])
+`slice()` returns a new `Buffer` object containing the bytes within the range specified. Both `start` and `end` are optional and will default to the beginning and end of the list respectively.
+
+If the requested range spans a single internal buffer then a slice of that buffer will be returned which shares the original memory range of that Buffer. If the range spans multiple buffers then copy operations will likely occur to give you a uniform Buffer.
+
+--------------------------------------------------------
+<a name="shallowSlice"></a>
+### bl.shallowSlice([ start, [ end ] ])
+`shallowSlice()` returns a new `BufferList` object containing the bytes within the range specified. Both `start` and `end` are optional and will default to the beginning and end of the list respectively.
+
+No copies will be performed. All buffers in the result share memory with the original list.
+
+--------------------------------------------------------
+<a name="copy"></a>
+### bl.copy(dest, [ destStart, [ srcStart [, srcEnd ] ] ])
+`copy()` copies the content of the list in the `dest` buffer, starting from `destStart` and containing the bytes within the range specified with `srcStart` to `srcEnd`. `destStart`, `start` and `end` are optional and will default to the beginning of the `dest` buffer, and the beginning and end of the list respectively.
+
+--------------------------------------------------------
+<a name="duplicate"></a>
+### bl.duplicate()
+`duplicate()` performs a **shallow-copy** of the list. The internal Buffers remains the same, so if you change the underlying Buffers, the change will be reflected in both the original and the duplicate. This method is needed if you want to call `consume()` or `pipe()` and still keep the original list.Example:
+
+```js
+var bl = new BufferList()
+
+bl.append('hello')
+bl.append(' world')
+bl.append('\n')
+
+bl.duplicate().pipe(process.stdout, { end: false })
+
+console.log(bl.toString())
+```
+
+--------------------------------------------------------
+<a name="consume"></a>
+### bl.consume(bytes)
+`consume()` will shift bytes *off the start of the list*. The number of bytes consumed don't need to line up with the sizes of the internal Buffers&mdash;initial offsets will be calculated accordingly in order to give you a consistent view of the data.
+
+--------------------------------------------------------
+<a name="toString"></a>
+### bl.toString([encoding, [ start, [ end ]]])
+`toString()` will return a string representation of the buffer. The optional `start` and `end` arguments are passed on to `slice()`, while the `encoding` is passed on to `toString()` of the resulting Buffer. See the [Buffer#toString()](http://nodejs.org/docs/latest/api/buffer.html#buffer_buf_tostring_encoding_start_end) documentation for more information.
+
+--------------------------------------------------------
+<a name="readXX"></a>
+### bl.readDoubleBE(), bl.readDoubleLE(), bl.readFloatBE(), bl.readFloatLE(), bl.readInt32BE(), bl.readInt32LE(), bl.readUInt32BE(), bl.readUInt32LE(), bl.readInt16BE(), bl.readInt16LE(), bl.readUInt16BE(), bl.readUInt16LE(), bl.readInt8(), bl.readUInt8()
+
+All of the standard byte-reading methods of the `Buffer` interface are implemented and will operate across internal Buffer boundaries transparently.
+
+See the <b><code>[Buffer](http://nodejs.org/docs/latest/api/buffer.html)</code></b> documentation for how these work.
+
+--------------------------------------------------------
+<a name="streams"></a>
+### Streams
+**bl** is a Node **[Duplex Stream](http://nodejs.org/docs/latest/api/stream.html#stream_class_stream_duplex)**, so it can be read from and written to like a standard Node stream. You can also `pipe()` to and from a **bl** instance.
+
+--------------------------------------------------------
+
+## Contributors
+
+**bl** is brought to you by the following hackers:
+
+ * [Rod Vagg](https://github.com/rvagg)
+ * [Matteo Collina](https://github.com/mcollina)
+ * [Jarett Cruger](https://github.com/jcrugzz)
+
+=======
+
+<a name="license"></a>
+## License &amp; copyright
+
+Copyright (c) 2013-2016 bl contributors (listed above).
+
+bl is licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE.md file for more details.
diff --git a/input_devices/mag/node_modules/bl/bl.js b/input_devices/mag/node_modules/bl/bl.js
new file mode 100644
index 00000000..db536f34
--- /dev/null
+++ b/input_devices/mag/node_modules/bl/bl.js
@@ -0,0 +1,281 @@
+var DuplexStream = require('readable-stream/duplex')
+  , util         = require('util')
+  , Buffer       = require('safe-buffer').Buffer
+
+
+function BufferList (callback) {
+  if (!(this instanceof BufferList))
+    return new BufferList(callback)
+
+  this._bufs  = []
+  this.length = 0
+
+  if (typeof callback == 'function') {
+    this._callback = callback
+
+    var piper = function piper (err) {
+      if (this._callback) {
+        this._callback(err)
+        this._callback = null
+      }
+    }.bind(this)
+
+    this.on('pipe', function onPipe (src) {
+      src.on('error', piper)
+    })
+    this.on('unpipe', function onUnpipe (src) {
+      src.removeListener('error', piper)
+    })
+  } else {
+    this.append(callback)
+  }
+
+  DuplexStream.call(this)
+}
+
+
+util.inherits(BufferList, DuplexStream)
+
+
+BufferList.prototype._offset = function _offset (offset) {
+  var tot = 0, i = 0, _t
+  if (offset === 0) return [ 0, 0 ]
+  for (; i < this._bufs.length; i++) {
+    _t = tot + this._bufs[i].length
+    if (offset < _t || i == this._bufs.length - 1)
+      return [ i, offset - tot ]
+    tot = _t
+  }
+}
+
+
+BufferList.prototype.append = function append (buf) {
+  var i = 0
+
+  if (Buffer.isBuffer(buf)) {
+    this._appendBuffer(buf);
+  } else if (Array.isArray(buf)) {
+    for (; i < buf.length; i++)
+      this.append(buf[i])
+  } else if (buf instanceof BufferList) {
+    // unwrap argument into individual BufferLists
+    for (; i < buf._bufs.length; i++)
+      this.append(buf._bufs[i])
+  } else if (buf != null) {
+    // coerce number arguments to strings, since Buffer(number) does
+    // uninitialized memory allocation
+    if (typeof buf == 'number')
+      buf = buf.toString()
+
+    this._appendBuffer(Buffer.from(buf));
+  }
+
+  return this
+}
+
+
+BufferList.prototype._appendBuffer = function appendBuffer (buf) {
+  this._bufs.push(buf)
+  this.length += buf.length
+}
+
+
+BufferList.prototype._write = function _write (buf, encoding, callback) {
+  this._appendBuffer(buf)
+
+  if (typeof callback == 'function')
+    callback()
+}
+
+
+BufferList.prototype._read = function _read (size) {
+  if (!this.length)
+    return this.push(null)
+
+  size = Math.min(size, this.length)
+  this.push(this.slice(0, size))
+  this.consume(size)
+}
+
+
+BufferList.prototype.end = function end (chunk) {
+  DuplexStream.prototype.end.call(this, chunk)
+
+  if (this._callback) {
+    this._callback(null, this.slice())
+    this._callback = null
+  }
+}
+
+
+BufferList.prototype.get = function get (index) {
+  return this.slice(index, index + 1)[0]
+}
+
+
+BufferList.prototype.slice = function slice (start, end) {
+  if (typeof start == 'number' && start < 0)
+    start += this.length
+  if (typeof end == 'number' && end < 0)
+    end += this.length
+  return this.copy(null, 0, start, end)
+}
+
+
+BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) {
+  if (typeof srcStart != 'number' || srcStart < 0)
+    srcStart = 0
+  if (typeof srcEnd != 'number' || srcEnd > this.length)
+    srcEnd = this.length
+  if (srcStart >= this.length)
+    return dst || Buffer.alloc(0)
+  if (srcEnd <= 0)
+    return dst || Buffer.alloc(0)
+
+  var copy   = !!dst
+    , off    = this._offset(srcStart)
+    , len    = srcEnd - srcStart
+    , bytes  = len
+    , bufoff = (copy && dstStart) || 0
+    , start  = off[1]
+    , l
+    , i
+
+  // copy/slice everything
+  if (srcStart === 0 && srcEnd == this.length) {
+    if (!copy) { // slice, but full concat if multiple buffers
+      return this._bufs.length === 1
+        ? this._bufs[0]
+        : Buffer.concat(this._bufs, this.length)
+    }
+
+    // copy, need to copy individual buffers
+    for (i = 0; i < this._bufs.length; i++) {
+      this._bufs[i].copy(dst, bufoff)
+      bufoff += this._bufs[i].length
+    }
+
+    return dst
+  }
+
+  // easy, cheap case where it's a subset of one of the buffers
+  if (bytes <= this._bufs[off[0]].length - start) {
+    return copy
+      ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes)
+      : this._bufs[off[0]].slice(start, start + bytes)
+  }
+
+  if (!copy) // a slice, we need something to copy in to
+    dst = Buffer.allocUnsafe(len)
+
+  for (i = off[0]; i < this._bufs.length; i++) {
+    l = this._bufs[i].length - start
+
+    if (bytes > l) {
+      this._bufs[i].copy(dst, bufoff, start)
+    } else {
+      this._bufs[i].copy(dst, bufoff, start, start + bytes)
+      break
+    }
+
+    bufoff += l
+    bytes -= l
+
+    if (start)
+      start = 0
+  }
+
+  return dst
+}
+
+BufferList.prototype.shallowSlice = function shallowSlice (start, end) {
+  start = start || 0
+  end = end || this.length
+
+  if (start < 0)
+    start += this.length
+  if (end < 0)
+    end += this.length
+
+  var startOffset = this._offset(start)
+    , endOffset = this._offset(end)
+    , buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1)
+
+  if (endOffset[1] == 0)
+    buffers.pop()
+  else
+    buffers[buffers.length-1] = buffers[buffers.length-1].slice(0, endOffset[1])
+
+  if (startOffset[1] != 0)
+    buffers[0] = buffers[0].slice(startOffset[1])
+
+  return new BufferList(buffers)
+}
+
+BufferList.prototype.toString = function toString (encoding, start, end) {
+  return this.slice(start, end).toString(encoding)
+}
+
+BufferList.prototype.consume = function consume (bytes) {
+  while (this._bufs.length) {
+    if (bytes >= this._bufs[0].length) {
+      bytes -= this._bufs[0].length
+      this.length -= this._bufs[0].length
+      this._bufs.shift()
+    } else {
+      this._bufs[0] = this._bufs[0].slice(bytes)
+      this.length -= bytes
+      break
+    }
+  }
+  return this
+}
+
+
+BufferList.prototype.duplicate = function duplicate () {
+  var i = 0
+    , copy = new BufferList()
+
+  for (; i < this._bufs.length; i++)
+    copy.append(this._bufs[i])
+
+  return copy
+}
+
+
+BufferList.prototype.destroy = function destroy () {
+  this._bufs.length = 0
+  this.length = 0
+  this.push(null)
+}
+
+
+;(function () {
+  var methods = {
+      'readDoubleBE' : 8
+    , 'readDoubleLE' : 8
+    , 'readFloatBE'  : 4
+    , 'readFloatLE'  : 4
+    , 'readInt32BE'  : 4
+    , 'readInt32LE'  : 4
+    , 'readUInt32BE' : 4
+    , 'readUInt32LE' : 4
+    , 'readInt16BE'  : 2
+    , 'readInt16LE'  : 2
+    , 'readUInt16BE' : 2
+    , 'readUInt16LE' : 2
+    , 'readInt8'     : 1
+    , 'readUInt8'    : 1
+  }
+
+  for (var m in methods) {
+    (function (m) {
+      BufferList.prototype[m] = function (offset) {
+        return this.slice(offset, offset + methods[m])[m](0)
+      }
+    }(m))
+  }
+}())
+
+
+module.exports = BufferList
diff --git a/input_devices/mag/node_modules/bl/package.json b/input_devices/mag/node_modules/bl/package.json
new file mode 100644
index 00000000..9eb54e2f
--- /dev/null
+++ b/input_devices/mag/node_modules/bl/package.json
@@ -0,0 +1,98 @@
+{
+  "_args": [
+    [
+      "bl@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream"
+    ]
+  ],
+  "_from": "bl@>=1.0.0 <2.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "bl@1.2.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/bl",
+  "_nodeVersion": "8.10.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/bl_1.2.2_1521669598170_0.7406366214040565"
+  },
+  "_npmUser": {
+    "email": "hello@matteocollina.com",
+    "name": "matteo.collina"
+  },
+  "_npmVersion": "5.7.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "bl",
+    "raw": "bl@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
+  "_shasum": "a160911717103c07410cef63ef51b397c025af9c",
+  "_shrinkwrap": null,
+  "_spec": "bl@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream",
+  "authors": [
+    "Jarett Cruger <jcrugzz@gmail.com> (https://github.com/jcrugzz)",
+    "Matteo Collina <matteo.collina@gmail.com> (https://github.com/mcollina)",
+    "Rod Vagg <rod@vagg.org> (https://github.com/rvagg)"
+  ],
+  "bugs": {
+    "url": "https://github.com/rvagg/bl/issues"
+  },
+  "dependencies": {
+    "readable-stream": "^2.3.5",
+    "safe-buffer": "^5.1.1"
+  },
+  "description": "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!",
+  "devDependencies": {
+    "faucet": "0.0.1",
+    "hash_file": "~0.1.1",
+    "tape": "~4.9.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 7,
+    "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
+    "shasum": "a160911717103c07410cef63ef51b397c025af9c",
+    "tarball": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
+    "unpackedSize": 38223
+  },
+  "gitHead": "feaaa4ca34417d7d2e659d25455a73a85ef989c3",
+  "homepage": "https://github.com/rvagg/bl",
+  "keywords": [
+    "awesomesauce",
+    "buffer",
+    "buffers",
+    "stream"
+  ],
+  "license": "MIT",
+  "main": "bl.js",
+  "maintainers": [
+    {
+      "name": "matteo.collina",
+      "email": "hello@matteocollina.com"
+    },
+    {
+      "name": "rvagg",
+      "email": "rod@vagg.org"
+    }
+  ],
+  "name": "bl",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/rvagg/bl.git"
+  },
+  "scripts": {
+    "test": "node test/test.js | faucet"
+  },
+  "version": "1.2.2"
+}
diff --git a/input_devices/mag/node_modules/bl/test/test.js b/input_devices/mag/node_modules/bl/test/test.js
new file mode 100644
index 00000000..e1214877
--- /dev/null
+++ b/input_devices/mag/node_modules/bl/test/test.js
@@ -0,0 +1,702 @@
+var tape       = require('tape')
+  , crypto     = require('crypto')
+  , fs         = require('fs')
+  , hash       = require('hash_file')
+  , BufferList = require('../')
+  , Buffer     = require('safe-buffer').Buffer
+
+  , encodings  =
+      ('hex utf8 utf-8 ascii binary base64'
+          + (process.browser ? '' : ' ucs2 ucs-2 utf16le utf-16le')).split(' ')
+
+tape('single bytes from single buffer', function (t) {
+  var bl = new BufferList()
+  bl.append(Buffer.from('abcd'))
+
+  t.equal(bl.length, 4)
+
+  t.equal(bl.get(0), 97)
+  t.equal(bl.get(1), 98)
+  t.equal(bl.get(2), 99)
+  t.equal(bl.get(3), 100)
+
+  t.end()
+})
+
+tape('single bytes from multiple buffers', function (t) {
+  var bl = new BufferList()
+  bl.append(Buffer.from('abcd'))
+  bl.append(Buffer.from('efg'))
+  bl.append(Buffer.from('hi'))
+  bl.append(Buffer.from('j'))
+
+  t.equal(bl.length, 10)
+
+  t.equal(bl.get(0), 97)
+  t.equal(bl.get(1), 98)
+  t.equal(bl.get(2), 99)
+  t.equal(bl.get(3), 100)
+  t.equal(bl.get(4), 101)
+  t.equal(bl.get(5), 102)
+  t.equal(bl.get(6), 103)
+  t.equal(bl.get(7), 104)
+  t.equal(bl.get(8), 105)
+  t.equal(bl.get(9), 106)
+  t.end()
+})
+
+tape('multi bytes from single buffer', function (t) {
+  var bl = new BufferList()
+  bl.append(Buffer.from('abcd'))
+
+  t.equal(bl.length, 4)
+
+  t.equal(bl.slice(0, 4).toString('ascii'), 'abcd')
+  t.equal(bl.slice(0, 3).toString('ascii'), 'abc')
+  t.equal(bl.slice(1, 4).toString('ascii'), 'bcd')
+  t.equal(bl.slice(-4, -1).toString('ascii'), 'abc')
+
+  t.end()
+})
+
+tape('multi bytes from single buffer (negative indexes)', function (t) {
+  var bl = new BufferList()
+  bl.append(Buffer.from('buffer'))
+
+  t.equal(bl.length, 6)
+
+  t.equal(bl.slice(-6, -1).toString('ascii'), 'buffe')
+  t.equal(bl.slice(-6, -2).toString('ascii'), 'buff')
+  t.equal(bl.slice(-5, -2).toString('ascii'), 'uff')
+
+  t.end()
+})
+
+tape('multiple bytes from multiple buffers', function (t) {
+  var bl = new BufferList()
+
+  bl.append(Buffer.from('abcd'))
+  bl.append(Buffer.from('efg'))
+  bl.append(Buffer.from('hi'))
+  bl.append(Buffer.from('j'))
+
+  t.equal(bl.length, 10)
+
+  t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij')
+  t.equal(bl.slice(3, 10).toString('ascii'), 'defghij')
+  t.equal(bl.slice(3, 6).toString('ascii'), 'def')
+  t.equal(bl.slice(3, 8).toString('ascii'), 'defgh')
+  t.equal(bl.slice(5, 10).toString('ascii'), 'fghij')
+  t.equal(bl.slice(-7, -4).toString('ascii'), 'def')
+
+  t.end()
+})
+
+tape('multiple bytes from multiple buffer lists', function (t) {
+  var bl = new BufferList()
+
+  bl.append(new BufferList([ Buffer.from('abcd'), Buffer.from('efg') ]))
+  bl.append(new BufferList([ Buffer.from('hi'), Buffer.from('j') ]))
+
+  t.equal(bl.length, 10)
+
+  t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij')
+
+  t.equal(bl.slice(3, 10).toString('ascii'), 'defghij')
+  t.equal(bl.slice(3, 6).toString('ascii'), 'def')
+  t.equal(bl.slice(3, 8).toString('ascii'), 'defgh')
+  t.equal(bl.slice(5, 10).toString('ascii'), 'fghij')
+
+  t.end()
+})
+
+// same data as previous test, just using nested constructors
+tape('multiple bytes from crazy nested buffer lists', function (t) {
+  var bl = new BufferList()
+
+  bl.append(new BufferList([
+      new BufferList([
+          new BufferList(Buffer.from('abc'))
+        , Buffer.from('d')
+        , new BufferList(Buffer.from('efg'))
+      ])
+    , new BufferList([ Buffer.from('hi') ])
+    , new BufferList(Buffer.from('j'))
+  ]))
+
+  t.equal(bl.length, 10)
+
+  t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij')
+
+  t.equal(bl.slice(3, 10).toString('ascii'), 'defghij')
+  t.equal(bl.slice(3, 6).toString('ascii'), 'def')
+  t.equal(bl.slice(3, 8).toString('ascii'), 'defgh')
+  t.equal(bl.slice(5, 10).toString('ascii'), 'fghij')
+
+  t.end()
+})
+
+tape('append accepts arrays of Buffers', function (t) {
+  var bl = new BufferList()
+  bl.append(Buffer.from('abc'))
+  bl.append([ Buffer.from('def') ])
+  bl.append([ Buffer.from('ghi'), Buffer.from('jkl') ])
+  bl.append([ Buffer.from('mnop'), Buffer.from('qrstu'), Buffer.from('vwxyz') ])
+  t.equal(bl.length, 26)
+  t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz')
+  t.end()
+})
+
+tape('append accepts arrays of BufferLists', function (t) {
+  var bl = new BufferList()
+  bl.append(Buffer.from('abc'))
+  bl.append([ new BufferList('def') ])
+  bl.append(new BufferList([ Buffer.from('ghi'), new BufferList('jkl') ]))
+  bl.append([ Buffer.from('mnop'), new BufferList([ Buffer.from('qrstu'), Buffer.from('vwxyz') ]) ])
+  t.equal(bl.length, 26)
+  t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz')
+  t.end()
+})
+
+tape('append chainable', function (t) {
+  var bl = new BufferList()
+  t.ok(bl.append(Buffer.from('abcd')) === bl)
+  t.ok(bl.append([ Buffer.from('abcd') ]) === bl)
+  t.ok(bl.append(new BufferList(Buffer.from('abcd'))) === bl)
+  t.ok(bl.append([ new BufferList(Buffer.from('abcd')) ]) === bl)
+  t.end()
+})
+
+tape('append chainable (test results)', function (t) {
+  var bl = new BufferList('abc')
+    .append([ new BufferList('def') ])
+    .append(new BufferList([ Buffer.from('ghi'), new BufferList('jkl') ]))
+    .append([ Buffer.from('mnop'), new BufferList([ Buffer.from('qrstu'), Buffer.from('vwxyz') ]) ])
+
+  t.equal(bl.length, 26)
+  t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz')
+  t.end()
+})
+
+tape('consuming from multiple buffers', function (t) {
+  var bl = new BufferList()
+
+  bl.append(Buffer.from('abcd'))
+  bl.append(Buffer.from('efg'))
+  bl.append(Buffer.from('hi'))
+  bl.append(Buffer.from('j'))
+
+  t.equal(bl.length, 10)
+
+  t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij')
+
+  bl.consume(3)
+  t.equal(bl.length, 7)
+  t.equal(bl.slice(0, 7).toString('ascii'), 'defghij')
+
+  bl.consume(2)
+  t.equal(bl.length, 5)
+  t.equal(bl.slice(0, 5).toString('ascii'), 'fghij')
+
+  bl.consume(1)
+  t.equal(bl.length, 4)
+  t.equal(bl.slice(0, 4).toString('ascii'), 'ghij')
+
+  bl.consume(1)
+  t.equal(bl.length, 3)
+  t.equal(bl.slice(0, 3).toString('ascii'), 'hij')
+
+  bl.consume(2)
+  t.equal(bl.length, 1)
+  t.equal(bl.slice(0, 1).toString('ascii'), 'j')
+
+  t.end()
+})
+
+tape('complete consumption', function (t) {
+  var bl = new BufferList()
+
+  bl.append(Buffer.from('a'))
+  bl.append(Buffer.from('b'))
+
+  bl.consume(2)
+
+  t.equal(bl.length, 0)
+  t.equal(bl._bufs.length, 0)
+
+  t.end()
+})
+
+tape('test readUInt8 / readInt8', function (t) {
+  var buf1 = Buffer.alloc(1)
+    , buf2 = Buffer.alloc(3)
+    , buf3 = Buffer.alloc(3)
+    , bl  = new BufferList()
+
+  buf2[1] = 0x3
+  buf2[2] = 0x4
+  buf3[0] = 0x23
+  buf3[1] = 0x42
+
+  bl.append(buf1)
+  bl.append(buf2)
+  bl.append(buf3)
+
+  t.equal(bl.readUInt8(2), 0x3)
+  t.equal(bl.readInt8(2), 0x3)
+  t.equal(bl.readUInt8(3), 0x4)
+  t.equal(bl.readInt8(3), 0x4)
+  t.equal(bl.readUInt8(4), 0x23)
+  t.equal(bl.readInt8(4), 0x23)
+  t.equal(bl.readUInt8(5), 0x42)
+  t.equal(bl.readInt8(5), 0x42)
+  t.end()
+})
+
+tape('test readUInt16LE / readUInt16BE / readInt16LE / readInt16BE', function (t) {
+  var buf1 = Buffer.alloc(1)
+    , buf2 = Buffer.alloc(3)
+    , buf3 = Buffer.alloc(3)
+    , bl   = new BufferList()
+
+  buf2[1] = 0x3
+  buf2[2] = 0x4
+  buf3[0] = 0x23
+  buf3[1] = 0x42
+
+  bl.append(buf1)
+  bl.append(buf2)
+  bl.append(buf3)
+
+  t.equal(bl.readUInt16BE(2), 0x0304)
+  t.equal(bl.readUInt16LE(2), 0x0403)
+  t.equal(bl.readInt16BE(2), 0x0304)
+  t.equal(bl.readInt16LE(2), 0x0403)
+  t.equal(bl.readUInt16BE(3), 0x0423)
+  t.equal(bl.readUInt16LE(3), 0x2304)
+  t.equal(bl.readInt16BE(3), 0x0423)
+  t.equal(bl.readInt16LE(3), 0x2304)
+  t.equal(bl.readUInt16BE(4), 0x2342)
+  t.equal(bl.readUInt16LE(4), 0x4223)
+  t.equal(bl.readInt16BE(4), 0x2342)
+  t.equal(bl.readInt16LE(4), 0x4223)
+  t.end()
+})
+
+tape('test readUInt32LE / readUInt32BE / readInt32LE / readInt32BE', function (t) {
+  var buf1 = Buffer.alloc(1)
+    , buf2 = Buffer.alloc(3)
+    , buf3 = Buffer.alloc(3)
+    , bl   = new BufferList()
+
+  buf2[1] = 0x3
+  buf2[2] = 0x4
+  buf3[0] = 0x23
+  buf3[1] = 0x42
+
+  bl.append(buf1)
+  bl.append(buf2)
+  bl.append(buf3)
+
+  t.equal(bl.readUInt32BE(2), 0x03042342)
+  t.equal(bl.readUInt32LE(2), 0x42230403)
+  t.equal(bl.readInt32BE(2), 0x03042342)
+  t.equal(bl.readInt32LE(2), 0x42230403)
+  t.end()
+})
+
+tape('test readFloatLE / readFloatBE', function (t) {
+  var buf1 = Buffer.alloc(1)
+    , buf2 = Buffer.alloc(3)
+    , buf3 = Buffer.alloc(3)
+    , bl   = new BufferList()
+
+  buf2[1] = 0x00
+  buf2[2] = 0x00
+  buf3[0] = 0x80
+  buf3[1] = 0x3f
+
+  bl.append(buf1)
+  bl.append(buf2)
+  bl.append(buf3)
+
+  t.equal(bl.readFloatLE(2), 0x01)
+  t.end()
+})
+
+tape('test readDoubleLE / readDoubleBE', function (t) {
+  var buf1 = Buffer.alloc(1)
+    , buf2 = Buffer.alloc(3)
+    , buf3 = Buffer.alloc(10)
+    , bl   = new BufferList()
+
+  buf2[1] = 0x55
+  buf2[2] = 0x55
+  buf3[0] = 0x55
+  buf3[1] = 0x55
+  buf3[2] = 0x55
+  buf3[3] = 0x55
+  buf3[4] = 0xd5
+  buf3[5] = 0x3f
+
+  bl.append(buf1)
+  bl.append(buf2)
+  bl.append(buf3)
+
+  t.equal(bl.readDoubleLE(2), 0.3333333333333333)
+  t.end()
+})
+
+tape('test toString', function (t) {
+  var bl = new BufferList()
+
+  bl.append(Buffer.from('abcd'))
+  bl.append(Buffer.from('efg'))
+  bl.append(Buffer.from('hi'))
+  bl.append(Buffer.from('j'))
+
+  t.equal(bl.toString('ascii', 0, 10), 'abcdefghij')
+  t.equal(bl.toString('ascii', 3, 10), 'defghij')
+  t.equal(bl.toString('ascii', 3, 6), 'def')
+  t.equal(bl.toString('ascii', 3, 8), 'defgh')
+  t.equal(bl.toString('ascii', 5, 10), 'fghij')
+
+  t.end()
+})
+
+tape('test toString encoding', function (t) {
+  var bl = new BufferList()
+    , b  = Buffer.from('abcdefghij\xff\x00')
+
+  bl.append(Buffer.from('abcd'))
+  bl.append(Buffer.from('efg'))
+  bl.append(Buffer.from('hi'))
+  bl.append(Buffer.from('j'))
+  bl.append(Buffer.from('\xff\x00'))
+
+  encodings.forEach(function (enc) {
+      t.equal(bl.toString(enc), b.toString(enc), enc)
+    })
+
+  t.end()
+})
+
+!process.browser && tape('test stream', function (t) {
+  var random = crypto.randomBytes(65534)
+    , rndhash = hash(random, 'md5')
+    , md5sum = crypto.createHash('md5')
+    , bl     = new BufferList(function (err, buf) {
+        t.ok(Buffer.isBuffer(buf))
+        t.ok(err === null)
+        t.equal(rndhash, hash(bl.slice(), 'md5'))
+        t.equal(rndhash, hash(buf, 'md5'))
+
+        bl.pipe(fs.createWriteStream('/tmp/bl_test_rnd_out.dat'))
+          .on('close', function () {
+            var s = fs.createReadStream('/tmp/bl_test_rnd_out.dat')
+            s.on('data', md5sum.update.bind(md5sum))
+            s.on('end', function() {
+              t.equal(rndhash, md5sum.digest('hex'), 'woohoo! correct hash!')
+              t.end()
+            })
+          })
+
+      })
+
+  fs.writeFileSync('/tmp/bl_test_rnd.dat', random)
+  fs.createReadStream('/tmp/bl_test_rnd.dat').pipe(bl)
+})
+
+tape('instantiation with Buffer', function (t) {
+  var buf  = crypto.randomBytes(1024)
+    , buf2 = crypto.randomBytes(1024)
+    , b    = BufferList(buf)
+
+  t.equal(buf.toString('hex'), b.slice().toString('hex'), 'same buffer')
+  b = BufferList([ buf, buf2 ])
+  t.equal(b.slice().toString('hex'), Buffer.concat([ buf, buf2 ]).toString('hex'), 'same buffer')
+  t.end()
+})
+
+tape('test String appendage', function (t) {
+  var bl = new BufferList()
+    , b  = Buffer.from('abcdefghij\xff\x00')
+
+  bl.append('abcd')
+  bl.append('efg')
+  bl.append('hi')
+  bl.append('j')
+  bl.append('\xff\x00')
+
+  encodings.forEach(function (enc) {
+      t.equal(bl.toString(enc), b.toString(enc))
+    })
+
+  t.end()
+})
+
+tape('test Number appendage', function (t) {
+  var bl = new BufferList()
+    , b  = Buffer.from('1234567890')
+
+  bl.append(1234)
+  bl.append(567)
+  bl.append(89)
+  bl.append(0)
+
+  encodings.forEach(function (enc) {
+      t.equal(bl.toString(enc), b.toString(enc))
+    })
+
+  t.end()
+})
+
+tape('write nothing, should get empty buffer', function (t) {
+  t.plan(3)
+  BufferList(function (err, data) {
+    t.notOk(err, 'no error')
+    t.ok(Buffer.isBuffer(data), 'got a buffer')
+    t.equal(0, data.length, 'got a zero-length buffer')
+    t.end()
+  }).end()
+})
+
+tape('unicode string', function (t) {
+  t.plan(2)
+  var inp1 = '\u2600'
+    , inp2 = '\u2603'
+    , exp = inp1 + ' and ' + inp2
+    , bl = BufferList()
+  bl.write(inp1)
+  bl.write(' and ')
+  bl.write(inp2)
+  t.equal(exp, bl.toString())
+  t.equal(Buffer.from(exp).toString('hex'), bl.toString('hex'))
+})
+
+tape('should emit finish', function (t) {
+  var source = BufferList()
+    , dest = BufferList()
+
+  source.write('hello')
+  source.pipe(dest)
+
+  dest.on('finish', function () {
+    t.equal(dest.toString('utf8'), 'hello')
+    t.end()
+  })
+})
+
+tape('basic copy', function (t) {
+  var buf  = crypto.randomBytes(1024)
+    , buf2 = Buffer.alloc(1024)
+    , b    = BufferList(buf)
+
+  b.copy(buf2)
+  t.equal(b.slice().toString('hex'), buf2.toString('hex'), 'same buffer')
+  t.end()
+})
+
+tape('copy after many appends', function (t) {
+  var buf  = crypto.randomBytes(512)
+    , buf2 = Buffer.alloc(1024)
+    , b    = BufferList(buf)
+
+  b.append(buf)
+  b.copy(buf2)
+  t.equal(b.slice().toString('hex'), buf2.toString('hex'), 'same buffer')
+  t.end()
+})
+
+tape('copy at a precise position', function (t) {
+  var buf  = crypto.randomBytes(1004)
+    , buf2 = Buffer.alloc(1024)
+    , b    = BufferList(buf)
+
+  b.copy(buf2, 20)
+  t.equal(b.slice().toString('hex'), buf2.slice(20).toString('hex'), 'same buffer')
+  t.end()
+})
+
+tape('copy starting from a precise location', function (t) {
+  var buf  = crypto.randomBytes(10)
+    , buf2 = Buffer.alloc(5)
+    , b    = BufferList(buf)
+
+  b.copy(buf2, 0, 5)
+  t.equal(b.slice(5).toString('hex'), buf2.toString('hex'), 'same buffer')
+  t.end()
+})
+
+tape('copy in an interval', function (t) {
+  var rnd      = crypto.randomBytes(10)
+    , b        = BufferList(rnd) // put the random bytes there
+    , actual   = Buffer.alloc(3)
+    , expected = Buffer.alloc(3)
+
+  rnd.copy(expected, 0, 5, 8)
+  b.copy(actual, 0, 5, 8)
+
+  t.equal(actual.toString('hex'), expected.toString('hex'), 'same buffer')
+  t.end()
+})
+
+tape('copy an interval between two buffers', function (t) {
+  var buf      = crypto.randomBytes(10)
+    , buf2     = Buffer.alloc(10)
+    , b        = BufferList(buf)
+
+  b.append(buf)
+  b.copy(buf2, 0, 5, 15)
+
+  t.equal(b.slice(5, 15).toString('hex'), buf2.toString('hex'), 'same buffer')
+  t.end()
+})
+
+tape('shallow slice across buffer boundaries', function (t) {
+  var bl = new BufferList(['First', 'Second', 'Third'])
+
+  t.equal(bl.shallowSlice(3, 13).toString(), 'stSecondTh')
+  t.end()
+})
+
+tape('shallow slice within single buffer', function (t) {
+  t.plan(2)
+  var bl = new BufferList(['First', 'Second', 'Third'])
+
+  t.equal(bl.shallowSlice(5, 10).toString(), 'Secon')
+  t.equal(bl.shallowSlice(7, 10).toString(), 'con')
+  t.end()
+})
+
+tape('shallow slice single buffer', function (t) {
+  t.plan(3)
+  var bl = new BufferList(['First', 'Second', 'Third'])
+
+  t.equal(bl.shallowSlice(0, 5).toString(), 'First')
+  t.equal(bl.shallowSlice(5, 11).toString(), 'Second')
+  t.equal(bl.shallowSlice(11, 16).toString(), 'Third')
+})
+
+tape('shallow slice with negative or omitted indices', function (t) {
+  t.plan(4)
+  var bl = new BufferList(['First', 'Second', 'Third'])
+
+  t.equal(bl.shallowSlice().toString(), 'FirstSecondThird')
+  t.equal(bl.shallowSlice(5).toString(), 'SecondThird')
+  t.equal(bl.shallowSlice(5, -3).toString(), 'SecondTh')
+  t.equal(bl.shallowSlice(-8).toString(), 'ondThird')
+})
+
+tape('shallow slice does not make a copy', function (t) {
+  t.plan(1)
+  var buffers = [Buffer.from('First'), Buffer.from('Second'), Buffer.from('Third')]
+  var bl = (new BufferList(buffers)).shallowSlice(5, -3)
+
+  buffers[1].fill('h')
+  buffers[2].fill('h')
+
+  t.equal(bl.toString(), 'hhhhhhhh')
+})
+
+tape('duplicate', function (t) {
+  t.plan(2)
+
+  var bl = new BufferList('abcdefghij\xff\x00')
+    , dup = bl.duplicate()
+
+  t.equal(bl.prototype, dup.prototype)
+  t.equal(bl.toString('hex'), dup.toString('hex'))
+})
+
+tape('destroy no pipe', function (t) {
+  t.plan(2)
+
+  var bl = new BufferList('alsdkfja;lsdkfja;lsdk')
+  bl.destroy()
+
+  t.equal(bl._bufs.length, 0)
+  t.equal(bl.length, 0)
+})
+
+!process.browser && tape('destroy with pipe before read end', function (t) {
+  t.plan(2)
+
+  var bl = new BufferList()
+  fs.createReadStream(__dirname + '/test.js')
+    .pipe(bl)
+
+  bl.destroy()
+
+  t.equal(bl._bufs.length, 0)
+  t.equal(bl.length, 0)
+
+})
+
+!process.browser && tape('destroy with pipe before read end with race', function (t) {
+  t.plan(2)
+
+  var bl = new BufferList()
+  fs.createReadStream(__dirname + '/test.js')
+    .pipe(bl)
+
+  setTimeout(function () {
+    bl.destroy()
+    setTimeout(function () {
+      t.equal(bl._bufs.length, 0)
+      t.equal(bl.length, 0)
+    }, 500)
+  }, 500)
+})
+
+!process.browser && tape('destroy with pipe after read end', function (t) {
+  t.plan(2)
+
+  var bl = new BufferList()
+  fs.createReadStream(__dirname + '/test.js')
+    .on('end', onEnd)
+    .pipe(bl)
+
+  function onEnd () {
+    bl.destroy()
+
+    t.equal(bl._bufs.length, 0)
+    t.equal(bl.length, 0)
+  }
+})
+
+!process.browser && tape('destroy with pipe while writing to a destination', function (t) {
+  t.plan(4)
+
+  var bl = new BufferList()
+    , ds = new BufferList()
+
+  fs.createReadStream(__dirname + '/test.js')
+    .on('end', onEnd)
+    .pipe(bl)
+
+  function onEnd () {
+    bl.pipe(ds)
+
+    setTimeout(function () {
+      bl.destroy()
+
+      t.equals(bl._bufs.length, 0)
+      t.equals(bl.length, 0)
+
+      ds.destroy()
+
+      t.equals(bl._bufs.length, 0)
+      t.equals(bl.length, 0)
+
+    }, 100)
+  }
+})
+
+!process.browser && tape('handle error', function (t) {
+  t.plan(2)
+  fs.createReadStream('/does/not/exist').pipe(BufferList(function (err, data) {
+    t.ok(err instanceof Error, 'has error')
+    t.notOk(data, 'no data')
+  }))
+})
diff --git a/input_devices/mag/node_modules/buffer-alloc-unsafe/index.js b/input_devices/mag/node_modules/buffer-alloc-unsafe/index.js
new file mode 100644
index 00000000..0bd335ff
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-alloc-unsafe/index.js
@@ -0,0 +1,17 @@
+function allocUnsafe (size) {
+  if (typeof size !== 'number') {
+    throw new TypeError('"size" argument must be a number')
+  }
+
+  if (size < 0) {
+    throw new RangeError('"size" argument must not be negative')
+  }
+
+  if (Buffer.allocUnsafe) {
+    return Buffer.allocUnsafe(size)
+  } else {
+    return new Buffer(size)
+  }
+}
+
+module.exports = allocUnsafe
diff --git a/input_devices/mag/node_modules/buffer-alloc-unsafe/package.json b/input_devices/mag/node_modules/buffer-alloc-unsafe/package.json
new file mode 100644
index 00000000..5abaf03c
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-alloc-unsafe/package.json
@@ -0,0 +1,89 @@
+{
+  "_args": [
+    [
+      "buffer-alloc-unsafe@^1.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/buffer-alloc"
+    ]
+  ],
+  "_from": "buffer-alloc-unsafe@>=1.1.0 <2.0.0",
+  "_id": "buffer-alloc-unsafe@1.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/buffer-alloc-unsafe",
+  "_nodeVersion": "10.2.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/buffer-alloc-unsafe_1.1.0_1527635919542_0.8786275682843983"
+  },
+  "_npmUser": {
+    "email": "linus@folkdatorn.se",
+    "name": "linusu"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "buffer-alloc-unsafe",
+    "raw": "buffer-alloc-unsafe@^1.1.0",
+    "rawSpec": "^1.1.0",
+    "scope": null,
+    "spec": ">=1.1.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/buffer-alloc"
+  ],
+  "_resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+  "_shasum": "bd7dc26ae2972d0eda253be061dba992349c19f0",
+  "_shrinkwrap": null,
+  "_spec": "buffer-alloc-unsafe@^1.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/buffer-alloc",
+  "bugs": {
+    "url": "https://github.com/LinusU/buffer-alloc-unsafe/issues"
+  },
+  "dependencies": {},
+  "description": "A [ponyfill](https://ponyfill.com) for `Buffer.allocUnsafe`.",
+  "devDependencies": {
+    "standard": "^7.1.2"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 3,
+    "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDd/RCRA9TVsSAnZWagAAyRsP/3sjiRG+h8mqwIs9CZjK\n4z+jUqruRnm7xqZAHwtEGUrrJiWpJ77P02u0A122fWxjofhLjkYbePG8ZGMR\nIovOroyc1lBEJ8cI85ZLirvEfUUQJ+SFPkL64o9n3AXVi66OWs0jJtSq7FYL\ntOdfqA942lKMEs3PCZ4K2kpgKmyNXxfhgdRbqFnDHP1XuswsPG3gnHxP2O5b\nqcgz4c+cKmVecfMHLJbGwR+Z+aghzBOiG0RxXpVi9lXDAnqdtTqBg83di8JA\nzQ0n/nFGx28xdISwGpdzdRCpsZu2D+sGDcEvwa0uwhU5QpID41Hddentg0dN\nW8j+afOdFT58DUVuUSRxxHBm27xJFkHfa4VosUmqQgkpUlmQpUBk0Mg5zj44\nFpOHd0vPuEVBrhics/uvch2k/r3+epwwMxpAZr8Z6mTtleet7C15CFbLlRyc\n11q9KO54/VqVdthhCCVrXXWH2FP73MbcE5chNX15vNJr7b+fXTDM/POR6uIa\nFmzBFL34oPdCpofQIp7OVFtrten9fKZKsg4l8Ly83cKhVAJWaotC0vIhhGYi\nslmAMdKL9GG8udV04WmFyGDXs8vzf3+7i+y6UaLUX7eJhVVM0w7iHyaO9Ljt\n4t74PZ3CZPzXylbGZqGmDg4DBvYG4FAaXu9zUkGhQBGSlPP4ohFNvmN7A7U2\nCH9/\r\n=fNVs\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "bd7dc26ae2972d0eda253be061dba992349c19f0",
+    "tarball": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+    "unpackedSize": 1936
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "93c66c6a1e0f812a55128036004d6ff8a561fd98",
+  "homepage": "https://github.com/LinusU/buffer-alloc-unsafe#readme",
+  "keywords": [
+    "allocUnsafe",
+    "allocate",
+    "buffer",
+    "buffer allocUnsafe",
+    "buffer unsafe allocate",
+    "ponyfill",
+    "unsafe allocate"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "linusu",
+      "email": "linus@folkdatorn.se"
+    }
+  ],
+  "name": "buffer-alloc-unsafe",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/LinusU/buffer-alloc-unsafe.git"
+  },
+  "scripts": {
+    "test": "standard && node test"
+  },
+  "version": "1.1.0"
+}
diff --git a/input_devices/mag/node_modules/buffer-alloc-unsafe/readme.md b/input_devices/mag/node_modules/buffer-alloc-unsafe/readme.md
new file mode 100644
index 00000000..8725ecf6
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-alloc-unsafe/readme.md
@@ -0,0 +1,46 @@
+# Buffer Alloc Unsafe
+
+A [ponyfill](https://ponyfill.com) for `Buffer.allocUnsafe`.
+
+Works as Node.js: `v7.0.0` <br>
+Works on Node.js: `v0.10.0`
+
+## Installation
+
+```sh
+npm install --save buffer-alloc-unsafe
+```
+
+## Usage
+
+```js
+const allocUnsafe = require('buffer-alloc-unsafe')
+
+console.log(allocUnsafe(10))
+//=> <Buffer 78 0c 80 03 01 00 00 00 05 00>
+
+console.log(allocUnsafe(10))
+//=> <Buffer 58 ed bf 5f ff 7f 00 00 01 00>
+
+console.log(allocUnsafe(10))
+//=> <Buffer 50 0c 80 03 01 00 00 00 0a 00>
+
+allocUnsafe(-10)
+//=> RangeError: "size" argument must not be negative
+```
+
+## API
+
+### allocUnsafe(size)
+
+- `size` &lt;Integer&gt; The desired length of the new `Buffer`
+
+Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must be
+less than or equal to the value of `buffer.kMaxLength` and greater than or equal
+to zero. Otherwise, a `RangeError` is thrown.
+
+## See also
+
+- [buffer-alloc](https://github.com/LinusU/buffer-alloc) A ponyfill for `Buffer.alloc`
+- [buffer-fill](https://github.com/LinusU/buffer-fill) A ponyfill for `Buffer.fill`
+- [buffer-from](https://github.com/LinusU/buffer-from) A ponyfill for `Buffer.from`
diff --git a/input_devices/mag/node_modules/buffer-alloc/index.js b/input_devices/mag/node_modules/buffer-alloc/index.js
new file mode 100644
index 00000000..fe658606
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-alloc/index.js
@@ -0,0 +1,32 @@
+var bufferFill = require('buffer-fill')
+var allocUnsafe = require('buffer-alloc-unsafe')
+
+module.exports = function alloc (size, fill, encoding) {
+  if (typeof size !== 'number') {
+    throw new TypeError('"size" argument must be a number')
+  }
+
+  if (size < 0) {
+    throw new RangeError('"size" argument must not be negative')
+  }
+
+  if (Buffer.alloc) {
+    return Buffer.alloc(size, fill, encoding)
+  }
+
+  var buffer = allocUnsafe(size)
+
+  if (size === 0) {
+    return buffer
+  }
+
+  if (fill === undefined) {
+    return bufferFill(buffer, 0)
+  }
+
+  if (typeof encoding !== 'string') {
+    encoding = undefined
+  }
+
+  return bufferFill(buffer, fill, encoding)
+}
diff --git a/input_devices/mag/node_modules/buffer-alloc/package.json b/input_devices/mag/node_modules/buffer-alloc/package.json
new file mode 100644
index 00000000..989f4db7
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-alloc/package.json
@@ -0,0 +1,90 @@
+{
+  "_args": [
+    [
+      "buffer-alloc@^1.2.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream"
+    ]
+  ],
+  "_from": "buffer-alloc@>=1.2.0 <2.0.0",
+  "_id": "buffer-alloc@1.2.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/buffer-alloc",
+  "_nodeVersion": "10.2.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/buffer-alloc_1.2.0_1527637266526_0.19419340644925764"
+  },
+  "_npmUser": {
+    "email": "linus@folkdatorn.se",
+    "name": "linusu"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "buffer-alloc",
+    "raw": "buffer-alloc@^1.2.0",
+    "rawSpec": "^1.2.0",
+    "scope": null,
+    "spec": ">=1.2.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+  "_shasum": "890dd90d923a873e08e10e5fd51a57e5b7cce0ec",
+  "_shrinkwrap": null,
+  "_spec": "buffer-alloc@^1.2.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream",
+  "bugs": {
+    "url": "https://github.com/LinusU/buffer-alloc/issues"
+  },
+  "dependencies": {
+    "buffer-alloc-unsafe": "^1.1.0",
+    "buffer-fill": "^1.0.0"
+  },
+  "description": "A [ponyfill](https://ponyfill.com) for `Buffer.alloc`.",
+  "devDependencies": {
+    "standard": "^7.1.2"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 3,
+    "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDeUSCRA9TVsSAnZWagAARAEP/32m9WSt0ZIpF7+umUJY\nTzwhGXcaMYWtZOBdw+xkBY9F5+NlRIwNk6/EupLFi/BShct7VMccElsFNX21\nSxi1Jo/+EZZCULaV8Uh8QwEIpDHWN4C9SDBMbdLWORRVriQYYZgqNLVDBv9O\njraOM3MfC/6ESCbN2x+OHubawV3t02lwTwWcbdM42Y4kDekIugesoVIj1+Sq\nbyrjs1zisKTPLacuMHKKXj13pIOXvSTz7PVenVJZAuwm2bUJmxrfwtXFYLfK\npMNwyu3tv6Ci85Mq5gXGecPNbmVej8qyqJmwk4cqhZH4pxWhpqSb7g2chmTe\nQnqG/WsT1CDD6b4fTe8qLUZzZRT/X4sKyvM4hAL7nveUsU3EjjXWmHLGXmN/\nWjH3ZIkm8O7owXcbpEycwnySZiG8BmlcjvHiywwckjCt8v7UwrQocG/lE8gF\nef00DQLtd2JRdkTZt+WTgUY6siVKquhuVavJbUkQ2bZD+WZjPetohMOTLhUy\nIVHxvNGxoUKS9fGdBDKViRehO/5qX84Ic2Y59NSPtAh5h52yviYtUam6qdKf\nXigpwDZBBqA4lAZ9TP0rs9ZfR/rsxTryRAYQz0LbHIFaYN3uNvkU11IMJ6wv\n/Yg3rVL4znO9w2R5FpsoMYReAnZLIM8QfpTIcIDgfI+LAU+Fgylznj7mNBwM\nLAJU\r\n=hQoj\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "890dd90d923a873e08e10e5fd51a57e5b7cce0ec",
+    "tarball": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+    "unpackedSize": 2274
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "a0d55382c805f3b117a055e0be203f13f2519cc5",
+  "homepage": "https://github.com/LinusU/buffer-alloc#readme",
+  "keywords": [
+    "alloc",
+    "allocate",
+    "buffer",
+    "buffer alloc",
+    "buffer allocate"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "linusu",
+      "email": "linus@folkdatorn.se"
+    }
+  ],
+  "name": "buffer-alloc",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/LinusU/buffer-alloc.git"
+  },
+  "scripts": {
+    "test": "standard && node test"
+  },
+  "version": "1.2.0"
+}
diff --git a/input_devices/mag/node_modules/buffer-alloc/readme.md b/input_devices/mag/node_modules/buffer-alloc/readme.md
new file mode 100644
index 00000000..80c7d7bb
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-alloc/readme.md
@@ -0,0 +1,43 @@
+# Buffer Alloc
+
+A [ponyfill](https://ponyfill.com) for `Buffer.alloc`.
+
+Works as Node.js: `v7.0.0` <br>
+Works on Node.js: `v0.10.0`
+
+## Installation
+
+```sh
+npm install --save buffer-alloc
+```
+
+## Usage
+
+```js
+const alloc = require('buffer-alloc')
+
+console.log(alloc(4))
+//=> <Buffer 00 00 00 00>
+
+console.log(alloc(6, 0x41))
+//=> <Buffer 41 41 41 41 41 41>
+
+console.log(alloc(10, 'linus', 'utf8'))
+//=> <Buffer 6c 69 6e 75 73 6c 69 6e 75 73>
+```
+
+## API
+
+### alloc(size[, fill[, encoding]])
+
+- `size` &lt;Integer&gt; The desired length of the new `Buffer`
+- `fill` &lt;String&gt; | &lt;Buffer&gt; | &lt;Integer&gt; A value to pre-fill the new `Buffer` with. **Default:** `0`
+- `encoding` &lt;String&gt; If `fill` is a string, this is its encoding. **Default:** `'utf8'`
+
+Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the `Buffer` will be zero-filled.
+
+## See also
+
+- [buffer-alloc-unsafe](https://github.com/LinusU/buffer-alloc-unsafe) A ponyfill for `Buffer.allocUnsafe`
+- [buffer-fill](https://github.com/LinusU/buffer-fill) A ponyfill for `Buffer.fill`
+- [buffer-from](https://github.com/LinusU/buffer-from) A ponyfill for `Buffer.from`
diff --git a/input_devices/mag/node_modules/buffer-fill/index.js b/input_devices/mag/node_modules/buffer-fill/index.js
new file mode 100644
index 00000000..428a9e1f
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-fill/index.js
@@ -0,0 +1,113 @@
+/* Node.js 6.4.0 and up has full support */
+var hasFullSupport = (function () {
+  try {
+    if (!Buffer.isEncoding('latin1')) {
+      return false
+    }
+
+    var buf = Buffer.alloc ? Buffer.alloc(4) : new Buffer(4)
+
+    buf.fill('ab', 'ucs2')
+
+    return (buf.toString('hex') === '61006200')
+  } catch (_) {
+    return false
+  }
+}())
+
+function isSingleByte (val) {
+  return (val.length === 1 && val.charCodeAt(0) < 256)
+}
+
+function fillWithNumber (buffer, val, start, end) {
+  if (start < 0 || end > buffer.length) {
+    throw new RangeError('Out of range index')
+  }
+
+  start = start >>> 0
+  end = end === undefined ? buffer.length : end >>> 0
+
+  if (end > start) {
+    buffer.fill(val, start, end)
+  }
+
+  return buffer
+}
+
+function fillWithBuffer (buffer, val, start, end) {
+  if (start < 0 || end > buffer.length) {
+    throw new RangeError('Out of range index')
+  }
+
+  if (end <= start) {
+    return buffer
+  }
+
+  start = start >>> 0
+  end = end === undefined ? buffer.length : end >>> 0
+
+  var pos = start
+  var len = val.length
+  while (pos <= (end - len)) {
+    val.copy(buffer, pos)
+    pos += len
+  }
+
+  if (pos !== end) {
+    val.copy(buffer, pos, 0, end - pos)
+  }
+
+  return buffer
+}
+
+function fill (buffer, val, start, end, encoding) {
+  if (hasFullSupport) {
+    return buffer.fill(val, start, end, encoding)
+  }
+
+  if (typeof val === 'number') {
+    return fillWithNumber(buffer, val, start, end)
+  }
+
+  if (typeof val === 'string') {
+    if (typeof start === 'string') {
+      encoding = start
+      start = 0
+      end = buffer.length
+    } else if (typeof end === 'string') {
+      encoding = end
+      end = buffer.length
+    }
+
+    if (encoding !== undefined && typeof encoding !== 'string') {
+      throw new TypeError('encoding must be a string')
+    }
+
+    if (encoding === 'latin1') {
+      encoding = 'binary'
+    }
+
+    if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
+      throw new TypeError('Unknown encoding: ' + encoding)
+    }
+
+    if (val === '') {
+      return fillWithNumber(buffer, 0, start, end)
+    }
+
+    if (isSingleByte(val)) {
+      return fillWithNumber(buffer, val.charCodeAt(0), start, end)
+    }
+
+    val = new Buffer(val, encoding)
+  }
+
+  if (Buffer.isBuffer(val)) {
+    return fillWithBuffer(buffer, val, start, end)
+  }
+
+  // Other values (e.g. undefined, boolean, object) results in zero-fill
+  return fillWithNumber(buffer, 0, start, end)
+}
+
+module.exports = fill
diff --git a/input_devices/mag/node_modules/buffer-fill/package.json b/input_devices/mag/node_modules/buffer-fill/package.json
new file mode 100644
index 00000000..ad94b280
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-fill/package.json
@@ -0,0 +1,80 @@
+{
+  "_args": [
+    [
+      "buffer-fill@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/buffer-alloc"
+    ]
+  ],
+  "_from": "buffer-fill@>=1.0.0 <2.0.0",
+  "_id": "buffer-fill@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/buffer-fill",
+  "_nodeVersion": "7.0.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/buffer-fill_1.0.0_1527636952747_0.20799370179837218"
+  },
+  "_npmUser": {
+    "email": "linus@folkdatorn.se",
+    "name": "linusu"
+  },
+  "_npmVersion": "3.10.8",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "buffer-fill",
+    "raw": "buffer-fill@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/buffer-alloc"
+  ],
+  "_resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+  "_shasum": "f8f78b76789888ef39f205cd637f68e702122b2c",
+  "_shrinkwrap": null,
+  "_spec": "buffer-fill@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/buffer-alloc",
+  "bugs": {
+    "url": "https://github.com/linusu/buffer-fill/issues"
+  },
+  "dependencies": {},
+  "description": "A [ponyfill](https://ponyfill.com) for `Buffer.fill`.",
+  "devDependencies": {
+    "buffer-alloc-unsafe": "^1.1.0",
+    "standard": "^7.1.2"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 3,
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDePZCRA9TVsSAnZWagAA6jAP/ilxGieW8Z7iZZjhfbLR\nhL+yhqdi5m0aSPzY4O7eb6e+Dd3/4fO8FxTcjQCpzie/n8Yo3uzY/RK0fN33\nDPh4kxNlHwrMhpBNuGG2RkKh114r1HkD+vVaWzZb+NFn523hv3OqDR7DOhHN\n7Zq9Y5QfHGma4dQRgfUvHFx0z6PRolCCB+3oGuSB8ER9VXMa6cOwr6whmccu\nwZzyVlpWEHCYekXGyrLtFRrIUezBDVitvz9QDMBn5feVh/tSsD42E/nUDaCW\njcm/TdvHssGyd1ZP6zGjgjvdMVBJgFsS8g9IJ/Vjojyd1KM3B5FI9bo4ChYt\nsL9FXZkcjVbsdGpnmXKVb2yHa9Bq/fPNRpi6zmLeKrsksLbkWMu8YU2U+sZ0\nBwIa/jCF9A1bMrrXgsPtgGQRQoVIL/MWRPtTgVlxupmAavZQJki4nKvQHF6H\nfCHDUTg3bBZgYXqPa+SBY7tqnw6b6CUioe2cZds96TXgZ+y+u28jj3+6j3ER\n+PBp/XMbTjUc8EVWEZEkNq4Hh9K4GhNGoM8CEKFtU6qmwLykrbB9JUskpNGk\naX/Tbx1MHxMU9o+uZ4AbIMmSTh097t6+Igx0HSQektms3mmtsAGx83oOLGd3\nK5Vil/u8V5//McTdf38G3kYlupClQQplYsSgvDxlU/Qg2rw8YJfDREXdAZI8\nnT2Y\r\n=hmqw\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "f8f78b76789888ef39f205cd637f68e702122b2c",
+    "tarball": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+    "unpackedSize": 4390
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "a2badd1de771c99285e385dccdebd63093f0285a",
+  "homepage": "https://github.com/linusu/buffer-fill#readme",
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "linusu",
+      "email": "linus@folkdatorn.se"
+    }
+  ],
+  "name": "buffer-fill",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/linusu/buffer-fill.git"
+  },
+  "scripts": {
+    "test": "standard && node test"
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/buffer-fill/readme.md b/input_devices/mag/node_modules/buffer-fill/readme.md
new file mode 100644
index 00000000..ac307383
--- /dev/null
+++ b/input_devices/mag/node_modules/buffer-fill/readme.md
@@ -0,0 +1,54 @@
+# Buffer Fill
+
+A [ponyfill](https://ponyfill.com) for `Buffer.fill`.
+
+Works as Node.js: `v6.4.0` <br>
+Works on Node.js: `v0.10.0`
+
+## Installation
+
+```sh
+npm install --save buffer-fill
+```
+
+## Usage
+
+```js
+const fill = require('buffer-fill')
+const buf = Buffer.allocUnsafe(5)
+
+console.log(buf.fill(8))
+//=> <Buffer 08 08 08 08 08>
+
+console.log(buf.fill(9, 2, 4))
+//=> <Buffer 08 08 09 09 08>
+
+console.log(buf.fill('linus', 'latin1'))
+//=> <Buffer 6c 69 6e 75 73>
+
+console.log(buf.fill('\u0222'))
+//=> <Buffer c8 a2 c8 a2 c8>
+```
+
+## API
+
+### fill(buf, value[, offset[, end]][, encoding])
+
+- `value` &lt;String&gt; | &lt;Buffer&gt; | &lt;Integer&gt; The value to fill `buf` with
+- `offset` &lt;Integer&gt; Where to start filling `buf`. **Default:** `0`
+- `end` &lt;Integer&gt; Where to stop filling `buf` (not inclusive). **Default:** `buf.length`
+- `encoding` &lt;String&gt; If `value` is a string, this is its encoding. **Default:** `'utf8'`
+- Return: &lt;Buffer&gt; A reference to `buf`
+
+Fills `buf` with the specified `value`. If the `offset` and `end` are not given,
+the entire `buf` will be filled. This is meant to be a small simplification to
+allow the creation and filling of a `Buffer` to be done on a single line.
+
+If the final write of a `fill()` operation falls on a multi-byte character, then
+only the first bytes of that character that fit into `buf` are written.
+
+## See also
+
+- [buffer-alloc-unsafe](https://github.com/LinusU/buffer-alloc-unsafe) A ponyfill for `Buffer.allocUnsafe`
+- [buffer-alloc](https://github.com/LinusU/buffer-alloc) A ponyfill for `Buffer.alloc`
+- [buffer-from](https://github.com/LinusU/buffer-from) A ponyfill for `Buffer.from`
diff --git a/input_devices/mag/node_modules/choices-separator/LICENSE b/input_devices/mag/node_modules/choices-separator/LICENSE
new file mode 100644
index 00000000..b11cb796
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/choices-separator/README.md b/input_devices/mag/node_modules/choices-separator/README.md
new file mode 100644
index 00000000..e7daf96e
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/README.md
@@ -0,0 +1,147 @@
+# choices-separator [![NPM version](https://img.shields.io/npm/v/choices-separator.svg?style=flat)](https://www.npmjs.com/package/choices-separator) [![NPM monthly downloads](https://img.shields.io/npm/dm/choices-separator.svg?style=flat)](https://npmjs.org/package/choices-separator) [![NPM total downloads](https://img.shields.io/npm/dt/choices-separator.svg?style=flat)](https://npmjs.org/package/choices-separator) [![Linux Build Status](https://img.shields.io/travis/enquirer/choices-separator.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/choices-separator)
+
+> Separator for choices arrays in prompts. Based on the Separator from inquirer.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save choices-separator
+```
+
+## Usage
+
+```js
+var Separator = require('choices-separator');
+var Prompt = require('prompt-checkbox');
+
+var prompt = new Prompt({
+  message: 'Which do you prefer?',
+  name: 'favorites',
+  choices: [
+    new Separator(' = Color = '),
+    {name: 'red'},
+    {name: 'yellow', checked: true },
+    {name: 'blue'},
+    new Separator(' = Shape = '),
+    {name: 'circle'},
+    {name: 'triangle'},
+    {name: 'square'}
+  ]
+});
+
+prompt.run()
+  .then(function(answer) {
+    console.log(answer)
+  });
+```
+
+## API
+
+### [Separator](index.js#L21)
+
+Separator object, used in choices arrays in prompts, to create a visual break between sections. The default separator line is `────────` styled with [ansi-dim](https://github.com/jonschlinkert/ansi-dim).
+
+**Params**
+
+* `options` **{String}**: Optionally provide a custom `line` and or `prefix` to use.
+
+**Example**
+
+```js
+new Separator('----');
+new Separator({line: '----'})
+new Separator({line: '----', prefix: '    '});
+```
+
+### [.raw](index.js#L56)
+
+Returns the `separator.line` stripped of ansi styling.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+var separator = new Separator();
+console.log(separator.raw());
+//=> '────────'
+```
+
+### [.render](index.js#L72)
+
+Render `separator.prefix` plus `separator.line`.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+var separator = new Separator();
+console.log(separator.render());
+//=> ' \u001b[2m────────\u001b[22m\n')
+```
+
+### [.exclude](index.js#L83)
+
+Returns false if the given object is a separator.
+
+**Params**
+
+* `choice` **{Object}**: object to test against
+* `returns` **{Boolean}**: Returns false if the given object is a separator
+
+### [.toString](index.js#L93)
+
+Stringify separator
+
+* `returns` **{String}**: Returns the `separator.line` string
+
+## Attribution
+
+Originally inspired by the `Separator` class from Inquirer.
+
+## About
+
+### Related projects
+
+[enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. Much faster and lighter alternative to Inquirer, with all… [more](https://github.com/enquirer/enquirer) | [homepage](https://github.com/enquirer/enquirer "Intuitive, plugin-based prompt system for node.js. Much faster and lighter alternative to Inquirer, with all the same prompt types and more, but without the bloat.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 17, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/choices-separator/index.js b/input_devices/mag/node_modules/choices-separator/index.js
new file mode 100644
index 00000000..176c29d0
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/index.js
@@ -0,0 +1,101 @@
+'use strict';
+
+var debug = require('debug')('choices-separator');
+var strip = require('strip-color');
+var dim = require('ansi-dim');
+
+/**
+ * Separator object, used in choices arrays in prompts, to
+ * create a visual break between sections. The default separator
+ * line is `────────` styled with [ansi-dim].
+ *
+ * ```js
+ * new Separator('----');
+ * new Separator({line: '----'})
+ * new Separator({line: '----', prefix: '    '});
+ * ```
+ * @param {String} `options` Optionally provide a custom `line` and or `prefix` to use.
+ * @api public
+ */
+
+function Separator(options) {
+  debug('initializing from <%s>', __filename);
+  this.isSeparator = true;
+  this.type = 'separator';
+
+  if (typeof options === 'string') {
+    options = { line: options };
+  }
+
+  this.options = options || {};
+  this.prefix = ' ';
+
+  if (typeof this.options.prefix === 'string') {
+    this.prefix = this.options.prefix;
+  }
+
+  if (typeof this.options.line === 'string') {
+    this.line = this.options.line;
+  } else {
+    this.line = dim('────────');
+  }
+}
+
+/**
+ * Returns the `separator.line` stripped of ansi styling.
+ *
+ * ```js
+ * var separator = new Separator();
+ * console.log(separator.raw());
+ * //=> '────────'
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Separator.prototype.raw = function() {
+  return strip(this.line);
+};
+
+/**
+ * Render `separator.prefix` plus `separator.line`.
+ *
+ * ```js
+ * var separator = new Separator();
+ * console.log(separator.render());
+ * //=> ' \u001b[2m────────\u001b[22m\n')
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Separator.prototype.render = function() {
+  return this.prefix + this.line + '\n';
+};
+
+/**
+ * Returns false if the given object is a separator.
+ * @param  {Object} `choice` object to test against
+ * @return {Boolean} Returns false if the given object is a separator
+ * @api public
+ */
+
+Separator.exclude = function(choice) {
+  return choice.type !== 'separator';
+};
+
+/**
+ * Stringify separator
+ * @return {String} Returns the `separator.line` string
+ * @api public
+ */
+
+Separator.prototype.toString = function() {
+  return this.line;
+};
+
+/**
+ * Expose `Separator`
+ */
+
+module.exports = Separator;
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/.coveralls.yml b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/.eslintrc b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+  "rules": {
+    "no-console": 0,
+    "no-empty": [1, { "allowEmptyCatch": true }]
+  },
+  "extends": "eslint:recommended"
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/.npmignore b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/.travis.yml b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+  - "6"
+  - "5"
+  - "4"
+
+install:
+  - make node_modules
+
+script:
+  - make lint
+  - make test
+  - make coveralls
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/CHANGELOG.md b/input_devices/mag/node_modules/choices-separator/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+  * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+  * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+  * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+  * Fix: Inline extend function in node implementation (#452, @dougwilson)
+  * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+  
+  * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+  * Misc: clean up browser reference checks (#447, @thebigredgeek)
+  * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+  * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+  * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+  * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+  * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+  * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+  * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+  * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+  * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+  * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+  * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+  * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+  * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+  * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+  * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+  * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+  * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+  * Docs: fixed README typo (#391, @lurch)
+  * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+  * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+  * Fix: wrong reference in bower file (@thebigredgeek)
+  * Fix: webworker compatibility (@thebigredgeek)
+  * Fix: output formatting issue (#388, @kribblo)
+  * Fix: babel-loader compatibility (#383, @escwald)
+  * Misc: removed built asset from repo and publications (@thebigredgeek)
+  * Misc: moved source files to /src (#378, @yamikuronue)
+  * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+  * Test: coveralls integration (#378, @yamikuronue)
+  * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+  * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+  * Fix: custom log function (#379, @hsiliev)
+  * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+  * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+  * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+  * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+  * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+  * Fix: browser colors (#367, @tootallnate)
+  * Misc: travis ci integration (@thebigredgeek)
+  * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+  * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+  * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+  * Fix: revert "handle regex special characters" (@tootallnate)
+  * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+  * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+  * Improvement: allow colors in workers (#335, @botverse)
+  * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+  * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+  * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+  * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+  * Fix: be super-safe in index.js as well (@TooTallNate)
+  * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+  * Fix: Added electron compatibility (#324, @paulcbetts)
+  * Improvement: Added performance optimizations (@tootallnate)
+  * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+  * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+  * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+  * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+  * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+  * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+  * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+  * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+  * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+  * Readme: fix USE_COLORS to DEBUG_COLORS
+  * Readme: Doc fixes for format string sugar (#269, @mlucool)
+  * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+  * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+  * Readme: better docs for browser support (#224, @matthewmueller)
+  * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+  * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+  * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+  * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+  * package: update "ms" to v0.7.1 (#202, @dougwilson)
+  * README: add logging to file example (#193, @DanielOchoa)
+  * README: fixed a typo (#191, @amir-s)
+  * browser: expose `storage` (#190, @stephenmathieson)
+  * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+  * Updated stdout/stderr example (#186)
+  * Updated example/stdout.js to match debug current behaviour
+  * Renamed example/stderr.js to stdout.js
+  * Update Readme.md (#184)
+  * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+  * dist: recompile
+  * update "ms" to v0.7.0
+  * package: update "browserify" to v9.0.3
+  * component: fix "ms.js" repo location
+  * changed bower package name
+  * updated documentation about using debug in a browser
+  * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+  * browser: use `typeof` to check for `console` existence
+  * browser: check for `console.log` truthiness (fix IE 8/9)
+  * browser: add support for Chrome apps
+  * Readme: added Windows usage remarks
+  * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+  * node: implement `DEBUG_FD` env variable support
+  * package: update "browserify" to v6.1.0
+  * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+  * package: update "browserify" to v5.11.0
+  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+  * dist: recompile
+  * example: remove `console.info()` log usage
+  * example: add "Content-Type" UTF-8 header to browser example
+  * browser: place %c marker after the space character
+  * browser: reset the "content" color via `color: inherit`
+  * browser: add colors support for Firefox >= v31
+  * debug: prefer an instance `log()` function over the global one (#119)
+  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+  * Add support for multiple wildcards in namespaces (#122, @seegno)
+  * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+  * browser: update color palette (#113, @gscottolson)
+  * common: make console logging function configurable (#108, @timoxley)
+  * node: fix %o colors on old node <= 0.8.x
+  * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+  * browser: use `removeItem()` to clear localStorage
+  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+  * package: add "contributors" section
+  * node: fix comment typo
+  * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+  * make ms diff be global, not be scope
+  * debug: ignore empty strings in enable()
+  * node: make DEBUG_COLORS able to disable coloring
+  * *: export the `colors` array
+  * npmignore: don't publish the `dist` dir
+  * Makefile: refactor to use browserify
+  * package: add "browserify" as a dev dependency
+  * Readme: add Web Inspector Colors section
+  * node: reset terminal color for the debug content
+  * node: map "%o" to `util.inspect()`
+  * browser: map "%j" to `JSON.stringify()`
+  * debug: add custom "formatters"
+  * debug: use "ms" module for humanizing the diff
+  * Readme: add "bash" syntax highlighting
+  * browser: add Firebug color support
+  * browser: add colors for WebKit browsers
+  * node: apply log to `console`
+  * rewrite: abstract common logic for Node & browsers
+  * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+  * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+  * add `enable()` method for nodejs. Closes #27
+  * change from stderr to stdout
+  * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+  * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+  * fix: catch localStorage security error when cookies are blocked (Chrome)
+  * add debug(err) support. Closes #46
+  * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/LICENSE b/input_devices/mag/node_modules/choices-separator/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/choices-separator/node_modules/debug/Makefile b/input_devices/mag/node_modules/choices-separator/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+	@NODE_ENV= $(PKG) install
+	@touch node_modules
+
+lint: .FORCE
+	eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+	istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+	mkdir -p dist
+
+	@$(BROWSERIFY) \
+		--standalone debug \
+		. > dist/debug.js
+
+	karma start --single-run
+	rimraf dist
+
+test: .FORCE
+	concurrently \
+		"make test-node" \
+		"make test-browser"
+
+coveralls:
+	cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/README.md b/input_devices/mag/node_modules/choices-separator/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) 
+[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+  ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+
+## Conventions
+
+  If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+  When running through Node.js, you can set a few environment variables that will
+  change the behavior of the debug logging:
+
+| Name      | Purpose                                         |
+|-----------|-------------------------------------------------|
+| `DEBUG`   | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+  __Note:__ The environment variables beginning with `DEBUG_` end up being
+  converted into an Options object that gets used with `%o`/`%O` formatters.
+  See the Node.js documentation for
+  [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+  for the complete list.
+
+## Formatters
+
+
+  Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O`      | Pretty-print an Object on multiple lines. |
+| `%o`      | Pretty-print an Object all on a single line. |
+| `%s`      | String. |
+| `%d`      | Number (both integer and float). |
+| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%`      | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+  You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+  return v.toString('hex')
+}
+
+// …elsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+//   foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+  You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+  or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+  if you don't want to build it yourself.
+
+  Debug's enable state is currently persisted by `localStorage`.
+  Consider the situation shown below where you have `worker:a` and `worker:b`,
+  and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+  Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+  option. These are WebKit web inspectors, Firefox ([since version
+  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+  and the Firebug plugin for Firefox (any version).
+
+  Colored output looks something like:
+
+  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
+
+
+## Output streams
+
+  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+ 
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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/input_devices/mag/node_modules/choices-separator/node_modules/debug/component.json b/input_devices/mag/node_modules/choices-separator/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+  "name": "debug",
+  "repo": "visionmedia/debug",
+  "description": "small debugging utility",
+  "version": "2.6.9",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "main": "src/browser.js",
+  "scripts": [
+    "src/browser.js",
+    "src/debug.js"
+  ],
+  "dependencies": {
+    "rauchg/ms.js": "0.7.1"
+  }
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/karma.conf.js b/input_devices/mag/node_modules/choices-separator/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['mocha', 'chai', 'sinon'],
+
+
+    // list of files / patterns to load in the browser
+    files: [
+      'dist/debug.js',
+      'test/*spec.js'
+    ],
+
+
+    // list of files to exclude
+    exclude: [
+      'src/node.js'
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['progress'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false,
+
+    // Concurrency level
+    // how many browser should be started simultaneous
+    concurrency: Infinity
+  })
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/node.js b/input_devices/mag/node_modules/choices-separator/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/package.json b/input_devices/mag/node_modules/choices-separator/node_modules/debug/package.json
new file mode 100644
index 00000000..d987062e
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/package.json
@@ -0,0 +1,128 @@
+{
+  "_args": [
+    [
+      "debug@^2.6.6",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/choices-separator"
+    ]
+  ],
+  "_from": "debug@>=2.6.6 <3.0.0",
+  "_id": "debug@2.6.9",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/choices-separator/debug",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196"
+  },
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "debug",
+    "raw": "debug@^2.6.6",
+    "rawSpec": "^2.6.6",
+    "scope": null,
+    "spec": ">=2.6.6 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/choices-separator"
+  ],
+  "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+  "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+  "_shrinkwrap": null,
+  "_spec": "debug@^2.6.6",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/choices-separator",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "browser": "./src/browser.js",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "component": {
+    "scripts": {
+      "debug/debug.js": "debug.js",
+      "debug/index.js": "browser.js"
+    }
+  },
+  "contributors": [
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "http://n8.io"
+    },
+    {
+      "name": "Andrew Rhyne",
+      "email": "rhyneandrew@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "ms": "2.0.0"
+  },
+  "description": "small debugging utility",
+  "devDependencies": {
+    "browserify": "9.0.3",
+    "chai": "^3.5.0",
+    "concurrently": "^3.1.0",
+    "coveralls": "^2.11.15",
+    "eslint": "^3.12.1",
+    "istanbul": "^0.4.5",
+    "karma": "^1.3.0",
+    "karma-chai": "^0.1.0",
+    "karma-mocha": "^1.3.0",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "karma-sinon": "^1.0.5",
+    "mocha": "^3.2.0",
+    "mocha-lcov-reporter": "^1.2.0",
+    "rimraf": "^2.5.4",
+    "sinon": "^1.17.6",
+    "sinon-chai": "^2.8.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+    "shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+    "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
+  },
+  "gitHead": "13abeae468fea297d0dccc50bc55590809241083",
+  "homepage": "https://github.com/visionmedia/debug#readme",
+  "keywords": [
+    "debug",
+    "debugger",
+    "log"
+  ],
+  "license": "MIT",
+  "main": "./src/index.js",
+  "maintainers": [
+    {
+      "name": "thebigredgeek",
+      "email": "rhyneandrew@gmail.com"
+    },
+    {
+      "name": "kolban",
+      "email": "kolban1@kolban.com"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    }
+  ],
+  "name": "debug",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "version": "2.6.9"
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/browser.js b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+               && 'undefined' != typeof chrome.storage
+                  ? chrome.storage.local
+                  : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+  'lightseagreen',
+  'forestgreen',
+  'goldenrod',
+  'dodgerblue',
+  'darkorchid',
+  'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+  // NB: In an Electron preload script, document will be defined but not fully
+  // initialized. Since we know we're in Chrome, we'll just detect this case
+  // explicitly
+  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+    return true;
+  }
+
+  // is webkit? http://stackoverflow.com/a/16459606/376773
+  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+    // is firebug? http://stackoverflow.com/a/398120/376773
+    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+    // is firefox >= v31?
+    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+    // double check webkit in userAgent just in case we are in a worker
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+  try {
+    return JSON.stringify(v);
+  } catch (err) {
+    return '[UnexpectedJSONParseError]: ' + err.message;
+  }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var useColors = this.useColors;
+
+  args[0] = (useColors ? '%c' : '')
+    + this.namespace
+    + (useColors ? ' %c' : ' ')
+    + args[0]
+    + (useColors ? '%c ' : ' ')
+    + '+' + exports.humanize(this.diff);
+
+  if (!useColors) return;
+
+  var c = 'color: ' + this.color;
+  args.splice(1, 0, c, 'color: inherit')
+
+  // the final "%c" is somewhat tricky, because there could be other
+  // arguments passed either before or after the %c, so we need to
+  // figure out the correct index to insert the CSS into
+  var index = 0;
+  var lastC = 0;
+  args[0].replace(/%[a-zA-Z%]/g, function(match) {
+    if ('%%' === match) return;
+    index++;
+    if ('%c' === match) {
+      // we only are interested in the *last* %c
+      // (the user may have provided their own)
+      lastC = index;
+    }
+  });
+
+  args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+  // this hackery is required for IE8/9, where
+  // the `console.log` function doesn't have 'apply'
+  return 'object' === typeof console
+    && console.log
+    && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  try {
+    if (null == namespaces) {
+      exports.storage.removeItem('debug');
+    } else {
+      exports.storage.debug = namespaces;
+    }
+  } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  var r;
+  try {
+    r = exports.storage.debug;
+  } catch(e) {}
+
+  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+  if (!r && typeof process !== 'undefined' && 'env' in process) {
+    r = process.env.DEBUG;
+  }
+
+  return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+  try {
+    return window.localStorage;
+  } catch (e) {}
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/debug.js b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+  var hash = 0, i;
+
+  for (i in namespace) {
+    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
+    hash |= 0; // Convert to 32bit integer
+  }
+
+  return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+  function debug() {
+    // disabled?
+    if (!debug.enabled) return;
+
+    var self = debug;
+
+    // set `diff` timestamp
+    var curr = +new Date();
+    var ms = curr - (prevTime || curr);
+    self.diff = ms;
+    self.prev = prevTime;
+    self.curr = curr;
+    prevTime = curr;
+
+    // turn the `arguments` into a proper Array
+    var args = new Array(arguments.length);
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i];
+    }
+
+    args[0] = exports.coerce(args[0]);
+
+    if ('string' !== typeof args[0]) {
+      // anything else let's inspect with %O
+      args.unshift('%O');
+    }
+
+    // apply any `formatters` transformations
+    var index = 0;
+    args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+      // if we encounter an escaped % then don't increase the array index
+      if (match === '%%') return match;
+      index++;
+      var formatter = exports.formatters[format];
+      if ('function' === typeof formatter) {
+        var val = args[index];
+        match = formatter.call(self, val);
+
+        // now we need to remove `args[index]` since it's inlined in the `format`
+        args.splice(index, 1);
+        index--;
+      }
+      return match;
+    });
+
+    // apply env-specific formatting (colors, etc.)
+    exports.formatArgs.call(self, args);
+
+    var logFn = debug.log || exports.log || console.log.bind(console);
+    logFn.apply(self, args);
+  }
+
+  debug.namespace = namespace;
+  debug.enabled = exports.enabled(namespace);
+  debug.useColors = exports.useColors();
+  debug.color = selectColor(namespace);
+
+  // env-specific initialization logic for debug instances
+  if ('function' === typeof exports.init) {
+    exports.init(debug);
+  }
+
+  return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+  exports.save(namespaces);
+
+  exports.names = [];
+  exports.skips = [];
+
+  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+  var len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    if (!split[i]) continue; // ignore empty strings
+    namespaces = split[i].replace(/\*/g, '.*?');
+    if (namespaces[0] === '-') {
+      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+    } else {
+      exports.names.push(new RegExp('^' + namespaces + '$'));
+    }
+  }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+  exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+  var i, len;
+  for (i = 0, len = exports.skips.length; i < len; i++) {
+    if (exports.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (i = 0, len = exports.names.length; i < len; i++) {
+    if (exports.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/index.js b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+  module.exports = require('./browser.js');
+} else {
+  module.exports = require('./node.js');
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/inspector-log.js b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+  const stdout = console._stdout;
+  console._stdout = nullStream;
+  console.log.apply(console, arguments);
+  console._stdout = stdout;
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/node.js b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+  return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+  // camel-case
+  var prop = key
+    .substring(6)
+    .toLowerCase()
+    .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+  // coerce string value into JS value
+  var val = process.env[key];
+  if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+  else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+  else if (val === 'null') val = null;
+  else val = Number(val);
+
+  obj[prop] = val;
+  return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ *   $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+  util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+             2 === fd ? process.stderr :
+             createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+  return 'colors' in exports.inspectOpts
+    ? Boolean(exports.inspectOpts.colors)
+    : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts)
+    .split('\n').map(function(str) {
+      return str.trim()
+    }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var name = this.namespace;
+  var useColors = this.useColors;
+
+  if (useColors) {
+    var c = this.color;
+    var prefix = '  \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+    args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+    args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+  } else {
+    args[0] = new Date().toUTCString()
+      + ' ' + name + ' ' + args[0];
+  }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+  return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  if (null == namespaces) {
+    // If you set a process.env field to null or undefined, it gets cast to the
+    // string 'null' or 'undefined'. Just delete instead.
+    delete process.env.DEBUG;
+  } else {
+    process.env.DEBUG = namespaces;
+  }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+  var stream;
+  var tty_wrap = process.binding('tty_wrap');
+
+  // Note stream._type is used for test-module-load-list.js
+
+  switch (tty_wrap.guessHandleType(fd)) {
+    case 'TTY':
+      stream = new tty.WriteStream(fd);
+      stream._type = 'tty';
+
+      // Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    case 'FILE':
+      var fs = require('fs');
+      stream = new fs.SyncWriteStream(fd, { autoClose: false });
+      stream._type = 'fs';
+      break;
+
+    case 'PIPE':
+    case 'TCP':
+      var net = require('net');
+      stream = new net.Socket({
+        fd: fd,
+        readable: false,
+        writable: true
+      });
+
+      // FIXME Should probably have an option in net.Socket to create a
+      // stream from an existing fd which is writable only. But for now
+      // we'll just add this hack and set the `readable` member to false.
+      // Test: ./node test/fixtures/echo.js < /etc/passwd
+      stream.readable = false;
+      stream.read = null;
+      stream._type = 'pipe';
+
+      // FIXME Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    default:
+      // Probably an error on in uv_guess_handle()
+      throw new Error('Implement me. Unknown stream file type!');
+  }
+
+  // For supporting legacy API we put the FD here.
+  stream.fd = fd;
+
+  stream._isStdio = true;
+
+  return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+  debug.inspectOpts = {};
+
+  var keys = Object.keys(exports.inspectOpts);
+  for (var i = 0; i < keys.length; i++) {
+    debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+  }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/ms/index.js b/input_devices/mag/node_modules/choices-separator/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+  options = options || {};
+  var type = typeof val;
+  if (type === 'string' && val.length > 0) {
+    return parse(val);
+  } else if (type === 'number' && isNaN(val) === false) {
+    return options.long ? fmtLong(val) : fmtShort(val);
+  }
+  throw new Error(
+    'val is not a non-empty string or a valid number. val=' +
+      JSON.stringify(val)
+  );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  str = String(str);
+  if (str.length > 100) {
+    return;
+  }
+  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+    str
+  );
+  if (!match) {
+    return;
+  }
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'yrs':
+    case 'yr':
+    case 'y':
+      return n * y;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'hrs':
+    case 'hr':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'mins':
+    case 'min':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 'secs':
+    case 'sec':
+    case 's':
+      return n * s;
+    case 'milliseconds':
+    case 'millisecond':
+    case 'msecs':
+    case 'msec':
+    case 'ms':
+      return n;
+    default:
+      return undefined;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+  if (ms >= d) {
+    return Math.round(ms / d) + 'd';
+  }
+  if (ms >= h) {
+    return Math.round(ms / h) + 'h';
+  }
+  if (ms >= m) {
+    return Math.round(ms / m) + 'm';
+  }
+  if (ms >= s) {
+    return Math.round(ms / s) + 's';
+  }
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+  return plural(ms, d, 'day') ||
+    plural(ms, h, 'hour') ||
+    plural(ms, m, 'minute') ||
+    plural(ms, s, 'second') ||
+    ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+  if (ms < n) {
+    return;
+  }
+  if (ms < n * 1.5) {
+    return Math.floor(ms / n) + ' ' + name;
+  }
+  return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/ms/license.md b/input_devices/mag/node_modules/choices-separator/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/input_devices/mag/node_modules/choices-separator/node_modules/ms/package.json b/input_devices/mag/node_modules/choices-separator/node_modules/ms/package.json
new file mode 100644
index 00000000..906b0331
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/ms/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "ms@2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/choices-separator/node_modules/debug"
+    ]
+  ],
+  "_from": "ms@2.0.0",
+  "_id": "ms@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/choices-separator/ms",
+  "_nodeVersion": "7.8.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945"
+  },
+  "_npmUser": {
+    "email": "leo@zeit.co",
+    "name": "leo"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ms",
+    "raw": "ms@2.0.0",
+    "rawSpec": "2.0.0",
+    "scope": null,
+    "spec": "2.0.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/choices-separator/debug"
+  ],
+  "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+  "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+  "_shrinkwrap": null,
+  "_spec": "ms@2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/choices-separator/node_modules/debug",
+  "bugs": {
+    "url": "https://github.com/zeit/ms/issues"
+  },
+  "dependencies": {},
+  "description": "Tiny milisecond conversion utility",
+  "devDependencies": {
+    "eslint": "3.19.0",
+    "expect.js": "0.3.1",
+    "husky": "0.13.3",
+    "lint-staged": "3.4.1",
+    "mocha": "3.4.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+    "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
+  },
+  "eslintConfig": {
+    "env": {
+      "es6": true,
+      "node": true
+    },
+    "extends": "eslint:recommended"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4",
+  "homepage": "https://github.com/zeit/ms#readme",
+  "license": "MIT",
+  "lint-staged": {
+    "*.js": [
+      "git add",
+      "npm run lint",
+      "prettier --single-quote --write"
+    ]
+  },
+  "main": "./index",
+  "maintainers": [
+    {
+      "name": "leo",
+      "email": "leo@zeit.co"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "name": "ms",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zeit/ms.git"
+  },
+  "scripts": {
+    "lint": "eslint lib/* bin/*",
+    "precommit": "lint-staged",
+    "test": "mocha tests.js"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/choices-separator/node_modules/ms/readme.md b/input_devices/mag/node_modules/choices-separator/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days')  // 172800000
+ms('1d')      // 86400000
+ms('10h')     // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h')      // 7200000
+ms('1m')      // 60000
+ms('5s')      // 5000
+ms('1y')      // 31557600000
+ms('100')     // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000)             // "1m"
+ms(2 * 60000)         // "2m"
+ms(ms('10 hours'))    // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true })             // "1 minute"
+ms(2 * 60000, { long: true })         // "2 minutes"
+ms(ms('10 hours'), { long: true })    // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/input_devices/mag/node_modules/choices-separator/package.json b/input_devices/mag/node_modules/choices-separator/package.json
new file mode 100644
index 00000000..6061d74d
--- /dev/null
+++ b/input_devices/mag/node_modules/choices-separator/package.json
@@ -0,0 +1,136 @@
+{
+  "_args": [
+    [
+      "choices-separator@^2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "choices-separator@>=2.0.0 <3.0.0",
+  "_id": "choices-separator@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/choices-separator",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/choices-separator-2.0.0.tgz_1495026751582_0.16359598701819777"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.5.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "choices-separator",
+    "raw": "choices-separator@^2.0.0",
+    "rawSpec": "^2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/choices-separator/-/choices-separator-2.0.0.tgz",
+  "_shasum": "92fd1763182d79033f5c5c51d0ba352e5567c696",
+  "_shrinkwrap": null,
+  "_spec": "choices-separator@^2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/choices-separator/issues"
+  },
+  "dependencies": {
+    "ansi-dim": "^0.1.1",
+    "debug": "^2.6.6",
+    "strip-color": "^0.1.0"
+  },
+  "description": "Separator for choices arrays in prompts. Based on the Separator from inquirer.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.3.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "92fd1763182d79033f5c5c51d0ba352e5567c696",
+    "tarball": "https://registry.npmjs.org/choices-separator/-/choices-separator-2.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "6a756f5ed71db26c0bd53a174971811e1bd59081",
+  "homepage": "https://github.com/enquirer/choices-separator",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "checkbox",
+    "choice",
+    "choices",
+    "cli",
+    "command",
+    "enquirer",
+    "enquirerprompt",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "password",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "separator",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "choices-separator",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/choices-separator.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "enquirer"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/chownr/LICENSE b/input_devices/mag/node_modules/chownr/LICENSE
new file mode 100644
index 00000000..19129e31
--- /dev/null
+++ b/input_devices/mag/node_modules/chownr/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/chownr/README.md b/input_devices/mag/node_modules/chownr/README.md
new file mode 100644
index 00000000..70e9a54a
--- /dev/null
+++ b/input_devices/mag/node_modules/chownr/README.md
@@ -0,0 +1,3 @@
+Like `chown -R`.
+
+Takes the same arguments as `fs.chown()`
diff --git a/input_devices/mag/node_modules/chownr/chownr.js b/input_devices/mag/node_modules/chownr/chownr.js
new file mode 100644
index 00000000..7e639288
--- /dev/null
+++ b/input_devices/mag/node_modules/chownr/chownr.js
@@ -0,0 +1,88 @@
+'use strict'
+const fs = require('fs')
+const path = require('path')
+
+/* istanbul ignore next */
+const LCHOWN = fs.lchown ? 'lchown' : 'chown'
+/* istanbul ignore next */
+const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync'
+
+// fs.readdir could only accept an options object as of node v6
+const nodeVersion = process.version
+let readdir = (path, options, cb) => fs.readdir(path, options, cb)
+let readdirSync = (path, options) => fs.readdirSync(path, options)
+/* istanbul ignore next */
+if (/^v4\./.test(nodeVersion))
+  readdir = (path, options, cb) => fs.readdir(path, cb)
+
+const chownrKid = (p, child, uid, gid, cb) => {
+  if (typeof child === 'string')
+    return fs.lstat(path.resolve(p, child), (er, stats) => {
+      if (er)
+        return cb(er)
+      stats.name = child
+      chownrKid(p, stats, uid, gid, cb)
+    })
+
+  if (child.isDirectory()) {
+    chownr(path.resolve(p, child.name), uid, gid, er => {
+      if (er)
+        return cb(er)
+      fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb)
+    })
+  } else
+    fs[LCHOWN](path.resolve(p, child.name), uid, gid, cb)
+}
+
+
+const chownr = (p, uid, gid, cb) => {
+  readdir(p, { withFileTypes: true }, (er, children) => {
+    // any error other than ENOTDIR or ENOTSUP means it's not readable,
+    // or doesn't exist.  give up.
+    if (er && er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP')
+      return cb(er)
+    if (er || !children.length) return fs[LCHOWN](p, uid, gid, cb)
+
+    let len = children.length
+    let errState = null
+    const then = er => {
+      if (errState) return
+      if (er) return cb(errState = er)
+      if (-- len === 0) return fs[LCHOWN](p, uid, gid, cb)
+    }
+
+    children.forEach(child => chownrKid(p, child, uid, gid, then))
+  })
+}
+
+const chownrKidSync = (p, child, uid, gid) => {
+  if (typeof child === 'string') {
+    const stats = fs.lstatSync(path.resolve(p, child))
+    stats.name = child
+    child = stats
+  }
+
+  if (child.isDirectory())
+    chownrSync(path.resolve(p, child.name), uid, gid)
+
+  fs[LCHOWNSYNC](path.resolve(p, child.name), uid, gid)
+}
+
+const chownrSync = (p, uid, gid) => {
+  let children
+  try {
+    children = readdirSync(p, { withFileTypes: true })
+  } catch (er) {
+    if (er && er.code === 'ENOTDIR' && er.code !== 'ENOTSUP')
+      return fs[LCHOWNSYNC](p, uid, gid)
+    throw er
+  }
+
+  if (children.length)
+    children.forEach(child => chownrKidSync(p, child, uid, gid))
+
+  return fs[LCHOWNSYNC](p, uid, gid)
+}
+
+module.exports = chownr
+chownr.sync = chownrSync
diff --git a/input_devices/mag/node_modules/chownr/package.json b/input_devices/mag/node_modules/chownr/package.json
new file mode 100644
index 00000000..2b6b0a9e
--- /dev/null
+++ b/input_devices/mag/node_modules/chownr/package.json
@@ -0,0 +1,89 @@
+{
+  "_args": [
+    [
+      "chownr@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-fs"
+    ]
+  ],
+  "_from": "chownr@>=1.0.1 <2.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "chownr@1.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/chownr",
+  "_nodeVersion": "10.10.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/chownr_1.1.1_1537067648822_0.8733677031057796"
+  },
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "6.4.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "chownr",
+    "raw": "chownr@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-fs"
+  ],
+  "_resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+  "_shasum": "54726b8b8fff4df053c42187e801fb4412df1494",
+  "_shrinkwrap": null,
+  "_spec": "chownr@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-fs",
+  "author": {
+    "email": "i@izs.me",
+    "name": "Isaac Z. Schlueter",
+    "url": "http://blog.izs.me/"
+  },
+  "bugs": {
+    "url": "https://github.com/isaacs/chownr/issues"
+  },
+  "dependencies": {},
+  "description": "like `chown -R`",
+  "devDependencies": {
+    "mkdirp": "0.3",
+    "rimraf": "",
+    "tap": "^12.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbncqBCRA9TVsSAnZWagAAzhUP/1pR2jFff+rVryKPm7jF\nc+IGuZPRxl4qLEjUSNSuVmq+eSWK3zMwSm+59eyI/+ArsjZvtIEi9TUo5ddV\n9vwa64C57bjTcbsSJgHUK+N+8qWggo3nXHYUhFUyVgaVihvVt4LUYPhWFpp2\nzjDdysskuD3hIkcsRPN7123OZwvl9NXU5E/DFmZJ95Jz0tVrABhE5GptOSab\nK69de/oz7tK+3tFAcApq1xNYfzkPSEQscQum+sleV56SEaEUQJfQzJC4iccM\nK7DjBNGkdH+japMi2vD9je2Jo5949wXBgOgjcZmoSgzb2gWivB4HcGeYh/fS\n5yX2CLCy0VOFdkK6C1bxIzxHQEqALY1pnPos1HkXSJMvzWdhNnq+n62IPOh9\n8MXEf0fUOdDfKSwAyOphtWmfu7Wy9gUrYDg4rHPDTQjGDM+mvIIMxMIwmQ0k\nsOOZMdXaaKf3tXtqNUT1j96hgVBTQ7X8/HrXxPuQI9hBrh4CdR7TekZFZ0NG\nrkiNT5fEGwpEz0EeiNlMkaNPkw+hvg6nTFp+0tePyWPC1weMlNCbhm4jipHt\nKl9t8ox+bsoKH/UviCYjC3XfJSEGqBpaox7i8Pjvcp25s4p9FwNiExE0pe2I\nvbWrbGEVL8lsoCJi84uI2n5PBcOyN51srZmWI6P9EU1nYzDPF/B2Z0N8yw5K\n8ks4\r\n=wIis\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "54726b8b8fff4df053c42187e801fb4412df1494",
+    "tarball": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+    "unpackedSize": 3901
+  },
+  "gitHead": "7a5c3d57c3691eebb9c66fa00fa6003d02ef9440",
+  "homepage": "https://github.com/isaacs/chownr#readme",
+  "license": "ISC",
+  "main": "chownr.js",
+  "maintainers": [
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    }
+  ],
+  "name": "chownr",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/chownr.git"
+  },
+  "scripts": {
+    "postpublish": "git push origin --all; git push origin --tags",
+    "postversion": "npm publish",
+    "preversion": "npm test",
+    "test": "tap test/*.js --cov"
+  },
+  "version": "1.1.1"
+}
diff --git a/input_devices/mag/node_modules/clone-deep/LICENSE b/input_devices/mag/node_modules/clone-deep/LICENSE
new file mode 100644
index 00000000..943e71d0
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/clone-deep/README.md b/input_devices/mag/node_modules/clone-deep/README.md
new file mode 100644
index 00000000..5986cbc4
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/README.md
@@ -0,0 +1,84 @@
+# clone-deep [![NPM version](https://img.shields.io/npm/v/clone-deep.svg?style=flat)](https://www.npmjs.com/package/clone-deep) [![NPM monthly downloads](https://img.shields.io/npm/dm/clone-deep.svg?style=flat)](https://npmjs.org/package/clone-deep) [![NPM total downloads](https://img.shields.io/npm/dt/clone-deep.svg?style=flat)](https://npmjs.org/package/clone-deep) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/clone-deep.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/clone-deep)
+
+> Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save clone-deep
+```
+
+## Usage
+
+```js
+var cloneDeep = require('clone-deep');
+
+var obj = {a: 'b'};
+var arr = [obj];
+
+var copy = cloneDeep(arr);
+obj.c = 'd';
+
+console.log(copy);
+//=> [{a: 'b'}]
+
+console.log(arr);
+//=> [{a: 'b', c: 'd'}]
+```
+
+## Heads up!
+
+The `instanceClone` function is invoked to clone objects that are not "plain" objects (as defined by [isPlainObject](#isPlainObject)`isPlainObject`) if it is provided. If `instanceClone` is not specified, it will not attempt to clone non-plain objects, and will copy the object reference.
+
+## Attribution
+
+Based on [mout's](https://github.com/mout/mout) implementation of deepClone.
+
+## About
+
+### Related projects
+
+* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+* [shallow-clone](https://www.npmjs.com/package/shallow-clone): Make a shallow clone of an object, array or primitive. | [homepage](https://github.com/jonschlinkert/shallow-clone "Make a shallow clone of an object, array or primitive.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 16, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/clone-deep/index.js b/input_devices/mag/node_modules/clone-deep/index.js
new file mode 100644
index 00000000..1697b2bf
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/index.js
@@ -0,0 +1,55 @@
+'use strict';
+
+/**
+ * Module dependenices
+ */
+
+var isObject = require('is-plain-object');
+var clone = require('shallow-clone');
+var typeOf = require('kind-of');
+var forOwn = require('for-own');
+
+/**
+ * Recursively clone native types.
+ */
+
+function cloneDeep(val, instanceClone) {
+  switch (typeOf(val)) {
+    case 'object':
+      return cloneObjectDeep(val, instanceClone);
+    case 'array':
+      return cloneArrayDeep(val, instanceClone);
+    default: {
+      return clone(val);
+    }
+  }
+}
+
+function cloneObjectDeep(obj, instanceClone) {
+  if (isObject(obj)) {
+    var res = {};
+    forOwn(obj, function(obj, key) {
+      this[key] = cloneDeep(obj, instanceClone);
+    }, res);
+    return res;
+  } else if (instanceClone) {
+    return instanceClone(obj);
+  } else {
+    return obj;
+  }
+}
+
+function cloneArrayDeep(arr, instanceClone) {
+  var len = arr.length, res = [];
+  var i = -1;
+  while (++i < len) {
+    res[i] = cloneDeep(arr[i], instanceClone);
+  }
+  return res;
+}
+
+/**
+ * Expose `cloneDeep`
+ */
+
+module.exports = cloneDeep;
diff --git a/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/README.md b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/README.md
new file mode 100644
index 00000000..170bf304
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/README.md
@@ -0,0 +1,342 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Release history
+
+### v4.0.0
+
+**Added**
+
+* `promise` support
+
+### v5.0.0
+
+**Added**
+
+* `Set Iterator` and `Map Iterator` support
+
+**Fixed**
+
+* Now returns `generatorfunction` for generator functions
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of is more correct than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly tests instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+<details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+<details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+<details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 82 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike](https://github.com/charlike) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on October 13, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/index.js b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/index.js
new file mode 100644
index 00000000..fc5cde96
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/index.js
@@ -0,0 +1,147 @@
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  var type = typeof val;
+
+  // primitivies
+  if (type === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (type === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (type === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (type === 'function' || val instanceof Function) {
+    if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') {
+      return 'generatorfunction';
+    }
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+  if (type === '[object Promise]') {
+    return 'promise';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+  
+  if (type === '[object Map Iterator]') {
+    return 'mapiterator';
+  }
+  if (type === '[object Set Iterator]') {
+    return 'setiterator';
+  }
+  if (type === '[object String Iterator]') {
+    return 'stringiterator';
+  }
+  if (type === '[object Array Iterator]') {
+    return 'arrayiterator';
+  }
+  
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  return val.constructor
+    && typeof val.constructor.isBuffer === 'function'
+    && val.constructor.isBuffer(val);
+}
diff --git a/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/package.json b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/package.json
new file mode 100644
index 00000000..590ecd04
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/node_modules/kind-of/package.json
@@ -0,0 +1,179 @@
+{
+  "_args": [
+    [
+      "kind-of@^5.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep"
+    ]
+  ],
+  "_from": "kind-of@>=5.0.0 <6.0.0",
+  "_id": "kind-of@5.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/clone-deep/kind-of",
+  "_nodeVersion": "8.7.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-5.1.0.tgz_1507878225264_0.114781056297943"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.4.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^5.0.0",
+    "rawSpec": "^5.0.0",
+    "scope": null,
+    "spec": ">=5.0.0 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/clone-deep"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+  "_shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^5.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.1.1",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^0.1.12",
+    "matched": "^0.4.4",
+    "mocha": "^3.4.2",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+    "shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ed479b6ee194dc1edff852f17095ae1de40bafbc",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "5.1.0"
+}
diff --git a/input_devices/mag/node_modules/clone-deep/package.json b/input_devices/mag/node_modules/clone-deep/package.json
new file mode 100644
index 00000000..ebb5c465
--- /dev/null
+++ b/input_devices/mag/node_modules/clone-deep/package.json
@@ -0,0 +1,137 @@
+{
+  "_args": [
+    [
+      "clone-deep@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question"
+    ]
+  ],
+  "_from": "clone-deep@>=1.0.0 <2.0.0",
+  "_id": "clone-deep@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/clone-deep",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/clone-deep-1.0.0.tgz_1500207488086_0.801335611147806"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "clone-deep",
+    "raw": "clone-deep@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-question"
+  ],
+  "_resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-1.0.0.tgz",
+  "_shasum": "b2f354444b5d4a0ce58faca337ef34da2b14a6c7",
+  "_shrinkwrap": null,
+  "_spec": "clone-deep@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/clone-deep/issues"
+  },
+  "dependencies": {
+    "for-own": "^1.0.0",
+    "is-plain-object": "^2.0.4",
+    "kind-of": "^5.0.0",
+    "shallow-clone": "^1.0.0"
+  },
+  "description": "Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.4.2"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-hmJRX8x1QOJVV+GUjOBzi6iauhPqc9hIF6xitWRBbiPZOBb6vGo/mDRIK9P74RTKSQK7AE8B0DDWY/vpRrPmQw==",
+    "shasum": "b2f354444b5d4a0ce58faca337ef34da2b14a6c7",
+    "tarball": "https://registry.npmjs.org/clone-deep/-/clone-deep-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "b033c5671c6a807b8b32bc2a1f66287482d3aee4",
+  "homepage": "https://github.com/jonschlinkert/clone-deep",
+  "keywords": [
+    "array",
+    "clone",
+    "clone-array",
+    "clone-array-deep",
+    "clone-date",
+    "clone-deep",
+    "clone-object",
+    "clone-object-deep",
+    "clone-reg-exp",
+    "date",
+    "deep",
+    "exp",
+    "for",
+    "for-in",
+    "for-own",
+    "javascript",
+    "mixin",
+    "mixin-object",
+    "object",
+    "own",
+    "reg",
+    "util",
+    "utility"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "clone-deep",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/clone-deep.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-plain-object",
+        "isobject",
+        "kind-of",
+        "shallow-clone"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/code-point-at/index.js b/input_devices/mag/node_modules/code-point-at/index.js
new file mode 100644
index 00000000..0432fe6a
--- /dev/null
+++ b/input_devices/mag/node_modules/code-point-at/index.js
@@ -0,0 +1,32 @@
+/* eslint-disable babel/new-cap, xo/throw-new-error */
+'use strict';
+module.exports = function (str, pos) {
+	if (str === null || str === undefined) {
+		throw TypeError();
+	}
+
+	str = String(str);
+
+	var size = str.length;
+	var i = pos ? Number(pos) : 0;
+
+	if (Number.isNaN(i)) {
+		i = 0;
+	}
+
+	if (i < 0 || i >= size) {
+		return undefined;
+	}
+
+	var first = str.charCodeAt(i);
+
+	if (first >= 0xD800 && first <= 0xDBFF && size > i + 1) {
+		var second = str.charCodeAt(i + 1);
+
+		if (second >= 0xDC00 && second <= 0xDFFF) {
+			return ((first - 0xD800) * 0x400) + second - 0xDC00 + 0x10000;
+		}
+	}
+
+	return first;
+};
diff --git a/input_devices/mag/node_modules/code-point-at/license b/input_devices/mag/node_modules/code-point-at/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/code-point-at/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/code-point-at/package.json b/input_devices/mag/node_modules/code-point-at/package.json
new file mode 100644
index 00000000..3df32ef3
--- /dev/null
+++ b/input_devices/mag/node_modules/code-point-at/package.json
@@ -0,0 +1,98 @@
+{
+  "_args": [
+    [
+      "code-point-at@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/string-width"
+    ]
+  ],
+  "_from": "code-point-at@>=1.0.0 <2.0.0",
+  "_id": "code-point-at@1.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/code-point-at",
+  "_nodeVersion": "4.6.1",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/code-point-at-1.1.0.tgz_1478169780337_0.8445875702891499"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.15.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "code-point-at",
+    "raw": "code-point-at@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/string-width"
+  ],
+  "_resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+  "_shasum": "0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77",
+  "_shrinkwrap": null,
+  "_spec": "code-point-at@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/string-width",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/code-point-at/issues"
+  },
+  "dependencies": {},
+  "description": "ES2015 `String#codePointAt()` ponyfill",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "^0.16.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77",
+    "tarball": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "f8f21c8df2d40248fef1b36ca9076e59c0c34791",
+  "homepage": "https://github.com/sindresorhus/code-point-at#readme",
+  "keywords": [
+    "at",
+    "code",
+    "codepoint",
+    "es2015",
+    "point",
+    "polyfill",
+    "ponyfill",
+    "shim",
+    "str",
+    "string",
+    "unicode"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "code-point-at",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/code-point-at.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "1.1.0"
+}
diff --git a/input_devices/mag/node_modules/code-point-at/readme.md b/input_devices/mag/node_modules/code-point-at/readme.md
new file mode 100644
index 00000000..4c97730e
--- /dev/null
+++ b/input_devices/mag/node_modules/code-point-at/readme.md
@@ -0,0 +1,32 @@
+# code-point-at [![Build Status](https://travis-ci.org/sindresorhus/code-point-at.svg?branch=master)](https://travis-ci.org/sindresorhus/code-point-at)
+
+> ES2015 [`String#codePointAt()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt) [ponyfill](https://ponyfill.com)
+
+
+## Install
+
+```
+$ npm install --save code-point-at
+```
+
+
+## Usage
+
+```js
+var codePointAt = require('code-point-at');
+
+codePointAt('🐴');
+//=> 128052
+
+codePointAt('abc', 2);
+//=> 99
+```
+
+## API
+
+### codePointAt(input, [position])
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/collection-visit/LICENSE b/input_devices/mag/node_modules/collection-visit/LICENSE
new file mode 100644
index 00000000..ec85897e
--- /dev/null
+++ b/input_devices/mag/node_modules/collection-visit/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, 2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/collection-visit/README.md b/input_devices/mag/node_modules/collection-visit/README.md
new file mode 100644
index 00000000..c4da3f18
--- /dev/null
+++ b/input_devices/mag/node_modules/collection-visit/README.md
@@ -0,0 +1,89 @@
+# collection-visit [![NPM version](https://img.shields.io/npm/v/collection-visit.svg?style=flat)](https://www.npmjs.com/package/collection-visit) [![NPM monthly downloads](https://img.shields.io/npm/dm/collection-visit.svg?style=flat)](https://npmjs.org/package/collection-visit)  [![NPM total downloads](https://img.shields.io/npm/dt/collection-visit.svg?style=flat)](https://npmjs.org/package/collection-visit) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/collection-visit.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/collection-visit)
+
+> Visit a method over the items in an object, or map visit over the objects in an array.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save collection-visit
+```
+
+## Usage
+
+```js
+var visit = require('collection-visit');
+
+var ctx = {
+  data: {},
+  set: function (key, value) {
+    if (typeof key === 'object') {
+      visit(ctx, 'set', key);
+    } else {
+      ctx.data[key] = value;
+    }
+  }
+};
+
+ctx.set('a', 'a');
+ctx.set('b', 'b');
+ctx.set('c', 'c');
+ctx.set({d: {e: 'f'}});
+
+console.log(ctx.data);
+//=> {a: 'a', b: 'b', c: 'c', d: { e: 'f' }};
+```
+
+## About
+
+### Related projects
+
+* [base-methods](https://www.npmjs.com/package/base-methods): base-methods is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting… [more](https://github.com/jonschlinkert/base-methods) | [homepage](https://github.com/jonschlinkert/base-methods "base-methods is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting with a handful of common methods, like `set`, `get`, `del` and `use`.")
+* [map-visit](https://www.npmjs.com/package/map-visit): Map `visit` over an array of objects. | [homepage](https://github.com/jonschlinkert/map-visit "Map `visit` over an array of objects.")
+* [object-visit](https://www.npmjs.com/package/object-visit): Call a specified method on each value in the given object. | [homepage](https://github.com/jonschlinkert/object-visit "Call a specified method on each value in the given object.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 13 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 9 | [doowb](https://github.com/doowb) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.5.0, on April 09, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/collection-visit/index.js b/input_devices/mag/node_modules/collection-visit/index.js
new file mode 100644
index 00000000..d1977ab2
--- /dev/null
+++ b/input_devices/mag/node_modules/collection-visit/index.js
@@ -0,0 +1,30 @@
+/*!
+ * collection-visit <https://github.com/jonschlinkert/collection-visit>
+ *
+ * Copyright (c) 2015, 2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var visit = require('object-visit');
+var mapVisit = require('map-visit');
+
+module.exports = function(collection, method, val) {
+  var result;
+
+  if (typeof val === 'string' && (method in collection)) {
+    var args = [].slice.call(arguments, 2);
+    result = collection[method].apply(collection, args);
+  } else if (Array.isArray(val)) {
+    result = mapVisit.apply(null, arguments);
+  } else {
+    result = visit.apply(null, arguments);
+  }
+
+  if (typeof result !== 'undefined') {
+    return result;
+  }
+
+  return collection;
+};
diff --git a/input_devices/mag/node_modules/collection-visit/package.json b/input_devices/mag/node_modules/collection-visit/package.json
new file mode 100644
index 00000000..8e27da8f
--- /dev/null
+++ b/input_devices/mag/node_modules/collection-visit/package.json
@@ -0,0 +1,146 @@
+{
+  "_args": [
+    [
+      "collection-visit@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "collection-visit@>=1.0.0 <2.0.0",
+  "_id": "collection-visit@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/collection-visit",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/collection-visit-1.0.0.tgz_1491775229437_0.10189219401217997"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.1.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "collection-visit",
+    "raw": "collection-visit@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+  "_shasum": "4bc0373c164bc3291b4d368c829cf1a80a59dca0",
+  "_shrinkwrap": null,
+  "_spec": "collection-visit@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/collection-visit/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "email": "brian.woodward@gmail.com",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "map-visit": "^1.0.0",
+    "object-visit": "^1.0.0"
+  },
+  "description": "Visit a method over the items in an object, or map visit over the objects in an array.",
+  "devDependencies": {
+    "clone-deep": "^0.2.4",
+    "gulp": "^3.9.1",
+    "gulp-eslint": "^3.0.1",
+    "gulp-format-md": "^0.1.12",
+    "gulp-istanbul": "^1.1.1",
+    "gulp-mocha": "^3.0.0",
+    "mocha": "^3.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "4bc0373c164bc3291b4d368c829cf1a80a59dca0",
+    "tarball": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "39c229dceb7e124cb821b59668df5da1d5c81a6c",
+  "homepage": "https://github.com/jonschlinkert/collection-visit",
+  "keywords": [
+    "array",
+    "arrays",
+    "collection",
+    "context",
+    "function",
+    "helper",
+    "invoke",
+    "key",
+    "map",
+    "method",
+    "object",
+    "objects",
+    "value",
+    "visit",
+    "visitor"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "collection-visit",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/collection-visit.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "base-methods",
+        "map-visit",
+        "object-visit"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/commander/CHANGELOG.md b/input_devices/mag/node_modules/commander/CHANGELOG.md
new file mode 100644
index 00000000..fd4f69c9
--- /dev/null
+++ b/input_devices/mag/node_modules/commander/CHANGELOG.md
@@ -0,0 +1,396 @@
+
+2.19.0 / 2018-10-02
+==================
+
+  * Removed newline after Options and Commands headers (#864)
+  * Bugfix - Error output (#862)
+  * Fix to change default value to string (#856)
+
+2.18.0 / 2018-09-07
+==================
+
+  * Standardize help output (#853)
+  * chmod 644 travis.yml (#851)
+  * add support for execute typescript subcommand via ts-node (#849)
+
+2.17.1 / 2018-08-07
+==================
+
+  * Fix bug in command emit (#844)
+
+2.17.0 / 2018-08-03
+==================
+
+  * fixed newline output after help information (#833)
+  * Fix to emit the action even without command (#778)
+  * npm update (#823)
+
+2.16.0 / 2018-06-29
+==================
+
+  * Remove Makefile and `test/run` (#821)
+  * Make 'npm test' run on Windows (#820)
+  * Add badge to display install size (#807)
+  * chore: cache node_modules (#814)
+  * chore: remove Node.js 4 (EOL), add Node.js 10 (#813)
+  * fixed typo in readme (#812)
+  * Fix types (#804)
+  * Update eslint to resolve vulnerabilities in lodash (#799)
+  * updated readme with custom event listeners. (#791)
+  * fix tests (#794)
+
+2.15.0 / 2018-03-07
+==================
+
+  * Update downloads badge to point to graph of downloads over time instead of duplicating link to npm
+  * Arguments description
+
+2.14.1 / 2018-02-07
+==================
+
+  * Fix typing of help function
+
+2.14.0 / 2018-02-05
+==================
+
+  * only register the option:version event once
+  * Fixes issue #727: Passing empty string for option on command is set to undefined
+  * enable eqeqeq rule
+  * resolves #754 add linter configuration to project
+  * resolves #560 respect custom name for version option
+  * document how to override the version flag
+  * document using options per command
+
+2.13.0 / 2018-01-09
+==================
+
+  * Do not print default for --no-
+  * remove trailing spaces in command help
+  * Update CI's Node.js to LTS and latest version
+  * typedefs: Command and Option types added to commander namespace
+
+2.12.2 / 2017-11-28
+==================
+
+  * fix: typings are not shipped
+
+2.12.1 / 2017-11-23
+==================
+
+  * Move @types/node to dev dependency
+
+2.12.0 / 2017-11-22
+==================
+
+  * add attributeName() method to Option objects
+  * Documentation updated for options with --no prefix
+  * typings: `outputHelp` takes a string as the first parameter
+  * typings: use overloads
+  * feat(typings): update to match js api
+  * Print default value in option help
+  * Fix translation error
+  * Fail when using same command and alias (#491)
+  * feat(typings): add help callback
+  * fix bug when description is add after command with options (#662)
+  * Format js code
+  * Rename History.md to CHANGELOG.md (#668)
+  * feat(typings): add typings to support TypeScript (#646)
+  * use current node
+
+2.11.0 / 2017-07-03
+==================
+
+  * Fix help section order and padding (#652)
+  * feature: support for signals to subcommands (#632)
+  * Fixed #37, --help should not display first (#447)
+  * Fix translation errors. (#570)
+  * Add package-lock.json
+  * Remove engines
+  * Upgrade package version
+  * Prefix events to prevent conflicts between commands and options (#494)
+  * Removing dependency on graceful-readlink
+  * Support setting name in #name function and make it chainable
+  * Add .vscode directory to .gitignore (Visual Studio Code metadata)
+  * Updated link to ruby commander in readme files
+
+2.10.0 / 2017-06-19
+==================
+
+  * Update .travis.yml. drop support for older node.js versions.
+  * Fix require arguments in README.md
+  * On SemVer you do not start from 0.0.1
+  * Add missing semi colon in readme
+  * Add save param to npm install
+  * node v6 travis test
+  * Update Readme_zh-CN.md
+  * Allow literal '--' to be passed-through as an argument
+  * Test subcommand alias help
+  * link build badge to master branch
+  * Support the alias of Git style sub-command
+  * added keyword commander for better search result on npm
+  * Fix Sub-Subcommands
+  * test node.js stable
+  * Fixes TypeError when a command has an option called `--description`
+  * Update README.md to make it beginner friendly and elaborate on the difference between angled and square brackets.
+  * Add chinese Readme file
+
+2.9.0 / 2015-10-13
+==================
+
+  * Add option `isDefault` to set default subcommand #415 @Qix-
+  * Add callback to allow filtering or post-processing of help text #434 @djulien
+  * Fix `undefined` text in help information close #414 #416 @zhiyelee
+
+2.8.1 / 2015-04-22
+==================
+
+ * Back out `support multiline description` Close #396 #397
+
+2.8.0 / 2015-04-07
+==================
+
+  * Add `process.execArg` support, execution args like `--harmony` will be passed to sub-commands #387 @DigitalIO @zhiyelee
+  * Fix bug in Git-style sub-commands #372 @zhiyelee
+  * Allow commands to be hidden from help #383 @tonylukasavage
+  * When git-style sub-commands are in use, yet none are called, display help #382 @claylo
+  * Add ability to specify arguments syntax for top-level command #258 @rrthomas
+  * Support multiline descriptions #208 @zxqfox
+
+2.7.1 / 2015-03-11
+==================
+
+ * Revert #347 (fix collisions when option and first arg have same name) which causes a bug in #367.
+
+2.7.0 / 2015-03-09
+==================
+
+ * Fix git-style bug when installed globally. Close #335 #349 @zhiyelee
+ * Fix collisions when option and first arg have same name. Close #346 #347 @tonylukasavage
+ * Add support for camelCase on `opts()`. Close #353  @nkzawa
+ * Add node.js 0.12 and io.js to travis.yml
+ * Allow RegEx options. #337 @palanik
+ * Fixes exit code when sub-command failing.  Close #260 #332 @pirelenito
+ * git-style `bin` files in $PATH make sense. Close #196 #327  @zhiyelee
+
+2.6.0 / 2014-12-30
+==================
+
+  * added `Command#allowUnknownOption` method. Close #138 #318 @doozr @zhiyelee
+  * Add application description to the help msg. Close #112 @dalssoft
+
+2.5.1 / 2014-12-15
+==================
+
+  * fixed two bugs incurred by variadic arguments. Close #291 @Quentin01 #302 @zhiyelee
+
+2.5.0 / 2014-10-24
+==================
+
+ * add support for variadic arguments. Closes #277 @whitlockjc
+
+2.4.0 / 2014-10-17
+==================
+
+ * fixed a bug on executing the coercion function of subcommands option. Closes #270
+ * added `Command.prototype.name` to retrieve command name. Closes #264 #266 @tonylukasavage
+ * added `Command.prototype.opts` to retrieve all the options as a simple object of key-value pairs. Closes #262 @tonylukasavage
+ * fixed a bug on subcommand name. Closes #248 @jonathandelgado
+ * fixed function normalize doesn’t honor option terminator. Closes #216 @abbr
+
+2.3.0 / 2014-07-16
+==================
+
+ * add command alias'. Closes PR #210
+ * fix: Typos. Closes #99
+ * fix: Unused fs module. Closes #217
+
+2.2.0 / 2014-03-29
+==================
+
+ * add passing of previous option value
+ * fix: support subcommands on windows. Closes #142
+ * Now the defaultValue passed as the second argument of the coercion function.
+
+2.1.0 / 2013-11-21
+==================
+
+ * add: allow cflag style option params, unit test, fixes #174
+
+2.0.0 / 2013-07-18
+==================
+
+ * remove input methods (.prompt, .confirm, etc)
+
+1.3.2 / 2013-07-18
+==================
+
+ * add support for sub-commands to co-exist with the original command
+
+1.3.1 / 2013-07-18
+==================
+
+ * add quick .runningCommand hack so you can opt-out of other logic when running a sub command
+
+1.3.0 / 2013-07-09
+==================
+
+ * add EACCES error handling
+ * fix sub-command --help
+
+1.2.0 / 2013-06-13
+==================
+
+ * allow "-" hyphen as an option argument
+ * support for RegExp coercion
+
+1.1.1 / 2012-11-20
+==================
+
+  * add more sub-command padding
+  * fix .usage() when args are present. Closes #106
+
+1.1.0 / 2012-11-16
+==================
+
+  * add git-style executable subcommand support. Closes #94
+
+1.0.5 / 2012-10-09
+==================
+
+  * fix `--name` clobbering. Closes #92
+  * fix examples/help. Closes #89
+
+1.0.4 / 2012-09-03
+==================
+
+  * add `outputHelp()` method.
+
+1.0.3 / 2012-08-30
+==================
+
+  * remove invalid .version() defaulting
+
+1.0.2 / 2012-08-24
+==================
+
+  * add `--foo=bar` support [arv]
+  * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus]
+
+1.0.1 / 2012-08-03
+==================
+
+  * fix issue #56
+  * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode())
+
+1.0.0 / 2012-07-05
+==================
+
+  * add support for optional option descriptions
+  * add defaulting of `.version()` to package.json's version
+
+0.6.1 / 2012-06-01
+==================
+
+  * Added: append (yes or no) on confirmation
+  * Added: allow node.js v0.7.x
+
+0.6.0 / 2012-04-10
+==================
+
+  * Added `.prompt(obj, callback)` support. Closes #49
+  * Added default support to .choose(). Closes #41
+  * Fixed the choice example
+
+0.5.1 / 2011-12-20
+==================
+
+  * Fixed `password()` for recent nodes. Closes #36
+
+0.5.0 / 2011-12-04
+==================
+
+  * Added sub-command option support [itay]
+
+0.4.3 / 2011-12-04
+==================
+
+  * Fixed custom help ordering. Closes #32
+
+0.4.2 / 2011-11-24
+==================
+
+  * Added travis support
+  * Fixed: line-buffered input automatically trimmed. Closes #31
+
+0.4.1 / 2011-11-18
+==================
+
+  * Removed listening for "close" on --help
+
+0.4.0 / 2011-11-15
+==================
+
+  * Added support for `--`. Closes #24
+
+0.3.3 / 2011-11-14
+==================
+
+  * Fixed: wait for close event when writing help info [Jerry Hamlet]
+
+0.3.2 / 2011-11-01
+==================
+
+  * Fixed long flag definitions with values [felixge]
+
+0.3.1 / 2011-10-31
+==================
+
+  * Changed `--version` short flag to `-V` from `-v`
+  * Changed `.version()` so it's configurable [felixge]
+
+0.3.0 / 2011-10-31
+==================
+
+  * Added support for long flags only. Closes #18
+
+0.2.1 / 2011-10-24
+==================
+
+  * "node": ">= 0.4.x < 0.7.0". Closes #20
+
+0.2.0 / 2011-09-26
+==================
+
+  * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]
+
+0.1.0 / 2011-08-24
+==================
+
+  * Added support for custom `--help` output
+
+0.0.5 / 2011-08-18
+==================
+
+  * Changed: when the user enters nothing prompt for password again
+  * Fixed issue with passwords beginning with numbers [NuckChorris]
+
+0.0.4 / 2011-08-15
+==================
+
+  * Fixed `Commander#args`
+
+0.0.3 / 2011-08-15
+==================
+
+  * Added default option value support
+
+0.0.2 / 2011-08-15
+==================
+
+  * Added mask support to `Command#password(str[, mask], fn)`
+  * Added `Command#password(str, fn)`
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/commander/LICENSE b/input_devices/mag/node_modules/commander/LICENSE
new file mode 100644
index 00000000..10f997ab
--- /dev/null
+++ b/input_devices/mag/node_modules/commander/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/commander/Readme.md b/input_devices/mag/node_modules/commander/Readme.md
new file mode 100644
index 00000000..a2a15473
--- /dev/null
+++ b/input_devices/mag/node_modules/commander/Readme.md
@@ -0,0 +1,417 @@
+# Commander.js
+
+
+[![Build Status](https://api.travis-ci.org/tj/commander.js.svg?branch=master)](http://travis-ci.org/tj/commander.js)
+[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
+[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://npmcharts.com/compare/commander?minimal=true)
+[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander)
+[![Join the chat at https://gitter.im/tj/commander.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tj/commander.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+  The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/commander-rb/commander).  
+  [API documentation](http://tj.github.com/commander.js/)
+
+
+## Installation
+
+    $ npm install commander --save
+
+## Option parsing
+
+Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.
+
+```js
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var program = require('commander');
+
+program
+  .version('0.1.0')
+  .option('-p, --peppers', 'Add peppers')
+  .option('-P, --pineapple', 'Add pineapple')
+  .option('-b, --bbq-sauce', 'Add bbq sauce')
+  .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
+  .parse(process.argv);
+
+console.log('you ordered a pizza with:');
+if (program.peppers) console.log('  - peppers');
+if (program.pineapple) console.log('  - pineapple');
+if (program.bbqSauce) console.log('  - bbq');
+console.log('  - %s cheese', program.cheese);
+```
+
+Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc.
+
+Note that multi-word options starting with `--no` prefix negate the boolean value of the following word. For example, `--no-sauce` sets the value of `program.sauce` to false.
+
+```js
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var program = require('commander');
+
+program
+  .option('--no-sauce', 'Remove sauce')
+  .parse(process.argv);
+
+console.log('you ordered a pizza');
+if (program.sauce) console.log('  with sauce');
+else console.log(' without sauce');
+```
+
+## Version option
+
+Calling the `version` implicitly adds the `-V` and `--version` options to the command.
+When either of these options is present, the command prints the version number and exits.
+
+    $ ./examples/pizza -V
+    0.0.1
+
+If you want your program to respond to the `-v` option instead of the `-V` option, simply pass custom flags to the `version` method using the same syntax as the `option` method.
+
+```js
+program
+  .version('0.0.1', '-v, --version')
+```
+
+The version flags can be named anything, but the long option is required.
+
+## Command-specific options
+
+You can attach options to a command.
+
+```js
+#!/usr/bin/env node
+
+var program = require('commander');
+
+program
+  .command('rm <dir>')
+  .option('-r, --recursive', 'Remove recursively')
+  .action(function (dir, cmd) {
+    console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
+  })
+
+program.parse(process.argv)
+```
+
+A command's options are validated when the command is used. Any unknown options will be reported as an error. However, if an action-based command does not define an action, then the options are not validated.
+
+## Coercion
+
+```js
+function range(val) {
+  return val.split('..').map(Number);
+}
+
+function list(val) {
+  return val.split(',');
+}
+
+function collect(val, memo) {
+  memo.push(val);
+  return memo;
+}
+
+function increaseVerbosity(v, total) {
+  return total + 1;
+}
+
+program
+  .version('0.1.0')
+  .usage('[options] <file ...>')
+  .option('-i, --integer <n>', 'An integer argument', parseInt)
+  .option('-f, --float <n>', 'A float argument', parseFloat)
+  .option('-r, --range <a>..<b>', 'A range', range)
+  .option('-l, --list <items>', 'A list', list)
+  .option('-o, --optional [value]', 'An optional value')
+  .option('-c, --collect [value]', 'A repeatable value', collect, [])
+  .option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0)
+  .parse(process.argv);
+
+console.log(' int: %j', program.integer);
+console.log(' float: %j', program.float);
+console.log(' optional: %j', program.optional);
+program.range = program.range || [];
+console.log(' range: %j..%j', program.range[0], program.range[1]);
+console.log(' list: %j', program.list);
+console.log(' collect: %j', program.collect);
+console.log(' verbosity: %j', program.verbose);
+console.log(' args: %j', program.args);
+```
+
+## Regular Expression
+```js
+program
+  .version('0.1.0')
+  .option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium')
+  .option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i)
+  .parse(process.argv);
+
+console.log(' size: %j', program.size);
+console.log(' drink: %j', program.drink);
+```
+
+## Variadic arguments
+
+ The last argument of a command can be variadic, and only the last argument.  To make an argument variadic you have to
+ append `...` to the argument name.  Here is an example:
+
+```js
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var program = require('commander');
+
+program
+  .version('0.1.0')
+  .command('rmdir <dir> [otherDirs...]')
+  .action(function (dir, otherDirs) {
+    console.log('rmdir %s', dir);
+    if (otherDirs) {
+      otherDirs.forEach(function (oDir) {
+        console.log('rmdir %s', oDir);
+      });
+    }
+  });
+
+program.parse(process.argv);
+```
+
+ An `Array` is used for the value of a variadic argument.  This applies to `program.args` as well as the argument passed
+ to your action as demonstrated above.
+
+## Specify the argument syntax
+
+```js
+#!/usr/bin/env node
+
+var program = require('commander');
+
+program
+  .version('0.1.0')
+  .arguments('<cmd> [env]')
+  .action(function (cmd, env) {
+     cmdValue = cmd;
+     envValue = env;
+  });
+
+program.parse(process.argv);
+
+if (typeof cmdValue === 'undefined') {
+   console.error('no command given!');
+   process.exit(1);
+}
+console.log('command:', cmdValue);
+console.log('environment:', envValue || "no environment given");
+```
+Angled brackets (e.g. `<cmd>`) indicate required input. Square brackets (e.g. `[env]`) indicate optional input.
+
+## Git-style sub-commands
+
+```js
+// file: ./examples/pm
+var program = require('commander');
+
+program
+  .version('0.1.0')
+  .command('install [name]', 'install one or more packages')
+  .command('search [query]', 'search with optional query')
+  .command('list', 'list packages installed', {isDefault: true})
+  .parse(process.argv);
+```
+
+When `.command()` is invoked with a description argument, no `.action(callback)` should be called to handle sub-commands, otherwise there will be an error. This tells commander that you're going to use separate executables for sub-commands, much like `git(1)` and other popular tools.  
+The commander will try to search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-command`, like `pm-install`, `pm-search`.
+
+Options can be passed with the call to `.command()`. Specifying `true` for `opts.noHelp` will remove the subcommand from the generated help output. Specifying `true` for `opts.isDefault` will run the subcommand if no other subcommand is specified.
+
+If the program is designed to be installed globally, make sure the executables have proper modes, like `755`.
+
+### `--harmony`
+
+You can enable `--harmony` option in two ways:
+* Use `#! /usr/bin/env node --harmony` in the sub-commands scripts. Note some os version don’t support this pattern.
+* Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning sub-command process.
+
+## Automated --help
+
+ The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:
+
+```  
+$ ./examples/pizza --help
+Usage: pizza [options]
+
+An application for pizzas ordering
+
+Options:
+  -h, --help           output usage information
+  -V, --version        output the version number
+  -p, --peppers        Add peppers
+  -P, --pineapple      Add pineapple
+  -b, --bbq            Add bbq sauce
+  -c, --cheese <type>  Add the specified type of cheese [marble]
+  -C, --no-cheese      You do not want any cheese
+```
+
+## Custom help
+
+ You can display arbitrary `-h, --help` information
+ by listening for "--help". Commander will automatically
+ exit once you are done so that the remainder of your program
+ does not execute causing undesired behaviors, for example
+ in the following executable "stuff" will not output when
+ `--help` is used.
+
+```js
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var program = require('commander');
+
+program
+  .version('0.1.0')
+  .option('-f, --foo', 'enable some foo')
+  .option('-b, --bar', 'enable some bar')
+  .option('-B, --baz', 'enable some baz');
+
+// must be before .parse() since
+// node's emit() is immediate
+
+program.on('--help', function(){
+  console.log('')
+  console.log('Examples:');
+  console.log('  $ custom-help --help');
+  console.log('  $ custom-help -h');
+});
+
+program.parse(process.argv);
+
+console.log('stuff');
+```
+
+Yields the following help output when `node script-name.js -h` or `node script-name.js --help` are run:
+
+```
+Usage: custom-help [options]
+
+Options:
+  -h, --help     output usage information
+  -V, --version  output the version number
+  -f, --foo      enable some foo
+  -b, --bar      enable some bar
+  -B, --baz      enable some baz
+
+Examples:
+  $ custom-help --help
+  $ custom-help -h
+```
+
+## .outputHelp(cb)
+
+Output help information without exiting.
+Optional callback cb allows post-processing of help text before it is displayed.
+
+If you want to display help by default (e.g. if no command was provided), you can use something like:
+
+```js
+var program = require('commander');
+var colors = require('colors');
+
+program
+  .version('0.1.0')
+  .command('getstream [url]', 'get stream URL')
+  .parse(process.argv);
+
+if (!process.argv.slice(2).length) {
+  program.outputHelp(make_red);
+}
+
+function make_red(txt) {
+  return colors.red(txt); //display the help text in red on the console
+}
+```
+
+## .help(cb)
+
+  Output help information and exit immediately.
+  Optional callback cb allows post-processing of help text before it is displayed.
+
+
+## Custom event listeners
+ You can execute custom actions by listening to command and option events.
+
+```js
+program.on('option:verbose', function () {
+  process.env.VERBOSE = this.verbose;
+});
+
+// error on unknown commands
+program.on('command:*', function () {
+  console.error('Invalid command: %s\nSee --help for a list of available commands.', program.args.join(' '));
+  process.exit(1);
+});
+```
+
+## Examples
+
+```js
+var program = require('commander');
+
+program
+  .version('0.1.0')
+  .option('-C, --chdir <path>', 'change the working directory')
+  .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
+  .option('-T, --no-tests', 'ignore test hook');
+
+program
+  .command('setup [env]')
+  .description('run setup commands for all envs')
+  .option("-s, --setup_mode [mode]", "Which setup mode to use")
+  .action(function(env, options){
+    var mode = options.setup_mode || "normal";
+    env = env || 'all';
+    console.log('setup for %s env(s) with %s mode', env, mode);
+  });
+
+program
+  .command('exec <cmd>')
+  .alias('ex')
+  .description('execute the given remote cmd')
+  .option("-e, --exec_mode <mode>", "Which exec mode to use")
+  .action(function(cmd, options){
+    console.log('exec "%s" using %s mode', cmd, options.exec_mode);
+  }).on('--help', function() {
+    console.log('');
+    console.log('Examples:');
+    console.log('');
+    console.log('  $ deploy exec sequential');
+    console.log('  $ deploy exec async');
+  });
+
+program
+  .command('*')
+  .action(function(env){
+    console.log('deploying "%s"', env);
+  });
+
+program.parse(process.argv);
+```
+
+More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/commander/index.js b/input_devices/mag/node_modules/commander/index.js
new file mode 100644
index 00000000..bf039c90
--- /dev/null
+++ b/input_devices/mag/node_modules/commander/index.js
@@ -0,0 +1,1227 @@
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter;
+var spawn = require('child_process').spawn;
+var path = require('path');
+var dirname = path.dirname;
+var basename = path.basename;
+var fs = require('fs');
+
+/**
+ * Inherit `Command` from `EventEmitter.prototype`.
+ */
+
+require('util').inherits(Command, EventEmitter);
+
+/**
+ * Expose the root command.
+ */
+
+exports = module.exports = new Command();
+
+/**
+ * Expose `Command`.
+ */
+
+exports.Command = Command;
+
+/**
+ * Expose `Option`.
+ */
+
+exports.Option = Option;
+
+/**
+ * Initialize a new `Option` with the given `flags` and `description`.
+ *
+ * @param {String} flags
+ * @param {String} description
+ * @api public
+ */
+
+function Option(flags, description) {
+  this.flags = flags;
+  this.required = flags.indexOf('<') >= 0;
+  this.optional = flags.indexOf('[') >= 0;
+  this.bool = flags.indexOf('-no-') === -1;
+  flags = flags.split(/[ ,|]+/);
+  if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift();
+  this.long = flags.shift();
+  this.description = description || '';
+}
+
+/**
+ * Return option name.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Option.prototype.name = function() {
+  return this.long
+    .replace('--', '')
+    .replace('no-', '');
+};
+
+/**
+ * Return option name, in a camelcase format that can be used
+ * as a object attribute key.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Option.prototype.attributeName = function() {
+  return camelcase(this.name());
+};
+
+/**
+ * Check if `arg` matches the short or long flag.
+ *
+ * @param {String} arg
+ * @return {Boolean}
+ * @api private
+ */
+
+Option.prototype.is = function(arg) {
+  return this.short === arg || this.long === arg;
+};
+
+/**
+ * Initialize a new `Command`.
+ *
+ * @param {String} name
+ * @api public
+ */
+
+function Command(name) {
+  this.commands = [];
+  this.options = [];
+  this._execs = {};
+  this._allowUnknownOption = false;
+  this._args = [];
+  this._name = name || '';
+}
+
+/**
+ * Add command `name`.
+ *
+ * The `.action()` callback is invoked when the
+ * command `name` is specified via __ARGV__,
+ * and the remaining arguments are applied to the
+ * function for access.
+ *
+ * When the `name` is "*" an un-matched command
+ * will be passed as the first arg, followed by
+ * the rest of __ARGV__ remaining.
+ *
+ * Examples:
+ *
+ *      program
+ *        .version('0.0.1')
+ *        .option('-C, --chdir <path>', 'change the working directory')
+ *        .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
+ *        .option('-T, --no-tests', 'ignore test hook')
+ *
+ *      program
+ *        .command('setup')
+ *        .description('run remote setup commands')
+ *        .action(function() {
+ *          console.log('setup');
+ *        });
+ *
+ *      program
+ *        .command('exec <cmd>')
+ *        .description('run the given remote command')
+ *        .action(function(cmd) {
+ *          console.log('exec "%s"', cmd);
+ *        });
+ *
+ *      program
+ *        .command('teardown <dir> [otherDirs...]')
+ *        .description('run teardown commands')
+ *        .action(function(dir, otherDirs) {
+ *          console.log('dir "%s"', dir);
+ *          if (otherDirs) {
+ *            otherDirs.forEach(function (oDir) {
+ *              console.log('dir "%s"', oDir);
+ *            });
+ *          }
+ *        });
+ *
+ *      program
+ *        .command('*')
+ *        .description('deploy the given env')
+ *        .action(function(env) {
+ *          console.log('deploying "%s"', env);
+ *        });
+ *
+ *      program.parse(process.argv);
+  *
+ * @param {String} name
+ * @param {String} [desc] for git-style sub-commands
+ * @return {Command} the new command
+ * @api public
+ */
+
+Command.prototype.command = function(name, desc, opts) {
+  if (typeof desc === 'object' && desc !== null) {
+    opts = desc;
+    desc = null;
+  }
+  opts = opts || {};
+  var args = name.split(/ +/);
+  var cmd = new Command(args.shift());
+
+  if (desc) {
+    cmd.description(desc);
+    this.executables = true;
+    this._execs[cmd._name] = true;
+    if (opts.isDefault) this.defaultExecutable = cmd._name;
+  }
+  cmd._noHelp = !!opts.noHelp;
+  this.commands.push(cmd);
+  cmd.parseExpectedArgs(args);
+  cmd.parent = this;
+
+  if (desc) return this;
+  return cmd;
+};
+
+/**
+ * Define argument syntax for the top-level command.
+ *
+ * @api public
+ */
+
+Command.prototype.arguments = function(desc) {
+  return this.parseExpectedArgs(desc.split(/ +/));
+};
+
+/**
+ * Add an implicit `help [cmd]` subcommand
+ * which invokes `--help` for the given command.
+ *
+ * @api private
+ */
+
+Command.prototype.addImplicitHelpCommand = function() {
+  this.command('help [cmd]', 'display help for [cmd]');
+};
+
+/**
+ * Parse expected `args`.
+ *
+ * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
+ *
+ * @param {Array} args
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.parseExpectedArgs = function(args) {
+  if (!args.length) return;
+  var self = this;
+  args.forEach(function(arg) {
+    var argDetails = {
+      required: false,
+      name: '',
+      variadic: false
+    };
+
+    switch (arg[0]) {
+      case '<':
+        argDetails.required = true;
+        argDetails.name = arg.slice(1, -1);
+        break;
+      case '[':
+        argDetails.name = arg.slice(1, -1);
+        break;
+    }
+
+    if (argDetails.name.length > 3 && argDetails.name.slice(-3) === '...') {
+      argDetails.variadic = true;
+      argDetails.name = argDetails.name.slice(0, -3);
+    }
+    if (argDetails.name) {
+      self._args.push(argDetails);
+    }
+  });
+  return this;
+};
+
+/**
+ * Register callback `fn` for the command.
+ *
+ * Examples:
+ *
+ *      program
+ *        .command('help')
+ *        .description('display verbose help')
+ *        .action(function() {
+ *           // output help here
+ *        });
+ *
+ * @param {Function} fn
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.action = function(fn) {
+  var self = this;
+  var listener = function(args, unknown) {
+    // Parse any so-far unknown options
+    args = args || [];
+    unknown = unknown || [];
+
+    var parsed = self.parseOptions(unknown);
+
+    // Output help if necessary
+    outputHelpIfNecessary(self, parsed.unknown);
+
+    // If there are still any unknown options, then we simply
+    // die, unless someone asked for help, in which case we give it
+    // to them, and then we die.
+    if (parsed.unknown.length > 0) {
+      self.unknownOption(parsed.unknown[0]);
+    }
+
+    // Leftover arguments need to be pushed back. Fixes issue #56
+    if (parsed.args.length) args = parsed.args.concat(args);
+
+    self._args.forEach(function(arg, i) {
+      if (arg.required && args[i] == null) {
+        self.missingArgument(arg.name);
+      } else if (arg.variadic) {
+        if (i !== self._args.length - 1) {
+          self.variadicArgNotLast(arg.name);
+        }
+
+        args[i] = args.splice(i);
+      }
+    });
+
+    // Always append ourselves to the end of the arguments,
+    // to make sure we match the number of arguments the user
+    // expects
+    if (self._args.length) {
+      args[self._args.length] = self;
+    } else {
+      args.push(self);
+    }
+
+    fn.apply(self, args);
+  };
+  var parent = this.parent || this;
+  var name = parent === this ? '*' : this._name;
+  parent.on('command:' + name, listener);
+  if (this._alias) parent.on('command:' + this._alias, listener);
+  return this;
+};
+
+/**
+ * Define option with `flags`, `description` and optional
+ * coercion `fn`.
+ *
+ * The `flags` string should contain both the short and long flags,
+ * separated by comma, a pipe or space. The following are all valid
+ * all will output this way when `--help` is used.
+ *
+ *    "-p, --pepper"
+ *    "-p|--pepper"
+ *    "-p --pepper"
+ *
+ * Examples:
+ *
+ *     // simple boolean defaulting to false
+ *     program.option('-p, --pepper', 'add pepper');
+ *
+ *     --pepper
+ *     program.pepper
+ *     // => Boolean
+ *
+ *     // simple boolean defaulting to true
+ *     program.option('-C, --no-cheese', 'remove cheese');
+ *
+ *     program.cheese
+ *     // => true
+ *
+ *     --no-cheese
+ *     program.cheese
+ *     // => false
+ *
+ *     // required argument
+ *     program.option('-C, --chdir <path>', 'change the working directory');
+ *
+ *     --chdir /tmp
+ *     program.chdir
+ *     // => "/tmp"
+ *
+ *     // optional argument
+ *     program.option('-c, --cheese [type]', 'add cheese [marble]');
+ *
+ * @param {String} flags
+ * @param {String} description
+ * @param {Function|*} [fn] or default
+ * @param {*} [defaultValue]
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.option = function(flags, description, fn, defaultValue) {
+  var self = this,
+    option = new Option(flags, description),
+    oname = option.name(),
+    name = option.attributeName();
+
+  // default as 3rd arg
+  if (typeof fn !== 'function') {
+    if (fn instanceof RegExp) {
+      var regex = fn;
+      fn = function(val, def) {
+        var m = regex.exec(val);
+        return m ? m[0] : def;
+      };
+    } else {
+      defaultValue = fn;
+      fn = null;
+    }
+  }
+
+  // preassign default value only for --no-*, [optional], or <required>
+  if (!option.bool || option.optional || option.required) {
+    // when --no-* we make sure default is true
+    if (!option.bool) defaultValue = true;
+    // preassign only if we have a default
+    if (defaultValue !== undefined) {
+      self[name] = defaultValue;
+      option.defaultValue = defaultValue;
+    }
+  }
+
+  // register the option
+  this.options.push(option);
+
+  // when it's passed assign the value
+  // and conditionally invoke the callback
+  this.on('option:' + oname, function(val) {
+    // coercion
+    if (val !== null && fn) {
+      val = fn(val, self[name] === undefined ? defaultValue : self[name]);
+    }
+
+    // unassigned or bool
+    if (typeof self[name] === 'boolean' || typeof self[name] === 'undefined') {
+      // if no value, bool true, and we have a default, then use it!
+      if (val == null) {
+        self[name] = option.bool
+          ? defaultValue || true
+          : false;
+      } else {
+        self[name] = val;
+      }
+    } else if (val !== null) {
+      // reassign
+      self[name] = val;
+    }
+  });
+
+  return this;
+};
+
+/**
+ * Allow unknown options on the command line.
+ *
+ * @param {Boolean} arg if `true` or omitted, no error will be thrown
+ * for unknown options.
+ * @api public
+ */
+Command.prototype.allowUnknownOption = function(arg) {
+  this._allowUnknownOption = arguments.length === 0 || arg;
+  return this;
+};
+
+/**
+ * Parse `argv`, settings options and invoking commands when defined.
+ *
+ * @param {Array} argv
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.parse = function(argv) {
+  // implicit help
+  if (this.executables) this.addImplicitHelpCommand();
+
+  // store raw args
+  this.rawArgs = argv;
+
+  // guess name
+  this._name = this._name || basename(argv[1], '.js');
+
+  // github-style sub-commands with no sub-command
+  if (this.executables && argv.length < 3 && !this.defaultExecutable) {
+    // this user needs help
+    argv.push('--help');
+  }
+
+  // process argv
+  var parsed = this.parseOptions(this.normalize(argv.slice(2)));
+  var args = this.args = parsed.args;
+
+  var result = this.parseArgs(this.args, parsed.unknown);
+
+  // executable sub-commands
+  var name = result.args[0];
+
+  var aliasCommand = null;
+  // check alias of sub commands
+  if (name) {
+    aliasCommand = this.commands.filter(function(command) {
+      return command.alias() === name;
+    })[0];
+  }
+
+  if (this._execs[name] && typeof this._execs[name] !== 'function') {
+    return this.executeSubCommand(argv, args, parsed.unknown);
+  } else if (aliasCommand) {
+    // is alias of a subCommand
+    args[0] = aliasCommand._name;
+    return this.executeSubCommand(argv, args, parsed.unknown);
+  } else if (this.defaultExecutable) {
+    // use the default subcommand
+    args.unshift(this.defaultExecutable);
+    return this.executeSubCommand(argv, args, parsed.unknown);
+  }
+
+  return result;
+};
+
+/**
+ * Execute a sub-command executable.
+ *
+ * @param {Array} argv
+ * @param {Array} args
+ * @param {Array} unknown
+ * @api private
+ */
+
+Command.prototype.executeSubCommand = function(argv, args, unknown) {
+  args = args.concat(unknown);
+
+  if (!args.length) this.help();
+  if (args[0] === 'help' && args.length === 1) this.help();
+
+  // <cmd> --help
+  if (args[0] === 'help') {
+    args[0] = args[1];
+    args[1] = '--help';
+  }
+
+  // executable
+  var f = argv[1];
+  // name of the subcommand, link `pm-install`
+  var bin = basename(f, path.extname(f)) + '-' + args[0];
+
+  // In case of globally installed, get the base dir where executable
+  //  subcommand file should be located at
+  var baseDir,
+    link = fs.lstatSync(f).isSymbolicLink() ? fs.readlinkSync(f) : f;
+
+  // when symbolink is relative path
+  if (link !== f && link.charAt(0) !== '/') {
+    link = path.join(dirname(f), link);
+  }
+  baseDir = dirname(link);
+
+  // prefer local `./<bin>` to bin in the $PATH
+  var localBin = path.join(baseDir, bin);
+
+  // whether bin file is a js script with explicit `.js` or `.ts` extension
+  var isExplicitJS = false;
+  if (exists(localBin + '.js')) {
+    bin = localBin + '.js';
+    isExplicitJS = true;
+  } else if (exists(localBin + '.ts')) {
+    bin = localBin + '.ts';
+    isExplicitJS = true;
+  } else if (exists(localBin)) {
+    bin = localBin;
+  }
+
+  args = args.slice(1);
+
+  var proc;
+  if (process.platform !== 'win32') {
+    if (isExplicitJS) {
+      args.unshift(bin);
+      // add executable arguments to spawn
+      args = (process.execArgv || []).concat(args);
+
+      proc = spawn(process.argv[0], args, { stdio: 'inherit', customFds: [0, 1, 2] });
+    } else {
+      proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] });
+    }
+  } else {
+    args.unshift(bin);
+    proc = spawn(process.execPath, args, { stdio: 'inherit' });
+  }
+
+  var signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];
+  signals.forEach(function(signal) {
+    process.on(signal, function() {
+      if (proc.killed === false && proc.exitCode === null) {
+        proc.kill(signal);
+      }
+    });
+  });
+  proc.on('close', process.exit.bind(process));
+  proc.on('error', function(err) {
+    if (err.code === 'ENOENT') {
+      console.error('error: %s(1) does not exist, try --help', bin);
+    } else if (err.code === 'EACCES') {
+      console.error('error: %s(1) not executable. try chmod or run with root', bin);
+    }
+    process.exit(1);
+  });
+
+  // Store the reference to the child process
+  this.runningCommand = proc;
+};
+
+/**
+ * Normalize `args`, splitting joined short flags. For example
+ * the arg "-abc" is equivalent to "-a -b -c".
+ * This also normalizes equal sign and splits "--abc=def" into "--abc def".
+ *
+ * @param {Array} args
+ * @return {Array}
+ * @api private
+ */
+
+Command.prototype.normalize = function(args) {
+  var ret = [],
+    arg,
+    lastOpt,
+    index;
+
+  for (var i = 0, len = args.length; i < len; ++i) {
+    arg = args[i];
+    if (i > 0) {
+      lastOpt = this.optionFor(args[i - 1]);
+    }
+
+    if (arg === '--') {
+      // Honor option terminator
+      ret = ret.concat(args.slice(i));
+      break;
+    } else if (lastOpt && lastOpt.required) {
+      ret.push(arg);
+    } else if (arg.length > 1 && arg[0] === '-' && arg[1] !== '-') {
+      arg.slice(1).split('').forEach(function(c) {
+        ret.push('-' + c);
+      });
+    } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) {
+      ret.push(arg.slice(0, index), arg.slice(index + 1));
+    } else {
+      ret.push(arg);
+    }
+  }
+
+  return ret;
+};
+
+/**
+ * Parse command `args`.
+ *
+ * When listener(s) are available those
+ * callbacks are invoked, otherwise the "*"
+ * event is emitted and those actions are invoked.
+ *
+ * @param {Array} args
+ * @return {Command} for chaining
+ * @api private
+ */
+
+Command.prototype.parseArgs = function(args, unknown) {
+  var name;
+
+  if (args.length) {
+    name = args[0];
+    if (this.listeners('command:' + name).length) {
+      this.emit('command:' + args.shift(), args, unknown);
+    } else {
+      this.emit('command:*', args);
+    }
+  } else {
+    outputHelpIfNecessary(this, unknown);
+
+    // If there were no args and we have unknown options,
+    // then they are extraneous and we need to error.
+    if (unknown.length > 0) {
+      this.unknownOption(unknown[0]);
+    }
+    if (this.commands.length === 0 &&
+        this._args.filter(function(a) { return a.required }).length === 0) {
+      this.emit('command:*');
+    }
+  }
+
+  return this;
+};
+
+/**
+ * Return an option matching `arg` if any.
+ *
+ * @param {String} arg
+ * @return {Option}
+ * @api private
+ */
+
+Command.prototype.optionFor = function(arg) {
+  for (var i = 0, len = this.options.length; i < len; ++i) {
+    if (this.options[i].is(arg)) {
+      return this.options[i];
+    }
+  }
+};
+
+/**
+ * Parse options from `argv` returning `argv`
+ * void of these options.
+ *
+ * @param {Array} argv
+ * @return {Array}
+ * @api public
+ */
+
+Command.prototype.parseOptions = function(argv) {
+  var args = [],
+    len = argv.length,
+    literal,
+    option,
+    arg;
+
+  var unknownOptions = [];
+
+  // parse options
+  for (var i = 0; i < len; ++i) {
+    arg = argv[i];
+
+    // literal args after --
+    if (literal) {
+      args.push(arg);
+      continue;
+    }
+
+    if (arg === '--') {
+      literal = true;
+      continue;
+    }
+
+    // find matching Option
+    option = this.optionFor(arg);
+
+    // option is defined
+    if (option) {
+      // requires arg
+      if (option.required) {
+        arg = argv[++i];
+        if (arg == null) return this.optionMissingArgument(option);
+        this.emit('option:' + option.name(), arg);
+      // optional arg
+      } else if (option.optional) {
+        arg = argv[i + 1];
+        if (arg == null || (arg[0] === '-' && arg !== '-')) {
+          arg = null;
+        } else {
+          ++i;
+        }
+        this.emit('option:' + option.name(), arg);
+      // bool
+      } else {
+        this.emit('option:' + option.name());
+      }
+      continue;
+    }
+
+    // looks like an option
+    if (arg.length > 1 && arg[0] === '-') {
+      unknownOptions.push(arg);
+
+      // If the next argument looks like it might be
+      // an argument for this option, we pass it on.
+      // If it isn't, then it'll simply be ignored
+      if ((i + 1) < argv.length && argv[i + 1][0] !== '-') {
+        unknownOptions.push(argv[++i]);
+      }
+      continue;
+    }
+
+    // arg
+    args.push(arg);
+  }
+
+  return { args: args, unknown: unknownOptions };
+};
+
+/**
+ * Return an object containing options as key-value pairs
+ *
+ * @return {Object}
+ * @api public
+ */
+Command.prototype.opts = function() {
+  var result = {},
+    len = this.options.length;
+
+  for (var i = 0; i < len; i++) {
+    var key = this.options[i].attributeName();
+    result[key] = key === this._versionOptionName ? this._version : this[key];
+  }
+  return result;
+};
+
+/**
+ * Argument `name` is missing.
+ *
+ * @param {String} name
+ * @api private
+ */
+
+Command.prototype.missingArgument = function(name) {
+  console.error("error: missing required argument `%s'", name);
+  process.exit(1);
+};
+
+/**
+ * `Option` is missing an argument, but received `flag` or nothing.
+ *
+ * @param {String} option
+ * @param {String} flag
+ * @api private
+ */
+
+Command.prototype.optionMissingArgument = function(option, flag) {
+  if (flag) {
+    console.error("error: option `%s' argument missing, got `%s'", option.flags, flag);
+  } else {
+    console.error("error: option `%s' argument missing", option.flags);
+  }
+  process.exit(1);
+};
+
+/**
+ * Unknown option `flag`.
+ *
+ * @param {String} flag
+ * @api private
+ */
+
+Command.prototype.unknownOption = function(flag) {
+  if (this._allowUnknownOption) return;
+  console.error("error: unknown option `%s'", flag);
+  process.exit(1);
+};
+
+/**
+ * Variadic argument with `name` is not the last argument as required.
+ *
+ * @param {String} name
+ * @api private
+ */
+
+Command.prototype.variadicArgNotLast = function(name) {
+  console.error("error: variadic arguments must be last `%s'", name);
+  process.exit(1);
+};
+
+/**
+ * Set the program version to `str`.
+ *
+ * This method auto-registers the "-V, --version" flag
+ * which will print the version number when passed.
+ *
+ * @param {String} str
+ * @param {String} [flags]
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.version = function(str, flags) {
+  if (arguments.length === 0) return this._version;
+  this._version = str;
+  flags = flags || '-V, --version';
+  var versionOption = new Option(flags, 'output the version number');
+  this._versionOptionName = versionOption.long.substr(2) || 'version';
+  this.options.push(versionOption);
+  this.on('option:' + this._versionOptionName, function() {
+    process.stdout.write(str + '\n');
+    process.exit(0);
+  });
+  return this;
+};
+
+/**
+ * Set the description to `str`.
+ *
+ * @param {String} str
+ * @param {Object} argsDescription
+ * @return {String|Command}
+ * @api public
+ */
+
+Command.prototype.description = function(str, argsDescription) {
+  if (arguments.length === 0) return this._description;
+  this._description = str;
+  this._argsDescription = argsDescription;
+  return this;
+};
+
+/**
+ * Set an alias for the command
+ *
+ * @param {String} alias
+ * @return {String|Command}
+ * @api public
+ */
+
+Command.prototype.alias = function(alias) {
+  var command = this;
+  if (this.commands.length !== 0) {
+    command = this.commands[this.commands.length - 1];
+  }
+
+  if (arguments.length === 0) return command._alias;
+
+  if (alias === command._name) throw new Error('Command alias can\'t be the same as its name');
+
+  command._alias = alias;
+  return this;
+};
+
+/**
+ * Set / get the command usage `str`.
+ *
+ * @param {String} str
+ * @return {String|Command}
+ * @api public
+ */
+
+Command.prototype.usage = function(str) {
+  var args = this._args.map(function(arg) {
+    return humanReadableArgName(arg);
+  });
+
+  var usage = '[options]' +
+    (this.commands.length ? ' [command]' : '') +
+    (this._args.length ? ' ' + args.join(' ') : '');
+
+  if (arguments.length === 0) return this._usage || usage;
+  this._usage = str;
+
+  return this;
+};
+
+/**
+ * Get or set the name of the command
+ *
+ * @param {String} str
+ * @return {String|Command}
+ * @api public
+ */
+
+Command.prototype.name = function(str) {
+  if (arguments.length === 0) return this._name;
+  this._name = str;
+  return this;
+};
+
+/**
+ * Return prepared commands.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+Command.prototype.prepareCommands = function() {
+  return this.commands.filter(function(cmd) {
+    return !cmd._noHelp;
+  }).map(function(cmd) {
+    var args = cmd._args.map(function(arg) {
+      return humanReadableArgName(arg);
+    }).join(' ');
+
+    return [
+      cmd._name +
+        (cmd._alias ? '|' + cmd._alias : '') +
+        (cmd.options.length ? ' [options]' : '') +
+        (args ? ' ' + args : ''),
+      cmd._description
+    ];
+  });
+};
+
+/**
+ * Return the largest command length.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+Command.prototype.largestCommandLength = function() {
+  var commands = this.prepareCommands();
+  return commands.reduce(function(max, command) {
+    return Math.max(max, command[0].length);
+  }, 0);
+};
+
+/**
+ * Return the largest option length.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+Command.prototype.largestOptionLength = function() {
+  var options = [].slice.call(this.options);
+  options.push({
+    flags: '-h, --help'
+  });
+  return options.reduce(function(max, option) {
+    return Math.max(max, option.flags.length);
+  }, 0);
+};
+
+/**
+ * Return the largest arg length.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+Command.prototype.largestArgLength = function() {
+  return this._args.reduce(function(max, arg) {
+    return Math.max(max, arg.name.length);
+  }, 0);
+};
+
+/**
+ * Return the pad width.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+Command.prototype.padWidth = function() {
+  var width = this.largestOptionLength();
+  if (this._argsDescription && this._args.length) {
+    if (this.largestArgLength() > width) {
+      width = this.largestArgLength();
+    }
+  }
+
+  if (this.commands && this.commands.length) {
+    if (this.largestCommandLength() > width) {
+      width = this.largestCommandLength();
+    }
+  }
+
+  return width;
+};
+
+/**
+ * Return help for options.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Command.prototype.optionHelp = function() {
+  var width = this.padWidth();
+
+  // Append the help information
+  return this.options.map(function(option) {
+    return pad(option.flags, width) + '  ' + option.description +
+      ((option.bool && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : '');
+  }).concat([pad('-h, --help', width) + '  ' + 'output usage information'])
+    .join('\n');
+};
+
+/**
+ * Return command help documentation.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Command.prototype.commandHelp = function() {
+  if (!this.commands.length) return '';
+
+  var commands = this.prepareCommands();
+  var width = this.padWidth();
+
+  return [
+    'Commands:',
+    commands.map(function(cmd) {
+      var desc = cmd[1] ? '  ' + cmd[1] : '';
+      return (desc ? pad(cmd[0], width) : cmd[0]) + desc;
+    }).join('\n').replace(/^/gm, '  '),
+    ''
+  ].join('\n');
+};
+
+/**
+ * Return program help documentation.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Command.prototype.helpInformation = function() {
+  var desc = [];
+  if (this._description) {
+    desc = [
+      this._description,
+      ''
+    ];
+
+    var argsDescription = this._argsDescription;
+    if (argsDescription && this._args.length) {
+      var width = this.padWidth();
+      desc.push('Arguments:');
+      desc.push('');
+      this._args.forEach(function(arg) {
+        desc.push('  ' + pad(arg.name, width) + '  ' + argsDescription[arg.name]);
+      });
+      desc.push('');
+    }
+  }
+
+  var cmdName = this._name;
+  if (this._alias) {
+    cmdName = cmdName + '|' + this._alias;
+  }
+  var usage = [
+    'Usage: ' + cmdName + ' ' + this.usage(),
+    ''
+  ];
+
+  var cmds = [];
+  var commandHelp = this.commandHelp();
+  if (commandHelp) cmds = [commandHelp];
+
+  var options = [
+    'Options:',
+    '' + this.optionHelp().replace(/^/gm, '  '),
+    ''
+  ];
+
+  return usage
+    .concat(desc)
+    .concat(options)
+    .concat(cmds)
+    .join('\n');
+};
+
+/**
+ * Output help information for this command
+ *
+ * @api public
+ */
+
+Command.prototype.outputHelp = function(cb) {
+  if (!cb) {
+    cb = function(passthru) {
+      return passthru;
+    };
+  }
+  process.stdout.write(cb(this.helpInformation()));
+  this.emit('--help');
+};
+
+/**
+ * Output help information and exit.
+ *
+ * @api public
+ */
+
+Command.prototype.help = function(cb) {
+  this.outputHelp(cb);
+  process.exit();
+};
+
+/**
+ * Camel-case the given `flag`
+ *
+ * @param {String} flag
+ * @return {String}
+ * @api private
+ */
+
+function camelcase(flag) {
+  return flag.split('-').reduce(function(str, word) {
+    return str + word[0].toUpperCase() + word.slice(1);
+  });
+}
+
+/**
+ * Pad `str` to `width`.
+ *
+ * @param {String} str
+ * @param {Number} width
+ * @return {String}
+ * @api private
+ */
+
+function pad(str, width) {
+  var len = Math.max(0, width - str.length);
+  return str + Array(len + 1).join(' ');
+}
+
+/**
+ * Output help information if necessary
+ *
+ * @param {Command} command to output help for
+ * @param {Array} array of options to search for -h or --help
+ * @api private
+ */
+
+function outputHelpIfNecessary(cmd, options) {
+  options = options || [];
+  for (var i = 0; i < options.length; i++) {
+    if (options[i] === '--help' || options[i] === '-h') {
+      cmd.outputHelp();
+      process.exit(0);
+    }
+  }
+}
+
+/**
+ * Takes an argument an returns its human readable equivalent for help usage.
+ *
+ * @param {Object} arg
+ * @return {String}
+ * @api private
+ */
+
+function humanReadableArgName(arg) {
+  var nameOutput = arg.name + (arg.variadic === true ? '...' : '');
+
+  return arg.required
+    ? '<' + nameOutput + '>'
+    : '[' + nameOutput + ']';
+}
+
+// for versions before node v0.8 when there weren't `fs.existsSync`
+function exists(file) {
+  try {
+    if (fs.statSync(file).isFile()) {
+      return true;
+    }
+  } catch (e) {
+    return false;
+  }
+}
diff --git a/input_devices/mag/node_modules/commander/package.json b/input_devices/mag/node_modules/commander/package.json
new file mode 100644
index 00000000..824b6b7d
--- /dev/null
+++ b/input_devices/mag/node_modules/commander/package.json
@@ -0,0 +1,114 @@
+{
+  "_args": [
+    [
+      "commander@^2.13.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "commander@>=2.13.0 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "commander@2.19.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/commander",
+  "_nodeVersion": "10.11.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/commander_2.19.0_1539035473746_0.9826574892249367"
+  },
+  "_npmUser": {
+    "email": "abe@enzou.tokyo",
+    "name": "abetomo"
+  },
+  "_npmVersion": "6.4.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "commander",
+    "raw": "commander@^2.13.0",
+    "rawSpec": "^2.13.0",
+    "scope": null,
+    "spec": ">=2.13.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
+  "_shasum": "f6198aa84e5b83c46054b94ddedbfed5ee9ff12a",
+  "_shrinkwrap": null,
+  "_spec": "commander@^2.13.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "bugs": {
+    "url": "https://github.com/tj/commander.js/issues"
+  },
+  "dependencies": {},
+  "description": "the complete solution for node.js command-line programs",
+  "devDependencies": {
+    "@types/node": "^10.11.3",
+    "eslint": "^5.6.1",
+    "should": "^13.2.3",
+    "sinon": "^6.3.4",
+    "standard": "^12.0.1",
+    "ts-node": "^7.0.1",
+    "typescript": "^2.9.2"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 6,
+    "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbu9FSCRA9TVsSAnZWagAAc5YQAIADsKVX+3i2QDdUwZzo\nMltfEFOMP1vIiiD0jgsOe6RWO0AwEIBds7dFc4bV4oRoOraZhE5gMAPGd1Y4\n7jekExbT/VYWZYJg+Pg2PppiD5W2PZRS+0LfGiujcyRlpFIsKKc7dUOEQ4Ty\n+htXGTetO5qeYH10dso+9Rel8dsIAKBMQycKS5cuEk4SQC7VjwalM2KJUeC/\noHRzLUtfw64zGGFoshAOWCdsuuMpKvjOiO70mZbmNF0h4Cqd2gZlzdA/XiFi\nM4//gqKcl2hAa6S2Y6cd6vb4P1azv5S2Go2tARL1OBhuI6ooofhAfmfClDl0\n7lfkGwtKkc/c5RgQLAyaBiT73WsAy7bSFW9HPDZNJvO7y4JdI4ZczSi5JeeQ\nt2/Zw5pnOWrIzygMAvhiXC2c8BC8BQ+8CuxuvCkPzonr4F56fC54JR0ANHWa\nRkwvQVWI3C5T1YX21ZzgsvaXaY460sXEksT89stxLfzN0FfFxHnwjRn3crX8\n6RltbIevb2gT8QyGL1WmwMdp94IkBpw+7LfLrEl5o95v8IAJr6k822A/bFiw\nOYAGTJ9OgtEuJd7N8a1kCEkF7u54Yd9YO9vfPkO6SnEMiENW96wuzFBpv3K/\n/M0+4X8VDPXjEsS8wfRhUYYawhhDcE7/I9nnbngbA66V5Ci3d27ASkx0i6XX\nZ798\r\n=7lGM\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "f6198aa84e5b83c46054b94ddedbfed5ee9ff12a",
+    "tarball": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
+    "unpackedSize": 61383
+  },
+  "gitHead": "78b7dbd18aabc23ccc9d151db411913237a3c483",
+  "homepage": "https://github.com/tj/commander.js#readme",
+  "keywords": [
+    "command",
+    "commander",
+    "option",
+    "parser"
+  ],
+  "license": "MIT",
+  "main": "index",
+  "maintainers": [
+    {
+      "name": "abetomo",
+      "email": "abe@enzou.tokyo"
+    },
+    {
+      "name": "somekittens",
+      "email": "rkoutnik@gmail.com"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    },
+    {
+      "name": "vanesyan",
+      "email": "romain.vanesyan@gmail.com"
+    },
+    {
+      "name": "zhiyelee",
+      "email": "zhiyelee@gmail.com"
+    }
+  ],
+  "name": "commander",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/tj/commander.js.git"
+  },
+  "scripts": {
+    "lint": "eslint index.js",
+    "test": "node test/run.js && npm run test-typings",
+    "test-typings": "tsc -p tsconfig.json"
+  },
+  "typings": "typings/index.d.ts",
+  "version": "2.19.0"
+}
diff --git a/input_devices/mag/node_modules/commander/typings/index.d.ts b/input_devices/mag/node_modules/commander/typings/index.d.ts
new file mode 100644
index 00000000..312b056d
--- /dev/null
+++ b/input_devices/mag/node_modules/commander/typings/index.d.ts
@@ -0,0 +1,309 @@
+// Type definitions for commander 2.11
+// Project: https://github.com/visionmedia/commander.js
+// Definitions by: Alan Agius <https://github.com/alan-agius4>, Marcelo Dezem <https://github.com/mdezem>, vvakame <https://github.com/vvakame>, Jules Randolph <https://github.com/sveinburne>
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+declare namespace local {
+
+  class Option {
+    flags: string;
+    required: boolean;
+    optional: boolean;
+    bool: boolean;
+    short?: string;
+    long: string;
+    description: string;
+
+    /**
+     * Initialize a new `Option` with the given `flags` and `description`.
+     *
+     * @param {string} flags
+     * @param {string} [description]
+     */
+    constructor(flags: string, description?: string);
+  }
+
+  class Command extends NodeJS.EventEmitter {
+    [key: string]: any;
+
+    args: string[];
+
+    /**
+     * Initialize a new `Command`.
+     *
+     * @param {string} [name]
+     */
+    constructor(name?: string);
+
+    /**
+     * Set the program version to `str`.
+     *
+     * This method auto-registers the "-V, --version" flag
+     * which will print the version number when passed.
+     *
+     * @param {string} str
+     * @param {string} [flags]
+     * @returns {Command} for chaining
+     */
+    version(str: string, flags?: string): Command;
+
+    /**
+     * Add command `name`.
+     *
+     * The `.action()` callback is invoked when the
+     * command `name` is specified via __ARGV__,
+     * and the remaining arguments are applied to the
+     * function for access.
+     *
+     * When the `name` is "*" an un-matched command
+     * will be passed as the first arg, followed by
+     * the rest of __ARGV__ remaining.
+     *
+     * @example
+     *      program
+     *        .version('0.0.1')
+     *        .option('-C, --chdir <path>', 'change the working directory')
+     *        .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
+     *        .option('-T, --no-tests', 'ignore test hook')
+     *
+     *      program
+     *        .command('setup')
+     *        .description('run remote setup commands')
+     *        .action(function() {
+     *          console.log('setup');
+     *        });
+     *
+     *      program
+     *        .command('exec <cmd>')
+     *        .description('run the given remote command')
+     *        .action(function(cmd) {
+     *          console.log('exec "%s"', cmd);
+     *        });
+     *
+     *      program
+     *        .command('teardown <dir> [otherDirs...]')
+     *        .description('run teardown commands')
+     *        .action(function(dir, otherDirs) {
+     *          console.log('dir "%s"', dir);
+     *          if (otherDirs) {
+     *            otherDirs.forEach(function (oDir) {
+     *              console.log('dir "%s"', oDir);
+     *            });
+     *          }
+     *        });
+     *
+     *      program
+     *        .command('*')
+     *        .description('deploy the given env')
+     *        .action(function(env) {
+     *          console.log('deploying "%s"', env);
+     *        });
+     *
+     *      program.parse(process.argv);
+     *
+     * @param {string} name
+     * @param {string} [desc] for git-style sub-commands
+     * @param {CommandOptions} [opts] command options
+     * @returns {Command} the new command
+     */
+    command(name: string, desc?: string, opts?: commander.CommandOptions): Command;
+
+    /**
+     * Define argument syntax for the top-level command.
+     *
+     * @param {string} desc
+     * @returns {Command} for chaining
+     */
+    arguments(desc: string): Command;
+
+    /**
+     * Parse expected `args`.
+     *
+     * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
+     *
+     * @param {string[]} args
+     * @returns {Command} for chaining
+     */
+    parseExpectedArgs(args: string[]): Command;
+
+    /**
+     * Register callback `fn` for the command.
+     *
+     * @example
+     *      program
+     *        .command('help')
+     *        .description('display verbose help')
+     *        .action(function() {
+     *           // output help here
+     *        });
+     *
+     * @param {(...args: any[]) => void} fn
+     * @returns {Command} for chaining
+     */
+    action(fn: (...args: any[]) => void): Command;
+
+    /**
+     * Define option with `flags`, `description` and optional
+     * coercion `fn`.
+     *
+     * The `flags` string should contain both the short and long flags,
+     * separated by comma, a pipe or space. The following are all valid
+     * all will output this way when `--help` is used.
+     *
+     *    "-p, --pepper"
+     *    "-p|--pepper"
+     *    "-p --pepper"
+     *
+     * @example
+     *     // simple boolean defaulting to false
+     *     program.option('-p, --pepper', 'add pepper');
+     *
+     *     --pepper
+     *     program.pepper
+     *     // => Boolean
+     *
+     *     // simple boolean defaulting to true
+     *     program.option('-C, --no-cheese', 'remove cheese');
+     *
+     *     program.cheese
+     *     // => true
+     *
+     *     --no-cheese
+     *     program.cheese
+     *     // => false
+     *
+     *     // required argument
+     *     program.option('-C, --chdir <path>', 'change the working directory');
+     *
+     *     --chdir /tmp
+     *     program.chdir
+     *     // => "/tmp"
+     *
+     *     // optional argument
+     *     program.option('-c, --cheese [type]', 'add cheese [marble]');
+     *
+     * @param {string} flags
+     * @param {string} [description]
+     * @param {((arg1: any, arg2: any) => void) | RegExp} [fn] function or default
+     * @param {*} [defaultValue]
+     * @returns {Command} for chaining
+     */
+    option(flags: string, description?: string, fn?: ((arg1: any, arg2: any) => void) | RegExp, defaultValue?: any): Command;
+    option(flags: string, description?: string, defaultValue?: any): Command;
+
+    /**
+     * Allow unknown options on the command line.
+     *
+     * @param {boolean} [arg] if `true` or omitted, no error will be thrown for unknown options.
+     * @returns {Command} for chaining
+     */
+    allowUnknownOption(arg?: boolean): Command;
+
+    /**
+     * Parse `argv`, settings options and invoking commands when defined.
+     *
+     * @param {string[]} argv
+     * @returns {Command} for chaining
+     */
+    parse(argv: string[]): Command;
+
+    /**
+     * Parse options from `argv` returning `argv` void of these options.
+     *
+     * @param {string[]} argv
+     * @returns {ParseOptionsResult}
+     */
+    parseOptions(argv: string[]): commander.ParseOptionsResult;
+
+    /**
+     * Return an object containing options as key-value pairs
+     *
+     * @returns {{[key: string]: any}}
+     */
+    opts(): { [key: string]: any };
+
+    /**
+     * Set the description to `str`.
+     *
+     * @param {string} str
+     * @return {(Command | string)}
+     */
+    description(str: string): Command;
+    description(): string;
+
+    /**
+     * Set an alias for the command.
+     *
+     * @param {string} alias
+     * @return {(Command | string)}
+     */
+    alias(alias: string): Command;
+    alias(): string;
+
+    /**
+     * Set or get the command usage.
+     *
+     * @param {string} str
+     * @return {(Command | string)}
+     */
+    usage(str: string): Command;
+    usage(): string;
+
+    /**
+     * Set the name of the command.
+     *
+     * @param {string} str
+     * @return {Command}
+     */
+    name(str: string): Command;
+
+    /**
+     * Get the name of the command.
+     *
+     * @return {string}
+     */
+    name(): string;
+
+    /**
+     * Output help information for this command.
+     *
+     * @param {(str: string) => string} [cb]
+     */
+    outputHelp(cb?: (str: string) => string): void;
+
+    /** Output help information and exit.
+     *
+     * @param {(str: string) => string} [cb]
+     */
+    help(cb?: (str: string) => string): never;
+  }
+
+}
+
+declare namespace commander {
+
+    type Command = local.Command
+
+    type Option = local.Option
+
+    interface CommandOptions {
+        noHelp?: boolean;
+        isDefault?: boolean;
+    }
+
+    interface ParseOptionsResult {
+        args: string[];
+        unknown: string[];
+    }
+
+    interface CommanderStatic extends Command {
+        Command: typeof local.Command;
+        Option: typeof local.Option;
+        CommandOptions: CommandOptions;
+        ParseOptionsResult: ParseOptionsResult;
+    }
+
+}
+
+declare const commander: commander.CommanderStatic;
+export = commander;
diff --git a/input_devices/mag/node_modules/component-emitter/History.md b/input_devices/mag/node_modules/component-emitter/History.md
new file mode 100644
index 00000000..9189c600
--- /dev/null
+++ b/input_devices/mag/node_modules/component-emitter/History.md
@@ -0,0 +1,68 @@
+
+1.2.1 / 2016-04-18
+==================
+
+ * enable client side use
+
+1.2.0 / 2014-02-12
+==================
+
+ * prefix events with `$` to support object prototype method names
+
+1.1.3 / 2014-06-20
+==================
+
+ * republish for npm
+ * add LICENSE file
+
+1.1.2 / 2014-02-10
+==================
+
+  * package: rename to "component-emitter"
+  * package: update "main" and "component" fields
+  * Add license to Readme (same format as the other components)
+  * created .npmignore
+  * travis stuff
+
+1.1.1 / 2013-12-01
+==================
+
+  * fix .once adding .on to the listener
+  * docs: Emitter#off()
+  * component: add `.repo` prop
+
+1.1.0 / 2013-10-20
+==================
+
+ * add `.addEventListener()` and `.removeEventListener()` aliases
+
+1.0.1 / 2013-06-27
+==================
+
+ * add support for legacy ie
+
+1.0.0 / 2013-02-26
+==================
+
+  * add `.off()` support for removing all listeners
+
+0.0.6 / 2012-10-08
+==================
+
+  * add `this._callbacks` initialization to prevent funky gotcha
+
+0.0.5 / 2012-09-07
+==================
+
+  * fix `Emitter.call(this)` usage
+
+0.0.3 / 2012-07-11
+==================
+
+  * add `.listeners()`
+  * rename `.has()` to `.hasListeners()`
+
+0.0.2 / 2012-06-28
+==================
+
+  * fix `.off()` with `.once()`-registered callbacks
diff --git a/input_devices/mag/node_modules/component-emitter/LICENSE b/input_devices/mag/node_modules/component-emitter/LICENSE
new file mode 100644
index 00000000..d6e43f2b
--- /dev/null
+++ b/input_devices/mag/node_modules/component-emitter/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2014 Component contributors <dev@component.io>
+
+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/input_devices/mag/node_modules/component-emitter/Readme.md b/input_devices/mag/node_modules/component-emitter/Readme.md
new file mode 100644
index 00000000..04664111
--- /dev/null
+++ b/input_devices/mag/node_modules/component-emitter/Readme.md
@@ -0,0 +1,74 @@
+# Emitter [![Build Status](https://travis-ci.org/component/emitter.png)](https://travis-ci.org/component/emitter)
+
+  Event emitter component.
+
+## Installation
+
+```
+$ component install component/emitter
+```
+
+## API
+
+### Emitter(obj)
+
+  The `Emitter` may also be used as a mixin. For example
+  a "plain" object may become an emitter, or you may
+  extend an existing prototype.
+
+  As an `Emitter` instance:
+
+```js
+var Emitter = require('emitter');
+var emitter = new Emitter;
+emitter.emit('something');
+```
+
+  As a mixin:
+
+```js
+var Emitter = require('emitter');
+var user = { name: 'tobi' };
+Emitter(user);
+
+user.emit('im a user');
+```
+
+  As a prototype mixin:
+
+```js
+var Emitter = require('emitter');
+Emitter(User.prototype);
+```
+
+### Emitter#on(event, fn)
+
+  Register an `event` handler `fn`.
+
+### Emitter#once(event, fn)
+
+  Register a single-shot `event` handler `fn`,
+  removed immediately after it is invoked the
+  first time.
+
+### Emitter#off(event, fn)
+
+  * Pass `event` and `fn` to remove a listener.
+  * Pass `event` to remove all listeners on that event.
+  * Pass nothing to remove all listeners on all events.
+
+### Emitter#emit(event, ...)
+
+  Emit an `event` with variable option args.
+
+### Emitter#listeners(event)
+
+  Return an array of callbacks, or an empty array.
+
+### Emitter#hasListeners(event)
+
+  Check if this emitter has `event` handlers.
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/component-emitter/index.js b/input_devices/mag/node_modules/component-emitter/index.js
new file mode 100644
index 00000000..df94c78e
--- /dev/null
+++ b/input_devices/mag/node_modules/component-emitter/index.js
@@ -0,0 +1,163 @@
+
+/**
+ * Expose `Emitter`.
+ */
+
+if (typeof module !== 'undefined') {
+  module.exports = Emitter;
+}
+
+/**
+ * Initialize a new `Emitter`.
+ *
+ * @api public
+ */
+
+function Emitter(obj) {
+  if (obj) return mixin(obj);
+};
+
+/**
+ * Mixin the emitter properties.
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+function mixin(obj) {
+  for (var key in Emitter.prototype) {
+    obj[key] = Emitter.prototype[key];
+  }
+  return obj;
+}
+
+/**
+ * Listen on the given `event` with `fn`.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.on =
+Emitter.prototype.addEventListener = function(event, fn){
+  this._callbacks = this._callbacks || {};
+  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
+    .push(fn);
+  return this;
+};
+
+/**
+ * Adds an `event` listener that will be invoked a single
+ * time then automatically removed.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.once = function(event, fn){
+  function on() {
+    this.off(event, on);
+    fn.apply(this, arguments);
+  }
+
+  on.fn = fn;
+  this.on(event, on);
+  return this;
+};
+
+/**
+ * Remove the given callback for `event` or all
+ * registered callbacks.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.off =
+Emitter.prototype.removeListener =
+Emitter.prototype.removeAllListeners =
+Emitter.prototype.removeEventListener = function(event, fn){
+  this._callbacks = this._callbacks || {};
+
+  // all
+  if (0 == arguments.length) {
+    this._callbacks = {};
+    return this;
+  }
+
+  // specific event
+  var callbacks = this._callbacks['$' + event];
+  if (!callbacks) return this;
+
+  // remove all handlers
+  if (1 == arguments.length) {
+    delete this._callbacks['$' + event];
+    return this;
+  }
+
+  // remove specific handler
+  var cb;
+  for (var i = 0; i < callbacks.length; i++) {
+    cb = callbacks[i];
+    if (cb === fn || cb.fn === fn) {
+      callbacks.splice(i, 1);
+      break;
+    }
+  }
+  return this;
+};
+
+/**
+ * Emit `event` with the given args.
+ *
+ * @param {String} event
+ * @param {Mixed} ...
+ * @return {Emitter}
+ */
+
+Emitter.prototype.emit = function(event){
+  this._callbacks = this._callbacks || {};
+  var args = [].slice.call(arguments, 1)
+    , callbacks = this._callbacks['$' + event];
+
+  if (callbacks) {
+    callbacks = callbacks.slice(0);
+    for (var i = 0, len = callbacks.length; i < len; ++i) {
+      callbacks[i].apply(this, args);
+    }
+  }
+
+  return this;
+};
+
+/**
+ * Return array of callbacks for `event`.
+ *
+ * @param {String} event
+ * @return {Array}
+ * @api public
+ */
+
+Emitter.prototype.listeners = function(event){
+  this._callbacks = this._callbacks || {};
+  return this._callbacks['$' + event] || [];
+};
+
+/**
+ * Check if this emitter has `event` handlers.
+ *
+ * @param {String} event
+ * @return {Boolean}
+ * @api public
+ */
+
+Emitter.prototype.hasListeners = function(event){
+  return !! this.listeners(event).length;
+};
diff --git a/input_devices/mag/node_modules/component-emitter/package.json b/input_devices/mag/node_modules/component-emitter/package.json
new file mode 100644
index 00000000..b1ded68a
--- /dev/null
+++ b/input_devices/mag/node_modules/component-emitter/package.json
@@ -0,0 +1,209 @@
+{
+  "_args": [
+    [
+      "component-emitter@^1.2.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "component-emitter@>=1.2.1 <2.0.0",
+  "_id": "component-emitter@1.2.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/component-emitter",
+  "_nodeVersion": "0.12.4",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/component-emitter-1.2.1.tgz_1461005707641_0.14232611074112356"
+  },
+  "_npmUser": {
+    "email": "karp@hotmail.fr",
+    "name": "nami-doc"
+  },
+  "_npmVersion": "2.10.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "component-emitter",
+    "raw": "component-emitter@^1.2.1",
+    "rawSpec": "^1.2.1",
+    "scope": null,
+    "spec": ">=1.2.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base",
+    "/readline-ui"
+  ],
+  "_resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+  "_shasum": "137918d6d78283f7df7a6b7c5a63e140e69425e6",
+  "_shrinkwrap": null,
+  "_spec": "component-emitter@^1.2.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "bugs": {
+    "url": "https://github.com/component/emitter/issues"
+  },
+  "component": {
+    "scripts": {
+      "emitter/index.js": "index.js"
+    }
+  },
+  "dependencies": {},
+  "description": "Event emitter",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "137918d6d78283f7df7a6b7c5a63e140e69425e6",
+    "tarball": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz"
+  },
+  "files": [
+    "LICENSE",
+    "index.js"
+  ],
+  "gitHead": "187492ab8028c7221b589bdfd482b715149cd868",
+  "homepage": "https://github.com/component/emitter#readme",
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "swatinem",
+      "email": "arpad.borsos@googlemail.com"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    },
+    {
+      "name": "trevorgerhardt",
+      "email": "trevorgerhardt@gmail.com"
+    },
+    {
+      "name": "timaschew",
+      "email": "timaschew@gmail.com"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    },
+    {
+      "name": "retrofox",
+      "email": "rdsuarez@gmail.com"
+    },
+    {
+      "name": "coreh",
+      "email": "thecoreh@gmail.com"
+    },
+    {
+      "name": "forbeslindesay",
+      "email": "forbes@lindesay.co.uk"
+    },
+    {
+      "name": "kelonye",
+      "email": "kelonyemitchel@gmail.com"
+    },
+    {
+      "name": "mattmueller",
+      "email": "mattmuelle@gmail.com"
+    },
+    {
+      "name": "yields",
+      "email": "yields@icloud.com"
+    },
+    {
+      "name": "anthonyshort",
+      "email": "antshort@gmail.com"
+    },
+    {
+      "name": "jongleberry",
+      "email": "jonathanrichardong@gmail.com"
+    },
+    {
+      "name": "ianstormtaylor",
+      "email": "ian@ianstormtaylor.com"
+    },
+    {
+      "name": "cristiandouce",
+      "email": "cristian@gravityonmars.com"
+    },
+    {
+      "name": "hughsk",
+      "email": "hughskennedy@gmail.com"
+    },
+    {
+      "name": "stagas",
+      "email": "gstagas@gmail.com"
+    },
+    {
+      "name": "amasad",
+      "email": "amjad.masad@gmail.com"
+    },
+    {
+      "name": "juliangruber",
+      "email": "julian@juliangruber.com"
+    },
+    {
+      "name": "calvinfo",
+      "email": "calvin@calv.info"
+    },
+    {
+      "name": "dominicbarnes",
+      "email": "dominic@dbarnes.info"
+    },
+    {
+      "name": "blakeembrey",
+      "email": "hello@blakeembrey.com"
+    },
+    {
+      "name": "timoxley",
+      "email": "secoif@gmail.com"
+    },
+    {
+      "name": "jonathanong",
+      "email": "jonathanrichardong@gmail.com"
+    },
+    {
+      "name": "queckezz",
+      "email": "fabian.eichenberger@gmail.com"
+    },
+    {
+      "name": "nami-doc",
+      "email": "vendethiel@hotmail.fr"
+    },
+    {
+      "name": "clintwood",
+      "email": "clint@anotherway.co.za"
+    },
+    {
+      "name": "thehydroimpulse",
+      "email": "dnfagnan@gmail.com"
+    },
+    {
+      "name": "stephenmathieson",
+      "email": "me@stephenmathieson.com"
+    },
+    {
+      "name": "dfcreative",
+      "email": "df.creative@gmail.com"
+    },
+    {
+      "name": "defunctzombie",
+      "email": "shtylman@gmail.com"
+    }
+  ],
+  "name": "component-emitter",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/component/emitter.git"
+  },
+  "scripts": {
+    "test": "make test"
+  },
+  "version": "1.2.1"
+}
diff --git a/input_devices/mag/node_modules/console-control-strings/LICENSE b/input_devices/mag/node_modules/console-control-strings/LICENSE
new file mode 100644
index 00000000..e7560529
--- /dev/null
+++ b/input_devices/mag/node_modules/console-control-strings/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2014, Rebecca Turner <me@re-becca.org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/console-control-strings/README.md b/input_devices/mag/node_modules/console-control-strings/README.md
new file mode 100644
index 00000000..f58cc8d8
--- /dev/null
+++ b/input_devices/mag/node_modules/console-control-strings/README.md
@@ -0,0 +1,145 @@
+# Console Control Strings
+
+A library of cross-platform tested terminal/console command strings for
+doing things like color and cursor positioning.  This is a subset of both
+ansi and vt100.  All control codes included work on both Windows & Unix-like
+OSes, except where noted.
+
+## Usage
+
+```js
+var consoleControl = require('console-control-strings')
+
+console.log(consoleControl.color('blue','bgRed', 'bold') + 'hi there' + consoleControl.color('reset'))
+process.stdout.write(consoleControl.goto(75, 10))
+```
+
+## Why Another?
+
+There are tons of libraries similar to this one.  I wanted one that was:
+
+1. Very clear about compatibility goals.
+2. Could emit, for instance, a start color code without an end one.
+3. Returned strings w/o writing to streams.
+4. Was not weighed down with other unrelated baggage.
+
+## Functions
+
+### var code = consoleControl.up(_num = 1_)
+
+Returns the escape sequence to move _num_ lines up.
+
+### var code = consoleControl.down(_num = 1_)
+
+Returns the escape sequence to move _num_ lines down.
+
+### var code = consoleControl.forward(_num = 1_)
+
+Returns the escape sequence to move _num_ lines righ.
+
+### var code = consoleControl.back(_num = 1_)
+
+Returns the escape sequence to move _num_ lines left.
+
+### var code = consoleControl.nextLine(_num = 1_)
+
+Returns the escape sequence to move _num_ lines down and to the beginning of
+the line.
+
+### var code = consoleControl.previousLine(_num = 1_)
+
+Returns the escape sequence to move _num_ lines up and to the beginning of
+the line.
+
+### var code = consoleControl.eraseData()
+
+Returns the escape sequence to erase everything from the current cursor
+position to the bottom right of the screen.  This is line based, so it
+erases the remainder of the current line and all following lines.
+
+### var code = consoleControl.eraseLine()
+
+Returns the escape sequence to erase to the end of the current line.
+
+### var code = consoleControl.goto(_x_, _y_)
+
+Returns the escape sequence to move the cursor to the designated position. 
+Note that the origin is _1, 1_ not _0, 0_.
+
+### var code = consoleControl.gotoSOL()
+
+Returns the escape sequence to move the cursor to the beginning of the
+current line. (That is, it returns a carriage return, `\r`.)
+
+### var code = consoleControl.beep()
+
+Returns the escape sequence to cause the termianl to beep.  (That is, it
+returns unicode character `\x0007`, a Control-G.)
+
+### var code = consoleControl.hideCursor()
+
+Returns the escape sequence to hide the cursor.
+
+### var code = consoleControl.showCursor()
+
+Returns the escape sequence to show the cursor.
+
+### var code = consoleControl.color(_colors = []_)
+
+### var code = consoleControl.color(_color1_, _color2_, _…_, _colorn_)
+
+Returns the escape sequence to set the current terminal display attributes
+(mostly colors).  Arguments can either be a list of attributes or an array
+of attributes.  The difference between passing in an array or list of colors
+and calling `.color` separately for each one, is that in the former case a
+single escape sequence will be produced where as in the latter each change
+will have its own distinct escape sequence.  Each attribute can be one of:
+
+* Reset:
+  * **reset** – Reset all attributes to the terminal default.
+* Styles:
+  * **bold** – Display text as bold.  In some terminals this means using a
+    bold font, in others this means changing the color.  In some it means
+    both.
+  * **italic** – Display text as italic. This is not available in most Windows terminals.
+  * **underline** – Underline text. This is not available in most Windows Terminals.
+  * **inverse** – Invert the foreground and background colors.
+  * **stopBold** – Do not display text as bold.
+  * **stopItalic** – Do not display text as italic.
+  * **stopUnderline** – Do not underline text.
+  * **stopInverse** – Do not invert foreground and background.
+* Colors:
+  * **white**
+  * **black**
+  * **blue**
+  * **cyan**
+  * **green**
+  * **magenta**
+  * **red**
+  * **yellow**
+  * **grey** / **brightBlack**
+  * **brightRed**
+  * **brightGreen**
+  * **brightYellow**
+  * **brightBlue**
+  * **brightMagenta**
+  * **brightCyan**
+  * **brightWhite**
+* Background Colors:
+  * **bgWhite**
+  * **bgBlack**
+  * **bgBlue**
+  * **bgCyan**
+  * **bgGreen**
+  * **bgMagenta**
+  * **bgRed**
+  * **bgYellow**
+  * **bgGrey** / **bgBrightBlack**
+  * **bgBrightRed**
+  * **bgBrightGreen**
+  * **bgBrightYellow**
+  * **bgBrightBlue**
+  * **bgBrightMagenta**
+  * **bgBrightCyan**
+  * **bgBrightWhite**
+
diff --git a/input_devices/mag/node_modules/console-control-strings/README.md~ b/input_devices/mag/node_modules/console-control-strings/README.md~
new file mode 100644
index 00000000..6eb34e89
--- /dev/null
+++ b/input_devices/mag/node_modules/console-control-strings/README.md~
@@ -0,0 +1,140 @@
+# Console Control Strings
+
+A library of cross-platform tested terminal/console command strings for
+doing things like color and cursor positioning.  This is a subset of both
+ansi and vt100.  All control codes included work on both Windows & Unix-like
+OSes, except where noted.
+
+## Usage
+
+```js
+var consoleControl = require('console-control-strings')
+
+console.log(consoleControl.color('blue','bgRed', 'bold') + 'hi there' + consoleControl.color('reset'))
+process.stdout.write(consoleControl.goto(75, 10))
+```
+
+## Why Another?
+
+There are tons of libraries similar to this one.  I wanted one that was:
+
+1. Very clear about compatibility goals.
+2. Could emit, for instance, a start color code without an end one.
+3. Returned strings w/o writing to streams.
+4. Was not weighed down with other unrelated baggage.
+
+## Functions
+
+### var code = consoleControl.up(_num = 1_)
+
+Returns the escape sequence to move _num_ lines up.
+
+### var code = consoleControl.down(_num = 1_)
+
+Returns the escape sequence to move _num_ lines down.
+
+### var code = consoleControl.forward(_num = 1_)
+
+Returns the escape sequence to move _num_ lines righ.
+
+### var code = consoleControl.back(_num = 1_)
+
+Returns the escape sequence to move _num_ lines left.
+
+### var code = consoleControl.nextLine(_num = 1_)
+
+Returns the escape sequence to move _num_ lines down and to the beginning of
+the line.
+
+### var code = consoleControl.previousLine(_num = 1_)
+
+Returns the escape sequence to move _num_ lines up and to the beginning of
+the line.
+
+### var code = consoleControl.eraseData()
+
+Returns the escape sequence to erase everything from the current cursor
+position to the bottom right of the screen.  This is line based, so it
+erases the remainder of the current line and all following lines.
+
+### var code = consoleControl.eraseLine()
+
+Returns the escape sequence to erase to the end of the current line.
+
+### var code = consoleControl.goto(_x_, _y_)
+
+Returns the escape sequence to move the cursor to the designated position. 
+Note that the origin is _1, 1_ not _0, 0_.
+
+### var code = consoleControl.gotoSOL()
+
+Returns the escape sequence to move the cursor to the beginning of the
+current line. (That is, it returns a carriage return, `\r`.)
+
+### var code = consoleControl.hideCursor()
+
+Returns the escape sequence to hide the cursor.
+
+### var code = consoleControl.showCursor()
+
+Returns the escape sequence to show the cursor.
+
+### var code = consoleControl.color(_colors = []_)
+
+### var code = consoleControl.color(_color1_, _color2_, _…_, _colorn_)
+
+Returns the escape sequence to set the current terminal display attributes
+(mostly colors).  Arguments can either be a list of attributes or an array
+of attributes.  The difference between passing in an array or list of colors
+and calling `.color` separately for each one, is that in the former case a
+single escape sequence will be produced where as in the latter each change
+will have its own distinct escape sequence.  Each attribute can be one of:
+
+* Reset:
+  * **reset** – Reset all attributes to the terminal default.
+* Styles:
+  * **bold** – Display text as bold.  In some terminals this means using a
+    bold font, in others this means changing the color.  In some it means
+    both.
+  * **italic** – Display text as italic. This is not available in most Windows terminals.
+  * **underline** – Underline text. This is not available in most Windows Terminals.
+  * **inverse** – Invert the foreground and background colors.
+  * **stopBold** – Do not display text as bold.
+  * **stopItalic** – Do not display text as italic.
+  * **stopUnderline** – Do not underline text.
+  * **stopInverse** – Do not invert foreground and background.
+* Colors:
+  * **white**
+  * **black**
+  * **blue**
+  * **cyan**
+  * **green**
+  * **magenta**
+  * **red**
+  * **yellow**
+  * **grey** / **brightBlack**
+  * **brightRed**
+  * **brightGreen**
+  * **brightYellow**
+  * **brightBlue**
+  * **brightMagenta**
+  * **brightCyan**
+  * **brightWhite**
+* Background Colors:
+  * **bgWhite**
+  * **bgBlack**
+  * **bgBlue**
+  * **bgCyan**
+  * **bgGreen**
+  * **bgMagenta**
+  * **bgRed**
+  * **bgYellow**
+  * **bgGrey** / **bgBrightBlack**
+  * **bgBrightRed**
+  * **bgBrightGreen**
+  * **bgBrightYellow**
+  * **bgBrightBlue**
+  * **bgBrightMagenta**
+  * **bgBrightCyan**
+  * **bgBrightWhite**
+
diff --git a/input_devices/mag/node_modules/console-control-strings/index.js b/input_devices/mag/node_modules/console-control-strings/index.js
new file mode 100644
index 00000000..bf890348
--- /dev/null
+++ b/input_devices/mag/node_modules/console-control-strings/index.js
@@ -0,0 +1,125 @@
+'use strict'
+
+// These tables borrowed from `ansi`
+
+var prefix = '\x1b['
+
+exports.up = function up (num) {
+  return prefix + (num || '') + 'A'
+}
+
+exports.down = function down (num) {
+  return prefix + (num || '') + 'B'
+}
+
+exports.forward = function forward (num) {
+  return prefix + (num || '') + 'C'
+}
+
+exports.back = function back (num) {
+  return prefix + (num || '') + 'D'
+}
+
+exports.nextLine = function nextLine (num) {
+  return prefix + (num || '') + 'E'
+}
+
+exports.previousLine = function previousLine (num) {
+  return prefix + (num || '') + 'F'
+}
+
+exports.horizontalAbsolute = function horizontalAbsolute (num) {
+  if (num == null) throw new Error('horizontalAboslute requires a column to position to')
+  return prefix + num + 'G'
+}
+
+exports.eraseData = function eraseData () {
+  return prefix + 'J'
+}
+
+exports.eraseLine = function eraseLine () {
+  return prefix + 'K'
+}
+
+exports.goto = function (x, y) {
+  return prefix + y + ';' + x + 'H'
+}
+
+exports.gotoSOL = function () {
+  return '\r'
+}
+
+exports.beep = function () {
+  return '\x07'
+}
+
+exports.hideCursor = function hideCursor () {
+  return prefix + '?25l'
+}
+
+exports.showCursor = function showCursor () {
+  return prefix + '?25h'
+}
+
+var colors = {
+  reset: 0,
+// styles
+  bold: 1,
+  italic: 3,
+  underline: 4,
+  inverse: 7,
+// resets
+  stopBold: 22,
+  stopItalic: 23,
+  stopUnderline: 24,
+  stopInverse: 27,
+// colors
+  white: 37,
+  black: 30,
+  blue: 34,
+  cyan: 36,
+  green: 32,
+  magenta: 35,
+  red: 31,
+  yellow: 33,
+  bgWhite: 47,
+  bgBlack: 40,
+  bgBlue: 44,
+  bgCyan: 46,
+  bgGreen: 42,
+  bgMagenta: 45,
+  bgRed: 41,
+  bgYellow: 43,
+
+  grey: 90,
+  brightBlack: 90,
+  brightRed: 91,
+  brightGreen: 92,
+  brightYellow: 93,
+  brightBlue: 94,
+  brightMagenta: 95,
+  brightCyan: 96,
+  brightWhite: 97,
+
+  bgGrey: 100,
+  bgBrightBlack: 100,
+  bgBrightRed: 101,
+  bgBrightGreen: 102,
+  bgBrightYellow: 103,
+  bgBrightBlue: 104,
+  bgBrightMagenta: 105,
+  bgBrightCyan: 106,
+  bgBrightWhite: 107
+}
+
+exports.color = function color (colorWith) {
+  if (arguments.length !== 1 || !Array.isArray(colorWith)) {
+    colorWith = Array.prototype.slice.call(arguments)
+  }
+  return prefix + colorWith.map(colorNameToCode).join(';') + 'm'
+}
+
+function colorNameToCode (color) {
+  if (colors[color] != null) return colors[color]
+  throw new Error('Unknown color or style name: ' + color)
+}
diff --git a/input_devices/mag/node_modules/console-control-strings/package.json b/input_devices/mag/node_modules/console-control-strings/package.json
new file mode 100644
index 00000000..b2815f2d
--- /dev/null
+++ b/input_devices/mag/node_modules/console-control-strings/package.json
@@ -0,0 +1,88 @@
+{
+  "_args": [
+    [
+      "console-control-strings@~1.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog"
+    ]
+  ],
+  "_from": "console-control-strings@>=1.1.0 <1.2.0",
+  "_id": "console-control-strings@1.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/console-control-strings",
+  "_nodeVersion": "4.4.0",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/console-control-strings-1.1.0.tgz_1466033396831_0.9470485949423164"
+  },
+  "_npmUser": {
+    "email": "me@re-becca.org",
+    "name": "iarna"
+  },
+  "_npmVersion": "3.9.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "console-control-strings",
+    "raw": "console-control-strings@~1.1.0",
+    "rawSpec": "~1.1.0",
+    "scope": null,
+    "spec": ">=1.1.0 <1.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge",
+    "/npmlog"
+  ],
+  "_resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+  "_shasum": "3d7cf4464db6446ea644bf4b39507f9851008e8e",
+  "_shrinkwrap": null,
+  "_spec": "console-control-strings@~1.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog",
+  "author": {
+    "email": "me@re-becca.org",
+    "name": "Rebecca Turner",
+    "url": "http://re-becca.org/"
+  },
+  "bugs": {
+    "url": "https://github.com/iarna/console-control-strings/issues"
+  },
+  "dependencies": {},
+  "description": "A library of cross-platform tested terminal/console command strings for doing things like color and cursor positioning.  This is a subset of both ansi and vt100.  All control codes included work on both Windows & Unix-like OSes, except where noted.",
+  "devDependencies": {
+    "standard": "^7.1.2",
+    "tap": "^5.7.2"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "dist": {
+    "shasum": "3d7cf4464db6446ea644bf4b39507f9851008e8e",
+    "tarball": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz"
+  },
+  "files": [
+    "LICENSE",
+    "index.js"
+  ],
+  "gitHead": "722439b4998d2964ac3d3f9ec175c008aa9b7b4b",
+  "homepage": "https://github.com/iarna/console-control-strings#readme",
+  "keywords": [],
+  "license": "ISC",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    }
+  ],
+  "name": "console-control-strings",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/iarna/console-control-strings.git"
+  },
+  "scripts": {
+    "test": "standard && tap test/*.js"
+  },
+  "version": "1.1.0"
+}
diff --git a/input_devices/mag/node_modules/copy-descriptor/LICENSE b/input_devices/mag/node_modules/copy-descriptor/LICENSE
new file mode 100644
index 00000000..65251717
--- /dev/null
+++ b/input_devices/mag/node_modules/copy-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2016, Jon Schlinkert
+
+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/input_devices/mag/node_modules/copy-descriptor/index.js b/input_devices/mag/node_modules/copy-descriptor/index.js
new file mode 100644
index 00000000..6da21b1b
--- /dev/null
+++ b/input_devices/mag/node_modules/copy-descriptor/index.js
@@ -0,0 +1,81 @@
+/*!
+ * copy-descriptor <https://github.com/jonschlinkert/copy-descriptor>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+/**
+ * Copy a descriptor from one object to another.
+ *
+ * ```js
+ * function App() {
+ *   this.cache = {};
+ * }
+ * App.prototype.set = function(key, val) {
+ *   this.cache[key] = val;
+ *   return this;
+ * };
+ * Object.defineProperty(App.prototype, 'count', {
+ *   get: function() {
+ *     return Object.keys(this.cache).length;
+ *   }
+ * });
+ *
+ * copy(App.prototype, 'count', 'len');
+ *
+ * // create an instance
+ * var app = new App();
+ *
+ * app.set('a', true);
+ * app.set('b', true);
+ * app.set('c', true);
+ *
+ * console.log(app.count);
+ * //=> 3
+ * console.log(app.len);
+ * //=> 3
+ * ```
+ * @name copy
+ * @param {Object} `receiver` The target object
+ * @param {Object} `provider` The provider object
+ * @param {String} `from` The key to copy on provider.
+ * @param {String} `to` Optionally specify a new key name to use.
+ * @return {Object}
+ * @api public
+ */
+
+module.exports = function copyDescriptor(receiver, provider, from, to) {
+  if (!isObject(provider) && typeof provider !== 'function') {
+    to = from;
+    from = provider;
+    provider = receiver;
+  }
+  if (!isObject(receiver) && typeof receiver !== 'function') {
+    throw new TypeError('expected the first argument to be an object');
+  }
+  if (!isObject(provider) && typeof provider !== 'function') {
+    throw new TypeError('expected provider to be an object');
+  }
+
+  if (typeof to !== 'string') {
+    to = from;
+  }
+  if (typeof from !== 'string') {
+    throw new TypeError('expected key to be a string');
+  }
+
+  if (!(from in provider)) {
+    throw new Error('property "' + from + '" does not exist');
+  }
+
+  var val = Object.getOwnPropertyDescriptor(provider, from);
+  if (val) Object.defineProperty(receiver, to, val);
+};
+
+function isObject(val) {
+  return {}.toString.call(val) === '[object Object]';
+}
+
diff --git a/input_devices/mag/node_modules/copy-descriptor/package.json b/input_devices/mag/node_modules/copy-descriptor/package.json
new file mode 100644
index 00000000..e1032c78
--- /dev/null
+++ b/input_devices/mag/node_modules/copy-descriptor/package.json
@@ -0,0 +1,115 @@
+{
+  "_args": [
+    [
+      "copy-descriptor@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy"
+    ]
+  ],
+  "_from": "copy-descriptor@>=0.1.0 <0.2.0",
+  "_id": "copy-descriptor@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/copy-descriptor",
+  "_nodeVersion": "6.2.0",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/copy-descriptor-0.1.1.tgz_1465497122701_0.666076025692746"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.8.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "copy-descriptor",
+    "raw": "copy-descriptor@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/object-copy"
+  ],
+  "_resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+  "_shasum": "676f6eb3c39997c2ee1ac3a924fd6124748f578d",
+  "_shrinkwrap": null,
+  "_spec": "copy-descriptor@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/copy-descriptor/issues"
+  },
+  "dependencies": {},
+  "description": "Copy a descriptor from object A to object B",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.9",
+    "mocha": "^2.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "676f6eb3c39997c2ee1ac3a924fd6124748f578d",
+    "tarball": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "572c31416d4538b7ba5f52e2bb0765ac237f79e2",
+  "homepage": "https://github.com/jonschlinkert/copy-descriptor",
+  "keywords": [
+    "copy",
+    "descriptor"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "copy-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/copy-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-readme-generator"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "is-plain-object",
+        "isobject"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/core-util-is/LICENSE b/input_devices/mag/node_modules/core-util-is/LICENSE
new file mode 100644
index 00000000..d8d7f943
--- /dev/null
+++ b/input_devices/mag/node_modules/core-util-is/LICENSE
@@ -0,0 +1,19 @@
+Copyright Node.js contributors. All rights reserved.
+
+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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/README.md b/input_devices/mag/node_modules/core-util-is/README.md
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/README.md
rename to input_devices/mag/node_modules/core-util-is/README.md
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/float.patch b/input_devices/mag/node_modules/core-util-is/float.patch
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/float.patch
rename to input_devices/mag/node_modules/core-util-is/float.patch
diff --git a/input_devices/mag/node_modules/core-util-is/lib/util.js b/input_devices/mag/node_modules/core-util-is/lib/util.js
new file mode 100644
index 00000000..ff4c851c
--- /dev/null
+++ b/input_devices/mag/node_modules/core-util-is/lib/util.js
@@ -0,0 +1,107 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+// NOTE: These type checking functions intentionally don't use `instanceof`
+// because it is fragile and can be easily faked with `Object.create()`.
+
+function isArray(arg) {
+  if (Array.isArray) {
+    return Array.isArray(arg);
+  }
+  return objectToString(arg) === '[object Array]';
+}
+exports.isArray = isArray;
+
+function isBoolean(arg) {
+  return typeof arg === 'boolean';
+}
+exports.isBoolean = isBoolean;
+
+function isNull(arg) {
+  return arg === null;
+}
+exports.isNull = isNull;
+
+function isNullOrUndefined(arg) {
+  return arg == null;
+}
+exports.isNullOrUndefined = isNullOrUndefined;
+
+function isNumber(arg) {
+  return typeof arg === 'number';
+}
+exports.isNumber = isNumber;
+
+function isString(arg) {
+  return typeof arg === 'string';
+}
+exports.isString = isString;
+
+function isSymbol(arg) {
+  return typeof arg === 'symbol';
+}
+exports.isSymbol = isSymbol;
+
+function isUndefined(arg) {
+  return arg === void 0;
+}
+exports.isUndefined = isUndefined;
+
+function isRegExp(re) {
+  return objectToString(re) === '[object RegExp]';
+}
+exports.isRegExp = isRegExp;
+
+function isObject(arg) {
+  return typeof arg === 'object' && arg !== null;
+}
+exports.isObject = isObject;
+
+function isDate(d) {
+  return objectToString(d) === '[object Date]';
+}
+exports.isDate = isDate;
+
+function isError(e) {
+  return (objectToString(e) === '[object Error]' || e instanceof Error);
+}
+exports.isError = isError;
+
+function isFunction(arg) {
+  return typeof arg === 'function';
+}
+exports.isFunction = isFunction;
+
+function isPrimitive(arg) {
+  return arg === null ||
+         typeof arg === 'boolean' ||
+         typeof arg === 'number' ||
+         typeof arg === 'string' ||
+         typeof arg === 'symbol' ||  // ES6 symbol
+         typeof arg === 'undefined';
+}
+exports.isPrimitive = isPrimitive;
+
+exports.isBuffer = Buffer.isBuffer;
+
+function objectToString(o) {
+  return Object.prototype.toString.call(o);
+}
diff --git a/input_devices/mag/node_modules/core-util-is/package.json b/input_devices/mag/node_modules/core-util-is/package.json
new file mode 100644
index 00000000..6c2dd783
--- /dev/null
+++ b/input_devices/mag/node_modules/core-util-is/package.json
@@ -0,0 +1,86 @@
+{
+  "_args": [
+    [
+      "core-util-is@~1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream"
+    ]
+  ],
+  "_from": "core-util-is@>=1.0.0 <1.1.0",
+  "_id": "core-util-is@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/core-util-is",
+  "_nodeVersion": "4.0.0",
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "3.3.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "core-util-is",
+    "raw": "core-util-is@~1.0.0",
+    "rawSpec": "~1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <1.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readable-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+  "_shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7",
+  "_shrinkwrap": null,
+  "_spec": "core-util-is@~1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream",
+  "author": {
+    "email": "i@izs.me",
+    "name": "Isaac Z. Schlueter",
+    "url": "http://blog.izs.me/"
+  },
+  "bugs": {
+    "url": "https://github.com/isaacs/core-util-is/issues"
+  },
+  "dependencies": {},
+  "description": "The `util.is*` functions introduced in Node v0.12.",
+  "devDependencies": {
+    "tap": "^2.3.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7",
+    "tarball": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
+  },
+  "gitHead": "a177da234df5638b363ddc15fa324619a38577c8",
+  "homepage": "https://github.com/isaacs/core-util-is#readme",
+  "keywords": [
+    "isArray",
+    "isBuffer",
+    "isNumber",
+    "isRegExp",
+    "isString",
+    "isThat",
+    "isThis",
+    "polyfill",
+    "util"
+  ],
+  "license": "MIT",
+  "main": "lib/util.js",
+  "maintainers": [
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    }
+  ],
+  "name": "core-util-is",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/core-util-is.git"
+  },
+  "scripts": {
+    "test": "tap test.js"
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/core-util-is/test.js b/input_devices/mag/node_modules/core-util-is/test.js
new file mode 100644
index 00000000..1a490c65
--- /dev/null
+++ b/input_devices/mag/node_modules/core-util-is/test.js
@@ -0,0 +1,68 @@
+var assert = require('tap');
+
+var t = require('./lib/util');
+
+assert.equal(t.isArray([]), true);
+assert.equal(t.isArray({}), false);
+
+assert.equal(t.isBoolean(null), false);
+assert.equal(t.isBoolean(true), true);
+assert.equal(t.isBoolean(false), true);
+
+assert.equal(t.isNull(null), true);
+assert.equal(t.isNull(undefined), false);
+assert.equal(t.isNull(false), false);
+assert.equal(t.isNull(), false);
+
+assert.equal(t.isNullOrUndefined(null), true);
+assert.equal(t.isNullOrUndefined(undefined), true);
+assert.equal(t.isNullOrUndefined(false), false);
+assert.equal(t.isNullOrUndefined(), true);
+
+assert.equal(t.isNumber(null), false);
+assert.equal(t.isNumber('1'), false);
+assert.equal(t.isNumber(1), true);
+
+assert.equal(t.isString(null), false);
+assert.equal(t.isString('1'), true);
+assert.equal(t.isString(1), false);
+
+assert.equal(t.isSymbol(null), false);
+assert.equal(t.isSymbol('1'), false);
+assert.equal(t.isSymbol(1), false);
+assert.equal(t.isSymbol(Symbol()), true);
+
+assert.equal(t.isUndefined(null), false);
+assert.equal(t.isUndefined(undefined), true);
+assert.equal(t.isUndefined(false), false);
+assert.equal(t.isUndefined(), true);
+
+assert.equal(t.isRegExp(null), false);
+assert.equal(t.isRegExp('1'), false);
+assert.equal(t.isRegExp(new RegExp()), true);
+
+assert.equal(t.isObject({}), true);
+assert.equal(t.isObject([]), true);
+assert.equal(t.isObject(new RegExp()), true);
+assert.equal(t.isObject(new Date()), true);
+
+assert.equal(t.isDate(null), false);
+assert.equal(t.isDate('1'), false);
+assert.equal(t.isDate(new Date()), true);
+
+assert.equal(t.isError(null), false);
+assert.equal(t.isError({ err: true }), false);
+assert.equal(t.isError(new Error()), true);
+
+assert.equal(t.isFunction(null), false);
+assert.equal(t.isFunction({ }), false);
+assert.equal(t.isFunction(function() {}), true);
+
+assert.equal(t.isPrimitive(null), true);
+assert.equal(t.isPrimitive(''), true);
+assert.equal(t.isPrimitive(0), true);
+assert.equal(t.isPrimitive(new Date()), false);
+
+assert.equal(t.isBuffer(null), false);
+assert.equal(t.isBuffer({}), false);
+assert.equal(t.isBuffer(new Buffer(0)), true);
diff --git a/input_devices/mag/node_modules/debug/CHANGELOG.md b/input_devices/mag/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..820d21e3
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,395 @@
+
+3.1.0 / 2017-09-26
+==================
+
+  * Add `DEBUG_HIDE_DATE` env var (#486)
+  * Remove ReDoS regexp in %o formatter (#504)
+  * Remove "component" from package.json
+  * Remove `component.json`
+  * Ignore package-lock.json
+  * Examples: fix colors printout
+  * Fix: browser detection
+  * Fix: spelling mistake (#496, @EdwardBetts)
+
+3.0.1 / 2017-08-24
+==================
+
+  * Fix: Disable colors in Edge and Internet Explorer (#489)
+
+3.0.0 / 2017-08-08
+==================
+
+  * Breaking: Remove DEBUG_FD (#406)
+  * Breaking: Use `Date#toISOString()` instead to `Date#toUTCString()` when output is not a TTY (#418)
+  * Breaking: Make millisecond timer namespace specific and allow 'always enabled' output (#408)
+  * Addition: document `enabled` flag (#465)
+  * Addition: add 256 colors mode (#481)
+  * Addition: `enabled()` updates existing debug instances, add `destroy()` function (#440)
+  * Update: component: update "ms" to v2.0.0
+  * Update: separate the Node and Browser tests in Travis-CI
+  * Update: refactor Readme, fixed documentation, added "Namespace Colors" section, redid screenshots
+  * Update: separate Node.js and web browser examples for organization
+  * Update: update "browserify" to v14.4.0
+  * Fix: fix Readme typo (#473)
+
+2.6.9 / 2017-09-22
+==================
+
+  * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+  * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+  * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+  * Fix: Inline extend function in node implementation (#452, @dougwilson)
+  * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+  
+  * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+  * Misc: clean up browser reference checks (#447, @thebigredgeek)
+  * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+  * Fix: bug that would occur if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+  * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+  * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+  * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+  * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+  * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+  * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+  * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+  * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+  * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+  * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+  * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+  * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+  * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+  * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+  * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+  * Docs: fixed README typo (#391, @lurch)
+  * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+  * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+  * Fix: wrong reference in bower file (@thebigredgeek)
+  * Fix: webworker compatibility (@thebigredgeek)
+  * Fix: output formatting issue (#388, @kribblo)
+  * Fix: babel-loader compatibility (#383, @escwald)
+  * Misc: removed built asset from repo and publications (@thebigredgeek)
+  * Misc: moved source files to /src (#378, @yamikuronue)
+  * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+  * Test: coveralls integration (#378, @yamikuronue)
+  * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+  * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+  * Fix: custom log function (#379, @hsiliev)
+  * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+  * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+  * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+  * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+  * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+  * Fix: browser colors (#367, @tootallnate)
+  * Misc: travis ci integration (@thebigredgeek)
+  * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+  * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+  * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+  * Fix: revert "handle regex special characters" (@tootallnate)
+  * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+  * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+  * Improvement: allow colors in workers (#335, @botverse)
+  * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+  * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+  * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+  * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+  * Fix: be super-safe in index.js as well (@TooTallNate)
+  * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+  * Fix: Added electron compatibility (#324, @paulcbetts)
+  * Improvement: Added performance optimizations (@tootallnate)
+  * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+  * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+  * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+  * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+  * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+  * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+  * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+  * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+  * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+  * Readme: fix USE_COLORS to DEBUG_COLORS
+  * Readme: Doc fixes for format string sugar (#269, @mlucool)
+  * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+  * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+  * Readme: better docs for browser support (#224, @matthewmueller)
+  * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+  * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+  * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+  * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+  * package: update "ms" to v0.7.1 (#202, @dougwilson)
+  * README: add logging to file example (#193, @DanielOchoa)
+  * README: fixed a typo (#191, @amir-s)
+  * browser: expose `storage` (#190, @stephenmathieson)
+  * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+  * Updated stdout/stderr example (#186)
+  * Updated example/stdout.js to match debug current behaviour
+  * Renamed example/stderr.js to stdout.js
+  * Update Readme.md (#184)
+  * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+  * dist: recompile
+  * update "ms" to v0.7.0
+  * package: update "browserify" to v9.0.3
+  * component: fix "ms.js" repo location
+  * changed bower package name
+  * updated documentation about using debug in a browser
+  * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+  * browser: use `typeof` to check for `console` existence
+  * browser: check for `console.log` truthiness (fix IE 8/9)
+  * browser: add support for Chrome apps
+  * Readme: added Windows usage remarks
+  * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+  * node: implement `DEBUG_FD` env variable support
+  * package: update "browserify" to v6.1.0
+  * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+  * package: update "browserify" to v5.11.0
+  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+  * dist: recompile
+  * example: remove `console.info()` log usage
+  * example: add "Content-Type" UTF-8 header to browser example
+  * browser: place %c marker after the space character
+  * browser: reset the "content" color via `color: inherit`
+  * browser: add colors support for Firefox >= v31
+  * debug: prefer an instance `log()` function over the global one (#119)
+  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+  * Add support for multiple wildcards in namespaces (#122, @seegno)
+  * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+  * browser: update color palette (#113, @gscottolson)
+  * common: make console logging function configurable (#108, @timoxley)
+  * node: fix %o colors on old node <= 0.8.x
+  * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+  * browser: use `removeItem()` to clear localStorage
+  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+  * package: add "contributors" section
+  * node: fix comment typo
+  * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+  * make ms diff be global, not be scope
+  * debug: ignore empty strings in enable()
+  * node: make DEBUG_COLORS able to disable coloring
+  * *: export the `colors` array
+  * npmignore: don't publish the `dist` dir
+  * Makefile: refactor to use browserify
+  * package: add "browserify" as a dev dependency
+  * Readme: add Web Inspector Colors section
+  * node: reset terminal color for the debug content
+  * node: map "%o" to `util.inspect()`
+  * browser: map "%j" to `JSON.stringify()`
+  * debug: add custom "formatters"
+  * debug: use "ms" module for humanizing the diff
+  * Readme: add "bash" syntax highlighting
+  * browser: add Firebug color support
+  * browser: add colors for WebKit browsers
+  * node: apply log to `console`
+  * rewrite: abstract common logic for Node & browsers
+  * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+  * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+  * add `enable()` method for nodejs. Closes #27
+  * change from stderr to stdout
+  * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+  * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+  * fix: catch localStorage security error when cookies are blocked (Chrome)
+  * add debug(err) support. Closes #46
+  * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/debug/LICENSE b/input_devices/mag/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/debug/README.md b/input_devices/mag/node_modules/debug/README.md
new file mode 100644
index 00000000..0ee7634d
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/README.md
@@ -0,0 +1,437 @@
+# debug
+[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers)
+[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
+
+<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
+
+A tiny JavaScript debugging utility modelled after Node.js core's debugging
+technique. Works in Node.js and web browsers.
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example [_app.js_](./examples/node/app.js):
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %o', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example [_worker.js_](./examples/node/worker.js):
+
+```js
+var a = require('debug')('worker:a')
+  , b = require('debug')('worker:b');
+
+function work() {
+  a('doing lots of uninteresting work');
+  setTimeout(work, Math.random() * 1000);
+}
+
+work();
+
+function workb() {
+  b('doing some work');
+  setTimeout(workb, Math.random() * 2000);
+}
+
+workb();
+```
+
+The `DEBUG` environment variable is then used to enable these based on space or
+comma-delimited names.
+
+Here are some examples:
+
+<img width="647" alt="screen shot 2017-08-08 at 12 53 04 pm" src="https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png">
+<img width="647" alt="screen shot 2017-08-08 at 12 53 38 pm" src="https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png">
+<img width="647" alt="screen shot 2017-08-08 at 12 53 25 pm" src="https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png">
+
+#### Windows command prompt notes
+
+##### CMD
+
+On Windows the environment variable is set using the `set` command.
+
+```cmd
+set DEBUG=*,-not_this
+```
+
+Example:
+
+```cmd
+set DEBUG=* & node app.js
+```
+
+##### PowerShell (VS Code default)
+
+PowerShell uses different syntax to set environment variables.
+
+```cmd
+$env:DEBUG = "*,-not_this"
+```
+
+Example:
+
+```cmd
+$env:DEBUG='app';node app.js
+```
+
+Then, run the program to be debugged as usual.
+
+npm script example:
+```js
+  "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
+```
+
+## Namespace Colors
+
+Every debug instance has a color generated for it based on its namespace name.
+This helps when visually parsing the debug output to identify which debug instance
+a debug line belongs to.
+
+#### Node.js
+
+In Node.js, colors are enabled when stderr is a TTY. You also _should_ install
+the [`supports-color`](https://npmjs.org/supports-color) module alongside debug,
+otherwise debug will only use a small handful of basic colors.
+
+<img width="521" src="https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png">
+
+#### Web Browser
+
+Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+option. These are WebKit web inspectors, Firefox ([since version
+31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+and the Firebug plugin for Firefox (any version).
+
+<img width="524" src="https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png">
+
+
+## Millisecond diff
+
+When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
+
+When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:
+
+<img width="647" src="https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.png">
+
+
+## Conventions
+
+If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".  If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable.  You can then use it for normal output as well as debug output.
+
+## Wildcards
+
+The `*` character may be used as a wildcard. Suppose for example your library has
+debuggers named "connect:bodyParser", "connect:compress", "connect:session",
+instead of listing all three with
+`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do
+`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+You can also exclude specific debuggers by prefixing them with a "-" character.
+For example, `DEBUG=*,-connect:*` would include all debuggers except those
+starting with "connect:".
+
+## Environment Variables
+
+When running through Node.js, you can set a few environment variables that will
+change the behavior of the debug logging:
+
+| Name      | Purpose                                         |
+|-----------|-------------------------------------------------|
+| `DEBUG`   | Enables/disables specific debugging namespaces. |
+| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY).  |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth.                    |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+__Note:__ The environment variables beginning with `DEBUG_` end up being
+converted into an Options object that gets used with `%o`/`%O` formatters.
+See the Node.js documentation for
+[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+for the complete list.
+
+## Formatters
+
+Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.
+Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O`      | Pretty-print an Object on multiple lines. |
+| `%o`      | Pretty-print an Object all on a single line. |
+| `%s`      | String. |
+| `%d`      | Number (both integer and float). |
+| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%`      | Single percent sign ('%'). This does not consume an argument. |
+
+
+### Custom formatters
+
+You can add custom formatters by extending the `debug.formatters` object.
+For example, if you wanted to add support for rendering a Buffer as hex with
+`%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+  return v.toString('hex')
+}
+
+// …elsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+//   foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+
+## Browser Support
+
+You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+if you don't want to build it yourself.
+
+Debug's enable state is currently persisted by `localStorage`.
+Consider the situation shown below where you have `worker:a` and `worker:b`,
+and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  b('doing some work');
+}, 1200);
+```
+
+
+## Output streams
+
+  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example [_stdout.js_](./examples/node/stdout.js):
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+## Extend
+You can simply extend debugger 
+```js
+const log = require('debug')('auth');
+
+//creates new debug instance with extended namespace
+const logSign = log.extend('sign');
+const logLogin = log.extend('login');
+
+log('hello'); // auth hello
+logSign('hello'); //auth:sign hello
+logLogin('hello'); //auth:login hello
+```
+
+## Set dynamically
+
+You can also enable debug dynamically by calling the `enable()` method :
+
+```js
+let debug = require('debug');
+
+console.log(1, debug.enabled('test'));
+
+debug.enable('test');
+console.log(2, debug.enabled('test'));
+
+debug.disable();
+console.log(3, debug.enabled('test'));
+
+```
+
+print :   
+```
+1 false
+2 true
+3 false
+```
+
+Usage :  
+`enable(namespaces)`  
+`namespaces` can include modes separated by a colon and wildcards.
+   
+Note that calling `enable()` completely overrides previously set DEBUG variable : 
+
+```
+$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
+=> false
+```
+
+## Checking whether a debug target is enabled
+
+After you've created a debug instance, you can determine whether or not it is
+enabled by checking the `enabled` property:
+
+```javascript
+const debug = require('debug')('http');
+
+if (debug.enabled) {
+  // do stuff...
+}
+```
+
+You can also manually toggle this property to force the debug instance to be
+enabled or disabled.
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2017 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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/input_devices/mag/node_modules/debug/dist/debug.js b/input_devices/mag/node_modules/debug/dist/debug.js
new file mode 100644
index 00000000..f271e01c
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/dist/debug.js
@@ -0,0 +1,886 @@
+"use strict";
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+(function (f) {
+  if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object" && typeof module !== "undefined") {
+    module.exports = f();
+  } else if (typeof define === "function" && define.amd) {
+    define([], f);
+  } else {
+    var g;
+
+    if (typeof window !== "undefined") {
+      g = window;
+    } else if (typeof global !== "undefined") {
+      g = global;
+    } else if (typeof self !== "undefined") {
+      g = self;
+    } else {
+      g = this;
+    }
+
+    g.debug = f();
+  }
+})(function () {
+  var define, module, exports;
+  return function () {
+    function r(e, n, t) {
+      function o(i, f) {
+        if (!n[i]) {
+          if (!e[i]) {
+            var c = "function" == typeof require && require;
+            if (!f && c) return c(i, !0);
+            if (u) return u(i, !0);
+            var a = new Error("Cannot find module '" + i + "'");
+            throw a.code = "MODULE_NOT_FOUND", a;
+          }
+
+          var p = n[i] = {
+            exports: {}
+          };
+          e[i][0].call(p.exports, function (r) {
+            var n = e[i][1][r];
+            return o(n || r);
+          }, p, p.exports, r, e, n, t);
+        }
+
+        return n[i].exports;
+      }
+
+      for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) {
+        o(t[i]);
+      }
+
+      return o;
+    }
+
+    return r;
+  }()({
+    1: [function (require, module, exports) {
+      /**
+       * Helpers.
+       */
+      var s = 1000;
+      var m = s * 60;
+      var h = m * 60;
+      var d = h * 24;
+      var w = d * 7;
+      var y = d * 365.25;
+      /**
+       * Parse or format the given `val`.
+       *
+       * Options:
+       *
+       *  - `long` verbose formatting [false]
+       *
+       * @param {String|Number} val
+       * @param {Object} [options]
+       * @throws {Error} throw an error if val is not a non-empty string or a number
+       * @return {String|Number}
+       * @api public
+       */
+
+      module.exports = function (val, options) {
+        options = options || {};
+
+        var type = _typeof(val);
+
+        if (type === 'string' && val.length > 0) {
+          return parse(val);
+        } else if (type === 'number' && isNaN(val) === false) {
+          return options.long ? fmtLong(val) : fmtShort(val);
+        }
+
+        throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val));
+      };
+      /**
+       * Parse the given `str` and return milliseconds.
+       *
+       * @param {String} str
+       * @return {Number}
+       * @api private
+       */
+
+
+      function parse(str) {
+        str = String(str);
+
+        if (str.length > 100) {
+          return;
+        }
+
+        var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);
+
+        if (!match) {
+          return;
+        }
+
+        var n = parseFloat(match[1]);
+        var type = (match[2] || 'ms').toLowerCase();
+
+        switch (type) {
+          case 'years':
+          case 'year':
+          case 'yrs':
+          case 'yr':
+          case 'y':
+            return n * y;
+
+          case 'weeks':
+          case 'week':
+          case 'w':
+            return n * w;
+
+          case 'days':
+          case 'day':
+          case 'd':
+            return n * d;
+
+          case 'hours':
+          case 'hour':
+          case 'hrs':
+          case 'hr':
+          case 'h':
+            return n * h;
+
+          case 'minutes':
+          case 'minute':
+          case 'mins':
+          case 'min':
+          case 'm':
+            return n * m;
+
+          case 'seconds':
+          case 'second':
+          case 'secs':
+          case 'sec':
+          case 's':
+            return n * s;
+
+          case 'milliseconds':
+          case 'millisecond':
+          case 'msecs':
+          case 'msec':
+          case 'ms':
+            return n;
+
+          default:
+            return undefined;
+        }
+      }
+      /**
+       * Short format for `ms`.
+       *
+       * @param {Number} ms
+       * @return {String}
+       * @api private
+       */
+
+
+      function fmtShort(ms) {
+        var msAbs = Math.abs(ms);
+
+        if (msAbs >= d) {
+          return Math.round(ms / d) + 'd';
+        }
+
+        if (msAbs >= h) {
+          return Math.round(ms / h) + 'h';
+        }
+
+        if (msAbs >= m) {
+          return Math.round(ms / m) + 'm';
+        }
+
+        if (msAbs >= s) {
+          return Math.round(ms / s) + 's';
+        }
+
+        return ms + 'ms';
+      }
+      /**
+       * Long format for `ms`.
+       *
+       * @param {Number} ms
+       * @return {String}
+       * @api private
+       */
+
+
+      function fmtLong(ms) {
+        var msAbs = Math.abs(ms);
+
+        if (msAbs >= d) {
+          return plural(ms, msAbs, d, 'day');
+        }
+
+        if (msAbs >= h) {
+          return plural(ms, msAbs, h, 'hour');
+        }
+
+        if (msAbs >= m) {
+          return plural(ms, msAbs, m, 'minute');
+        }
+
+        if (msAbs >= s) {
+          return plural(ms, msAbs, s, 'second');
+        }
+
+        return ms + ' ms';
+      }
+      /**
+       * Pluralization helper.
+       */
+
+
+      function plural(ms, msAbs, n, name) {
+        var isPlural = msAbs >= n * 1.5;
+        return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
+      }
+    }, {}],
+    2: [function (require, module, exports) {
+      // shim for using process in browser
+      var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it
+      // don't break things.  But we need to wrap it in a try catch in case it is
+      // wrapped in strict mode code which doesn't define any globals.  It's inside a
+      // function because try/catches deoptimize in certain engines.
+
+      var cachedSetTimeout;
+      var cachedClearTimeout;
+
+      function defaultSetTimout() {
+        throw new Error('setTimeout has not been defined');
+      }
+
+      function defaultClearTimeout() {
+        throw new Error('clearTimeout has not been defined');
+      }
+
+      (function () {
+        try {
+          if (typeof setTimeout === 'function') {
+            cachedSetTimeout = setTimeout;
+          } else {
+            cachedSetTimeout = defaultSetTimout;
+          }
+        } catch (e) {
+          cachedSetTimeout = defaultSetTimout;
+        }
+
+        try {
+          if (typeof clearTimeout === 'function') {
+            cachedClearTimeout = clearTimeout;
+          } else {
+            cachedClearTimeout = defaultClearTimeout;
+          }
+        } catch (e) {
+          cachedClearTimeout = defaultClearTimeout;
+        }
+      })();
+
+      function runTimeout(fun) {
+        if (cachedSetTimeout === setTimeout) {
+          //normal enviroments in sane situations
+          return setTimeout(fun, 0);
+        } // if setTimeout wasn't available but was latter defined
+
+
+        if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+          cachedSetTimeout = setTimeout;
+          return setTimeout(fun, 0);
+        }
+
+        try {
+          // when when somebody has screwed with setTimeout but no I.E. maddness
+          return cachedSetTimeout(fun, 0);
+        } catch (e) {
+          try {
+            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+            return cachedSetTimeout.call(null, fun, 0);
+          } catch (e) {
+            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+            return cachedSetTimeout.call(this, fun, 0);
+          }
+        }
+      }
+
+      function runClearTimeout(marker) {
+        if (cachedClearTimeout === clearTimeout) {
+          //normal enviroments in sane situations
+          return clearTimeout(marker);
+        } // if clearTimeout wasn't available but was latter defined
+
+
+        if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+          cachedClearTimeout = clearTimeout;
+          return clearTimeout(marker);
+        }
+
+        try {
+          // when when somebody has screwed with setTimeout but no I.E. maddness
+          return cachedClearTimeout(marker);
+        } catch (e) {
+          try {
+            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+            return cachedClearTimeout.call(null, marker);
+          } catch (e) {
+            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+            return cachedClearTimeout.call(this, marker);
+          }
+        }
+      }
+
+      var queue = [];
+      var draining = false;
+      var currentQueue;
+      var queueIndex = -1;
+
+      function cleanUpNextTick() {
+        if (!draining || !currentQueue) {
+          return;
+        }
+
+        draining = false;
+
+        if (currentQueue.length) {
+          queue = currentQueue.concat(queue);
+        } else {
+          queueIndex = -1;
+        }
+
+        if (queue.length) {
+          drainQueue();
+        }
+      }
+
+      function drainQueue() {
+        if (draining) {
+          return;
+        }
+
+        var timeout = runTimeout(cleanUpNextTick);
+        draining = true;
+        var len = queue.length;
+
+        while (len) {
+          currentQueue = queue;
+          queue = [];
+
+          while (++queueIndex < len) {
+            if (currentQueue) {
+              currentQueue[queueIndex].run();
+            }
+          }
+
+          queueIndex = -1;
+          len = queue.length;
+        }
+
+        currentQueue = null;
+        draining = false;
+        runClearTimeout(timeout);
+      }
+
+      process.nextTick = function (fun) {
+        var args = new Array(arguments.length - 1);
+
+        if (arguments.length > 1) {
+          for (var i = 1; i < arguments.length; i++) {
+            args[i - 1] = arguments[i];
+          }
+        }
+
+        queue.push(new Item(fun, args));
+
+        if (queue.length === 1 && !draining) {
+          runTimeout(drainQueue);
+        }
+      }; // v8 likes predictible objects
+
+
+      function Item(fun, array) {
+        this.fun = fun;
+        this.array = array;
+      }
+
+      Item.prototype.run = function () {
+        this.fun.apply(null, this.array);
+      };
+
+      process.title = 'browser';
+      process.browser = true;
+      process.env = {};
+      process.argv = [];
+      process.version = ''; // empty string to avoid regexp issues
+
+      process.versions = {};
+
+      function noop() {}
+
+      process.on = noop;
+      process.addListener = noop;
+      process.once = noop;
+      process.off = noop;
+      process.removeListener = noop;
+      process.removeAllListeners = noop;
+      process.emit = noop;
+      process.prependListener = noop;
+      process.prependOnceListener = noop;
+
+      process.listeners = function (name) {
+        return [];
+      };
+
+      process.binding = function (name) {
+        throw new Error('process.binding is not supported');
+      };
+
+      process.cwd = function () {
+        return '/';
+      };
+
+      process.chdir = function (dir) {
+        throw new Error('process.chdir is not supported');
+      };
+
+      process.umask = function () {
+        return 0;
+      };
+    }, {}],
+    3: [function (require, module, exports) {
+      /**
+       * This is the common logic for both the Node.js and web browser
+       * implementations of `debug()`.
+       */
+      function setup(env) {
+        createDebug.debug = createDebug;
+        createDebug.default = createDebug;
+        createDebug.coerce = coerce;
+        createDebug.disable = disable;
+        createDebug.enable = enable;
+        createDebug.enabled = enabled;
+        createDebug.humanize = require('ms');
+        Object.keys(env).forEach(function (key) {
+          createDebug[key] = env[key];
+        });
+        /**
+        * Active `debug` instances.
+        */
+
+        createDebug.instances = [];
+        /**
+        * The currently active debug mode names, and names to skip.
+        */
+
+        createDebug.names = [];
+        createDebug.skips = [];
+        /**
+        * Map of special "%n" handling functions, for the debug "format" argument.
+        *
+        * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+        */
+
+        createDebug.formatters = {};
+        /**
+        * Selects a color for a debug namespace
+        * @param {String} namespace The namespace string for the for the debug instance to be colored
+        * @return {Number|String} An ANSI color code for the given namespace
+        * @api private
+        */
+
+        function selectColor(namespace) {
+          var hash = 0;
+
+          for (var i = 0; i < namespace.length; i++) {
+            hash = (hash << 5) - hash + namespace.charCodeAt(i);
+            hash |= 0; // Convert to 32bit integer
+          }
+
+          return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
+        }
+
+        createDebug.selectColor = selectColor;
+        /**
+        * Create a debugger with the given `namespace`.
+        *
+        * @param {String} namespace
+        * @return {Function}
+        * @api public
+        */
+
+        function createDebug(namespace) {
+          var prevTime;
+
+          function debug() {
+            for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+              args[_key] = arguments[_key];
+            }
+
+            // Disabled?
+            if (!debug.enabled) {
+              return;
+            }
+
+            var self = debug; // Set `diff` timestamp
+
+            var curr = Number(new Date());
+            var ms = curr - (prevTime || curr);
+            self.diff = ms;
+            self.prev = prevTime;
+            self.curr = curr;
+            prevTime = curr;
+            args[0] = createDebug.coerce(args[0]);
+
+            if (typeof args[0] !== 'string') {
+              // Anything else let's inspect with %O
+              args.unshift('%O');
+            } // Apply any `formatters` transformations
+
+
+            var index = 0;
+            args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {
+              // If we encounter an escaped % then don't increase the array index
+              if (match === '%%') {
+                return match;
+              }
+
+              index++;
+              var formatter = createDebug.formatters[format];
+
+              if (typeof formatter === 'function') {
+                var val = args[index];
+                match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`
+
+                args.splice(index, 1);
+                index--;
+              }
+
+              return match;
+            }); // Apply env-specific formatting (colors, etc.)
+
+            createDebug.formatArgs.call(self, args);
+            var logFn = self.log || createDebug.log;
+            logFn.apply(self, args);
+          }
+
+          debug.namespace = namespace;
+          debug.enabled = createDebug.enabled(namespace);
+          debug.useColors = createDebug.useColors();
+          debug.color = selectColor(namespace);
+          debug.destroy = destroy;
+          debug.extend = extend; // Debug.formatArgs = formatArgs;
+          // debug.rawLog = rawLog;
+          // env-specific initialization logic for debug instances
+
+          if (typeof createDebug.init === 'function') {
+            createDebug.init(debug);
+          }
+
+          createDebug.instances.push(debug);
+          return debug;
+        }
+
+        function destroy() {
+          var index = createDebug.instances.indexOf(this);
+
+          if (index !== -1) {
+            createDebug.instances.splice(index, 1);
+            return true;
+          }
+
+          return false;
+        }
+
+        function extend(namespace, delimiter) {
+          return createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
+        }
+        /**
+        * Enables a debug mode by namespaces. This can include modes
+        * separated by a colon and wildcards.
+        *
+        * @param {String} namespaces
+        * @api public
+        */
+
+
+        function enable(namespaces) {
+          createDebug.save(namespaces);
+          createDebug.names = [];
+          createDebug.skips = [];
+          var i;
+          var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+          var len = split.length;
+
+          for (i = 0; i < len; i++) {
+            if (!split[i]) {
+              // ignore empty strings
+              continue;
+            }
+
+            namespaces = split[i].replace(/\*/g, '.*?');
+
+            if (namespaces[0] === '-') {
+              createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+            } else {
+              createDebug.names.push(new RegExp('^' + namespaces + '$'));
+            }
+          }
+
+          for (i = 0; i < createDebug.instances.length; i++) {
+            var instance = createDebug.instances[i];
+            instance.enabled = createDebug.enabled(instance.namespace);
+          }
+        }
+        /**
+        * Disable debug output.
+        *
+        * @api public
+        */
+
+
+        function disable() {
+          createDebug.enable('');
+        }
+        /**
+        * Returns true if the given mode name is enabled, false otherwise.
+        *
+        * @param {String} name
+        * @return {Boolean}
+        * @api public
+        */
+
+
+        function enabled(name) {
+          if (name[name.length - 1] === '*') {
+            return true;
+          }
+
+          var i;
+          var len;
+
+          for (i = 0, len = createDebug.skips.length; i < len; i++) {
+            if (createDebug.skips[i].test(name)) {
+              return false;
+            }
+          }
+
+          for (i = 0, len = createDebug.names.length; i < len; i++) {
+            if (createDebug.names[i].test(name)) {
+              return true;
+            }
+          }
+
+          return false;
+        }
+        /**
+        * Coerce `val`.
+        *
+        * @param {Mixed} val
+        * @return {Mixed}
+        * @api private
+        */
+
+
+        function coerce(val) {
+          if (val instanceof Error) {
+            return val.stack || val.message;
+          }
+
+          return val;
+        }
+
+        createDebug.enable(createDebug.load());
+        return createDebug;
+      }
+
+      module.exports = setup;
+    }, {
+      "ms": 1
+    }],
+    4: [function (require, module, exports) {
+      (function (process) {
+        /* eslint-env browser */
+
+        /**
+         * This is the web browser implementation of `debug()`.
+         */
+        exports.log = log;
+        exports.formatArgs = formatArgs;
+        exports.save = save;
+        exports.load = load;
+        exports.useColors = useColors;
+        exports.storage = localstorage();
+        /**
+         * Colors.
+         */
+
+        exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];
+        /**
+         * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+         * and the Firebug extension (any Firefox version) are known
+         * to support "%c" CSS customizations.
+         *
+         * TODO: add a `localStorage` variable to explicitly enable/disable colors
+         */
+        // eslint-disable-next-line complexity
+
+        function useColors() {
+          // NB: In an Electron preload script, document will be defined but not fully
+          // initialized. Since we know we're in Chrome, we'll just detect this case
+          // explicitly
+          if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
+            return true;
+          } // Internet Explorer and Edge do not support colors.
+
+
+          if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
+            return false;
+          } // Is webkit? http://stackoverflow.com/a/16459606/376773
+          // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+
+
+          return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
+          typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
+          // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+          typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
+          typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
+        }
+        /**
+         * Colorize log arguments if enabled.
+         *
+         * @api public
+         */
+
+
+        function formatArgs(args) {
+          args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);
+
+          if (!this.useColors) {
+            return;
+          }
+
+          var c = 'color: ' + this.color;
+          args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other
+          // arguments passed either before or after the %c, so we need to
+          // figure out the correct index to insert the CSS into
+
+          var index = 0;
+          var lastC = 0;
+          args[0].replace(/%[a-zA-Z%]/g, function (match) {
+            if (match === '%%') {
+              return;
+            }
+
+            index++;
+
+            if (match === '%c') {
+              // We only are interested in the *last* %c
+              // (the user may have provided their own)
+              lastC = index;
+            }
+          });
+          args.splice(lastC, 0, c);
+        }
+        /**
+         * Invokes `console.log()` when available.
+         * No-op when `console.log` is not a "function".
+         *
+         * @api public
+         */
+
+
+        function log() {
+          var _console;
+
+          // This hackery is required for IE8/9, where
+          // the `console.log` function doesn't have 'apply'
+          return (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);
+        }
+        /**
+         * Save `namespaces`.
+         *
+         * @param {String} namespaces
+         * @api private
+         */
+
+
+        function save(namespaces) {
+          try {
+            if (namespaces) {
+              exports.storage.setItem('debug', namespaces);
+            } else {
+              exports.storage.removeItem('debug');
+            }
+          } catch (error) {// Swallow
+            // XXX (@Qix-) should we be logging these?
+          }
+        }
+        /**
+         * Load `namespaces`.
+         *
+         * @return {String} returns the previously persisted debug modes
+         * @api private
+         */
+
+
+        function load() {
+          var r;
+
+          try {
+            r = exports.storage.getItem('debug');
+          } catch (error) {} // Swallow
+          // XXX (@Qix-) should we be logging these?
+          // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+
+
+          if (!r && typeof process !== 'undefined' && 'env' in process) {
+            r = process.env.DEBUG;
+          }
+
+          return r;
+        }
+        /**
+         * Localstorage attempts to return the localstorage.
+         *
+         * This is necessary because safari throws
+         * when a user disables cookies/localstorage
+         * and you attempt to access it.
+         *
+         * @return {LocalStorage}
+         * @api private
+         */
+
+
+        function localstorage() {
+          try {
+            // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
+            // The Browser also has localStorage in the global context.
+            return localStorage;
+          } catch (error) {// Swallow
+            // XXX (@Qix-) should we be logging these?
+          }
+        }
+
+        module.exports = require('./common')(exports);
+        var formatters = module.exports.formatters;
+        /**
+         * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+         */
+
+        formatters.j = function (v) {
+          try {
+            return JSON.stringify(v);
+          } catch (error) {
+            return '[UnexpectedJSONParseError]: ' + error.message;
+          }
+        };
+      }).call(this, require('_process'));
+    }, {
+      "./common": 3,
+      "_process": 2
+    }]
+  }, {}, [4])(4);
+});
+
diff --git a/input_devices/mag/node_modules/debug/node.js b/input_devices/mag/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/input_devices/mag/node_modules/debug/package.json b/input_devices/mag/node_modules/debug/package.json
new file mode 100644
index 00000000..e9b74381
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/package.json
@@ -0,0 +1,142 @@
+{
+  "_args": [
+    [
+      "debug@^3.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "debug@>=3.1.0 <4.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "debug@3.2.6",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/debug",
+  "_nodeVersion": "10.10.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/debug_3.2.6_1539154080132_0.756699343768702"
+  },
+  "_npmUser": {
+    "email": "i.am.qix@gmail.com",
+    "name": "qix"
+  },
+  "_npmVersion": "6.1.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "debug",
+    "raw": "debug@^3.1.0",
+    "rawSpec": "^3.1.0",
+    "scope": null,
+    "spec": ">=3.1.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/binding-abstract",
+    "/@serialport/binding-mock",
+    "/@serialport/bindings",
+    "/@serialport/stream",
+    "/prompt-base",
+    "/prompt-question",
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+  "_shasum": "e83d17de16d8a7efb7717edbe5fb10135eee629b",
+  "_shrinkwrap": null,
+  "_spec": "debug@^3.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "browser": "./src/browser.js",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "contributors": [
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "http://n8.io"
+    },
+    {
+      "name": "Andrew Rhyne",
+      "email": "rhyneandrew@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "ms": "^2.1.1"
+  },
+  "description": "small debugging utility",
+  "devDependencies": {
+    "@babel/cli": "^7.0.0",
+    "@babel/core": "^7.0.0",
+    "@babel/preset-env": "^7.0.0",
+    "browserify": "14.4.0",
+    "chai": "^3.5.0",
+    "concurrently": "^3.1.0",
+    "coveralls": "^3.0.2",
+    "istanbul": "^0.4.5",
+    "karma": "^3.0.0",
+    "karma-chai": "^0.1.0",
+    "karma-mocha": "^1.3.0",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "mocha": "^5.2.0",
+    "mocha-lcov-reporter": "^1.2.0",
+    "rimraf": "^2.5.4",
+    "xo": "^0.23.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 10,
+    "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvaCgCRA9TVsSAnZWagAAhucQAJjxFVneDDxkspue4yaR\nlpOoIrP8ms/Oek53bmD1y/qlwsfpS/Y/KnS1yL/qSQkEAL2qYAETIMie3Op5\niP03s2xTTrVwCUDCEtTO7oMnl6kApMiexgUkop4eznA+AfEdz/jInFiN/yDU\ntHoR1UV0bIOSccVhrjH2aTt/96AETu8B7x8J722gjPUGDni2luYM+r2V8XYh\nN/9/kNn6HN1FjfOUl662iZTLE8OAVbrnmfVS6etTiG2SSLI898s+goyOD32K\nduwANgqjKrlvSxlMxKFr46G8GR+Otk9rOwsFO7yiufJ62dYefJIw6sfWYGXa\n8joI2StGT6p9T6iTN9959Y6naoSrN0cb3DocOjGQMrxUoBugoBWKd4fD+ACU\nMN3VA2PN8cZIh5eLu5IsJAECy4frUKpzbPYR129/Rtx0K7syhcvSwBqRE4Pb\nPNDHdddx1bix8m+xyT6sAiaWym9x+WX7GPuQAlCM5xZ4lFzjNpu5LgxpIbHo\njtRF6SLdMDBSImhH6NyPcw374QT+zwOc8l2G506RfBA5bB2fsYUBLrIXLkxm\n/CzEphFk++bPvYDiCy2EFUJW5MjnschBV65QUZBdBSg2YJnl3yGS8QHC8AR0\nM1IcRqI8NUlpTByPVoc7GoevruOjXxk+B+dflYRvBNwBMDatSA0eYT9aILK0\nJp/G\r\n=QKY3\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "e83d17de16d8a7efb7717edbe5fb10135eee629b",
+    "tarball": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+    "unpackedSize": 79525
+  },
+  "gitHead": "a7a17c9955460435592de2a4d3c722e9b32047a8",
+  "homepage": "https://github.com/visionmedia/debug#readme",
+  "keywords": [
+    "debug",
+    "debugger",
+    "log"
+  ],
+  "license": "MIT",
+  "main": "./src/index.js",
+  "maintainers": [
+    {
+      "name": "kolban",
+      "email": "kolban1@kolban.com"
+    },
+    {
+      "name": "qix",
+      "email": "i.am.qix@gmail.com"
+    },
+    {
+      "name": "qix-",
+      "email": "i.am.qix@gmail.com"
+    },
+    {
+      "name": "thebigredgeek",
+      "email": "rhyneandrew@gmail.com"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    }
+  ],
+  "name": "debug",
+  "optionalDependencies": {},
+  "readme": "# debug\n[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers)\n[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)\n\n<img width=\"647\" src=\"https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png\">\n\nA tiny JavaScript debugging utility modelled after Node.js core's debugging\ntechnique. Works in Node.js and web browsers.\n\n## Installation\n\n```bash\n$ npm install debug\n```\n\n## Usage\n\n`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.\n\nExample [_app.js_](./examples/node/app.js):\n\n```js\nvar debug = require('debug')('http')\n  , http = require('http')\n  , name = 'My App';\n\n// fake app\n\ndebug('booting %o', name);\n\nhttp.createServer(function(req, res){\n  debug(req.method + ' ' + req.url);\n  res.end('hello\\n');\n}).listen(3000, function(){\n  debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample [_worker.js_](./examples/node/worker.js):\n\n```js\nvar a = require('debug')('worker:a')\n  , b = require('debug')('worker:b');\n\nfunction work() {\n  a('doing lots of uninteresting work');\n  setTimeout(work, Math.random() * 1000);\n}\n\nwork();\n\nfunction workb() {\n  b('doing some work');\n  setTimeout(workb, Math.random() * 2000);\n}\n\nworkb();\n```\n\nThe `DEBUG` environment variable is then used to enable these based on space or\ncomma-delimited names.\n\nHere are some examples:\n\n<img width=\"647\" alt=\"screen shot 2017-08-08 at 12 53 04 pm\" src=\"https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png\">\n<img width=\"647\" alt=\"screen shot 2017-08-08 at 12 53 38 pm\" src=\"https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png\">\n<img width=\"647\" alt=\"screen shot 2017-08-08 at 12 53 25 pm\" src=\"https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png\">\n\n#### Windows command prompt notes\n\n##### CMD\n\nOn Windows the environment variable is set using the `set` command.\n\n```cmd\nset DEBUG=*,-not_this\n```\n\nExample:\n\n```cmd\nset DEBUG=* & node app.js\n```\n\n##### PowerShell (VS Code default)\n\nPowerShell uses different syntax to set environment variables.\n\n```cmd\n$env:DEBUG = \"*,-not_this\"\n```\n\nExample:\n\n```cmd\n$env:DEBUG='app';node app.js\n```\n\nThen, run the program to be debugged as usual.\n\nnpm script example:\n```js\n  \"windowsDebug\": \"@powershell -Command $env:DEBUG='*';node app.js\",\n```\n\n## Namespace Colors\n\nEvery debug instance has a color generated for it based on its namespace name.\nThis helps when visually parsing the debug output to identify which debug instance\na debug line belongs to.\n\n#### Node.js\n\nIn Node.js, colors are enabled when stderr is a TTY. You also _should_ install\nthe [`supports-color`](https://npmjs.org/supports-color) module alongside debug,\notherwise debug will only use a small handful of basic colors.\n\n<img width=\"521\" src=\"https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png\">\n\n#### Web Browser\n\nColors are also enabled on \"Web Inspectors\" that understand the `%c` formatting\noption. These are WebKit web inspectors, Firefox ([since version\n31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))\nand the Firebug plugin for Firefox (any version).\n\n<img width=\"524\" src=\"https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png\">\n\n\n## Millisecond diff\n\nWhen actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n<img width=\"647\" src=\"https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png\">\n\nWhen stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:\n\n<img width=\"647\" src=\"https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.png\">\n\n\n## Conventions\n\nIf you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\".  If you append a \"*\" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable.  You can then use it for normal output as well as debug output.\n\n## Wildcards\n\nThe `*` character may be used as a wildcard. Suppose for example your library has\ndebuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\",\ninstead of listing all three with\n`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do\n`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\nYou can also exclude specific debuggers by prefixing them with a \"-\" character.\nFor example, `DEBUG=*,-connect:*` would include all debuggers except those\nstarting with \"connect:\".\n\n## Environment Variables\n\nWhen running through Node.js, you can set a few environment variables that will\nchange the behavior of the debug logging:\n\n| Name      | Purpose                                         |\n|-----------|-------------------------------------------------|\n| `DEBUG`   | Enables/disables specific debugging namespaces. |\n| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY).  |\n| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |\n| `DEBUG_DEPTH` | Object inspection depth.                    |\n| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |\n\n\n__Note:__ The environment variables beginning with `DEBUG_` end up being\nconverted into an Options object that gets used with `%o`/`%O` formatters.\nSee the Node.js documentation for\n[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)\nfor the complete list.\n\n## Formatters\n\nDebug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.\nBelow are the officially supported formatters:\n\n| Formatter | Representation |\n|-----------|----------------|\n| `%O`      | Pretty-print an Object on multiple lines. |\n| `%o`      | Pretty-print an Object all on a single line. |\n| `%s`      | String. |\n| `%d`      | Number (both integer and float). |\n| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |\n| `%%`      | Single percent sign ('%'). This does not consume an argument. |\n\n\n### Custom formatters\n\nYou can add custom formatters by extending the `debug.formatters` object.\nFor example, if you wanted to add support for rendering a Buffer as hex with\n`%h`, you could do something like:\n\n```js\nconst createDebug = require('debug')\ncreateDebug.formatters.h = (v) => {\n  return v.toString('hex')\n}\n\n// …elsewhere\nconst debug = createDebug('foo')\ndebug('this is hex: %h', new Buffer('hello world'))\n//   foo this is hex: 68656c6c6f20776f726c6421 +0ms\n```\n\n\n## Browser Support\n\nYou can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),\nor just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),\nif you don't want to build it yourself.\n\nDebug's enable state is currently persisted by `localStorage`.\nConsider the situation shown below where you have `worker:a` and `worker:b`,\nand wish to debug both. You can enable this using `localStorage.debug`:\n\n```js\nlocalStorage.debug = 'worker:*'\n```\n\nAnd then refresh the page.\n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n  a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n  b('doing some work');\n}, 1200);\n```\n\n\n## Output streams\n\n  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:\n\nExample [_stdout.js_](./examples/node/stdout.js):\n\n```js\nvar debug = require('debug');\nvar error = debug('app:error');\n\n// by default stderr is used\nerror('goes to stderr!');\n\nvar log = debug('app:log');\n// set this namespace to log via console.log\nlog.log = console.log.bind(console); // don't forget to bind to console!\nlog('goes to stdout');\nerror('still goes to stderr!');\n\n// set all output to go via console.info\n// overrides all per-namespace log settings\ndebug.log = console.info.bind(console);\nerror('now goes to stdout via console.info');\nlog('still goes to stdout, but via console.info now');\n```\n\n## Extend\nYou can simply extend debugger \n```js\nconst log = require('debug')('auth');\n\n//creates new debug instance with extended namespace\nconst logSign = log.extend('sign');\nconst logLogin = log.extend('login');\n\nlog('hello'); // auth hello\nlogSign('hello'); //auth:sign hello\nlogLogin('hello'); //auth:login hello\n```\n\n## Set dynamically\n\nYou can also enable debug dynamically by calling the `enable()` method :\n\n```js\nlet debug = require('debug');\n\nconsole.log(1, debug.enabled('test'));\n\ndebug.enable('test');\nconsole.log(2, debug.enabled('test'));\n\ndebug.disable();\nconsole.log(3, debug.enabled('test'));\n\n```\n\nprint :   \n```\n1 false\n2 true\n3 false\n```\n\nUsage :  \n`enable(namespaces)`  \n`namespaces` can include modes separated by a colon and wildcards.\n   \nNote that calling `enable()` completely overrides previously set DEBUG variable : \n\n```\n$ DEBUG=foo node -e 'var dbg = require(\"debug\"); dbg.enable(\"bar\"); console.log(dbg.enabled(\"foo\"))'\n=> false\n```\n\n## Checking whether a debug target is enabled\n\nAfter you've created a debug instance, you can determine whether or not it is\nenabled by checking the `enabled` property:\n\n```javascript\nconst debug = require('debug')('http');\n\nif (debug.enabled) {\n  // do stuff...\n}\n```\n\nYou can also manually toggle this property to force the debug instance to be\nenabled or disabled.\n\n\n## Authors\n\n - TJ Holowaychuk\n - Nathan Rajlich\n - Andrew Rhyne\n\n## Backers\n\nSupport us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]\n\n<a href=\"https://opencollective.com/debug/backer/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/9/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/10/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/10/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/11/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/11/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/12/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/12/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/13/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/13/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/14/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/14/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/15/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/15/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/16/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/16/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/17/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/17/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/18/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/18/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/19/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/19/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/20/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/20/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/21/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/21/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/22/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/22/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/23/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/23/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/24/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/24/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/25/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/25/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/26/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/26/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/27/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/27/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/28/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/28/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/backer/29/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/backer/29/avatar.svg\"></a>\n\n\n## Sponsors\n\nBecome a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]\n\n<a href=\"https://opencollective.com/debug/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/9/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/10/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/10/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/11/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/11/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/12/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/12/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/13/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/13/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/14/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/14/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/15/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/15/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/16/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/16/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/17/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/17/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/18/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/18/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/19/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/19/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/20/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/20/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/21/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/21/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/22/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/22/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/23/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/23/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/24/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/24/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/25/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/25/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/26/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/26/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/27/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/27/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/28/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/28/avatar.svg\"></a>\n<a href=\"https://opencollective.com/debug/sponsor/29/website\" target=\"_blank\"><img src=\"https://opencollective.com/debug/sponsor/29/avatar.svg\"></a>\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2014-2017 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
+  "readmeFilename": "README.md",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "unpkg": "./dist/debug.js",
+  "version": "3.2.6"
+}
diff --git a/input_devices/mag/node_modules/debug/src/browser.js b/input_devices/mag/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..c924b0ac
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/src/browser.js
@@ -0,0 +1,180 @@
+"use strict";
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+/* eslint-env browser */
+
+/**
+ * This is the web browser implementation of `debug()`.
+ */
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = localstorage();
+/**
+ * Colors.
+ */
+
+exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+// eslint-disable-next-line complexity
+
+function useColors() {
+  // NB: In an Electron preload script, document will be defined but not fully
+  // initialized. Since we know we're in Chrome, we'll just detect this case
+  // explicitly
+  if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
+    return true;
+  } // Internet Explorer and Edge do not support colors.
+
+
+  if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
+    return false;
+  } // Is webkit? http://stackoverflow.com/a/16459606/376773
+  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+
+
+  return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
+  typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
+  // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
+  typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
+}
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+
+function formatArgs(args) {
+  args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);
+
+  if (!this.useColors) {
+    return;
+  }
+
+  var c = 'color: ' + this.color;
+  args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other
+  // arguments passed either before or after the %c, so we need to
+  // figure out the correct index to insert the CSS into
+
+  var index = 0;
+  var lastC = 0;
+  args[0].replace(/%[a-zA-Z%]/g, function (match) {
+    if (match === '%%') {
+      return;
+    }
+
+    index++;
+
+    if (match === '%c') {
+      // We only are interested in the *last* %c
+      // (the user may have provided their own)
+      lastC = index;
+    }
+  });
+  args.splice(lastC, 0, c);
+}
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+
+function log() {
+  var _console;
+
+  // This hackery is required for IE8/9, where
+  // the `console.log` function doesn't have 'apply'
+  return (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);
+}
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+
+function save(namespaces) {
+  try {
+    if (namespaces) {
+      exports.storage.setItem('debug', namespaces);
+    } else {
+      exports.storage.removeItem('debug');
+    }
+  } catch (error) {// Swallow
+    // XXX (@Qix-) should we be logging these?
+  }
+}
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+
+function load() {
+  var r;
+
+  try {
+    r = exports.storage.getItem('debug');
+  } catch (error) {} // Swallow
+  // XXX (@Qix-) should we be logging these?
+  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+
+
+  if (!r && typeof process !== 'undefined' && 'env' in process) {
+    r = process.env.DEBUG;
+  }
+
+  return r;
+}
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+
+function localstorage() {
+  try {
+    // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
+    // The Browser also has localStorage in the global context.
+    return localStorage;
+  } catch (error) {// Swallow
+    // XXX (@Qix-) should we be logging these?
+  }
+}
+
+module.exports = require('./common')(exports);
+var formatters = module.exports.formatters;
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+formatters.j = function (v) {
+  try {
+    return JSON.stringify(v);
+  } catch (error) {
+    return '[UnexpectedJSONParseError]: ' + error.message;
+  }
+};
+
diff --git a/input_devices/mag/node_modules/debug/src/common.js b/input_devices/mag/node_modules/debug/src/common.js
new file mode 100644
index 00000000..e0de3fb5
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/src/common.js
@@ -0,0 +1,249 @@
+"use strict";
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ */
+function setup(env) {
+  createDebug.debug = createDebug;
+  createDebug.default = createDebug;
+  createDebug.coerce = coerce;
+  createDebug.disable = disable;
+  createDebug.enable = enable;
+  createDebug.enabled = enabled;
+  createDebug.humanize = require('ms');
+  Object.keys(env).forEach(function (key) {
+    createDebug[key] = env[key];
+  });
+  /**
+  * Active `debug` instances.
+  */
+
+  createDebug.instances = [];
+  /**
+  * The currently active debug mode names, and names to skip.
+  */
+
+  createDebug.names = [];
+  createDebug.skips = [];
+  /**
+  * Map of special "%n" handling functions, for the debug "format" argument.
+  *
+  * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+  */
+
+  createDebug.formatters = {};
+  /**
+  * Selects a color for a debug namespace
+  * @param {String} namespace The namespace string for the for the debug instance to be colored
+  * @return {Number|String} An ANSI color code for the given namespace
+  * @api private
+  */
+
+  function selectColor(namespace) {
+    var hash = 0;
+
+    for (var i = 0; i < namespace.length; i++) {
+      hash = (hash << 5) - hash + namespace.charCodeAt(i);
+      hash |= 0; // Convert to 32bit integer
+    }
+
+    return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
+  }
+
+  createDebug.selectColor = selectColor;
+  /**
+  * Create a debugger with the given `namespace`.
+  *
+  * @param {String} namespace
+  * @return {Function}
+  * @api public
+  */
+
+  function createDebug(namespace) {
+    var prevTime;
+
+    function debug() {
+      // Disabled?
+      if (!debug.enabled) {
+        return;
+      }
+
+      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+        args[_key] = arguments[_key];
+      }
+
+      var self = debug; // Set `diff` timestamp
+
+      var curr = Number(new Date());
+      var ms = curr - (prevTime || curr);
+      self.diff = ms;
+      self.prev = prevTime;
+      self.curr = curr;
+      prevTime = curr;
+      args[0] = createDebug.coerce(args[0]);
+
+      if (typeof args[0] !== 'string') {
+        // Anything else let's inspect with %O
+        args.unshift('%O');
+      } // Apply any `formatters` transformations
+
+
+      var index = 0;
+      args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {
+        // If we encounter an escaped % then don't increase the array index
+        if (match === '%%') {
+          return match;
+        }
+
+        index++;
+        var formatter = createDebug.formatters[format];
+
+        if (typeof formatter === 'function') {
+          var val = args[index];
+          match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`
+
+          args.splice(index, 1);
+          index--;
+        }
+
+        return match;
+      }); // Apply env-specific formatting (colors, etc.)
+
+      createDebug.formatArgs.call(self, args);
+      var logFn = self.log || createDebug.log;
+      logFn.apply(self, args);
+    }
+
+    debug.namespace = namespace;
+    debug.enabled = createDebug.enabled(namespace);
+    debug.useColors = createDebug.useColors();
+    debug.color = selectColor(namespace);
+    debug.destroy = destroy;
+    debug.extend = extend; // Debug.formatArgs = formatArgs;
+    // debug.rawLog = rawLog;
+    // env-specific initialization logic for debug instances
+
+    if (typeof createDebug.init === 'function') {
+      createDebug.init(debug);
+    }
+
+    createDebug.instances.push(debug);
+    return debug;
+  }
+
+  function destroy() {
+    var index = createDebug.instances.indexOf(this);
+
+    if (index !== -1) {
+      createDebug.instances.splice(index, 1);
+      return true;
+    }
+
+    return false;
+  }
+
+  function extend(namespace, delimiter) {
+    return createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
+  }
+  /**
+  * Enables a debug mode by namespaces. This can include modes
+  * separated by a colon and wildcards.
+  *
+  * @param {String} namespaces
+  * @api public
+  */
+
+
+  function enable(namespaces) {
+    createDebug.save(namespaces);
+    createDebug.names = [];
+    createDebug.skips = [];
+    var i;
+    var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+    var len = split.length;
+
+    for (i = 0; i < len; i++) {
+      if (!split[i]) {
+        // ignore empty strings
+        continue;
+      }
+
+      namespaces = split[i].replace(/\*/g, '.*?');
+
+      if (namespaces[0] === '-') {
+        createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+      } else {
+        createDebug.names.push(new RegExp('^' + namespaces + '$'));
+      }
+    }
+
+    for (i = 0; i < createDebug.instances.length; i++) {
+      var instance = createDebug.instances[i];
+      instance.enabled = createDebug.enabled(instance.namespace);
+    }
+  }
+  /**
+  * Disable debug output.
+  *
+  * @api public
+  */
+
+
+  function disable() {
+    createDebug.enable('');
+  }
+  /**
+  * Returns true if the given mode name is enabled, false otherwise.
+  *
+  * @param {String} name
+  * @return {Boolean}
+  * @api public
+  */
+
+
+  function enabled(name) {
+    if (name[name.length - 1] === '*') {
+      return true;
+    }
+
+    var i;
+    var len;
+
+    for (i = 0, len = createDebug.skips.length; i < len; i++) {
+      if (createDebug.skips[i].test(name)) {
+        return false;
+      }
+    }
+
+    for (i = 0, len = createDebug.names.length; i < len; i++) {
+      if (createDebug.names[i].test(name)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+  /**
+  * Coerce `val`.
+  *
+  * @param {Mixed} val
+  * @return {Mixed}
+  * @api private
+  */
+
+
+  function coerce(val) {
+    if (val instanceof Error) {
+      return val.stack || val.message;
+    }
+
+    return val;
+  }
+
+  createDebug.enable(createDebug.load());
+  return createDebug;
+}
+
+module.exports = setup;
+
diff --git a/input_devices/mag/node_modules/debug/src/index.js b/input_devices/mag/node_modules/debug/src/index.js
new file mode 100644
index 00000000..02173159
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/src/index.js
@@ -0,0 +1,12 @@
+"use strict";
+
+/**
+ * Detect Electron renderer / nwjs process, which is node, but we should
+ * treat as a browser.
+ */
+if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
+  module.exports = require('./browser.js');
+} else {
+  module.exports = require('./node.js');
+}
+
diff --git a/input_devices/mag/node_modules/debug/src/node.js b/input_devices/mag/node_modules/debug/src/node.js
new file mode 100644
index 00000000..dbbb5f10
--- /dev/null
+++ b/input_devices/mag/node_modules/debug/src/node.js
@@ -0,0 +1,174 @@
+"use strict";
+
+/**
+ * Module dependencies.
+ */
+var tty = require('tty');
+
+var util = require('util');
+/**
+ * This is the Node.js implementation of `debug()`.
+ */
+
+
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+try {
+  // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
+  // eslint-disable-next-line import/no-extraneous-dependencies
+  var supportsColor = require('supports-color');
+
+  if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
+    exports.colors = [20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 220, 221];
+  }
+} catch (error) {} // Swallow - we only care if `supports-color` is available; it doesn't have to be.
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+  return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+  // Camel-case
+  var prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, function (_, k) {
+    return k.toUpperCase();
+  }); // Coerce string value into JS value
+
+  var val = process.env[key];
+
+  if (/^(yes|on|true|enabled)$/i.test(val)) {
+    val = true;
+  } else if (/^(no|off|false|disabled)$/i.test(val)) {
+    val = false;
+  } else if (val === 'null') {
+    val = null;
+  } else {
+    val = Number(val);
+  }
+
+  obj[prop] = val;
+  return obj;
+}, {});
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+  return 'colors' in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd);
+}
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+
+function formatArgs(args) {
+  var name = this.namespace,
+      useColors = this.useColors;
+
+  if (useColors) {
+    var c = this.color;
+    var colorCode = "\x1B[3" + (c < 8 ? c : '8;5;' + c);
+    var prefix = "  ".concat(colorCode, ";1m").concat(name, " \x1B[0m");
+    args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+    args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + "\x1B[0m");
+  } else {
+    args[0] = getDate() + name + ' ' + args[0];
+  }
+}
+
+function getDate() {
+  if (exports.inspectOpts.hideDate) {
+    return '';
+  }
+
+  return new Date().toISOString() + ' ';
+}
+/**
+ * Invokes `util.format()` with the specified arguments and writes to stderr.
+ */
+
+
+function log() {
+  return process.stderr.write(util.format.apply(util, arguments) + '\n');
+}
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+
+function save(namespaces) {
+  if (namespaces) {
+    process.env.DEBUG = namespaces;
+  } else {
+    // If you set a process.env field to null or undefined, it gets cast to the
+    // string 'null' or 'undefined'. Just delete instead.
+    delete process.env.DEBUG;
+  }
+}
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+
+function load() {
+  return process.env.DEBUG;
+}
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+
+function init(debug) {
+  debug.inspectOpts = {};
+  var keys = Object.keys(exports.inspectOpts);
+
+  for (var i = 0; i < keys.length; i++) {
+    debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+  }
+}
+
+module.exports = require('./common')(exports);
+var formatters = module.exports.formatters;
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+formatters.o = function (v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts).replace(/\s*\n\s*/g, ' ');
+};
+/**
+ * Map %O to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+
+formatters.O = function (v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts);
+};
+
diff --git a/input_devices/mag/node_modules/decompress-response/index.js b/input_devices/mag/node_modules/decompress-response/index.js
new file mode 100644
index 00000000..d8acd4a3
--- /dev/null
+++ b/input_devices/mag/node_modules/decompress-response/index.js
@@ -0,0 +1,29 @@
+'use strict';
+const PassThrough = require('stream').PassThrough;
+const zlib = require('zlib');
+const mimicResponse = require('mimic-response');
+
+module.exports = response => {
+	// TODO: Use Array#includes when targeting Node.js 6
+	if (['gzip', 'deflate'].indexOf(response.headers['content-encoding']) === -1) {
+		return response;
+	}
+
+	const unzip = zlib.createUnzip();
+	const stream = new PassThrough();
+
+	mimicResponse(response, stream);
+
+	unzip.on('error', err => {
+		if (err.code === 'Z_BUF_ERROR') {
+			stream.end();
+			return;
+		}
+
+		stream.emit('error', err);
+	});
+
+	response.pipe(unzip).pipe(stream);
+
+	return stream;
+};
diff --git a/input_devices/mag/node_modules/decompress-response/license b/input_devices/mag/node_modules/decompress-response/license
new file mode 100644
index 00000000..32a16ce3
--- /dev/null
+++ b/input_devices/mag/node_modules/decompress-response/license
@@ -0,0 +1,21 @@
+`The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/decompress-response/package.json b/input_devices/mag/node_modules/decompress-response/package.json
new file mode 100644
index 00000000..4580d6ed
--- /dev/null
+++ b/input_devices/mag/node_modules/decompress-response/package.json
@@ -0,0 +1,100 @@
+{
+  "_args": [
+    [
+      "decompress-response@^3.3.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/simple-get"
+    ]
+  ],
+  "_from": "decompress-response@>=3.3.0 <4.0.0",
+  "_id": "decompress-response@3.3.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/decompress-response",
+  "_nodeVersion": "4.8.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/decompress-response-3.3.0.tgz_1496432627972_0.16955837607383728"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.15.11",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "decompress-response",
+    "raw": "decompress-response@^3.3.0",
+    "rawSpec": "^3.3.0",
+    "scope": null,
+    "spec": ">=3.3.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/simple-get"
+  ],
+  "_resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+  "_shasum": "80a4dd323748384bfa248083622aedec982adff3",
+  "_shrinkwrap": null,
+  "_spec": "decompress-response@^3.3.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/simple-get",
+  "bugs": {
+    "url": "https://github.com/sindresorhus/decompress-response/issues"
+  },
+  "dependencies": {
+    "mimic-response": "^1.0.0"
+  },
+  "description": "Decompress a HTTP response if needed",
+  "devDependencies": {
+    "ava": "*",
+    "get-stream": "^3.0.0",
+    "pify": "^3.0.0",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "80a4dd323748384bfa248083622aedec982adff3",
+    "tarball": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz"
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "dcd62471a9758f970cdcc9a33c104e8d37f366ee",
+  "homepage": "https://github.com/sindresorhus/decompress-response#readme",
+  "keywords": [
+    "compressed",
+    "decompress",
+    "deflate",
+    "gzip",
+    "http",
+    "https",
+    "incoming",
+    "message",
+    "response",
+    "stream",
+    "ungzip",
+    "unzip",
+    "zip",
+    "zlib"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "decompress-response",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/decompress-response.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "3.3.0"
+}
diff --git a/input_devices/mag/node_modules/decompress-response/readme.md b/input_devices/mag/node_modules/decompress-response/readme.md
new file mode 100644
index 00000000..1b98767f
--- /dev/null
+++ b/input_devices/mag/node_modules/decompress-response/readme.md
@@ -0,0 +1,31 @@
+# decompress-response [![Build Status](https://travis-ci.org/sindresorhus/decompress-response.svg?branch=master)](https://travis-ci.org/sindresorhus/decompress-response)
+
+> Decompress a HTTP response if needed
+
+Decompresses the [response](https://nodejs.org/api/http.html#http_class_http_incomingmessage) from [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) if it's gzipped or deflated, otherwise just passes it through.
+
+Used by [`got`](https://github.com/sindresorhus/got).
+
+
+## Install
+
+```
+$ npm install decompress-response
+```
+
+
+## Usage
+
+```js
+const http = require('http');
+const decompressResponse = require('decompress-response');
+
+http.get('http://sindresorhus.com', response => {
+	response = decompressResponse(response);
+});
+```
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/deep-extend/CHANGELOG.md b/input_devices/mag/node_modules/deep-extend/CHANGELOG.md
new file mode 100644
index 00000000..dd13ec13
--- /dev/null
+++ b/input_devices/mag/node_modules/deep-extend/CHANGELOG.md
@@ -0,0 +1,46 @@
+Changelog
+=========
+
+v0.6.0
+------
+
+- Updated "devDependencies" versions to fix vulnerability alerts
+- Dropped support of io.js and node.js v0.12.x and lower since new versions of
+  "devDependencies" couldn't work with those old node.js versions
+  (minimal supported version of node.js now is v4.0.0)
+
+v0.5.1
+------
+
+- Fix prototype pollution vulnerability (thanks to @mwakerman for the PR)
+- Avoid using deprecated Buffer API (thanks to @ChALkeR for the PR)
+
+v0.5.0
+------
+
+- Auto-testing provided by Travis CI;
+- Support older Node.JS versions (`v0.11.x` and `v0.10.x`);
+- Removed tests files from npm package.
+
+v0.4.2
+------
+
+- Fix for `null` as an argument.
+
+v0.4.1
+------
+
+- Removed test code from <b>npm</b> package
+  ([see pull request #21](https://github.com/unclechu/node-deep-extend/pull/21));
+- Increased minimal version of Node from `0.4.0` to `0.12.0`
+  (because can't run tests on lesser version anyway).
+
+v0.4.0
+------
+
+- **WARNING!** Broken backward compatibility with `v0.3.x`;
+- Fixed bug with extending arrays instead of cloning;
+- Deep cloning for arrays;
+- Check for own property;
+- Fixed some documentation issues;
+- Strict JS mode.
diff --git a/input_devices/mag/node_modules/deep-extend/LICENSE b/input_devices/mag/node_modules/deep-extend/LICENSE
new file mode 100644
index 00000000..5c58916f
--- /dev/null
+++ b/input_devices/mag/node_modules/deep-extend/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2018, Viacheslav Lotsmanov
+
+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/input_devices/mag/node_modules/deep-extend/README.md b/input_devices/mag/node_modules/deep-extend/README.md
new file mode 100644
index 00000000..67c7fc08
--- /dev/null
+++ b/input_devices/mag/node_modules/deep-extend/README.md
@@ -0,0 +1,91 @@
+Deep Extend
+===========
+
+Recursive object extending.
+
+[![Build Status](https://api.travis-ci.org/unclechu/node-deep-extend.svg?branch=master)](https://travis-ci.org/unclechu/node-deep-extend)
+
+[![NPM](https://nodei.co/npm/deep-extend.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/deep-extend/)
+
+Install
+-------
+
+```bash
+$ npm install deep-extend
+```
+
+Usage
+-----
+
+```javascript
+var deepExtend = require('deep-extend');
+var obj1 = {
+  a: 1,
+  b: 2,
+  d: {
+    a: 1,
+    b: [],
+    c: { test1: 123, test2: 321 }
+  },
+  f: 5,
+  g: 123,
+  i: 321,
+  j: [1, 2]
+};
+var obj2 = {
+  b: 3,
+  c: 5,
+  d: {
+    b: { first: 'one', second: 'two' },
+    c: { test2: 222 }
+  },
+  e: { one: 1, two: 2 },
+  f: [],
+  g: (void 0),
+  h: /abc/g,
+  i: null,
+  j: [3, 4]
+};
+
+deepExtend(obj1, obj2);
+
+console.log(obj1);
+/*
+{ a: 1,
+  b: 3,
+  d:
+   { a: 1,
+     b: { first: 'one', second: 'two' },
+     c: { test1: 123, test2: 222 } },
+  f: [],
+  g: undefined,
+  c: 5,
+  e: { one: 1, two: 2 },
+  h: /abc/g,
+  i: null,
+  j: [3, 4] }
+*/
+```
+
+Unit testing
+------------
+
+```bash
+$ npm test
+```
+
+Changelog
+---------
+
+[CHANGELOG.md](./CHANGELOG.md)
+
+Any issues?
+-----------
+
+Please, report about issues
+[here](https://github.com/unclechu/node-deep-extend/issues).
+
+License
+-------
+
+[MIT](./LICENSE)
diff --git a/input_devices/mag/node_modules/deep-extend/index.js b/input_devices/mag/node_modules/deep-extend/index.js
new file mode 100644
index 00000000..762d81e9
--- /dev/null
+++ b/input_devices/mag/node_modules/deep-extend/index.js
@@ -0,0 +1 @@
+module.exports = require('./lib/deep-extend');
diff --git a/input_devices/mag/node_modules/deep-extend/lib/deep-extend.js b/input_devices/mag/node_modules/deep-extend/lib/deep-extend.js
new file mode 100644
index 00000000..651fd8d3
--- /dev/null
+++ b/input_devices/mag/node_modules/deep-extend/lib/deep-extend.js
@@ -0,0 +1,150 @@
+/*!
+ * @description Recursive object extending
+ * @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
+ * @license MIT
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2018 Viacheslav Lotsmanov
+ *
+ * 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.
+ */
+
+'use strict';
+
+function isSpecificValue(val) {
+	return (
+		val instanceof Buffer
+		|| val instanceof Date
+		|| val instanceof RegExp
+	) ? true : false;
+}
+
+function cloneSpecificValue(val) {
+	if (val instanceof Buffer) {
+		var x = Buffer.alloc
+			? Buffer.alloc(val.length)
+			: new Buffer(val.length);
+		val.copy(x);
+		return x;
+	} else if (val instanceof Date) {
+		return new Date(val.getTime());
+	} else if (val instanceof RegExp) {
+		return new RegExp(val);
+	} else {
+		throw new Error('Unexpected situation');
+	}
+}
+
+/**
+ * Recursive cloning array.
+ */
+function deepCloneArray(arr) {
+	var clone = [];
+	arr.forEach(function (item, index) {
+		if (typeof item === 'object' && item !== null) {
+			if (Array.isArray(item)) {
+				clone[index] = deepCloneArray(item);
+			} else if (isSpecificValue(item)) {
+				clone[index] = cloneSpecificValue(item);
+			} else {
+				clone[index] = deepExtend({}, item);
+			}
+		} else {
+			clone[index] = item;
+		}
+	});
+	return clone;
+}
+
+function safeGetProperty(object, property) {
+	return property === '__proto__' ? undefined : object[property];
+}
+
+/**
+ * Extening object that entered in first argument.
+ *
+ * Returns extended object or false if have no target object or incorrect type.
+ *
+ * If you wish to clone source object (without modify it), just use empty new
+ * object as first argument, like this:
+ *   deepExtend({}, yourObj_1, [yourObj_N]);
+ */
+var deepExtend = module.exports = function (/*obj_1, [obj_2], [obj_N]*/) {
+	if (arguments.length < 1 || typeof arguments[0] !== 'object') {
+		return false;
+	}
+
+	if (arguments.length < 2) {
+		return arguments[0];
+	}
+
+	var target = arguments[0];
+
+	// convert arguments to array and cut off target object
+	var args = Array.prototype.slice.call(arguments, 1);
+
+	var val, src, clone;
+
+	args.forEach(function (obj) {
+		// skip argument if isn't an object, is null, or is an array
+		if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
+			return;
+		}
+
+		Object.keys(obj).forEach(function (key) {
+			src = safeGetProperty(target, key); // source value
+			val = safeGetProperty(obj, key); // new value
+
+			// recursion prevention
+			if (val === target) {
+				return;
+
+			/**
+			 * if new value isn't object then just overwrite by new value
+			 * instead of extending.
+			 */
+			} else if (typeof val !== 'object' || val === null) {
+				target[key] = val;
+				return;
+
+			// just clone arrays (and recursive clone objects inside)
+			} else if (Array.isArray(val)) {
+				target[key] = deepCloneArray(val);
+				return;
+
+			// custom cloning and overwrite for specific objects
+			} else if (isSpecificValue(val)) {
+				target[key] = cloneSpecificValue(val);
+				return;
+
+			// overwrite by new value if source isn't object or array
+			} else if (typeof src !== 'object' || src === null || Array.isArray(src)) {
+				target[key] = deepExtend({}, val);
+				return;
+
+			// source value and new value is objects both, extending...
+			} else {
+				target[key] = deepExtend(src, val);
+				return;
+			}
+		});
+	});
+
+	return target;
+};
diff --git a/input_devices/mag/node_modules/deep-extend/package.json b/input_devices/mag/node_modules/deep-extend/package.json
new file mode 100644
index 00000000..821609a7
--- /dev/null
+++ b/input_devices/mag/node_modules/deep-extend/package.json
@@ -0,0 +1,124 @@
+{
+  "_args": [
+    [
+      "deep-extend@^0.6.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/rc"
+    ]
+  ],
+  "_from": "deep-extend@>=0.6.0 <0.7.0",
+  "_id": "deep-extend@0.6.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/deep-extend",
+  "_nodeVersion": "8.11.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/deep-extend_0.6.0_1527012797367_0.028784991930715043"
+  },
+  "_npmUser": {
+    "email": "lotsmanov89@gmail.com",
+    "name": "unclechu"
+  },
+  "_npmVersion": "6.0.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "deep-extend",
+    "raw": "deep-extend@^0.6.0",
+    "rawSpec": "^0.6.0",
+    "scope": null,
+    "spec": ">=0.6.0 <0.7.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/rc"
+  ],
+  "_resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+  "_shasum": "c4fa7c95404a17a9c3e8ca7e1537312b736330ac",
+  "_shrinkwrap": null,
+  "_spec": "deep-extend@^0.6.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/rc",
+  "author": {
+    "email": "lotsmanov89@gmail.com",
+    "name": "Viacheslav Lotsmanov"
+  },
+  "bugs": {
+    "url": "https://github.com/unclechu/node-deep-extend/issues"
+  },
+  "contributors": [
+    {
+      "name": "Romain Prieto",
+      "url": "https://github.com/rprieto"
+    },
+    {
+      "name": "Max Maximov",
+      "url": "https://github.com/maxmaximov"
+    },
+    {
+      "name": "Marshall Bowers",
+      "url": "https://github.com/maxdeviant"
+    },
+    {
+      "name": "Misha Wakerman",
+      "url": "https://github.com/mwakerman"
+    }
+  ],
+  "dependencies": {},
+  "description": "Recursive object extending",
+  "devDependencies": {
+    "mocha": "5.2.0",
+    "should": "13.2.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 6,
+    "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbBF2+CRA9TVsSAnZWagAAWWsP+wayRHY/u4XwuxCopF6q\nVXfgmhXakYrxCXNpIUVCPC2lBajceZ6X4IOqXIIMnta+x+aYha0TAqH6FT+k\n5f9heBarQk4e3oLMJgaFDYkdTPOqVpDy95g+WOW+NiZN/87z2WnRsPzknkpY\n7R8FQGyR9PEromNmL4pCQY+0G1U4MB8o4rWqu9wp8oY2ebYJ3yNWe2CT9PeZ\nmIGjqyWLH84t8Yp40onc/15YHIAheYA5l9eD7pZeuxc+kddfSDbiwwpedWCV\nJLmKNnNoI4EHDuf+M8RN3U7CJpzAJWKSPN5wId+vFOjGaMnbrSA83DS66JvV\n8JVnzCFhbfpabiqDfkzE8Lq+QRE4P25Tjbc9kxS9yuQTShF3AJUzZUl5rQsw\n5Ov0fOt+BaT1e1/CvYlH8M8tvnGDPkYZ1A3tyRtjZUG/tNkNlLethX77kaf/\nzvnrdsOmReJ8wAacGKEB8+VLVaYg4bDCd5FGgSzO66J0OW2MYghZQi/9Scz8\nzgWmYdgrJ8ftxMDWrOqvcxI+df2bATGtXg1djPb0snsye3HAlNnWDK0lMtwF\n9K22xEK0jaqwDnwCFZKQU2aC6zWgQxlByZu2zA8Kiy3ahRe3XIdUEmxjsmuo\nc13UN9IIjuqHv+2P1U9kL6OEy2omLae/rd/GRy1xPfE/1EdkrcQ//0kTsVBh\nXI++\r\n=u4KH\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "c4fa7c95404a17a9c3e8ca7e1537312b736330ac",
+    "tarball": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+    "unpackedSize": 9190
+  },
+  "engines": {
+    "node": ">=4.0.0"
+  },
+  "files": [
+    "index.js",
+    "lib/"
+  ],
+  "gitHead": "f3f2b4f30fffe8abc9a99a7d6469fb354ca206e9",
+  "homepage": "https://github.com/unclechu/node-deep-extend",
+  "keywords": [
+    "clone",
+    "deep",
+    "deep-extend",
+    "extend",
+    "json",
+    "merge",
+    "recursive",
+    "xtend"
+  ],
+  "license": "MIT",
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://raw.githubusercontent.com/unclechu/node-deep-extend/master/LICENSE"
+    }
+  ],
+  "main": "lib/deep-extend.js",
+  "maintainers": [
+    {
+      "name": "unclechu",
+      "email": "lotsmanov89@gmail.com"
+    }
+  ],
+  "name": "deep-extend",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/unclechu/node-deep-extend.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.6.0"
+}
diff --git a/input_devices/mag/node_modules/define-property/LICENSE b/input_devices/mag/node_modules/define-property/LICENSE
new file mode 100644
index 00000000..ec85897e
--- /dev/null
+++ b/input_devices/mag/node_modules/define-property/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, 2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/define-property/README.md b/input_devices/mag/node_modules/define-property/README.md
new file mode 100644
index 00000000..2f1af05f
--- /dev/null
+++ b/input_devices/mag/node_modules/define-property/README.md
@@ -0,0 +1,95 @@
+# define-property [![NPM version](https://img.shields.io/npm/v/define-property.svg?style=flat)](https://www.npmjs.com/package/define-property) [![NPM monthly downloads](https://img.shields.io/npm/dm/define-property.svg?style=flat)](https://npmjs.org/package/define-property)  [![NPM total downloads](https://img.shields.io/npm/dt/define-property.svg?style=flat)](https://npmjs.org/package/define-property) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/define-property.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/define-property)
+
+> Define a non-enumerable property on an object.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save define-property
+```
+
+Install with [yarn](https://yarnpkg.com):
+
+```sh
+$ yarn add define-property
+```
+
+## Usage
+
+**Params**
+
+* `obj`: The object on which to define the property.
+* `prop`: The name of the property to be defined or modified.
+* `descriptor`: The descriptor for the property being defined or modified.
+
+```js
+var define = require('define-property');
+var obj = {};
+define(obj, 'foo', function(val) {
+  return val.toUpperCase();
+});
+
+console.log(obj);
+//=> {}
+
+console.log(obj.foo('bar'));
+//=> 'BAR'
+```
+
+**get/set**
+
+```js
+define(obj, 'foo', {
+  get: function() {},
+  set: function() {}
+});
+```
+
+## About
+
+### Related projects
+
+* [assign-deep](https://www.npmjs.com/package/assign-deep): Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target… [more](https://github.com/jonschlinkert/assign-deep) | [homepage](https://github.com/jonschlinkert/assign-deep "Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target (first) object.")
+* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow "Extend an object with the properties of additional objects. node.js/javascript util.")
+* [merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep "Recursively merge values in a javascript object.")
+* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep "Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.5.0, on April 20, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/define-property/index.js b/input_devices/mag/node_modules/define-property/index.js
new file mode 100644
index 00000000..27c19ebf
--- /dev/null
+++ b/input_devices/mag/node_modules/define-property/index.js
@@ -0,0 +1,31 @@
+/*!
+ * define-property <https://github.com/jonschlinkert/define-property>
+ *
+ * Copyright (c) 2015, 2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var isDescriptor = require('is-descriptor');
+
+module.exports = function defineProperty(obj, prop, val) {
+  if (typeof obj !== 'object' && typeof obj !== 'function') {
+    throw new TypeError('expected an object or function.');
+  }
+
+  if (typeof prop !== 'string') {
+    throw new TypeError('expected `prop` to be a string.');
+  }
+
+  if (isDescriptor(val) && ('set' in val || 'get' in val)) {
+    return Object.defineProperty(obj, prop, val);
+  }
+
+  return Object.defineProperty(obj, prop, {
+    configurable: true,
+    enumerable: false,
+    writable: true,
+    value: val
+  });
+};
diff --git a/input_devices/mag/node_modules/define-property/package.json b/input_devices/mag/node_modules/define-property/package.json
new file mode 100644
index 00000000..20dffcbc
--- /dev/null
+++ b/input_devices/mag/node_modules/define-property/package.json
@@ -0,0 +1,121 @@
+{
+  "_args": [
+    [
+      "define-property@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question"
+    ]
+  ],
+  "_from": "define-property@>=1.0.0 <2.0.0",
+  "_id": "define-property@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/define-property",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/define-property-1.0.0.tgz_1492669183321_0.5127195529639721"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "define-property",
+    "raw": "define-property@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-question",
+    "/window-size"
+  ],
+  "_resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+  "_shasum": "769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6",
+  "_shrinkwrap": null,
+  "_spec": "define-property@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/define-property/issues"
+  },
+  "dependencies": {
+    "is-descriptor": "^1.0.0"
+  },
+  "description": "Define a non-enumerable property on an object.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6",
+    "tarball": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "4811e7c7999e82ab086265eefeb5d9cbffe10912",
+  "homepage": "https://github.com/jonschlinkert/define-property",
+  "keywords": [
+    "define",
+    "define-property",
+    "enumerable",
+    "key",
+    "non",
+    "non-enumerable",
+    "object",
+    "prop",
+    "property",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "define-property",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/define-property.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "assign-deep",
+        "extend-shallow",
+        "merge-deep",
+        "mixin-deep"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/.npmignore b/input_devices/mag/node_modules/delegates/.npmignore
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/.npmignore
rename to input_devices/mag/node_modules/delegates/.npmignore
diff --git a/input_devices/mag/node_modules/delegates/History.md b/input_devices/mag/node_modules/delegates/History.md
new file mode 100644
index 00000000..25959eab
--- /dev/null
+++ b/input_devices/mag/node_modules/delegates/History.md
@@ -0,0 +1,22 @@
+
+1.0.0 / 2015-12-14
+==================
+
+  * Merge pull request #12 from kasicka/master
+  * Add license text
+
+0.1.0 / 2014-10-17
+==================
+
+ * adds `.fluent()` to api
+
+0.0.3 / 2014-01-13
+==================
+
+ * fix receiver for .method()
+
+0.0.2 / 2014-01-13
+==================
+
+ * Object.defineProperty() sucks
+ * Initial commit
diff --git a/input_devices/mag/node_modules/delegates/License b/input_devices/mag/node_modules/delegates/License
new file mode 100644
index 00000000..60de60ad
--- /dev/null
+++ b/input_devices/mag/node_modules/delegates/License
@@ -0,0 +1,20 @@
+Copyright (c) 2015 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/delegates/Makefile b/input_devices/mag/node_modules/delegates/Makefile
new file mode 100644
index 00000000..a9dcfd50
--- /dev/null
+++ b/input_devices/mag/node_modules/delegates/Makefile
@@ -0,0 +1,8 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--require should \
+		--reporter spec \
+		--bail
+
+.PHONY: test
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/delegates/Readme.md b/input_devices/mag/node_modules/delegates/Readme.md
new file mode 100644
index 00000000..ab8cf4ac
--- /dev/null
+++ b/input_devices/mag/node_modules/delegates/Readme.md
@@ -0,0 +1,94 @@
+
+# delegates
+
+  Node method and accessor delegation utilty.
+
+## Installation
+
+```
+$ npm install delegates
+```
+
+## Example
+
+```js
+var delegate = require('delegates');
+
+...
+
+delegate(proto, 'request')
+  .method('acceptsLanguages')
+  .method('acceptsEncodings')
+  .method('acceptsCharsets')
+  .method('accepts')
+  .method('is')
+  .access('querystring')
+  .access('idempotent')
+  .access('socket')
+  .access('length')
+  .access('query')
+  .access('search')
+  .access('status')
+  .access('method')
+  .access('path')
+  .access('body')
+  .access('host')
+  .access('url')
+  .getter('subdomains')
+  .getter('protocol')
+  .getter('header')
+  .getter('stale')
+  .getter('fresh')
+  .getter('secure')
+  .getter('ips')
+  .getter('ip')
+```
+
+# API
+
+## Delegate(proto, prop)
+
+Creates a delegator instance used to configure using the `prop` on the given
+`proto` object. (which is usually a prototype)
+
+## Delegate#method(name)
+
+Allows the given method `name` to be accessed on the host.
+
+## Delegate#getter(name)
+
+Creates a "getter" for the property with the given `name` on the delegated
+object.
+
+## Delegate#setter(name)
+
+Creates a "setter" for the property with the given `name` on the delegated
+object.
+
+## Delegate#access(name)
+
+Creates an "accessor" (ie: both getter *and* setter) for the property with the
+given `name` on the delegated object.
+
+## Delegate#fluent(name)
+
+A unique type of "accessor" that works for a "fluent" API. When called as a
+getter, the method returns the expected value. However, if the method is called
+with a value, it will return itself so it can be chained. For example:
+
+```js
+delegate(proto, 'request')
+  .fluent('query')
+
+// getter
+var q = request.query();
+
+// setter (chainable)
+request
+  .query({ a: 1 })
+  .query({ b: 2 });
+```
+
+# License
+
+  MIT
diff --git a/input_devices/mag/node_modules/delegates/index.js b/input_devices/mag/node_modules/delegates/index.js
new file mode 100644
index 00000000..17c222d5
--- /dev/null
+++ b/input_devices/mag/node_modules/delegates/index.js
@@ -0,0 +1,121 @@
+
+/**
+ * Expose `Delegator`.
+ */
+
+module.exports = Delegator;
+
+/**
+ * Initialize a delegator.
+ *
+ * @param {Object} proto
+ * @param {String} target
+ * @api public
+ */
+
+function Delegator(proto, target) {
+  if (!(this instanceof Delegator)) return new Delegator(proto, target);
+  this.proto = proto;
+  this.target = target;
+  this.methods = [];
+  this.getters = [];
+  this.setters = [];
+  this.fluents = [];
+}
+
+/**
+ * Delegate method `name`.
+ *
+ * @param {String} name
+ * @return {Delegator} self
+ * @api public
+ */
+
+Delegator.prototype.method = function(name){
+  var proto = this.proto;
+  var target = this.target;
+  this.methods.push(name);
+
+  proto[name] = function(){
+    return this[target][name].apply(this[target], arguments);
+  };
+
+  return this;
+};
+
+/**
+ * Delegator accessor `name`.
+ *
+ * @param {String} name
+ * @return {Delegator} self
+ * @api public
+ */
+
+Delegator.prototype.access = function(name){
+  return this.getter(name).setter(name);
+};
+
+/**
+ * Delegator getter `name`.
+ *
+ * @param {String} name
+ * @return {Delegator} self
+ * @api public
+ */
+
+Delegator.prototype.getter = function(name){
+  var proto = this.proto;
+  var target = this.target;
+  this.getters.push(name);
+
+  proto.__defineGetter__(name, function(){
+    return this[target][name];
+  });
+
+  return this;
+};
+
+/**
+ * Delegator setter `name`.
+ *
+ * @param {String} name
+ * @return {Delegator} self
+ * @api public
+ */
+
+Delegator.prototype.setter = function(name){
+  var proto = this.proto;
+  var target = this.target;
+  this.setters.push(name);
+
+  proto.__defineSetter__(name, function(val){
+    return this[target][name] = val;
+  });
+
+  return this;
+};
+
+/**
+ * Delegator fluent accessor
+ *
+ * @param {String} name
+ * @return {Delegator} self
+ * @api public
+ */
+
+Delegator.prototype.fluent = function (name) {
+  var proto = this.proto;
+  var target = this.target;
+  this.fluents.push(name);
+
+  proto[name] = function(val){
+    if ('undefined' != typeof val) {
+      this[target][name] = val;
+      return this;
+    } else {
+      return this[target][name];
+    }
+  };
+
+  return this;
+};
diff --git a/input_devices/mag/node_modules/delegates/package.json b/input_devices/mag/node_modules/delegates/package.json
new file mode 100644
index 00000000..50f2b796
--- /dev/null
+++ b/input_devices/mag/node_modules/delegates/package.json
@@ -0,0 +1,76 @@
+{
+  "_args": [
+    [
+      "delegates@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/are-we-there-yet"
+    ]
+  ],
+  "_from": "delegates@>=1.0.0 <2.0.0",
+  "_id": "delegates@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/delegates",
+  "_nodeVersion": "4.2.1",
+  "_npmUser": {
+    "email": "tj@vision-media.ca",
+    "name": "tjholowaychuk"
+  },
+  "_npmVersion": "3.3.12",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "delegates",
+    "raw": "delegates@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/are-we-there-yet"
+  ],
+  "_resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+  "_shasum": "84c6e159b81904fdca59a0ef44cd870d31250f9a",
+  "_shrinkwrap": null,
+  "_spec": "delegates@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/are-we-there-yet",
+  "bugs": {
+    "url": "https://github.com/visionmedia/node-delegates/issues"
+  },
+  "dependencies": {},
+  "description": "delegate methods and accessors to another property",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "84c6e159b81904fdca59a0ef44cd870d31250f9a",
+    "tarball": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz"
+  },
+  "gitHead": "c4dc07ef1ed51c2b2a63f3585e5ef949ee577a49",
+  "homepage": "https://github.com/visionmedia/node-delegates#readme",
+  "keywords": [
+    "delegate",
+    "delegation"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    },
+    {
+      "name": "dominicbarnes",
+      "email": "dominic@dbarnes.info"
+    }
+  ],
+  "name": "delegates",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/visionmedia/node-delegates.git"
+  },
+  "scripts": {},
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/delegates/test/index.js b/input_devices/mag/node_modules/delegates/test/index.js
new file mode 100644
index 00000000..7b6e3d4d
--- /dev/null
+++ b/input_devices/mag/node_modules/delegates/test/index.js
@@ -0,0 +1,94 @@
+
+var assert = require('assert');
+var delegate = require('..');
+
+describe('.method(name)', function(){
+  it('should delegate methods', function(){
+    var obj = {};
+
+    obj.request = {
+      foo: function(bar){
+        assert(this == obj.request);
+        return bar;
+      }
+    };
+
+    delegate(obj, 'request').method('foo');
+
+    obj.foo('something').should.equal('something');
+  })
+})
+
+describe('.getter(name)', function(){
+  it('should delegate getters', function(){
+    var obj = {};
+
+    obj.request = {
+      get type() {
+        return 'text/html';
+      }
+    }
+
+    delegate(obj, 'request').getter('type');
+
+    obj.type.should.equal('text/html');
+  })
+})
+
+describe('.setter(name)', function(){
+  it('should delegate setters', function(){
+    var obj = {};
+
+    obj.request = {
+      get type() {
+        return this._type.toUpperCase();
+      },
+
+      set type(val) {
+        this._type = val;
+      }
+    }
+
+    delegate(obj, 'request').setter('type');
+
+    obj.type = 'hey';
+    obj.request.type.should.equal('HEY');
+  })
+})
+
+describe('.access(name)', function(){
+  it('should delegate getters and setters', function(){
+    var obj = {};
+
+    obj.request = {
+      get type() {
+        return this._type.toUpperCase();
+      },
+
+      set type(val) {
+        this._type = val;
+      }
+    }
+
+    delegate(obj, 'request').access('type');
+
+    obj.type = 'hey';
+    obj.type.should.equal('HEY');
+  })
+})
+
+describe('.fluent(name)', function () {
+  it('should delegate in a fluent fashion', function () {
+    var obj = {
+      settings: {
+        env: 'development'
+      }
+    };
+
+    delegate(obj, 'settings').fluent('env');
+
+    obj.env().should.equal('development');
+    obj.env('production').should.equal(obj);
+    obj.settings.env.should.equal('production');
+  })
+})
diff --git a/input_devices/mag/node_modules/detect-libc/.npmignore b/input_devices/mag/node_modules/detect-libc/.npmignore
new file mode 100644
index 00000000..8fc0e8d3
--- /dev/null
+++ b/input_devices/mag/node_modules/detect-libc/.npmignore
@@ -0,0 +1,7 @@
+.nyc_output
+.travis.yml
+coverage
+test.js
+node_modules
+/.circleci
+/tests/integration
diff --git a/input_devices/mag/node_modules/detect-libc/LICENSE b/input_devices/mag/node_modules/detect-libc/LICENSE
new file mode 100644
index 00000000..8dada3ed
--- /dev/null
+++ b/input_devices/mag/node_modules/detect-libc/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/input_devices/mag/node_modules/detect-libc/README.md b/input_devices/mag/node_modules/detect-libc/README.md
new file mode 100644
index 00000000..31763574
--- /dev/null
+++ b/input_devices/mag/node_modules/detect-libc/README.md
@@ -0,0 +1,78 @@
+# detect-libc
+
+Node.js module to detect the C standard library (libc) implementation
+family and version in use on a given Linux system.
+
+Provides a value suitable for use with the `LIBC` option of
+[prebuild](https://www.npmjs.com/package/prebuild),
+[prebuild-ci](https://www.npmjs.com/package/prebuild-ci) and
+[prebuild-install](https://www.npmjs.com/package/prebuild-install),
+therefore allowing build and provision of pre-compiled binaries
+for musl-based Linux e.g. Alpine as well as glibc-based.
+
+Currently supports libc detection of `glibc` and `musl`.
+
+## Install
+
+```sh
+npm install detect-libc
+```
+
+## Usage
+
+### API
+
+```js
+const { GLIBC, MUSL, family, version, isNonGlibcLinux } = require('detect-libc');
+```
+
+* `GLIBC` is a String containing the value "glibc" for comparison with `family`.
+* `MUSL` is a String containing the value "musl" for comparison with `family`.
+* `family` is a String representing the system libc family.
+* `version` is a String representing the system libc version number.
+* `isNonGlibcLinux` is a Boolean representing whether the system is a non-glibc Linux, e.g. Alpine.
+
+### detect-libc command line tool
+
+When run on a Linux system with a non-glibc libc,
+the child command will be run with the `LIBC` environment variable
+set to the relevant value.
+
+On all other platforms will run the child command as-is.
+
+The command line feature requires `spawnSync` provided by Node v0.12+.
+
+```sh
+detect-libc child-command
+```
+
+## Integrating with prebuild
+
+```json
+  "scripts": {
+    "install": "detect-libc prebuild-install || node-gyp rebuild",
+    "test": "mocha && detect-libc prebuild-ci"
+  },
+  "dependencies": {
+    "detect-libc": "^1.0.2",
+    "prebuild-install": "^2.2.0"
+  },
+  "devDependencies": {
+    "prebuild": "^6.2.1",
+    "prebuild-ci": "^2.2.3"
+  }
+```
+
+## Licence
+
+Copyright 2017 Lovell Fuller
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/input_devices/mag/node_modules/detect-libc/bin/detect-libc.js b/input_devices/mag/node_modules/detect-libc/bin/detect-libc.js
new file mode 100755
index 00000000..5486127f
--- /dev/null
+++ b/input_devices/mag/node_modules/detect-libc/bin/detect-libc.js
@@ -0,0 +1,18 @@
+#!/usr/bin/env node
+
+'use strict';
+
+var spawnSync = require('child_process').spawnSync;
+var libc = require('../');
+
+var spawnOptions = {
+  env: process.env,
+  shell: true,
+  stdio: 'inherit'
+};
+
+if (libc.isNonGlibcLinux) {
+  spawnOptions.env.LIBC = process.env.LIBC || libc.family;
+}
+
+process.exit(spawnSync(process.argv[2], process.argv.slice(3), spawnOptions).status);
diff --git a/input_devices/mag/node_modules/detect-libc/lib/detect-libc.js b/input_devices/mag/node_modules/detect-libc/lib/detect-libc.js
new file mode 100644
index 00000000..1855fe18
--- /dev/null
+++ b/input_devices/mag/node_modules/detect-libc/lib/detect-libc.js
@@ -0,0 +1,92 @@
+'use strict';
+
+var platform = require('os').platform();
+var spawnSync = require('child_process').spawnSync;
+var readdirSync = require('fs').readdirSync;
+
+var GLIBC = 'glibc';
+var MUSL = 'musl';
+
+var spawnOptions = {
+  encoding: 'utf8',
+  env: process.env
+};
+
+if (!spawnSync) {
+  spawnSync = function () {
+    return { status: 126, stdout: '', stderr: '' };
+  };
+}
+
+function contains (needle) {
+  return function (haystack) {
+    return haystack.indexOf(needle) !== -1;
+  };
+}
+
+function versionFromMuslLdd (out) {
+  return out.split(/[\r\n]+/)[1].trim().split(/\s/)[1];
+}
+
+function safeReaddirSync (path) {
+  try {
+    return readdirSync(path);
+  } catch (e) {}
+  return [];
+}
+
+var family = '';
+var version = '';
+var method = '';
+
+if (platform === 'linux') {
+  // Try getconf
+  var glibc = spawnSync('getconf', ['GNU_LIBC_VERSION'], spawnOptions);
+  if (glibc.status === 0) {
+    family = GLIBC;
+    version = glibc.stdout.trim().split(' ')[1];
+    method = 'getconf';
+  } else {
+    // Try ldd
+    var ldd = spawnSync('ldd', ['--version'], spawnOptions);
+    if (ldd.status === 0 && ldd.stdout.indexOf(MUSL) !== -1) {
+      family = MUSL;
+      version = versionFromMuslLdd(ldd.stdout);
+      method = 'ldd';
+    } else if (ldd.status === 1 && ldd.stderr.indexOf(MUSL) !== -1) {
+      family = MUSL;
+      version = versionFromMuslLdd(ldd.stderr);
+      method = 'ldd';
+    } else {
+      // Try filesystem (family only)
+      var lib = safeReaddirSync('/lib');
+      if (lib.some(contains('-linux-gnu'))) {
+        family = GLIBC;
+        method = 'filesystem';
+      } else if (lib.some(contains('libc.musl-'))) {
+        family = MUSL;
+        method = 'filesystem';
+      } else if (lib.some(contains('ld-musl-'))) {
+        family = MUSL;
+        method = 'filesystem';
+      } else {
+        var usrSbin = safeReaddirSync('/usr/sbin');
+        if (usrSbin.some(contains('glibc'))) {
+          family = GLIBC;
+          method = 'filesystem';
+        }
+      }
+    }
+  }
+}
+
+var isNonGlibcLinux = (family !== '' && family !== GLIBC);
+
+module.exports = {
+  GLIBC: GLIBC,
+  MUSL: MUSL,
+  family: family,
+  version: version,
+  method: method,
+  isNonGlibcLinux: isNonGlibcLinux
+};
diff --git a/input_devices/mag/node_modules/detect-libc/package.json b/input_devices/mag/node_modules/detect-libc/package.json
new file mode 100644
index 00000000..5acf322b
--- /dev/null
+++ b/input_devices/mag/node_modules/detect-libc/package.json
@@ -0,0 +1,98 @@
+{
+  "_args": [
+    [
+      "detect-libc@^1.0.3",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "detect-libc@>=1.0.3 <2.0.0",
+  "_id": "detect-libc@1.0.3",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/detect-libc",
+  "_nodeVersion": "8.1.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/detect-libc-1.0.3.tgz_1511377655799_0.23113705799914896"
+  },
+  "_npmUser": {
+    "email": "npm@lovell.info",
+    "name": "lovell"
+  },
+  "_npmVersion": "3.10.10",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "detect-libc",
+    "raw": "detect-libc@^1.0.3",
+    "rawSpec": "^1.0.3",
+    "scope": null,
+    "spec": ">=1.0.3 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+  "_shasum": "fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b",
+  "_shrinkwrap": null,
+  "_spec": "detect-libc@^1.0.3",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "npm@lovell.info",
+    "name": "Lovell Fuller"
+  },
+  "bin": {
+    "detect-libc": "./bin/detect-libc.js"
+  },
+  "bugs": {
+    "url": "https://github.com/lovell/detect-libc/issues"
+  },
+  "contributors": [
+    {
+      "name": "Niklas Salmoukas",
+      "email": "niklas@salmoukas.com"
+    }
+  ],
+  "dependencies": {},
+  "description": "Node.js module to detect the C standard library (libc) implementation family and version",
+  "devDependencies": {
+    "ava": "^0.23.0",
+    "nyc": "^11.3.0",
+    "proxyquire": "^1.8.0",
+    "semistandard": "^11.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b",
+    "tarball": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz"
+  },
+  "engines": {
+    "node": ">=0.10"
+  },
+  "gitHead": "88df1a5950bf3cd9bffa1e0137ab6471c4546118",
+  "homepage": "https://github.com/lovell/detect-libc#readme",
+  "keywords": [
+    "glibc",
+    "libc",
+    "musl"
+  ],
+  "license": "Apache-2.0",
+  "main": "lib/detect-libc.js",
+  "maintainers": [
+    {
+      "name": "lovell",
+      "email": "npm@lovell.info"
+    }
+  ],
+  "name": "detect-libc",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/lovell/detect-libc.git"
+  },
+  "scripts": {
+    "test": "semistandard && nyc --reporter=lcov ava"
+  },
+  "version": "1.0.3"
+}
diff --git a/input_devices/mag/node_modules/end-of-stream/LICENSE b/input_devices/mag/node_modules/end-of-stream/LICENSE
new file mode 100644
index 00000000..757562ec
--- /dev/null
+++ b/input_devices/mag/node_modules/end-of-stream/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mathias Buus
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/end-of-stream/README.md b/input_devices/mag/node_modules/end-of-stream/README.md
new file mode 100644
index 00000000..f2560c93
--- /dev/null
+++ b/input_devices/mag/node_modules/end-of-stream/README.md
@@ -0,0 +1,52 @@
+# end-of-stream
+
+A node module that calls a callback when a readable/writable/duplex stream has completed or failed.
+
+	npm install end-of-stream
+
+## Usage
+
+Simply pass a stream and a callback to the `eos`.
+Both legacy streams, streams2 and stream3 are supported.
+
+``` js
+var eos = require('end-of-stream');
+
+eos(readableStream, function(err) {
+  // this will be set to the stream instance
+	if (err) return console.log('stream had an error or closed early');
+	console.log('stream has ended', this === readableStream);
+});
+
+eos(writableStream, function(err) {
+	if (err) return console.log('stream had an error or closed early');
+	console.log('stream has finished', this === writableStream);
+});
+
+eos(duplexStream, function(err) {
+	if (err) return console.log('stream had an error or closed early');
+	console.log('stream has ended and finished', this === duplexStream);
+});
+
+eos(duplexStream, {readable:false}, function(err) {
+	if (err) return console.log('stream had an error or closed early');
+	console.log('stream has finished but might still be readable');
+});
+
+eos(duplexStream, {writable:false}, function(err) {
+	if (err) return console.log('stream had an error or closed early');
+	console.log('stream has ended but might still be writable');
+});
+
+eos(readableStream, {error:false}, function(err) {
+	// do not treat emit('error', err) as a end-of-stream
+});
+```
+
+## License
+
+MIT
+
+## Related
+
+`end-of-stream` is part of the [mississippi stream utility collection](https://github.com/maxogden/mississippi) which includes more useful stream modules similar to this one.
diff --git a/input_devices/mag/node_modules/end-of-stream/index.js b/input_devices/mag/node_modules/end-of-stream/index.js
new file mode 100644
index 00000000..be426c22
--- /dev/null
+++ b/input_devices/mag/node_modules/end-of-stream/index.js
@@ -0,0 +1,87 @@
+var once = require('once');
+
+var noop = function() {};
+
+var isRequest = function(stream) {
+	return stream.setHeader && typeof stream.abort === 'function';
+};
+
+var isChildProcess = function(stream) {
+	return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3
+};
+
+var eos = function(stream, opts, callback) {
+	if (typeof opts === 'function') return eos(stream, null, opts);
+	if (!opts) opts = {};
+
+	callback = once(callback || noop);
+
+	var ws = stream._writableState;
+	var rs = stream._readableState;
+	var readable = opts.readable || (opts.readable !== false && stream.readable);
+	var writable = opts.writable || (opts.writable !== false && stream.writable);
+
+	var onlegacyfinish = function() {
+		if (!stream.writable) onfinish();
+	};
+
+	var onfinish = function() {
+		writable = false;
+		if (!readable) callback.call(stream);
+	};
+
+	var onend = function() {
+		readable = false;
+		if (!writable) callback.call(stream);
+	};
+
+	var onexit = function(exitCode) {
+		callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null);
+	};
+
+	var onerror = function(err) {
+		callback.call(stream, err);
+	};
+
+	var onclose = function() {
+		if (readable && !(rs && rs.ended)) return callback.call(stream, new Error('premature close'));
+		if (writable && !(ws && ws.ended)) return callback.call(stream, new Error('premature close'));
+	};
+
+	var onrequest = function() {
+		stream.req.on('finish', onfinish);
+	};
+
+	if (isRequest(stream)) {
+		stream.on('complete', onfinish);
+		stream.on('abort', onclose);
+		if (stream.req) onrequest();
+		else stream.on('request', onrequest);
+	} else if (writable && !ws) { // legacy streams
+		stream.on('end', onlegacyfinish);
+		stream.on('close', onlegacyfinish);
+	}
+
+	if (isChildProcess(stream)) stream.on('exit', onexit);
+
+	stream.on('end', onend);
+	stream.on('finish', onfinish);
+	if (opts.error !== false) stream.on('error', onerror);
+	stream.on('close', onclose);
+
+	return function() {
+		stream.removeListener('complete', onfinish);
+		stream.removeListener('abort', onclose);
+		stream.removeListener('request', onrequest);
+		if (stream.req) stream.req.removeListener('finish', onfinish);
+		stream.removeListener('end', onlegacyfinish);
+		stream.removeListener('close', onlegacyfinish);
+		stream.removeListener('finish', onfinish);
+		stream.removeListener('exit', onexit);
+		stream.removeListener('end', onend);
+		stream.removeListener('error', onerror);
+		stream.removeListener('close', onclose);
+	};
+};
+
+module.exports = eos;
diff --git a/input_devices/mag/node_modules/end-of-stream/package.json b/input_devices/mag/node_modules/end-of-stream/package.json
new file mode 100644
index 00000000..3145ffc6
--- /dev/null
+++ b/input_devices/mag/node_modules/end-of-stream/package.json
@@ -0,0 +1,93 @@
+{
+  "_args": [
+    [
+      "end-of-stream@^1.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/pump"
+    ]
+  ],
+  "_from": "end-of-stream@>=1.1.0 <2.0.0",
+  "_id": "end-of-stream@1.4.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/end-of-stream",
+  "_nodeVersion": "8.9.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/end-of-stream-1.4.1.tgz_1515600688004_0.3708031203132123"
+  },
+  "_npmUser": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "mafintosh"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "end-of-stream",
+    "raw": "end-of-stream@^1.1.0",
+    "rawSpec": "^1.1.0",
+    "scope": null,
+    "spec": ">=1.1.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/pump",
+    "/tar-fs/pump",
+    "/tar-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+  "_shasum": "ed29634d19baba463b6ce6b80a37213eab71ec43",
+  "_shrinkwrap": null,
+  "_spec": "end-of-stream@^1.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/pump",
+  "author": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "Mathias Buus"
+  },
+  "bugs": {
+    "url": "https://github.com/mafintosh/end-of-stream/issues"
+  },
+  "dependencies": {
+    "once": "^1.4.0"
+  },
+  "description": "Call a callback when a readable/writable/duplex stream has completed or failed.",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+    "shasum": "ed29634d19baba463b6ce6b80a37213eab71ec43",
+    "tarball": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "8a49159ed2661ee8ddb393c2503aee489f9ae271",
+  "homepage": "https://github.com/mafintosh/end-of-stream",
+  "keywords": [
+    "callback",
+    "close",
+    "end",
+    "finish",
+    "stream",
+    "streams",
+    "wait"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    }
+  ],
+  "name": "end-of-stream",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mafintosh/end-of-stream.git"
+  },
+  "scripts": {
+    "test": "node test.js"
+  },
+  "version": "1.4.1"
+}
diff --git a/input_devices/mag/node_modules/error-symbol/LICENSE b/input_devices/mag/node_modules/error-symbol/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/error-symbol/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/error-symbol/README.md b/input_devices/mag/node_modules/error-symbol/README.md
new file mode 100644
index 00000000..d9453241
--- /dev/null
+++ b/input_devices/mag/node_modules/error-symbol/README.md
@@ -0,0 +1,52 @@
+# error-symbol [![NPM version](https://badge.fury.io/js/error-symbol.svg)](http://badge.fury.io/js/error-symbol)
+
+> Cross-platform error symbol.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i error-symbol --save
+```
+
+## Usage
+
+```js
+var error = require('error-symbol');
+```
+
+## Related projects
+
+* [success-symbol](https://github.com/jonschlinkert/success-symbol)
+* [warning-symbol](https://github.com/jonschlinkert/warning-symbol)
+* [error-symbol](https://github.com/jonschlinkert/error-symbol)
+* [info-symbol](https://github.com/jonschlinkert/info-symbol)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/error-symbol/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 27, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/error-symbol/index.js b/input_devices/mag/node_modules/error-symbol/index.js
new file mode 100644
index 00000000..ab0a9d6f
--- /dev/null
+++ b/input_devices/mag/node_modules/error-symbol/index.js
@@ -0,0 +1 @@
+module.exports = process.platform === 'win32' ? '×' : '✖';
diff --git a/input_devices/mag/node_modules/error-symbol/package.json b/input_devices/mag/node_modules/error-symbol/package.json
new file mode 100644
index 00000000..9b1e2f9e
--- /dev/null
+++ b/input_devices/mag/node_modules/error-symbol/package.json
@@ -0,0 +1,106 @@
+{
+  "_args": [
+    [
+      "error-symbol@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils"
+    ]
+  ],
+  "_from": "error-symbol@>=0.1.0 <0.2.0",
+  "_id": "error-symbol@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/error-symbol",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "error-symbol",
+    "raw": "error-symbol@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/log-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/error-symbol/-/error-symbol-0.1.0.tgz",
+  "_shasum": "0a4dae37d600d15a29ba453d8ef920f1844333f6",
+  "_shrinkwrap": null,
+  "_spec": "error-symbol@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/error-symbol/issues"
+  },
+  "dependencies": {},
+  "description": "Cross-platform error symbol.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "0a4dae37d600d15a29ba453d8ef920f1844333f6",
+    "tarball": "https://registry.npmjs.org/error-symbol/-/error-symbol-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/error-symbol",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "error",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "symbol",
+    "symbols",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "error-symbol",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/error-symbol.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/expand-template/.travis.yml b/input_devices/mag/node_modules/expand-template/.travis.yml
new file mode 100644
index 00000000..cac9fc8a
--- /dev/null
+++ b/input_devices/mag/node_modules/expand-template/.travis.yml
@@ -0,0 +1,10 @@
+sudo: false
+
+language: node_js
+
+node_js:
+  - 4
+  - 6
+  - 8
+  - 9
+  - 10
diff --git a/input_devices/mag/node_modules/expand-template/README.md b/input_devices/mag/node_modules/expand-template/README.md
new file mode 100644
index 00000000..f6a417c1
--- /dev/null
+++ b/input_devices/mag/node_modules/expand-template/README.md
@@ -0,0 +1,43 @@
+# expand-template
+
+> Expand placeholders in a template string.
+
+[![npm](https://img.shields.io/npm/v/expand-template.svg)](https://www.npmjs.com/package/expand-template)
+[![Build Status](https://travis-ci.org/ralphtheninja/expand-template.svg?branch=master)](https://travis-ci.org/ralphtheninja/expand-template)
+[![dependencies](https://david-dm.org/ralptheninja/expand-template.svg)](https://david-dm.org/ralptheninja/expand-template)
+[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
+
+## Install
+
+```
+$ npm i expand-template -S
+```
+
+## Usage
+
+Default functionality expands templates using `{}` as separators for string placeholders.
+
+```js
+var expand = require('expand-template')()
+var template = '{foo}/{foo}/{bar}/{bar}'
+console.log(expand(template, {
+  foo: 'BAR',
+  bar: 'FOO'
+}))
+// -> BAR/BAR/FOO/FOO
+```
+
+Custom separators:
+
+```js
+var expand = require('expand-template')({ sep: '[]' })
+var template = '[foo]/[foo]/[bar]/[bar]'
+console.log(expand(template, {
+  foo: 'BAR',
+  bar: 'FOO'
+}))
+// -> BAR/BAR/FOO/FOO
+```
+
+## License
+All code, unless stated otherwise, is dual-licensed under [`WTFPL`](http://www.wtfpl.net/txt/copying/) and [`MIT`](https://opensource.org/licenses/MIT).
diff --git a/input_devices/mag/node_modules/expand-template/index.js b/input_devices/mag/node_modules/expand-template/index.js
new file mode 100644
index 00000000..627fa996
--- /dev/null
+++ b/input_devices/mag/node_modules/expand-template/index.js
@@ -0,0 +1,25 @@
+module.exports = function (opts) {
+  var sep = opts ? opts.sep : '{}'
+  var len = sep.length
+
+  var whitespace = '\\s*'
+  var left = escape(sep.substring(0, len / 2)) + whitespace
+  var right = whitespace + escape(sep.substring(len / 2, len))
+
+  return function (template, values) {
+    Object.keys(values).forEach(function (key) {
+      template = template.replace(regExp(key), values[key])
+    })
+    return template
+  }
+
+  function escape (s) {
+    return [].map.call(s, function (char) {
+      return '\\' + char
+    }).join('')
+  }
+
+  function regExp (key) {
+    return new RegExp(left + key + right, 'g')
+  }
+}
diff --git a/input_devices/mag/node_modules/expand-template/package.json b/input_devices/mag/node_modules/expand-template/package.json
new file mode 100644
index 00000000..8bc1ae15
--- /dev/null
+++ b/input_devices/mag/node_modules/expand-template/package.json
@@ -0,0 +1,88 @@
+{
+  "_args": [
+    [
+      "expand-template@^1.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "expand-template@>=1.0.2 <2.0.0",
+  "_id": "expand-template@1.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/expand-template",
+  "_nodeVersion": "10.0.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/expand-template_1.1.1_1525727689264_0.6627704267065915"
+  },
+  "_npmUser": {
+    "email": "ralphtheninja@riseup.net",
+    "name": "ralphtheninja"
+  },
+  "_npmVersion": "6.0.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "expand-template",
+    "raw": "expand-template@^1.0.2",
+    "rawSpec": "^1.0.2",
+    "scope": null,
+    "spec": ">=1.0.2 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz",
+  "_shasum": "981f188c0c3a87d2e28f559bc541426ff94f21dd",
+  "_shrinkwrap": null,
+  "_spec": "expand-template@^1.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "ralphtheninja@riseup.net",
+    "name": "LM"
+  },
+  "bugs": {
+    "url": "https://github.com/ralphtheninja/expand-template/issues"
+  },
+  "dependencies": {},
+  "description": "Expand placeholders in a template string",
+  "devDependencies": {
+    "standard": "^11.0.0",
+    "tape": "^4.2.2"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8MHJCRA9TVsSAnZWagAA2kIP/iGdY4tWpPFhaPcMfpE2\nKq2v7zEs48vRoVUaXGrixMuebwFWnl82PbTmoOsfOZ0SGCPjol2Zl9tOR069\n+rB6Edp77i8UTdG4RFaT5BZSIEVCMxjv8eav0//A2wunZTB7CHmKUqfSkF8t\nwOa8yXKcaYJzbzCaUp3a5nylvxKza3fLXY0IoDJusfQYimn3Wj6BmMsgymfg\nosWhkXROEhvoRVBzmVj5nwuFUwdzEkKt3AU+ZmLE/PySNKismc0U2MCmOTpc\n/SlppovsbexJybQgfDigORuVZDNmFtLMJYe9H1y9pardvKdyXxLMFIyHVDxk\nswRC76TeqF2P2hEsZ1L6AYqU4oFQfNSberzr+0/w60KA48IhgxVVzTBVOaW4\n9dPWAdNWnunvK5Bt2iiDy3vlCGe3Jen6+6NPzLv153R6Oz1UV77MnAz6PiU+\ncGgzO+RgDcFOYur0+fs1YPYuYvJaPufhs7I0g9GF2pGlZKBVHFWzvRaY4VtG\nQ6GPk6Kb9ds1j6HEx+MDZAhX6FSk0T1GlCTgOuEDWDzGFO+HeGous2WHZqSo\n6GfQT/63TtgvZol1bJGbuQJz0fVLqhqgSAXWTQxwJpqDkU/2U5F2x7OFu4hK\n16BcRLsR5wYZSuiH3rAML5PW62mGDr+a1wke0T0IydtLC+x9Bm+ss2FTB9h2\nqFrr\r\n=eA/K\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "981f188c0c3a87d2e28f559bc541426ff94f21dd",
+    "tarball": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz",
+    "unpackedSize": 3833
+  },
+  "gitHead": "252aee7952b3c4ea6a1b9699ee4f6324586952b3",
+  "homepage": "https://github.com/ralphtheninja/expand-template",
+  "keywords": [
+    "expand",
+    "replace",
+    "template"
+  ],
+  "license": "WTFPL",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "ralphtheninja",
+      "email": "ralphtheninja@riseup.net"
+    }
+  ],
+  "name": "expand-template",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/ralphtheninja/expand-template.git"
+  },
+  "scripts": {
+    "test": "tape test.js && standard"
+  },
+  "version": "1.1.1"
+}
diff --git a/input_devices/mag/node_modules/expand-template/test.js b/input_devices/mag/node_modules/expand-template/test.js
new file mode 100644
index 00000000..4ff43a0f
--- /dev/null
+++ b/input_devices/mag/node_modules/expand-template/test.js
@@ -0,0 +1,47 @@
+var test = require('tape')
+var Expand = require('./')
+
+test('default expands {} placeholders', function (t) {
+  var expand = Expand()
+  t.equal(typeof expand, 'function', 'is a function')
+  t.equal(expand('{foo}/{bar}', {
+    foo: 'BAR', bar: 'FOO'
+  }), 'BAR/FOO')
+  t.equal(expand('{foo}{foo}{foo}', {
+    foo: 'FOO'
+  }), 'FOOFOOFOO', 'expands one placeholder many times')
+  t.end()
+})
+
+test('support for custom separators', function (t) {
+  var expand = Expand({ sep: '[]' })
+  t.equal(expand('[foo]/[bar]', {
+    foo: 'BAR', bar: 'FOO'
+  }), 'BAR/FOO')
+  t.equal(expand('[foo][foo][foo]', {
+    foo: 'FOO'
+  }), 'FOOFOOFOO', 'expands one placeholder many times')
+  t.end()
+})
+
+test('support for longer custom separators', function (t) {
+  var expand = Expand({ sep: '[[]]' })
+  t.equal(expand('[[foo]]/[[bar]]', {
+    foo: 'BAR', bar: 'FOO'
+  }), 'BAR/FOO')
+  t.equal(expand('[[foo]][[foo]][[foo]]', {
+    foo: 'FOO'
+  }), 'FOOFOOFOO', 'expands one placeholder many times')
+  t.end()
+})
+
+test('whitespace-insensitive', function (t) {
+  var expand = Expand({ sep: '[]' })
+  t.equal(expand('[ foo ]/[ bar ]', {
+    foo: 'BAR', bar: 'FOO'
+  }), 'BAR/FOO')
+  t.equal(expand('[ foo ][ foo  ][ foo]', {
+    foo: 'FOO'
+  }), 'FOOFOOFOO', 'expands one placeholder many times')
+  t.end()
+})
diff --git a/input_devices/mag/node_modules/extend-shallow/LICENSE b/input_devices/mag/node_modules/extend-shallow/LICENSE
new file mode 100644
index 00000000..fa30c4cb
--- /dev/null
+++ b/input_devices/mag/node_modules/extend-shallow/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/extend-shallow/README.md b/input_devices/mag/node_modules/extend-shallow/README.md
new file mode 100644
index 00000000..cdc45d4f
--- /dev/null
+++ b/input_devices/mag/node_modules/extend-shallow/README.md
@@ -0,0 +1,61 @@
+# extend-shallow [![NPM version](https://badge.fury.io/js/extend-shallow.svg)](http://badge.fury.io/js/extend-shallow)  [![Build Status](https://travis-ci.org/jonschlinkert/extend-shallow.svg)](https://travis-ci.org/jonschlinkert/extend-shallow)
+
+> Extend an object with the properties of additional objects. node.js/javascript util.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i extend-shallow --save
+```
+
+## Usage
+
+```js
+var extend = require('extend-shallow');
+
+extend({a: 'b'}, {c: 'd'})
+//=> {a: 'b', c: 'd'}
+```
+
+Pass an empty object to shallow clone:
+
+```js
+var obj = {};
+extend(obj, {a: 'b'}, {c: 'd'})
+//=> {a: 'b', c: 'd'}
+```
+
+## Related
+
+* [extend-shallow](https://github.com/jonschlinkert/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util.
+* [for-own](https://github.com/jonschlinkert/for-own): Iterate over the own enumerable properties of an object, and return an object with properties… [more](https://github.com/jonschlinkert/for-own)
+* [for-in](https://github.com/jonschlinkert/for-in): Iterate over the own and inherited enumerable properties of an objecte, and return an object… [more](https://github.com/jonschlinkert/for-in)
+* [is-plain-object](https://github.com/jonschlinkert/is-plain-object): Returns true if an object was created by the `Object` constructor.
+* [isobject](https://github.com/jonschlinkert/isobject): Returns true if the value is an object and not an array or null.
+* [kind-of](https://github.com/jonschlinkert/kind-of): Get the native type of a value.
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 29, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/extend-shallow/index.js b/input_devices/mag/node_modules/extend-shallow/index.js
new file mode 100644
index 00000000..92a067fc
--- /dev/null
+++ b/input_devices/mag/node_modules/extend-shallow/index.js
@@ -0,0 +1,33 @@
+'use strict';
+
+var isObject = require('is-extendable');
+
+module.exports = function extend(o/*, objects*/) {
+  if (!isObject(o)) { o = {}; }
+
+  var len = arguments.length;
+  for (var i = 1; i < len; i++) {
+    var obj = arguments[i];
+
+    if (isObject(obj)) {
+      assign(o, obj);
+    }
+  }
+  return o;
+};
+
+function assign(a, b) {
+  for (var key in b) {
+    if (hasOwn(b, key)) {
+      a[key] = b[key];
+    }
+  }
+}
+
+/**
+ * Returns true if the given `key` is an own property of `obj`.
+ */
+
+function hasOwn(obj, key) {
+  return Object.prototype.hasOwnProperty.call(obj, key);
+}
diff --git a/input_devices/mag/node_modules/extend-shallow/package.json b/input_devices/mag/node_modules/extend-shallow/package.json
new file mode 100644
index 00000000..5950db62
--- /dev/null
+++ b/input_devices/mag/node_modules/extend-shallow/package.json
@@ -0,0 +1,111 @@
+{
+  "_args": [
+    [
+      "extend-shallow@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/terminal-paginator"
+    ]
+  ],
+  "_from": "extend-shallow@>=2.0.1 <3.0.0",
+  "_id": "extend-shallow@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/extend-shallow",
+  "_nodeVersion": "0.12.4",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "extend-shallow",
+    "raw": "extend-shallow@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": null,
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-utils",
+    "/terminal-paginator"
+  ],
+  "_resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+  "_shasum": "51af7d614ad9a9f610ea1bafbb989d6b1c56890f",
+  "_shrinkwrap": null,
+  "_spec": "extend-shallow@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/terminal-paginator",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/extend-shallow/issues"
+  },
+  "dependencies": {
+    "is-extendable": "^0.1.0"
+  },
+  "description": "Extend an object with the properties of additional objects. node.js/javascript util.",
+  "devDependencies": {
+    "array-slice": "^0.2.3",
+    "benchmarked": "^0.1.4",
+    "chalk": "^1.0.0",
+    "for-own": "^0.1.3",
+    "glob": "^5.0.12",
+    "is-plain-object": "^2.0.1",
+    "kind-of": "^2.0.0",
+    "minimist": "^1.1.1",
+    "mocha": "^2.2.5",
+    "should": "^7.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "51af7d614ad9a9f610ea1bafbb989d6b1c56890f",
+    "tarball": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e9b1f1d2ff9d2990ec4a127afa7c14732d1eec8a",
+  "homepage": "https://github.com/jonschlinkert/extend-shallow",
+  "keywords": [
+    "assign",
+    "extend",
+    "javascript",
+    "js",
+    "keys",
+    "merge",
+    "obj",
+    "object",
+    "prop",
+    "properties",
+    "property",
+    "props",
+    "shallow",
+    "util",
+    "utility",
+    "utils",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "extend-shallow",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/extend-shallow.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/for-in/LICENSE b/input_devices/mag/node_modules/for-in/LICENSE
new file mode 100644
index 00000000..d734237b
--- /dev/null
+++ b/input_devices/mag/node_modules/for-in/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/for-in/README.md b/input_devices/mag/node_modules/for-in/README.md
new file mode 100644
index 00000000..874e1895
--- /dev/null
+++ b/input_devices/mag/node_modules/for-in/README.md
@@ -0,0 +1,85 @@
+# for-in [![NPM version](https://img.shields.io/npm/v/for-in.svg?style=flat)](https://www.npmjs.com/package/for-in) [![NPM monthly downloads](https://img.shields.io/npm/dm/for-in.svg?style=flat)](https://npmjs.org/package/for-in)  [![NPM total downloads](https://img.shields.io/npm/dt/for-in.svg?style=flat)](https://npmjs.org/package/for-in) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/for-in.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/for-in)
+
+> Iterate over the own and inherited enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save for-in
+```
+
+## Usage
+
+```js
+var forIn = require('for-in');
+
+var obj = {a: 'foo', b: 'bar', c: 'baz'};
+var values = [];
+var keys = [];
+
+forIn(obj, function (value, key, o) {
+  keys.push(key);
+  values.push(value);
+});
+
+console.log(keys);
+//=> ['a', 'b', 'c'];
+
+console.log(values);
+//=> ['foo', 'bar', 'baz'];
+```
+
+## About
+
+### Related projects
+
+* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays. This is the fastest implementation of array flatten.")
+* [collection-map](https://www.npmjs.com/package/collection-map): Returns an array of mapped values from an array or object. | [homepage](https://github.com/jonschlinkert/collection-map "Returns an array of mapped values from an array or object.")
+* [for-own](https://www.npmjs.com/package/for-own): Iterate over the own enumerable properties of an object, and return an object with properties… [more](https://github.com/jonschlinkert/for-own) | [homepage](https://github.com/jonschlinkert/for-own "Iterate over the own enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 16 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 2 | [paulirish](https://github.com/paulirish) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 28, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/for-in/index.js b/input_devices/mag/node_modules/for-in/index.js
new file mode 100644
index 00000000..0b5f95f0
--- /dev/null
+++ b/input_devices/mag/node_modules/for-in/index.js
@@ -0,0 +1,16 @@
+/*!
+ * for-in <https://github.com/jonschlinkert/for-in>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+module.exports = function forIn(obj, fn, thisArg) {
+  for (var key in obj) {
+    if (fn.call(thisArg, obj[key], key, obj) === false) {
+      break;
+    }
+  }
+};
diff --git a/input_devices/mag/node_modules/for-in/package.json b/input_devices/mag/node_modules/for-in/package.json
new file mode 100644
index 00000000..3252d15a
--- /dev/null
+++ b/input_devices/mag/node_modules/for-in/package.json
@@ -0,0 +1,138 @@
+{
+  "_args": [
+    [
+      "for-in@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/for-own"
+    ]
+  ],
+  "_from": "for-in@>=1.0.1 <2.0.0",
+  "_id": "for-in@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/for-in",
+  "_nodeVersion": "7.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/for-in-1.0.2.tgz_1488298375632_0.9562143329530954"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.1.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "for-in",
+    "raw": "for-in@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/for-own"
+  ],
+  "_resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+  "_shasum": "81068d295a8142ec0ac726c6e2200c30fb6d5e80",
+  "_shrinkwrap": null,
+  "_spec": "for-in@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/for-own",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/for-in/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Paul Irish",
+      "url": "http://paulirish.com"
+    }
+  ],
+  "dependencies": {},
+  "description": "Iterate over the own and inherited enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.11",
+    "mocha": "^3.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "81068d295a8142ec0ac726c6e2200c30fb6d5e80",
+    "tarball": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "5f97ad4f6556e938d9b71614259ddd8044a081e3",
+  "homepage": "https://github.com/jonschlinkert/for-in",
+  "keywords": [
+    "for",
+    "for-in",
+    "for-own",
+    "has",
+    "has-own",
+    "hasOwn",
+    "in",
+    "key",
+    "keys",
+    "object",
+    "own",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "for-in",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/for-in.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "arr-flatten",
+        "collection-map",
+        "for-own"
+      ]
+    },
+    "run": true,
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/for-own/LICENSE b/input_devices/mag/node_modules/for-own/LICENSE
new file mode 100644
index 00000000..d290fe00
--- /dev/null
+++ b/input_devices/mag/node_modules/for-own/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2015, 2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/for-own/README.md b/input_devices/mag/node_modules/for-own/README.md
new file mode 100644
index 00000000..fd56877a
--- /dev/null
+++ b/input_devices/mag/node_modules/for-own/README.md
@@ -0,0 +1,85 @@
+# for-own [![NPM version](https://img.shields.io/npm/v/for-own.svg?style=flat)](https://www.npmjs.com/package/for-own) [![NPM monthly downloads](https://img.shields.io/npm/dm/for-own.svg?style=flat)](https://npmjs.org/package/for-own)  [![NPM total downloads](https://img.shields.io/npm/dt/for-own.svg?style=flat)](https://npmjs.org/package/for-own) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/for-own.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/for-own)
+
+> Iterate over the own enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save for-own
+```
+
+## Usage
+
+```js
+var forOwn = require('for-own');
+
+var obj = {a: 'foo', b: 'bar', c: 'baz'};
+var values = [];
+var keys = [];
+
+forOwn(obj, function (value, key, o) {
+  keys.push(key);
+  values.push(value);
+});
+
+console.log(keys);
+//=> ['a', 'b', 'c'];
+
+console.log(values);
+//=> ['foo', 'bar', 'baz'];
+```
+
+## About
+
+### Related projects
+
+* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays. This is the fastest implementation of array flatten.")
+* [collection-map](https://www.npmjs.com/package/collection-map): Returns an array of mapped values from an array or object. | [homepage](https://github.com/jonschlinkert/collection-map "Returns an array of mapped values from an array or object.")
+* [for-in](https://www.npmjs.com/package/for-in): Iterate over the own and inherited enumerable properties of an object, and return an object… [more](https://github.com/jonschlinkert/for-in) | [homepage](https://github.com/jonschlinkert/for-in "Iterate over the own and inherited enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 10 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [javiercejudo](https://github.com/javiercejudo) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 26, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/for-own/index.js b/input_devices/mag/node_modules/for-own/index.js
new file mode 100644
index 00000000..74e2d755
--- /dev/null
+++ b/input_devices/mag/node_modules/for-own/index.js
@@ -0,0 +1,19 @@
+/*!
+ * for-own <https://github.com/jonschlinkert/for-own>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var forIn = require('for-in');
+var hasOwn = Object.prototype.hasOwnProperty;
+
+module.exports = function forOwn(obj, fn, thisArg) {
+  forIn(obj, function(val, key) {
+    if (hasOwn.call(obj, key)) {
+      return fn.call(thisArg, obj[key], key, obj);
+    }
+  });
+};
diff --git a/input_devices/mag/node_modules/for-own/package.json b/input_devices/mag/node_modules/for-own/package.json
new file mode 100644
index 00000000..a02b8a9a
--- /dev/null
+++ b/input_devices/mag/node_modules/for-own/package.json
@@ -0,0 +1,140 @@
+{
+  "_args": [
+    [
+      "for-own@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep"
+    ]
+  ],
+  "_from": "for-own@>=1.0.0 <2.0.0",
+  "_id": "for-own@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/for-own",
+  "_nodeVersion": "7.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/for-own-1.0.0.tgz_1488159207065_0.6514356201514602"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.1.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "for-own",
+    "raw": "for-own@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/clone-deep"
+  ],
+  "_resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+  "_shasum": "c63332f415cedc4b04dbfe70cf836494c53cb44b",
+  "_shrinkwrap": null,
+  "_spec": "for-own@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/for-own/issues"
+  },
+  "contributors": [
+    {
+      "name": "Javier Cejudo",
+      "email": "javier@javiercejudo.com",
+      "url": "https://www.javiercejudo.com"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "for-in": "^1.0.1"
+  },
+  "description": "Iterate over the own enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.11",
+    "mocha": "^3.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "c63332f415cedc4b04dbfe70cf836494c53cb44b",
+    "tarball": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "2d39447529c7b41f41e0d3443e46c5de607720ab",
+  "homepage": "https://github.com/jonschlinkert/for-own",
+  "keywords": [
+    "for",
+    "for-in",
+    "for-own",
+    "has",
+    "has-own",
+    "hasOwn",
+    "key",
+    "keys",
+    "object",
+    "own",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "for-own",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/for-own.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "arr-flatten",
+        "collection-map",
+        "for-in"
+      ]
+    },
+    "run": true,
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/fs-constants/LICENSE b/input_devices/mag/node_modules/fs-constants/LICENSE
new file mode 100644
index 00000000..cb757e5d
--- /dev/null
+++ b/input_devices/mag/node_modules/fs-constants/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 Mathias Buus
+
+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/input_devices/mag/node_modules/fs-constants/README.md b/input_devices/mag/node_modules/fs-constants/README.md
new file mode 100644
index 00000000..62b33742
--- /dev/null
+++ b/input_devices/mag/node_modules/fs-constants/README.md
@@ -0,0 +1,26 @@
+# fs-constants
+
+Small module that allows you to get the fs constants across
+Node and the browser. 
+
+```
+npm install fs-constants
+```
+
+Previously you would use `require('constants')` for this in node but that has been
+deprecated and changed to `require('fs').constants` which does not browserify.
+
+This module uses `require('constants')` in the browser and `require('fs').constants` in node to work around this
+
+
+## Usage
+
+``` js
+var constants = require('fs-constants')
+
+console.log('constants:', constants)
+```
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/fs-constants/browser.js b/input_devices/mag/node_modules/fs-constants/browser.js
new file mode 100644
index 00000000..3c87638d
--- /dev/null
+++ b/input_devices/mag/node_modules/fs-constants/browser.js
@@ -0,0 +1 @@
+module.exports = require('constants')
diff --git a/input_devices/mag/node_modules/fs-constants/index.js b/input_devices/mag/node_modules/fs-constants/index.js
new file mode 100644
index 00000000..2a3aadf3
--- /dev/null
+++ b/input_devices/mag/node_modules/fs-constants/index.js
@@ -0,0 +1 @@
+module.exports = require('fs').constants || require('constants')
diff --git a/input_devices/mag/node_modules/fs-constants/package.json b/input_devices/mag/node_modules/fs-constants/package.json
new file mode 100644
index 00000000..06dc96c0
--- /dev/null
+++ b/input_devices/mag/node_modules/fs-constants/package.json
@@ -0,0 +1,78 @@
+{
+  "_args": [
+    [
+      "fs-constants@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream"
+    ]
+  ],
+  "_from": "fs-constants@>=1.0.0 <2.0.0",
+  "_id": "fs-constants@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/fs-constants",
+  "_nodeVersion": "9.11.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/fs-constants_1.0.0_1524753752667_0.578647269374104"
+  },
+  "_npmUser": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "mafintosh"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "fs-constants",
+    "raw": "fs-constants@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+  "_shasum": "6be0de9be998ce16af8afc24497b9ee9b7ccd9ad",
+  "_shrinkwrap": null,
+  "_spec": "fs-constants@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream",
+  "author": {
+    "name": "Mathias Buus",
+    "url": "@mafintosh"
+  },
+  "browser": "browser.js",
+  "bugs": {
+    "url": "https://github.com/mafintosh/fs-constants/issues"
+  },
+  "dependencies": {},
+  "description": "Require constants across node and the browser",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4eVZCRA9TVsSAnZWagAAwToP/1iImDmdSp3+yQXUS7r5\nAiuHdDIJFdm4uZbS5R+C7LhNCfFHYTOiI1Q0+0yO6zRr+SHAFJJsVZwXcfp2\nDyRm3TY0X9QdjAJs9SifNpIkdWgOwQBrE5QZEUOM8EJ2hNB7zCskk3SUc5FR\noGbkGZEov6pFBn3OpV0IBm2PaiAIyZ+0Xt+TiLlRR5lR0NR+X6LwKtEuNuYC\nfQNCr2Z7uRnJtrvfPOYH6Jycvumt86CgqUfjeWek7CDUgapw2/zA/u+voEoY\nMDbQeaHq+Dzd9F9fVn7/aCh7bKxWwkVHxPB7wEoA8r+u4lJOPLX2sLEjq/QV\nKwGlHKZMFVU6D3kBkg/8deRWuFJpaMkUxqtSKfURbEwWaChq8X7+UNQ+Jx2a\nRdC1gO7od7Jf0srQbPgEGRLXeg19r8NTJOrLStOzZHqrH0oS3iIekGeibNEu\nwKbLJDdJgIVhp1kzzlPtiiv2vV6YVfp/8a3Ny7iysDlP7p/rit5BQeQ9hKaK\nFMeSToWnJfxrSVOYwKZro6vueSxczDgHW6ocxeWXxkZaTTgCidqwqEfzRZ3G\njptJQcVXbbg+TJIPCsOPpRMPGweDjPDsIbx4tIdURMCzzwSv2UHOpy1a9uAn\nq2xKRxLYo6IT8uHlhrfoGFemJk9xkio/gXREaT8DaNVrRoIn3/iYRqOH7BsE\nrITK\r\n=XQxt\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "6be0de9be998ce16af8afc24497b9ee9b7ccd9ad",
+    "tarball": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+    "unpackedSize": 2223
+  },
+  "gitHead": "3636fd76cf948ebfc143c1913af6d3c4450b1c46",
+  "homepage": "https://github.com/mafintosh/fs-constants",
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    }
+  ],
+  "name": "fs-constants",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/mafintosh/fs-constants.git"
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/gauge/CHANGELOG.md b/input_devices/mag/node_modules/gauge/CHANGELOG.md
new file mode 100644
index 00000000..407bc192
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/CHANGELOG.md
@@ -0,0 +1,160 @@
+### v2.7.4
+
+* Reset colors prior to ending a line, to eliminate flicker when a line
+  is trucated between start and end color sequences.
+
+### v2.7.3
+
+* Only create our onExit handler when we're enabled and remove it when we're
+  disabled.  This stops us from creating multiple onExit handlers when
+  multiple gauge objects are being used.
+* Fix bug where if a theme name were given instead of a theme object, it
+  would crash.
+* Remove supports-color because it's not actually used.  Uhm.  Yes, I just
+  updated it.  >.>
+
+### v2.7.2
+
+* Use supports-color instead of has-color (as the module has been renamed)
+
+### v2.7.1
+
+* Bug fix: Calls to show/pulse while the progress bar is disabled should still
+  update our internal representation of what would be shown should it be enabled.
+
+### v2.7.0
+
+* New feature: Add new `isEnabled` method to allow introspection of the gauge's
+  "enabledness" as controlled by `.enable()` and `.disable()`.
+
+### v2.6.0
+
+* Bug fix: Don't run the code associated with `enable`/`disable` if the gauge
+  is already enabled or disabled respectively.  This prevents leaking event
+  listeners, amongst other weirdness.
+* New feature: Template items can have default values that will be used if no
+  value was otherwise passed in.
+
+### v2.5.3
+
+* Default to `enabled` only if we have a tty.  Users can always override
+  this by passing in the `enabled` option explicitly or by calling calling
+  `gauge.enable()`.
+
+### v2.5.2
+
+* Externalized `./console-strings.js` into `console-control-strings`.
+
+### v2.5.1
+
+* Update to `signal-exit@3.0.0`, which fixes a compatibility bug with the
+  node profiler.
+* [#39](https://github.com/iarna/gauge/pull/39) Fix tests on 0.10 and add
+  a missing devDependency. ([@helloyou2012](https://github.com/helloyou2012))
+
+### v2.5.0
+
+* Add way to programmatically fetch a list of theme names in a themeset
+  (`Themeset.getThemeNames`).
+
+### v2.4.0
+
+* Add support for setting themesets on existing gauge objects.
+* Add post-IO callback to `gauge.hide()` as it is somtetimes necessary when
+  your terminal is interleaving output from multiple filehandles (ie, stdout
+  & stderr).
+
+### v2.3.1
+
+* Fix a refactor bug in setTheme where it wasn't accepting the various types
+  of args it should.
+
+### v2.3.0
+
+#### FEATURES
+
+* Add setTemplate & setTheme back in.
+* Add support for named themes, you can now ask for things like 'colorASCII'
+  and 'brailleSpinner'.  Of course, you can still pass in theme objects.
+  Additionally you can now pass in an object with `hasUnicode`, `hasColor` and
+  `platform` keys in order to override our guesses as to those values when
+  selecting a default theme from the themeset.
+* Make the output stream optional (it defaults to `process.stderr` now).
+* Add `setWriteTo(stream[, tty])` to change the output stream and,
+  optionally, tty.
+
+#### BUG FIXES & REFACTORING
+
+* Abort the display phase early if we're supposed to be hidden and we are.
+* Stop printing a bunch of spaces at the end of lines, since we're already
+  using an erase-to-end-of-line code anyway.
+* The unicode themes were missing the subsection separator.
+
+### v2.2.1
+
+* Fix image in readme
+
+### v2.2.0
+
+* All new themes API– reference themes by name and pass in custom themes and
+  themesets (themesets get platform support autodetection done on them to
+  select the best theme).  Theme mixins let you add features to all existing
+  themes.
+* Much, much improved test coverage.
+
+### v2.1.0
+
+* Got rid of ░ in the default platform, noUnicode, hasColor theme.  Thanks
+  to @yongtw123 for pointing out this had snuck in.
+* Fiddled with the demo output to make it easier to see the spinner spin. Also
+  added prints before each platforms test output.
+* I forgot to include `signal-exit` in our deps.  <.< Thank you @KenanY for
+  finding this. Then I was lazy and made a new commit instead of using his
+  PR. Again, thank you for your patience @KenenY.
+* Drastically speed up travis testing.
+* Add a small javascript demo (demo.js) for showing off the various themes
+  (and testing them on diff platforms).
+* Change: The subsection separator from ⁄ and / (different chars) to >.
+* Fix crasher: A show or pulse without a label would cause the template renderer
+  to complain about a missing value.
+* New feature: Add the ability to disable the clean-up-on-exit behavior.
+  Not something I expect to be widely desirable, but important if you have
+  multiple distinct gauge instances in your app.
+* Use our own color support detection.
+  The `has-color` module proved too magic for my needs, making assumptions
+  as to which stream we write to and reading command line arguments.
+
+### v2.0.0
+
+This is a major rewrite of the internals.  Externally there are fewer
+changes:
+
+* On node>0.8 gauge object now prints updates at a fixed rate.  This means
+  that when you call `show` it may wate up to `updateInterval` ms before it
+  actually prints an update.  You override this behavior with the
+  `fixedFramerate` option.
+* The gauge object now keeps the cursor hidden as long as it's enabled and
+  shown.
+* The constructor's arguments have changed, now it takes a mandatory output
+  stream and an optional options object.  The stream no longer needs to be
+  an `ansi`ified stream, although it can be if you want (but we won't make
+  use of its special features).
+* Previously the gauge was disabled by default if `process.stdout` wasn't a
+  tty.  Now it always defaults to enabled.  If you want the previous
+  behavior set the `enabled` option to `process.stdout.isTTY`.
+* The constructor's options have changed– see the docs for details.
+* Themes are entirely different.  If you were using a custom theme, or
+  referring to one directly (eg via `Gauge.unicode` or `Gauge.ascii`) then
+  you'll need to change your code.  You can get the equivalent of the latter
+  with:
+  ```
+  var themes = require('gauge/themes')
+  var unicodeTheme = themes(true, true) // returns the color unicode theme for your platform
+  ```
+  The default themes no longer use any ambiguous width characters, so even
+  if you choose to display those as wide your progress bar should still
+  display correctly.
+* Templates are entirely different and if you were using a custom one, you
+  should consult the documentation to learn how to recreate it.  If you were
+  using the default, be aware that it has changed and the result looks quite
+  a bit different.
diff --git a/input_devices/mag/node_modules/gauge/LICENSE b/input_devices/mag/node_modules/gauge/LICENSE
new file mode 100644
index 00000000..e7560529
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2014, Rebecca Turner <me@re-becca.org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/gauge/README.md b/input_devices/mag/node_modules/gauge/README.md
new file mode 100644
index 00000000..bdd60e38
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/README.md
@@ -0,0 +1,399 @@
+gauge
+=====
+
+A nearly stateless terminal based horizontal gauge / progress bar.
+
+```javascript
+var Gauge = require("gauge")
+
+var gauge = new Gauge()
+
+gauge.show("test", 0.20)
+
+gauge.pulse("this")
+
+gauge.hide()
+```
+
+![](gauge-demo.gif)
+
+
+### CHANGES FROM 1.x
+
+Gauge 2.x is breaking release, please see the [changelog] for details on
+what's changed if you were previously a user of this module.
+
+[changelog]: CHANGELOG.md
+
+### THE GAUGE CLASS
+
+This is the typical interface to the module– it provides a pretty
+fire-and-forget interface to displaying your status information.
+
+```
+var Gauge = require("gauge")
+
+var gauge = new Gauge([stream], [options])
+```
+
+* **stream** – *(optional, default STDERR)* A stream that progress bar
+  updates are to be written to.  Gauge honors backpressure and will pause
+  most writing if it is indicated.
+* **options** – *(optional)* An option object.
+
+Constructs a new gauge. Gauges are drawn on a single line, and are not drawn
+if **stream** isn't a tty and a tty isn't explicitly provided.
+
+If **stream** is a terminal or if you pass in **tty** to **options** then we
+will detect terminal resizes and redraw to fit.  We do this by watching for
+`resize` events on the tty.  (To work around a bug in verisons of Node prior
+to 2.5.0, we watch for them on stdout if the tty is stderr.) Resizes to
+larger window sizes will be clean, but shrinking the window will always
+result in some cruft.
+
+**IMPORTANT:** If you prevously were passing in a non-tty stream but you still
+want output (for example, a stream wrapped by the `ansi` module) then you
+need to pass in the **tty** option below, as `gauge` needs access to
+the underlying tty in order to do things like terminal resizes and terminal
+width detection.
+
+The **options** object can have the following properties, all of which are
+optional:
+
+* **updateInterval**: How often gauge updates should be drawn, in miliseconds.
+* **fixedFramerate**: Defaults to false on node 0.8, true on everything
+  else.  When this is true a timer is created to trigger once every
+  `updateInterval` ms, when false, updates are printed as soon as they come
+  in but updates more often than `updateInterval` are ignored.  The reason
+  0.8 doesn't have this set to true is that it can't `unref` its timer and
+  so it would stop your program from exiting– if you want to use this
+  feature with 0.8 just make sure you call `gauge.disable()` before you
+  expect your program to exit.
+* **themes**: A themeset to use when selecting the theme to use. Defaults
+  to `gauge/themes`, see the [themes] documentation for details.
+* **theme**: Select a theme for use, it can be a:
+  * Theme object, in which case the **themes** is not used.
+  * The name of a theme, which will be looked up in the current *themes*
+    object.
+  * A configuration object with any of `hasUnicode`, `hasColor` or
+    `platform` keys, which if wlll be used to override our guesses when making
+    a default theme selection.
+
+  If no theme is selected then a default is picked using a combination of our
+  best guesses at your OS, color support and unicode support.
+* **template**: Describes what you want your gauge to look like.  The
+  default is what npm uses.  Detailed [documentation] is later in this
+  document.
+* **hideCursor**: Defaults to true.  If true, then the cursor will be hidden
+  while the gauge is displayed.
+* **tty**: The tty that you're ultimately writing to.  Defaults to the same
+  as **stream**.  This is used for detecting the width of the terminal and
+  resizes. The width used is `tty.columns - 1`. If no tty is available then
+  a width of `79` is assumed.
+* **enabled**: Defaults to true if `tty` is a TTY, false otherwise.  If true
+  the gauge starts enabled.  If disabled then all update commands are
+  ignored and no gauge will be printed until you call `.enable()`.
+* **Plumbing**: The class to use to actually generate the gauge for
+  printing.  This defaults to `require('gauge/plumbing')` and ordinarly you
+  shouldn't need to override this.
+* **cleanupOnExit**: Defaults to true. Ordinarily we register an exit
+  handler to make sure your cursor is turned back on and the progress bar
+  erased when your process exits, even if you Ctrl-C out or otherwise exit
+  unexpectedly. You can disable this and it won't register the exit handler.
+
+[has-unicode]: https://www.npmjs.com/package/has-unicode
+[themes]: #themes
+[documentation]: #templates
+
+#### `gauge.show(section | status, [completed])`
+
+The first argument is either the section, the name of the current thing
+contributing to progress, or an object with keys like **section**,
+**subsection** & **completed** (or any others you have types for in a custom
+template).  If you don't want to update or set any of these you can pass
+`null` and it will be ignored.
+
+The second argument is the percent completed as a value between 0 and 1.
+Without it, completion is just not updated. You'll also note that completion
+can be passed in as part of a status object as the first argument. If both
+it and the completed argument are passed in, the completed argument wins.
+
+#### `gauge.hide([cb])`
+
+Removes the gauge from the terminal.  Optionally, callback `cb` after IO has
+had an opportunity to happen (currently this just means after `setImmediate`
+has called back.)
+
+It turns out this is important when you're pausing the progress bar on one
+filehandle and printing to another– otherwise (with a big enough print) node
+can end up printing the "end progress bar" bits to the progress bar filehandle
+while other stuff is printing to another filehandle. These getting interleaved
+can cause corruption in some terminals.
+
+#### `gauge.pulse([subsection])`
+
+* **subsection** – *(optional)* The specific thing that triggered this pulse
+
+Spins the spinner in the gauge to show output.  If **subsection** is
+included then it will be combined with the last name passed to `gauge.show`.
+
+#### `gauge.disable()`
+
+Hides the gauge and ignores further calls to `show` or `pulse`.
+
+#### `gauge.enable()`
+
+Shows the gauge and resumes updating when `show` or `pulse` is called.
+
+#### `gauge.isEnabled()`
+
+Returns true if the gauge is enabled.
+
+#### `gauge.setThemeset(themes)`
+
+Change the themeset to select a theme from. The same as the `themes` option
+used in the constructor. The theme will be reselected from this themeset.
+
+#### `gauge.setTheme(theme)`
+
+Change the active theme, will be displayed with the next show or pulse. This can be:
+
+* Theme object, in which case the **themes** is not used.
+* The name of a theme, which will be looked up in the current *themes*
+  object.
+* A configuration object with any of `hasUnicode`, `hasColor` or
+  `platform` keys, which if wlll be used to override our guesses when making
+  a default theme selection.
+
+If no theme is selected then a default is picked using a combination of our
+best guesses at your OS, color support and unicode support.
+
+#### `gauge.setTemplate(template)`
+
+Change the active template, will be displayed with the next show or pulse
+
+### Tracking Completion
+
+If you have more than one thing going on that you want to track completion
+of, you may find the related [are-we-there-yet] helpful.  It's `change`
+event can be wired up to the `show` method to get a more traditional
+progress bar interface.
+
+[are-we-there-yet]: https://www.npmjs.com/package/are-we-there-yet
+
+### THEMES
+
+```
+var themes = require('gauge/themes')
+
+// fetch the default color unicode theme for this platform
+var ourTheme = themes({hasUnicode: true, hasColor: true})
+
+// fetch the default non-color unicode theme for osx
+var ourTheme = themes({hasUnicode: true, hasColor: false, platform: 'darwin'})
+
+// create a new theme based on the color ascii theme for this platform
+// that brackets the progress bar with arrows
+var ourTheme = themes.newTheme(theme(hasUnicode: false, hasColor: true}), {
+  preProgressbar: '→',
+  postProgressbar: '←'
+})
+```
+
+The object returned by `gauge/themes` is an instance of the `ThemeSet` class.
+
+```
+var ThemeSet = require('gauge/theme-set')
+var themes = new ThemeSet()
+// or
+var themes = require('gauge/themes')
+var mythemes = themes.newThemeset() // creates a new themeset based on the default themes
+```
+
+#### themes(opts)
+#### themes.getDefault(opts)
+
+Theme objects are a function that fetches the default theme based on
+platform, unicode and color support.
+
+Options is an object with the following properties:
+
+* **hasUnicode** - If true, fetch a unicode theme, if no unicode theme is
+  available then a non-unicode theme will be used.
+* **hasColor** - If true, fetch a color theme, if no color theme is
+  available a non-color theme will be used.
+* **platform** (optional) - Defaults to `process.platform`.  If no
+  platform match is available then `fallback` is used instead.
+
+If no compatible theme can be found then an error will be thrown with a
+`code` of `EMISSINGTHEME`.
+
+#### themes.addTheme(themeName, themeObj)
+#### themes.addTheme(themeName, [parentTheme], newTheme)
+
+Adds a named theme to the themeset.  You can pass in either a theme object,
+as returned by `themes.newTheme` or the arguments you'd pass to
+`themes.newTheme`.
+
+#### themes.getThemeNames()
+
+Return a list of all of the names of the themes in this themeset. Suitable
+for use in `themes.getTheme(…)`.
+
+#### themes.getTheme(name)
+
+Returns the theme object from this theme set named `name`.
+
+If `name` does not exist in this themeset an error will be thrown with
+a `code` of `EMISSINGTHEME`.
+
+#### themes.setDefault([opts], themeName)
+
+`opts` is an object with the following properties.
+
+* **platform** - Defaults to `'fallback'`.  If your theme is platform
+  specific, specify that here with the platform from `process.platform`, eg,
+  `win32`, `darwin`, etc.
+* **hasUnicode** - Defaults to `false`. If your theme uses unicode you
+  should set this to true.
+* **hasColor** - Defaults to `false`.  If your theme uses color you should
+  set this to true.
+
+`themeName` is the name of the theme (as given to `addTheme`) to use for
+this set of `opts`.
+
+#### themes.newTheme([parentTheme,] newTheme)
+
+Create a new theme object based on `parentTheme`.  If no `parentTheme` is
+provided then a minimal parentTheme that defines functions for rendering the
+activity indicator (spinner) and progress bar will be defined. (This
+fallback parent is defined in `gauge/base-theme`.)
+
+newTheme should be a bare object– we'll start by discussing the properties
+defined by the default themes:
+
+* **preProgressbar** - displayed prior to the progress bar, if the progress
+  bar is displayed.
+* **postProgressbar** - displayed after the progress bar, if the progress bar
+  is displayed.
+* **progressBarTheme** - The subtheme passed through to the progress bar
+  renderer, it's an object with `complete` and `remaining` properties
+  that are the strings you want repeated for those sections of the progress
+  bar.
+* **activityIndicatorTheme** - The theme for the activity indicator (spinner),
+  this can either be a string, in which each character is a different step, or
+  an array of strings.
+* **preSubsection** - Displayed as a separator between the `section` and
+  `subsection` when the latter is printed.
+
+More generally, themes can have any value that would be a valid value when rendering
+templates. The properties in the theme are used when their name matches a type in
+the template. Their values can be:
+
+* **strings & numbers** - They'll be included as is
+* **function (values, theme, width)** - Should return what you want in your output.
+  *values* is an object with values provided via `gauge.show`,
+  *theme* is the theme specific to this item (see below) or this theme object,
+  and *width* is the number of characters wide your result should be.
+
+There are a couple of special prefixes:
+
+* **pre** - Is shown prior to the property, if its displayed.
+* **post** - Is shown after the property, if its displayed.
+
+And one special suffix:
+
+* **Theme** - Its value is passed to a function-type item as the theme.
+
+#### themes.addToAllThemes(theme)
+
+This *mixes-in* `theme` into all themes currently defined. It also adds it
+to the default parent theme for this themeset, so future themes added to
+this themeset will get the values from `theme` by default.
+
+#### themes.newThemeset()
+
+Copy the current themeset into a new one.  This allows you to easily inherit
+one themeset from another.
+
+### TEMPLATES
+
+A template is an array of objects and strings that, after being evaluated,
+will be turned into the gauge line.  The default template is:
+
+```javascript
+[
+    {type: 'progressbar', length: 20},
+    {type: 'activityIndicator', kerning: 1, length: 1},
+    {type: 'section', kerning: 1, default: ''},
+    {type: 'subsection', kerning: 1, default: ''}
+]
+```
+
+The various template elements can either be **plain strings**, in which case they will
+be be included verbatum in the output, or objects with the following properties:
+
+* *type* can be any of the following plus any keys you pass into `gauge.show` plus
+  any keys you have on a custom theme.
+  * `section` – What big thing you're working on now.
+  * `subsection` – What component of that thing is currently working.
+  * `activityIndicator` – Shows a spinner using the `activityIndicatorTheme`
+    from your active theme.
+  * `progressbar` – A progress bar representing your current `completed`
+    using the `progressbarTheme` from your active theme.
+* *kerning* – Number of spaces that must be between this item and other
+  items, if this item is displayed at all.
+* *maxLength* – The maximum length for this element. If its value is longer it
+  will be truncated.
+* *minLength* – The minimum length for this element. If its value is shorter it
+  will be padded according to the *align* value.
+* *align* – (Default: left) Possible values "left", "right" and "center". Works
+  as you'd expect from word processors.
+* *length* – Provides a single value for both *minLength* and *maxLength*. If both
+  *length* and *minLength or *maxLength* are specifed then the latter take precedence.
+* *value* – A literal value to use for this template item.
+* *default* – A default value to use for this template item if a value
+  wasn't otherwise passed in.
+
+### PLUMBING
+
+This is the super simple, assume nothing, do no magic internals used by gauge to
+implement its ordinary interface.
+
+```
+var Plumbing = require('gauge/plumbing')
+var gauge = new Plumbing(theme, template, width)
+```
+
+* **theme**: The theme to use.
+* **template**: The template to use.
+* **width**: How wide your gauge should be
+
+#### `gauge.setTheme(theme)`
+
+Change the active theme.
+
+#### `gauge.setTemplate(template)`
+
+Change the active template.
+
+#### `gauge.setWidth(width)`
+
+Change the width to render at.
+
+#### `gauge.hide()`
+
+Return the string necessary to hide the progress bar
+
+#### `gauge.hideCursor()`
+
+Return a string to hide the cursor.
+
+#### `gauge.showCursor()`
+
+Return a string to show the cursor.
+
+#### `gauge.show(status)`
+
+Using `status` for values, render the provided template with the theme and return
+a string that is suitable for printing to update the gauge.
diff --git a/input_devices/mag/node_modules/gauge/base-theme.js b/input_devices/mag/node_modules/gauge/base-theme.js
new file mode 100644
index 00000000..0b67638e
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/base-theme.js
@@ -0,0 +1,14 @@
+'use strict'
+var spin = require('./spin.js')
+var progressBar = require('./progress-bar.js')
+
+module.exports = {
+  activityIndicator: function (values, theme, width) {
+    if (values.spun == null) return
+    return spin(theme, values.spun)
+  },
+  progressbar: function (values, theme, width) {
+    if (values.completed == null) return
+    return progressBar(theme, width, values.completed)
+  }
+}
diff --git a/input_devices/mag/node_modules/gauge/error.js b/input_devices/mag/node_modules/gauge/error.js
new file mode 100644
index 00000000..d9914ba5
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/error.js
@@ -0,0 +1,24 @@
+'use strict'
+var util = require('util')
+
+var User = exports.User = function User (msg) {
+  var err = new Error(msg)
+  Error.captureStackTrace(err, User)
+  err.code = 'EGAUGE'
+  return err
+}
+
+exports.MissingTemplateValue = function MissingTemplateValue (item, values) {
+  var err = new User(util.format('Missing template value "%s"', item.type))
+  Error.captureStackTrace(err, MissingTemplateValue)
+  err.template = item
+  err.values = values
+  return err
+}
+
+exports.Internal = function Internal (msg) {
+  var err = new Error(msg)
+  Error.captureStackTrace(err, Internal)
+  err.code = 'EGAUGEINTERNAL'
+  return err
+}
diff --git a/input_devices/mag/node_modules/gauge/has-color.js b/input_devices/mag/node_modules/gauge/has-color.js
new file mode 100644
index 00000000..e283a256
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/has-color.js
@@ -0,0 +1,12 @@
+'use strict'
+
+module.exports = isWin32() || isColorTerm()
+
+function isWin32 () {
+  return process.platform === 'win32'
+}
+
+function isColorTerm () {
+  var termHasColor = /^screen|^xterm|^vt100|color|ansi|cygwin|linux/i
+  return !!process.env.COLORTERM || termHasColor.test(process.env.TERM)
+}
diff --git a/input_devices/mag/node_modules/gauge/index.js b/input_devices/mag/node_modules/gauge/index.js
new file mode 100644
index 00000000..c5532400
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/index.js
@@ -0,0 +1,233 @@
+'use strict'
+var Plumbing = require('./plumbing.js')
+var hasUnicode = require('has-unicode')
+var hasColor = require('./has-color.js')
+var onExit = require('signal-exit')
+var defaultThemes = require('./themes')
+var setInterval = require('./set-interval.js')
+var process = require('./process.js')
+var setImmediate = require('./set-immediate')
+
+module.exports = Gauge
+
+function callWith (obj, method) {
+  return function () {
+    return method.call(obj)
+  }
+}
+
+function Gauge (arg1, arg2) {
+  var options, writeTo
+  if (arg1 && arg1.write) {
+    writeTo = arg1
+    options = arg2 || {}
+  } else if (arg2 && arg2.write) {
+    writeTo = arg2
+    options = arg1 || {}
+  } else {
+    writeTo = process.stderr
+    options = arg1 || arg2 || {}
+  }
+
+  this._status = {
+    spun: 0,
+    section: '',
+    subsection: ''
+  }
+  this._paused = false // are we paused for back pressure?
+  this._disabled = true // are all progress bar updates disabled?
+  this._showing = false // do we WANT the progress bar on screen
+  this._onScreen = false // IS the progress bar on screen
+  this._needsRedraw = false // should we print something at next tick?
+  this._hideCursor = options.hideCursor == null ? true : options.hideCursor
+  this._fixedFramerate = options.fixedFramerate == null
+    ? !(/^v0\.8\./.test(process.version))
+    : options.fixedFramerate
+  this._lastUpdateAt = null
+  this._updateInterval = options.updateInterval == null ? 50 : options.updateInterval
+
+  this._themes = options.themes || defaultThemes
+  this._theme = options.theme
+  var theme = this._computeTheme(options.theme)
+  var template = options.template || [
+    {type: 'progressbar', length: 20},
+    {type: 'activityIndicator', kerning: 1, length: 1},
+    {type: 'section', kerning: 1, default: ''},
+    {type: 'subsection', kerning: 1, default: ''}
+  ]
+  this.setWriteTo(writeTo, options.tty)
+  var PlumbingClass = options.Plumbing || Plumbing
+  this._gauge = new PlumbingClass(theme, template, this.getWidth())
+
+  this._$$doRedraw = callWith(this, this._doRedraw)
+  this._$$handleSizeChange = callWith(this, this._handleSizeChange)
+
+  this._cleanupOnExit = options.cleanupOnExit == null || options.cleanupOnExit
+  this._removeOnExit = null
+
+  if (options.enabled || (options.enabled == null && this._tty && this._tty.isTTY)) {
+    this.enable()
+  } else {
+    this.disable()
+  }
+}
+Gauge.prototype = {}
+
+Gauge.prototype.isEnabled = function () {
+  return !this._disabled
+}
+
+Gauge.prototype.setTemplate = function (template) {
+  this._gauge.setTemplate(template)
+  if (this._showing) this._requestRedraw()
+}
+
+Gauge.prototype._computeTheme = function (theme) {
+  if (!theme) theme = {}
+  if (typeof theme === 'string') {
+    theme = this._themes.getTheme(theme)
+  } else if (theme && (Object.keys(theme).length === 0 || theme.hasUnicode != null || theme.hasColor != null)) {
+    var useUnicode = theme.hasUnicode == null ? hasUnicode() : theme.hasUnicode
+    var useColor = theme.hasColor == null ? hasColor : theme.hasColor
+    theme = this._themes.getDefault({hasUnicode: useUnicode, hasColor: useColor, platform: theme.platform})
+  }
+  return theme
+}
+
+Gauge.prototype.setThemeset = function (themes) {
+  this._themes = themes
+  this.setTheme(this._theme)
+}
+
+Gauge.prototype.setTheme = function (theme) {
+  this._gauge.setTheme(this._computeTheme(theme))
+  if (this._showing) this._requestRedraw()
+  this._theme = theme
+}
+
+Gauge.prototype._requestRedraw = function () {
+  this._needsRedraw = true
+  if (!this._fixedFramerate) this._doRedraw()
+}
+
+Gauge.prototype.getWidth = function () {
+  return ((this._tty && this._tty.columns) || 80) - 1
+}
+
+Gauge.prototype.setWriteTo = function (writeTo, tty) {
+  var enabled = !this._disabled
+  if (enabled) this.disable()
+  this._writeTo = writeTo
+  this._tty = tty ||
+    (writeTo === process.stderr && process.stdout.isTTY && process.stdout) ||
+    (writeTo.isTTY && writeTo) ||
+    this._tty
+  if (this._gauge) this._gauge.setWidth(this.getWidth())
+  if (enabled) this.enable()
+}
+
+Gauge.prototype.enable = function () {
+  if (!this._disabled) return
+  this._disabled = false
+  if (this._tty) this._enableEvents()
+  if (this._showing) this.show()
+}
+
+Gauge.prototype.disable = function () {
+  if (this._disabled) return
+  if (this._showing) {
+    this._lastUpdateAt = null
+    this._showing = false
+    this._doRedraw()
+    this._showing = true
+  }
+  this._disabled = true
+  if (this._tty) this._disableEvents()
+}
+
+Gauge.prototype._enableEvents = function () {
+  if (this._cleanupOnExit) {
+    this._removeOnExit = onExit(callWith(this, this.disable))
+  }
+  this._tty.on('resize', this._$$handleSizeChange)
+  if (this._fixedFramerate) {
+    this.redrawTracker = setInterval(this._$$doRedraw, this._updateInterval)
+    if (this.redrawTracker.unref) this.redrawTracker.unref()
+  }
+}
+
+Gauge.prototype._disableEvents = function () {
+  this._tty.removeListener('resize', this._$$handleSizeChange)
+  if (this._fixedFramerate) clearInterval(this.redrawTracker)
+  if (this._removeOnExit) this._removeOnExit()
+}
+
+Gauge.prototype.hide = function (cb) {
+  if (this._disabled) return cb && process.nextTick(cb)
+  if (!this._showing) return cb && process.nextTick(cb)
+  this._showing = false
+  this._doRedraw()
+  cb && setImmediate(cb)
+}
+
+Gauge.prototype.show = function (section, completed) {
+  this._showing = true
+  if (typeof section === 'string') {
+    this._status.section = section
+  } else if (typeof section === 'object') {
+    var sectionKeys = Object.keys(section)
+    for (var ii = 0; ii < sectionKeys.length; ++ii) {
+      var key = sectionKeys[ii]
+      this._status[key] = section[key]
+    }
+  }
+  if (completed != null) this._status.completed = completed
+  if (this._disabled) return
+  this._requestRedraw()
+}
+
+Gauge.prototype.pulse = function (subsection) {
+  this._status.subsection = subsection || ''
+  this._status.spun ++
+  if (this._disabled) return
+  if (!this._showing) return
+  this._requestRedraw()
+}
+
+Gauge.prototype._handleSizeChange = function () {
+  this._gauge.setWidth(this._tty.columns - 1)
+  this._requestRedraw()
+}
+
+Gauge.prototype._doRedraw = function () {
+  if (this._disabled || this._paused) return
+  if (!this._fixedFramerate) {
+    var now = Date.now()
+    if (this._lastUpdateAt && now - this._lastUpdateAt < this._updateInterval) return
+    this._lastUpdateAt = now
+  }
+  if (!this._showing && this._onScreen) {
+    this._onScreen = false
+    var result = this._gauge.hide()
+    if (this._hideCursor) {
+      result += this._gauge.showCursor()
+    }
+    return this._writeTo.write(result)
+  }
+  if (!this._showing && !this._onScreen) return
+  if (this._showing && !this._onScreen) {
+    this._onScreen = true
+    this._needsRedraw = true
+    if (this._hideCursor) {
+      this._writeTo.write(this._gauge.hideCursor())
+    }
+  }
+  if (!this._needsRedraw) return
+  if (!this._writeTo.write(this._gauge.show(this._status))) {
+    this._paused = true
+    this._writeTo.on('drain', callWith(this, function () {
+      this._paused = false
+      this._doRedraw()
+    }))
+  }
+}
diff --git a/input_devices/mag/node_modules/gauge/package.json b/input_devices/mag/node_modules/gauge/package.json
new file mode 100644
index 00000000..d570b690
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/package.json
@@ -0,0 +1,118 @@
+{
+  "_args": [
+    [
+      "gauge@~2.7.3",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog"
+    ]
+  ],
+  "_from": "gauge@>=2.7.3 <2.8.0",
+  "_id": "gauge@2.7.4",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/gauge",
+  "_nodeVersion": "7.7.4",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/gauge-2.7.4.tgz_1492815975490_0.4050216095056385"
+  },
+  "_npmUser": {
+    "email": "me@re-becca.org",
+    "name": "iarna"
+  },
+  "_npmVersion": "4.5.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "gauge",
+    "raw": "gauge@~2.7.3",
+    "rawSpec": "~2.7.3",
+    "scope": null,
+    "spec": ">=2.7.3 <2.8.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/npmlog"
+  ],
+  "_resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+  "_shasum": "2c03405c7538c39d7eb37b317022e325fb018bf7",
+  "_shrinkwrap": null,
+  "_spec": "gauge@~2.7.3",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog",
+  "author": {
+    "email": "me@re-becca.org",
+    "name": "Rebecca Turner"
+  },
+  "bugs": {
+    "url": "https://github.com/iarna/gauge/issues"
+  },
+  "dependencies": {
+    "aproba": "^1.0.3",
+    "console-control-strings": "^1.0.0",
+    "has-unicode": "^2.0.0",
+    "object-assign": "^4.1.0",
+    "signal-exit": "^3.0.0",
+    "string-width": "^1.0.1",
+    "strip-ansi": "^3.0.1",
+    "wide-align": "^1.1.0"
+  },
+  "description": "A terminal based horizontal guage",
+  "devDependencies": {
+    "readable-stream": "^2.0.6",
+    "require-inject": "^1.4.0",
+    "standard": "^7.1.2",
+    "tap": "^5.7.2",
+    "through2": "^2.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "2c03405c7538c39d7eb37b317022e325fb018bf7",
+    "tarball": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz"
+  },
+  "files": [
+    "CHANGELOG.md",
+    "LICENSE",
+    "README.md",
+    "base-theme.js",
+    "error.js",
+    "has-color.js",
+    "index.js",
+    "package.json",
+    "plumbing.js",
+    "process.js",
+    "progress-bar.js",
+    "render-template.js",
+    "set-immediate.js",
+    "set-interval.js",
+    "spin.js",
+    "template-item.js",
+    "theme-set.js",
+    "themes.js",
+    "wide-truncate.js"
+  ],
+  "gitHead": "1011abf6c2cb7ae89a3ee76fb447d3182d4e8d3a",
+  "homepage": "https://github.com/iarna/gauge",
+  "keywords": [
+    "gauge",
+    "progress",
+    "progressbar"
+  ],
+  "license": "ISC",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    }
+  ],
+  "name": "gauge",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/iarna/gauge.git"
+  },
+  "scripts": {
+    "prepublish": "rm -f *~",
+    "test": "standard && tap test/*.js --coverage"
+  },
+  "version": "2.7.4"
+}
diff --git a/input_devices/mag/node_modules/gauge/plumbing.js b/input_devices/mag/node_modules/gauge/plumbing.js
new file mode 100644
index 00000000..1afb4af6
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/plumbing.js
@@ -0,0 +1,48 @@
+'use strict'
+var consoleControl = require('console-control-strings')
+var renderTemplate = require('./render-template.js')
+var validate = require('aproba')
+
+var Plumbing = module.exports = function (theme, template, width) {
+  if (!width) width = 80
+  validate('OAN', [theme, template, width])
+  this.showing = false
+  this.theme = theme
+  this.width = width
+  this.template = template
+}
+Plumbing.prototype = {}
+
+Plumbing.prototype.setTheme = function (theme) {
+  validate('O', [theme])
+  this.theme = theme
+}
+
+Plumbing.prototype.setTemplate = function (template) {
+  validate('A', [template])
+  this.template = template
+}
+
+Plumbing.prototype.setWidth = function (width) {
+  validate('N', [width])
+  this.width = width
+}
+
+Plumbing.prototype.hide = function () {
+  return consoleControl.gotoSOL() + consoleControl.eraseLine()
+}
+
+Plumbing.prototype.hideCursor = consoleControl.hideCursor
+
+Plumbing.prototype.showCursor = consoleControl.showCursor
+
+Plumbing.prototype.show = function (status) {
+  var values = Object.create(this.theme)
+  for (var key in status) {
+    values[key] = status[key]
+  }
+
+  return renderTemplate(this.width, this.template, values).trim() +
+         consoleControl.color('reset') +
+         consoleControl.eraseLine() + consoleControl.gotoSOL()
+}
diff --git a/input_devices/mag/node_modules/gauge/process.js b/input_devices/mag/node_modules/gauge/process.js
new file mode 100644
index 00000000..05e85694
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/process.js
@@ -0,0 +1,3 @@
+'use strict'
+// this exists so we can replace it during testing
+module.exports = process
diff --git a/input_devices/mag/node_modules/gauge/progress-bar.js b/input_devices/mag/node_modules/gauge/progress-bar.js
new file mode 100644
index 00000000..7f8dd68b
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/progress-bar.js
@@ -0,0 +1,35 @@
+'use strict'
+var validate = require('aproba')
+var renderTemplate = require('./render-template.js')
+var wideTruncate = require('./wide-truncate')
+var stringWidth = require('string-width')
+
+module.exports = function (theme, width, completed) {
+  validate('ONN', [theme, width, completed])
+  if (completed < 0) completed = 0
+  if (completed > 1) completed = 1
+  if (width <= 0) return ''
+  var sofar = Math.round(width * completed)
+  var rest = width - sofar
+  var template = [
+    {type: 'complete', value: repeat(theme.complete, sofar), length: sofar},
+    {type: 'remaining', value: repeat(theme.remaining, rest), length: rest}
+  ]
+  return renderTemplate(width, template, theme)
+}
+
+// lodash's way of repeating
+function repeat (string, width) {
+  var result = ''
+  var n = width
+  do {
+    if (n % 2) {
+      result += string
+    }
+    n = Math.floor(n / 2)
+    /*eslint no-self-assign: 0*/
+    string += string
+  } while (n && stringWidth(result) < width)
+
+  return wideTruncate(result, width)
+}
diff --git a/input_devices/mag/node_modules/gauge/render-template.js b/input_devices/mag/node_modules/gauge/render-template.js
new file mode 100644
index 00000000..3261bfbe
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/render-template.js
@@ -0,0 +1,181 @@
+'use strict'
+var align = require('wide-align')
+var validate = require('aproba')
+var objectAssign = require('object-assign')
+var wideTruncate = require('./wide-truncate')
+var error = require('./error')
+var TemplateItem = require('./template-item')
+
+function renderValueWithValues (values) {
+  return function (item) {
+    return renderValue(item, values)
+  }
+}
+
+var renderTemplate = module.exports = function (width, template, values) {
+  var items = prepareItems(width, template, values)
+  var rendered = items.map(renderValueWithValues(values)).join('')
+  return align.left(wideTruncate(rendered, width), width)
+}
+
+function preType (item) {
+  var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1)
+  return 'pre' + cappedTypeName
+}
+
+function postType (item) {
+  var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1)
+  return 'post' + cappedTypeName
+}
+
+function hasPreOrPost (item, values) {
+  if (!item.type) return
+  return values[preType(item)] || values[postType(item)]
+}
+
+function generatePreAndPost (baseItem, parentValues) {
+  var item = objectAssign({}, baseItem)
+  var values = Object.create(parentValues)
+  var template = []
+  var pre = preType(item)
+  var post = postType(item)
+  if (values[pre]) {
+    template.push({value: values[pre]})
+    values[pre] = null
+  }
+  item.minLength = null
+  item.length = null
+  item.maxLength = null
+  template.push(item)
+  values[item.type] = values[item.type]
+  if (values[post]) {
+    template.push({value: values[post]})
+    values[post] = null
+  }
+  return function ($1, $2, length) {
+    return renderTemplate(length, template, values)
+  }
+}
+
+function prepareItems (width, template, values) {
+  function cloneAndObjectify (item, index, arr) {
+    var cloned = new TemplateItem(item, width)
+    var type = cloned.type
+    if (cloned.value == null) {
+      if (!(type in values)) {
+        if (cloned.default == null) {
+          throw new error.MissingTemplateValue(cloned, values)
+        } else {
+          cloned.value = cloned.default
+        }
+      } else {
+        cloned.value = values[type]
+      }
+    }
+    if (cloned.value == null || cloned.value === '') return null
+    cloned.index = index
+    cloned.first = index === 0
+    cloned.last = index === arr.length - 1
+    if (hasPreOrPost(cloned, values)) cloned.value = generatePreAndPost(cloned, values)
+    return cloned
+  }
+
+  var output = template.map(cloneAndObjectify).filter(function (item) { return item != null })
+
+  var outputLength = 0
+  var remainingSpace = width
+  var variableCount = output.length
+
+  function consumeSpace (length) {
+    if (length > remainingSpace) length = remainingSpace
+    outputLength += length
+    remainingSpace -= length
+  }
+
+  function finishSizing (item, length) {
+    if (item.finished) throw new error.Internal('Tried to finish template item that was already finished')
+    if (length === Infinity) throw new error.Internal('Length of template item cannot be infinity')
+    if (length != null) item.length = length
+    item.minLength = null
+    item.maxLength = null
+    --variableCount
+    item.finished = true
+    if (item.length == null) item.length = item.getBaseLength()
+    if (item.length == null) throw new error.Internal('Finished template items must have a length')
+    consumeSpace(item.getLength())
+  }
+
+  output.forEach(function (item) {
+    if (!item.kerning) return
+    var prevPadRight = item.first ? 0 : output[item.index - 1].padRight
+    if (!item.first && prevPadRight < item.kerning) item.padLeft = item.kerning - prevPadRight
+    if (!item.last) item.padRight = item.kerning
+  })
+
+  // Finish any that have a fixed (literal or intuited) length
+  output.forEach(function (item) {
+    if (item.getBaseLength() == null) return
+    finishSizing(item)
+  })
+
+  var resized = 0
+  var resizing
+  var hunkSize
+  do {
+    resizing = false
+    hunkSize = Math.round(remainingSpace / variableCount)
+    output.forEach(function (item) {
+      if (item.finished) return
+      if (!item.maxLength) return
+      if (item.getMaxLength() < hunkSize) {
+        finishSizing(item, item.maxLength)
+        resizing = true
+      }
+    })
+  } while (resizing && resized++ < output.length)
+  if (resizing) throw new error.Internal('Resize loop iterated too many times while determining maxLength')
+
+  resized = 0
+  do {
+    resizing = false
+    hunkSize = Math.round(remainingSpace / variableCount)
+    output.forEach(function (item) {
+      if (item.finished) return
+      if (!item.minLength) return
+      if (item.getMinLength() >= hunkSize) {
+        finishSizing(item, item.minLength)
+        resizing = true
+      }
+    })
+  } while (resizing && resized++ < output.length)
+  if (resizing) throw new error.Internal('Resize loop iterated too many times while determining minLength')
+
+  hunkSize = Math.round(remainingSpace / variableCount)
+  output.forEach(function (item) {
+    if (item.finished) return
+    finishSizing(item, hunkSize)
+  })
+
+  return output
+}
+
+function renderFunction (item, values, length) {
+  validate('OON', arguments)
+  if (item.type) {
+    return item.value(values, values[item.type + 'Theme'] || {}, length)
+  } else {
+    return item.value(values, {}, length)
+  }
+}
+
+function renderValue (item, values) {
+  var length = item.getBaseLength()
+  var value = typeof item.value === 'function' ? renderFunction(item, values, length) : item.value
+  if (value == null || value === '') return ''
+  var alignWith = align[item.align] || align.left
+  var leftPadding = item.padLeft ? align.left('', item.padLeft) : ''
+  var rightPadding = item.padRight ? align.right('', item.padRight) : ''
+  var truncated = wideTruncate(String(value), length)
+  var aligned = alignWith(truncated, length)
+  return leftPadding + aligned + rightPadding
+}
diff --git a/input_devices/mag/node_modules/gauge/set-immediate.js b/input_devices/mag/node_modules/gauge/set-immediate.js
new file mode 100644
index 00000000..6650a485
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/set-immediate.js
@@ -0,0 +1,7 @@
+'use strict'
+var process = require('./process')
+try {
+  module.exports = setImmediate
+} catch (ex) {
+  module.exports = process.nextTick
+}
diff --git a/input_devices/mag/node_modules/gauge/set-interval.js b/input_devices/mag/node_modules/gauge/set-interval.js
new file mode 100644
index 00000000..57619879
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/set-interval.js
@@ -0,0 +1,3 @@
+'use strict'
+// this exists so we can replace it during testing
+module.exports = setInterval
diff --git a/input_devices/mag/node_modules/gauge/spin.js b/input_devices/mag/node_modules/gauge/spin.js
new file mode 100644
index 00000000..34142ee3
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/spin.js
@@ -0,0 +1,5 @@
+'use strict'
+
+module.exports = function spin (spinstr, spun) {
+  return spinstr[spun % spinstr.length]
+}
diff --git a/input_devices/mag/node_modules/gauge/template-item.js b/input_devices/mag/node_modules/gauge/template-item.js
new file mode 100644
index 00000000..e46f447c
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/template-item.js
@@ -0,0 +1,73 @@
+'use strict'
+var stringWidth = require('string-width')
+
+module.exports = TemplateItem
+
+function isPercent (num) {
+  if (typeof num !== 'string') return false
+  return num.slice(-1) === '%'
+}
+
+function percent (num) {
+  return Number(num.slice(0, -1)) / 100
+}
+
+function TemplateItem (values, outputLength) {
+  this.overallOutputLength = outputLength
+  this.finished = false
+  this.type = null
+  this.value = null
+  this.length = null
+  this.maxLength = null
+  this.minLength = null
+  this.kerning = null
+  this.align = 'left'
+  this.padLeft = 0
+  this.padRight = 0
+  this.index = null
+  this.first = null
+  this.last = null
+  if (typeof values === 'string') {
+    this.value = values
+  } else {
+    for (var prop in values) this[prop] = values[prop]
+  }
+  // Realize percents
+  if (isPercent(this.length)) {
+    this.length = Math.round(this.overallOutputLength * percent(this.length))
+  }
+  if (isPercent(this.minLength)) {
+    this.minLength = Math.round(this.overallOutputLength * percent(this.minLength))
+  }
+  if (isPercent(this.maxLength)) {
+    this.maxLength = Math.round(this.overallOutputLength * percent(this.maxLength))
+  }
+  return this
+}
+
+TemplateItem.prototype = {}
+
+TemplateItem.prototype.getBaseLength = function () {
+  var length = this.length
+  if (length == null && typeof this.value === 'string' && this.maxLength == null && this.minLength == null) {
+    length = stringWidth(this.value)
+  }
+  return length
+}
+
+TemplateItem.prototype.getLength = function () {
+  var length = this.getBaseLength()
+  if (length == null) return null
+  return length + this.padLeft + this.padRight
+}
+
+TemplateItem.prototype.getMaxLength = function () {
+  if (this.maxLength == null) return null
+  return this.maxLength + this.padLeft + this.padRight
+}
+
+TemplateItem.prototype.getMinLength = function () {
+  if (this.minLength == null) return null
+  return this.minLength + this.padLeft + this.padRight
+}
+
diff --git a/input_devices/mag/node_modules/gauge/theme-set.js b/input_devices/mag/node_modules/gauge/theme-set.js
new file mode 100644
index 00000000..68971d5d
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/theme-set.js
@@ -0,0 +1,115 @@
+'use strict'
+var objectAssign = require('object-assign')
+
+module.exports = function () {
+  return ThemeSetProto.newThemeSet()
+}
+
+var ThemeSetProto = {}
+
+ThemeSetProto.baseTheme = require('./base-theme.js')
+
+ThemeSetProto.newTheme = function (parent, theme) {
+  if (!theme) {
+    theme = parent
+    parent = this.baseTheme
+  }
+  return objectAssign({}, parent, theme)
+}
+
+ThemeSetProto.getThemeNames = function () {
+  return Object.keys(this.themes)
+}
+
+ThemeSetProto.addTheme = function (name, parent, theme) {
+  this.themes[name] = this.newTheme(parent, theme)
+}
+
+ThemeSetProto.addToAllThemes = function (theme) {
+  var themes = this.themes
+  Object.keys(themes).forEach(function (name) {
+    objectAssign(themes[name], theme)
+  })
+  objectAssign(this.baseTheme, theme)
+}
+
+ThemeSetProto.getTheme = function (name) {
+  if (!this.themes[name]) throw this.newMissingThemeError(name)
+  return this.themes[name]
+}
+
+ThemeSetProto.setDefault = function (opts, name) {
+  if (name == null) {
+    name = opts
+    opts = {}
+  }
+  var platform = opts.platform == null ? 'fallback' : opts.platform
+  var hasUnicode = !!opts.hasUnicode
+  var hasColor = !!opts.hasColor
+  if (!this.defaults[platform]) this.defaults[platform] = {true: {}, false: {}}
+  this.defaults[platform][hasUnicode][hasColor] = name
+}
+
+ThemeSetProto.getDefault = function (opts) {
+  if (!opts) opts = {}
+  var platformName = opts.platform || process.platform
+  var platform = this.defaults[platformName] || this.defaults.fallback
+  var hasUnicode = !!opts.hasUnicode
+  var hasColor = !!opts.hasColor
+  if (!platform) throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor)
+  if (!platform[hasUnicode][hasColor]) {
+    if (hasUnicode && hasColor && platform[!hasUnicode][hasColor]) {
+      hasUnicode = false
+    } else if (hasUnicode && hasColor && platform[hasUnicode][!hasColor]) {
+      hasColor = false
+    } else if (hasUnicode && hasColor && platform[!hasUnicode][!hasColor]) {
+      hasUnicode = false
+      hasColor = false
+    } else if (hasUnicode && !hasColor && platform[!hasUnicode][hasColor]) {
+      hasUnicode = false
+    } else if (!hasUnicode && hasColor && platform[hasUnicode][!hasColor]) {
+      hasColor = false
+    } else if (platform === this.defaults.fallback) {
+      throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor)
+    }
+  }
+  if (platform[hasUnicode][hasColor]) {
+    return this.getTheme(platform[hasUnicode][hasColor])
+  } else {
+    return this.getDefault(objectAssign({}, opts, {platform: 'fallback'}))
+  }
+}
+
+ThemeSetProto.newMissingThemeError = function newMissingThemeError (name) {
+  var err = new Error('Could not find a gauge theme named "' + name + '"')
+  Error.captureStackTrace.call(err, newMissingThemeError)
+  err.theme = name
+  err.code = 'EMISSINGTHEME'
+  return err
+}
+
+ThemeSetProto.newMissingDefaultThemeError = function newMissingDefaultThemeError (platformName, hasUnicode, hasColor) {
+  var err = new Error(
+    'Could not find a gauge theme for your platform/unicode/color use combo:\n' +
+    '    platform = ' + platformName + '\n' +
+    '    hasUnicode = ' + hasUnicode + '\n' +
+    '    hasColor = ' + hasColor)
+  Error.captureStackTrace.call(err, newMissingDefaultThemeError)
+  err.platform = platformName
+  err.hasUnicode = hasUnicode
+  err.hasColor = hasColor
+  err.code = 'EMISSINGTHEME'
+  return err
+}
+
+ThemeSetProto.newThemeSet = function () {
+  var themeset = function (opts) {
+    return themeset.getDefault(opts)
+  }
+  return objectAssign(themeset, ThemeSetProto, {
+    themes: objectAssign({}, this.themes),
+    baseTheme: objectAssign({}, this.baseTheme),
+    defaults: JSON.parse(JSON.stringify(this.defaults || {}))
+  })
+}
+
diff --git a/input_devices/mag/node_modules/gauge/themes.js b/input_devices/mag/node_modules/gauge/themes.js
new file mode 100644
index 00000000..eb5a4f5b
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/themes.js
@@ -0,0 +1,54 @@
+'use strict'
+var consoleControl = require('console-control-strings')
+var ThemeSet = require('./theme-set.js')
+
+var themes = module.exports = new ThemeSet()
+
+themes.addTheme('ASCII', {
+  preProgressbar: '[',
+  postProgressbar: ']',
+  progressbarTheme: {
+    complete: '#',
+    remaining: '.'
+  },
+  activityIndicatorTheme: '-\\|/',
+  preSubsection: '>'
+})
+
+themes.addTheme('colorASCII', themes.getTheme('ASCII'), {
+  progressbarTheme: {
+    preComplete: consoleControl.color('inverse'),
+    complete: ' ',
+    postComplete: consoleControl.color('stopInverse'),
+    preRemaining: consoleControl.color('brightBlack'),
+    remaining: '.',
+    postRemaining: consoleControl.color('reset')
+  }
+})
+
+themes.addTheme('brailleSpinner', {
+  preProgressbar: '⸨',
+  postProgressbar: '⸩',
+  progressbarTheme: {
+    complete: '░',
+    remaining: '⠂'
+  },
+  activityIndicatorTheme: '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏',
+  preSubsection: '>'
+})
+
+themes.addTheme('colorBrailleSpinner', themes.getTheme('brailleSpinner'), {
+  progressbarTheme: {
+    preComplete: consoleControl.color('inverse'),
+    complete: ' ',
+    postComplete: consoleControl.color('stopInverse'),
+    preRemaining: consoleControl.color('brightBlack'),
+    remaining: '░',
+    postRemaining: consoleControl.color('reset')
+  }
+})
+
+themes.setDefault({}, 'ASCII')
+themes.setDefault({hasColor: true}, 'colorASCII')
+themes.setDefault({platform: 'darwin', hasUnicode: true}, 'brailleSpinner')
+themes.setDefault({platform: 'darwin', hasUnicode: true, hasColor: true}, 'colorBrailleSpinner')
diff --git a/input_devices/mag/node_modules/gauge/wide-truncate.js b/input_devices/mag/node_modules/gauge/wide-truncate.js
new file mode 100644
index 00000000..c531bc49
--- /dev/null
+++ b/input_devices/mag/node_modules/gauge/wide-truncate.js
@@ -0,0 +1,25 @@
+'use strict'
+var stringWidth = require('string-width')
+var stripAnsi = require('strip-ansi')
+
+module.exports = wideTruncate
+
+function wideTruncate (str, target) {
+  if (stringWidth(str) === 0) return str
+  if (target <= 0) return ''
+  if (stringWidth(str) <= target) return str
+
+  // We compute the number of bytes of ansi sequences here and add
+  // that to our initial truncation to ensure that we don't slice one
+  // that we want to keep in half.
+  var noAnsi = stripAnsi(str)
+  var ansiSize = str.length + noAnsi.length
+  var truncated = str.slice(0, target + ansiSize)
+
+  // we have to shrink the result to account for our ansi sequence buffer
+  // (if an ansi sequence was truncated) and double width characters.
+  while (stringWidth(truncated) > target) {
+    truncated = truncated.slice(0, -1)
+  }
+  return truncated
+}
diff --git a/input_devices/mag/node_modules/github-from-package/.travis.yml b/input_devices/mag/node_modules/github-from-package/.travis.yml
new file mode 100644
index 00000000..895dbd36
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.8
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/LICENSE b/input_devices/mag/node_modules/github-from-package/LICENSE
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/LICENSE
rename to input_devices/mag/node_modules/github-from-package/LICENSE
diff --git a/input_devices/mag/node_modules/github-from-package/example/package.json b/input_devices/mag/node_modules/github-from-package/example/package.json
new file mode 100644
index 00000000..03494f48
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/example/package.json
@@ -0,0 +1,8 @@
+{
+  "name": "beep-boop",
+  "version": "1.2.3",
+  "repository" : {
+    "type" : "git",
+    "url": "git@github.com:substack/beep-boop.git"
+  }
+}
diff --git a/input_devices/mag/node_modules/github-from-package/example/url.js b/input_devices/mag/node_modules/github-from-package/example/url.js
new file mode 100644
index 00000000..138fb8a6
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/example/url.js
@@ -0,0 +1,3 @@
+var github = require('../');
+var url = github(require('./package.json'));
+console.log(url);
diff --git a/input_devices/mag/node_modules/github-from-package/index.js b/input_devices/mag/node_modules/github-from-package/index.js
new file mode 100644
index 00000000..3d1d657b
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/index.js
@@ -0,0 +1,17 @@
+module.exports = function (pkg) {
+    var m;
+    if (m = match(JSON.stringify(pkg.repository))) {
+        return m;
+    }
+    else if (m = match(JSON.stringify(pkg))) {
+        return m;
+    }
+    return undefined;
+};
+
+function match (str) {
+    var m = /\bgithub.com[:\/]([^\/"]+)\/([^\/"]+)/.exec(str);
+    if (m) {
+        return 'https://github.com/' + m[1] + '/' + m[2].replace(/\.git$/, '');
+    }
+}
diff --git a/input_devices/mag/node_modules/github-from-package/package.json b/input_devices/mag/node_modules/github-from-package/package.json
new file mode 100644
index 00000000..ca922812
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/package.json
@@ -0,0 +1,80 @@
+{
+  "_args": [
+    [
+      "github-from-package@0.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "github-from-package@0.0.0",
+  "_id": "github-from-package@0.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/github-from-package",
+  "_npmUser": {
+    "email": "mail@substack.net",
+    "name": "substack"
+  },
+  "_npmVersion": "1.1.59",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "github-from-package",
+    "raw": "github-from-package@0.0.0",
+    "rawSpec": "0.0.0",
+    "scope": null,
+    "spec": "0.0.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+  "_shasum": "97fb5d96bfde8973313f20e8288ef9a167fa64ce",
+  "_shrinkwrap": null,
+  "_spec": "github-from-package@0.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "mail@substack.net",
+    "name": "James Halliday",
+    "url": "http://substack.net"
+  },
+  "bugs": {
+    "url": "https://github.com/substack/github-from-package/issues"
+  },
+  "dependencies": {},
+  "description": "return the github url from a package.json file",
+  "devDependencies": {
+    "tap": "~0.3.0",
+    "tape": "~0.1.5"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "97fb5d96bfde8973313f20e8288ef9a167fa64ce",
+    "tarball": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz"
+  },
+  "homepage": "https://github.com/substack/github-from-package",
+  "keywords": [
+    "github",
+    "npm",
+    "package.json",
+    "repository"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "substack",
+      "email": "mail@substack.net"
+    }
+  ],
+  "name": "github-from-package",
+  "optionalDependencies": {},
+  "readme": "# github-from-package\n\nreturn the github url from a package.json file\n\n[![build status](https://secure.travis-ci.org/substack/github-from-package.png)](http://travis-ci.org/substack/github-from-package)\n\n# example\n\nFor the `./package.json` file:\n\n``` json\n{\n  \"name\": \"beep-boop\",\n  \"version\": \"1.2.3\",\n  \"repository\" : {\n    \"type\" : \"git\",\n    \"url\": \"git@github.com:substack/beep-boop.git\"\n  }\n}\n```\n\n``` js\nvar github = require('github-from-package');\nvar url = github(require('./package.json'));\nconsole.log(url);\n```\n\n```\nhttps://github.com/substack/beep-boop\n```\n\n# methods\n\n``` js\nvar github = require('github-from-package')\n```\n\n## var url = github(pkg)\n\nReturn the most likely github url from the package.json contents `pkg`. If no\ngithub url can be determined, return `undefined`.\n\n# install\n\nWith [npm](https://npmjs.org) do:\n\n```\nnpm install github-from-package\n```\n\n# license\n\nMIT\n",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/substack/github-from-package.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "version": "0.0.0"
+}
diff --git a/input_devices/mag/node_modules/github-from-package/readme.markdown b/input_devices/mag/node_modules/github-from-package/readme.markdown
new file mode 100644
index 00000000..5ba397da
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/readme.markdown
@@ -0,0 +1,53 @@
+# github-from-package
+
+return the github url from a package.json file
+
+[![build status](https://secure.travis-ci.org/substack/github-from-package.png)](http://travis-ci.org/substack/github-from-package)
+
+# example
+
+For the `./package.json` file:
+
+``` json
+{
+  "name": "beep-boop",
+  "version": "1.2.3",
+  "repository" : {
+    "type" : "git",
+    "url": "git@github.com:substack/beep-boop.git"
+  }
+}
+```
+
+``` js
+var github = require('github-from-package');
+var url = github(require('./package.json'));
+console.log(url);
+```
+
+```
+https://github.com/substack/beep-boop
+```
+
+# methods
+
+``` js
+var github = require('github-from-package')
+```
+
+## var url = github(pkg)
+
+Return the most likely github url from the package.json contents `pkg`. If no
+github url can be determined, return `undefined`.
+
+# install
+
+With [npm](https://npmjs.org) do:
+
+```
+npm install github-from-package
+```
+
+# license
+
+MIT
diff --git a/input_devices/mag/node_modules/github-from-package/test/a.json b/input_devices/mag/node_modules/github-from-package/test/a.json
new file mode 100644
index 00000000..03494f48
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/test/a.json
@@ -0,0 +1,8 @@
+{
+  "name": "beep-boop",
+  "version": "1.2.3",
+  "repository" : {
+    "type" : "git",
+    "url": "git@github.com:substack/beep-boop.git"
+  }
+}
diff --git a/input_devices/mag/node_modules/github-from-package/test/b.json b/input_devices/mag/node_modules/github-from-package/test/b.json
new file mode 100644
index 00000000..02093257
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/test/b.json
@@ -0,0 +1,5 @@
+{
+  "name": "beep-boop",
+  "version": "1.2.3",
+  "repository" : "git@github.com:substack/beep-boop.git"
+}
diff --git a/input_devices/mag/node_modules/github-from-package/test/c.json b/input_devices/mag/node_modules/github-from-package/test/c.json
new file mode 100644
index 00000000..65f6ddad
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/test/c.json
@@ -0,0 +1,5 @@
+{
+  "name": "beep-boop",
+  "version": "1.2.3",
+  "repository" : "https://github.com/substack/beep-boop.git"
+}
diff --git a/input_devices/mag/node_modules/github-from-package/test/d.json b/input_devices/mag/node_modules/github-from-package/test/d.json
new file mode 100644
index 00000000..c61f3cd3
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/test/d.json
@@ -0,0 +1,7 @@
+{
+  "name": "beep-boop",
+  "version": "1.2.3",
+  "repository" : {
+    "url": "https://github.com/substack/beep-boop"
+  }
+}
diff --git a/input_devices/mag/node_modules/github-from-package/test/e.json b/input_devices/mag/node_modules/github-from-package/test/e.json
new file mode 100644
index 00000000..770b4384
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/test/e.json
@@ -0,0 +1,5 @@
+{
+  "name": "beep-boop",
+  "version": "1.2.3",
+  "homepage": "https://github.com/substack/beep-boop/issues"
+}
diff --git a/input_devices/mag/node_modules/github-from-package/test/url.js b/input_devices/mag/node_modules/github-from-package/test/url.js
new file mode 100644
index 00000000..d5a0a667
--- /dev/null
+++ b/input_devices/mag/node_modules/github-from-package/test/url.js
@@ -0,0 +1,19 @@
+var test = require('tape');
+var github = require('../');
+var packages = {
+    a : require('./a.json'),
+    b : require('./b.json'),
+    c : require('./c.json'),
+    d : require('./d.json'),
+    e : require('./e.json')
+};
+
+test(function (t) {
+    t.plan(5);
+    var url = 'https://github.com/substack/beep-boop';
+    t.equal(url, github(packages.a), 'a.json comparison');
+    t.equal(url, github(packages.b), 'b.json comparison');
+    t.equal(url, github(packages.c), 'c.json comparison');
+    t.equal(url, github(packages.d), 'd.json comparison');
+    t.equal(url, github(packages.e), 'e.json comparison');
+});
diff --git a/input_devices/mag/node_modules/has-unicode/LICENSE b/input_devices/mag/node_modules/has-unicode/LICENSE
new file mode 100644
index 00000000..d42e25e9
--- /dev/null
+++ b/input_devices/mag/node_modules/has-unicode/LICENSE
@@ -0,0 +1,14 @@
+Copyright (c) 2014, Rebecca Turner <me@re-becca.org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/input_devices/mag/node_modules/has-unicode/README.md b/input_devices/mag/node_modules/has-unicode/README.md
new file mode 100644
index 00000000..5a03e599
--- /dev/null
+++ b/input_devices/mag/node_modules/has-unicode/README.md
@@ -0,0 +1,43 @@
+has-unicode
+===========
+
+Try to guess if your terminal supports unicode
+
+```javascript
+var hasUnicode = require("has-unicode")
+
+if (hasUnicode()) {
+  // the terminal probably has unicode support
+}
+```
+```javascript
+var hasUnicode = require("has-unicode").tryHarder
+hasUnicode(function(unicodeSupported) {
+  if (unicodeSupported) {
+    // the terminal probably has unicode support
+  }
+})
+```
+
+## Detecting Unicode
+
+What we actually detect is UTF-8 support, as that's what Node itself supports.
+If you have a UTF-16 locale then you won't be detected as unicode capable.
+
+### Windows
+
+Since at least Windows 7, `cmd` and `powershell` have been unicode capable,
+but unfortunately even then it's not guaranteed. In many localizations it
+still uses legacy code pages and there's no facility short of running
+programs or linking C++ that will let us detect this. As such, we
+report any Windows installation as NOT unicode capable, and recommend
+that you encourage your users to override this via config.
+
+### Unix Like Operating Systems
+
+We look at the environment variables `LC_ALL`, `LC_CTYPE`, and `LANG` in
+that order.  For `LC_ALL` and `LANG`, it looks for `.UTF-8` in the value. 
+For `LC_CTYPE` it looks to see if the value is `UTF-8`.  This is sufficient
+for most POSIX systems.  While locale data can be put in `/etc/locale.conf`
+as well, AFAIK it's always copied into the environment.
+
diff --git a/input_devices/mag/node_modules/has-unicode/index.js b/input_devices/mag/node_modules/has-unicode/index.js
new file mode 100644
index 00000000..9b0fe445
--- /dev/null
+++ b/input_devices/mag/node_modules/has-unicode/index.js
@@ -0,0 +1,16 @@
+"use strict"
+var os = require("os")
+
+var hasUnicode = module.exports = function () {
+  // Recent Win32 platforms (>XP) CAN support unicode in the console but
+  // don't have to, and in non-english locales often use traditional local
+  // code pages. There's no way, short of windows system calls or execing
+  // the chcp command line program to figure this out. As such, we default
+  // this to false and encourage your users to override it via config if
+  // appropriate.
+  if (os.type() == "Windows_NT") { return false }
+
+  var isUTF8 = /UTF-?8$/i
+  var ctype = process.env.LC_ALL || process.env.LC_CTYPE || process.env.LANG
+  return isUTF8.test(ctype)
+}
diff --git a/input_devices/mag/node_modules/has-unicode/package.json b/input_devices/mag/node_modules/has-unicode/package.json
new file mode 100644
index 00000000..dc0b1a26
--- /dev/null
+++ b/input_devices/mag/node_modules/has-unicode/package.json
@@ -0,0 +1,86 @@
+{
+  "_args": [
+    [
+      "has-unicode@^2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge"
+    ]
+  ],
+  "_from": "has-unicode@>=2.0.0 <3.0.0",
+  "_id": "has-unicode@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/has-unicode",
+  "_nodeVersion": "4.4.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/has-unicode-2.0.1.tgz_1466719828333_0.48896647873334587"
+  },
+  "_npmUser": {
+    "email": "me@re-becca.org",
+    "name": "iarna"
+  },
+  "_npmVersion": "3.10.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "has-unicode",
+    "raw": "has-unicode@^2.0.0",
+    "rawSpec": "^2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge"
+  ],
+  "_resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+  "_shasum": "e0e6fe6a28cf51138855e086d1691e771de2a8b9",
+  "_shrinkwrap": null,
+  "_spec": "has-unicode@^2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge",
+  "author": {
+    "email": "me@re-becca.org",
+    "name": "Rebecca Turner"
+  },
+  "bugs": {
+    "url": "https://github.com/iarna/has-unicode/issues"
+  },
+  "dependencies": {},
+  "description": "Try to guess if your terminal supports unicode",
+  "devDependencies": {
+    "require-inject": "^1.3.0",
+    "tap": "^2.3.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "e0e6fe6a28cf51138855e086d1691e771de2a8b9",
+    "tarball": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "0a05df154e8d89a7fb9798da60b68c78c2df6646",
+  "homepage": "https://github.com/iarna/has-unicode",
+  "keywords": [
+    "terminal",
+    "unicode"
+  ],
+  "license": "ISC",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    }
+  ],
+  "name": "has-unicode",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/iarna/has-unicode.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/info-symbol/LICENSE b/input_devices/mag/node_modules/info-symbol/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/info-symbol/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/info-symbol/README.md b/input_devices/mag/node_modules/info-symbol/README.md
new file mode 100644
index 00000000..df5327ec
--- /dev/null
+++ b/input_devices/mag/node_modules/info-symbol/README.md
@@ -0,0 +1,52 @@
+# info-symbol [![NPM version](https://badge.fury.io/js/info-symbol.svg)](http://badge.fury.io/js/info-symbol)
+
+> Cross-platform info symbol.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i info-symbol --save
+```
+
+## Usage
+
+```js
+var info = require('info-symbol');
+```
+
+## Related projects
+
+* [success-symbol](https://github.com/jonschlinkert/success-symbol)
+* [warning-symbol](https://github.com/jonschlinkert/warning-symbol)
+* [error-symbol](https://github.com/jonschlinkert/error-symbol)
+* [info-symbol](https://github.com/jonschlinkert/info-symbol)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/info-symbol/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 27, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/info-symbol/index.js b/input_devices/mag/node_modules/info-symbol/index.js
new file mode 100644
index 00000000..726b6b71
--- /dev/null
+++ b/input_devices/mag/node_modules/info-symbol/index.js
@@ -0,0 +1 @@
+module.exports = process.platform === 'win32' ? 'i' : 'ℹ';
diff --git a/input_devices/mag/node_modules/info-symbol/package.json b/input_devices/mag/node_modules/info-symbol/package.json
new file mode 100644
index 00000000..d88c9402
--- /dev/null
+++ b/input_devices/mag/node_modules/info-symbol/package.json
@@ -0,0 +1,106 @@
+{
+  "_args": [
+    [
+      "info-symbol@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils"
+    ]
+  ],
+  "_from": "info-symbol@>=0.1.0 <0.2.0",
+  "_id": "info-symbol@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/info-symbol",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "info-symbol",
+    "raw": "info-symbol@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/log-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/info-symbol/-/info-symbol-0.1.0.tgz",
+  "_shasum": "27841d72867ddb4242cd612d79c10633881c6a78",
+  "_shrinkwrap": null,
+  "_spec": "info-symbol@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/info-symbol/issues"
+  },
+  "dependencies": {},
+  "description": "Cross-platform info symbol.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "27841d72867ddb4242cd612d79c10633881c6a78",
+    "tarball": "https://registry.npmjs.org/info-symbol/-/info-symbol-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/info-symbol",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "info",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "symbol",
+    "symbols",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "info-symbol",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/info-symbol.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/LICENSE b/input_devices/mag/node_modules/inherits/LICENSE
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/LICENSE
rename to input_devices/mag/node_modules/inherits/LICENSE
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/README.md b/input_devices/mag/node_modules/inherits/README.md
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/README.md
rename to input_devices/mag/node_modules/inherits/README.md
diff --git a/input_devices/mag/node_modules/inherits/inherits.js b/input_devices/mag/node_modules/inherits/inherits.js
new file mode 100644
index 00000000..3b94763a
--- /dev/null
+++ b/input_devices/mag/node_modules/inherits/inherits.js
@@ -0,0 +1,7 @@
+try {
+  var util = require('util');
+  if (typeof util.inherits !== 'function') throw '';
+  module.exports = util.inherits;
+} catch (e) {
+  module.exports = require('./inherits_browser.js');
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/inherits_browser.js b/input_devices/mag/node_modules/inherits/inherits_browser.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/inherits_browser.js
rename to input_devices/mag/node_modules/inherits/inherits_browser.js
diff --git a/input_devices/mag/node_modules/inherits/package.json b/input_devices/mag/node_modules/inherits/package.json
new file mode 100644
index 00000000..1d2b251f
--- /dev/null
+++ b/input_devices/mag/node_modules/inherits/package.json
@@ -0,0 +1,89 @@
+{
+  "_args": [
+    [
+      "inherits@~2.0.3",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream"
+    ]
+  ],
+  "_from": "inherits@>=2.0.3 <2.1.0",
+  "_id": "inherits@2.0.3",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/inherits",
+  "_nodeVersion": "6.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/inherits-2.0.3.tgz_1473295776489_0.08142363070510328"
+  },
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "3.10.7",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "inherits",
+    "raw": "inherits@~2.0.3",
+    "rawSpec": "~2.0.3",
+    "scope": null,
+    "spec": ">=2.0.3 <2.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readable-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+  "_shasum": "633c2c83e3da42a502f52466022480f4208261de",
+  "_shrinkwrap": null,
+  "_spec": "inherits@~2.0.3",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream",
+  "browser": "./inherits_browser.js",
+  "bugs": {
+    "url": "https://github.com/isaacs/inherits/issues"
+  },
+  "dependencies": {},
+  "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
+  "devDependencies": {
+    "tap": "^7.1.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "633c2c83e3da42a502f52466022480f4208261de",
+    "tarball": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
+  },
+  "files": [
+    "inherits.js",
+    "inherits_browser.js"
+  ],
+  "gitHead": "e05d0fb27c61a3ec687214f0476386b765364d5f",
+  "homepage": "https://github.com/isaacs/inherits#readme",
+  "keywords": [
+    "browser",
+    "browserify",
+    "class",
+    "inheritance",
+    "inherits",
+    "klass",
+    "object-oriented",
+    "oop"
+  ],
+  "license": "ISC",
+  "main": "./inherits.js",
+  "maintainers": [
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    }
+  ],
+  "name": "inherits",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/inherits.git"
+  },
+  "scripts": {
+    "test": "node test"
+  },
+  "version": "2.0.3"
+}
diff --git a/input_devices/mag/node_modules/ini/LICENSE b/input_devices/mag/node_modules/ini/LICENSE
new file mode 100644
index 00000000..19129e31
--- /dev/null
+++ b/input_devices/mag/node_modules/ini/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/ini/README.md b/input_devices/mag/node_modules/ini/README.md
new file mode 100644
index 00000000..33df2582
--- /dev/null
+++ b/input_devices/mag/node_modules/ini/README.md
@@ -0,0 +1,102 @@
+An ini format parser and serializer for node.
+
+Sections are treated as nested objects.  Items before the first
+heading are saved on the object directly.
+
+## Usage
+
+Consider an ini-file `config.ini` that looks like this:
+
+    ; this comment is being ignored
+    scope = global
+
+    [database]
+    user = dbuser
+    password = dbpassword
+    database = use_this_database
+
+    [paths.default]
+    datadir = /var/lib/data
+    array[] = first value
+    array[] = second value
+    array[] = third value
+
+You can read, manipulate and write the ini-file like so:
+
+    var fs = require('fs')
+      , ini = require('ini')
+
+    var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'))
+
+    config.scope = 'local'
+    config.database.database = 'use_another_database'
+    config.paths.default.tmpdir = '/tmp'
+    delete config.paths.default.datadir
+    config.paths.default.array.push('fourth value')
+
+    fs.writeFileSync('./config_modified.ini', ini.stringify(config, { section: 'section' }))
+
+This will result in a file called `config_modified.ini` being written
+to the filesystem with the following content:
+
+    [section]
+    scope=local
+    [section.database]
+    user=dbuser
+    password=dbpassword
+    database=use_another_database
+    [section.paths.default]
+    tmpdir=/tmp
+    array[]=first value
+    array[]=second value
+    array[]=third value
+    array[]=fourth value
+
+
+## API
+
+### decode(inistring)
+
+Decode the ini-style formatted `inistring` into a nested object.
+
+### parse(inistring)
+
+Alias for `decode(inistring)`
+
+### encode(object, [options])
+
+Encode the object `object` into an ini-style formatted string. If the
+optional parameter `section` is given, then all top-level properties
+of the object are put into this section and the `section`-string is
+prepended to all sub-sections, see the usage example above.
+
+The `options` object may contain the following:
+
+* `section` A string which will be the first `section` in the encoded
+  ini data.  Defaults to none.
+* `whitespace` Boolean to specify whether to put whitespace around the
+  `=` character.  By default, whitespace is omitted, to be friendly to
+  some persnickety old parsers that don't tolerate it well.  But some
+  find that it's more human-readable and pretty with the whitespace.
+
+For backwards compatibility reasons, if a `string` options is passed
+in, then it is assumed to be the `section` value.
+
+### stringify(object, [options])
+
+Alias for `encode(object, [options])`
+
+### safe(val)
+
+Escapes the string `val` such that it is safe to be used as a key or
+value in an ini-file. Basically escapes quotes. For example
+
+    ini.safe('"unsafe string"')
+
+would result in
+
+    "\"unsafe string\""
+
+### unsafe(val)
+
+Unescapes the string `val`
diff --git a/input_devices/mag/node_modules/ini/ini.js b/input_devices/mag/node_modules/ini/ini.js
new file mode 100644
index 00000000..590195dd
--- /dev/null
+++ b/input_devices/mag/node_modules/ini/ini.js
@@ -0,0 +1,194 @@
+exports.parse = exports.decode = decode
+
+exports.stringify = exports.encode = encode
+
+exports.safe = safe
+exports.unsafe = unsafe
+
+var eol = typeof process !== 'undefined' &&
+  process.platform === 'win32' ? '\r\n' : '\n'
+
+function encode (obj, opt) {
+  var children = []
+  var out = ''
+
+  if (typeof opt === 'string') {
+    opt = {
+      section: opt,
+      whitespace: false
+    }
+  } else {
+    opt = opt || {}
+    opt.whitespace = opt.whitespace === true
+  }
+
+  var separator = opt.whitespace ? ' = ' : '='
+
+  Object.keys(obj).forEach(function (k, _, __) {
+    var val = obj[k]
+    if (val && Array.isArray(val)) {
+      val.forEach(function (item) {
+        out += safe(k + '[]') + separator + safe(item) + '\n'
+      })
+    } else if (val && typeof val === 'object') {
+      children.push(k)
+    } else {
+      out += safe(k) + separator + safe(val) + eol
+    }
+  })
+
+  if (opt.section && out.length) {
+    out = '[' + safe(opt.section) + ']' + eol + out
+  }
+
+  children.forEach(function (k, _, __) {
+    var nk = dotSplit(k).join('\\.')
+    var section = (opt.section ? opt.section + '.' : '') + nk
+    var child = encode(obj[k], {
+      section: section,
+      whitespace: opt.whitespace
+    })
+    if (out.length && child.length) {
+      out += eol
+    }
+    out += child
+  })
+
+  return out
+}
+
+function dotSplit (str) {
+  return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002')
+    .replace(/\\\./g, '\u0001')
+    .split(/\./).map(function (part) {
+      return part.replace(/\1/g, '\\.')
+      .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001')
+    })
+}
+
+function decode (str) {
+  var out = {}
+  var p = out
+  var section = null
+  //          section     |key      = value
+  var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i
+  var lines = str.split(/[\r\n]+/g)
+
+  lines.forEach(function (line, _, __) {
+    if (!line || line.match(/^\s*[;#]/)) return
+    var match = line.match(re)
+    if (!match) return
+    if (match[1] !== undefined) {
+      section = unsafe(match[1])
+      p = out[section] = out[section] || {}
+      return
+    }
+    var key = unsafe(match[2])
+    var value = match[3] ? unsafe(match[4]) : true
+    switch (value) {
+      case 'true':
+      case 'false':
+      case 'null': value = JSON.parse(value)
+    }
+
+    // Convert keys with '[]' suffix to an array
+    if (key.length > 2 && key.slice(-2) === '[]') {
+      key = key.substring(0, key.length - 2)
+      if (!p[key]) {
+        p[key] = []
+      } else if (!Array.isArray(p[key])) {
+        p[key] = [p[key]]
+      }
+    }
+
+    // safeguard against resetting a previously defined
+    // array by accidentally forgetting the brackets
+    if (Array.isArray(p[key])) {
+      p[key].push(value)
+    } else {
+      p[key] = value
+    }
+  })
+
+  // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
+  // use a filter to return the keys that have to be deleted.
+  Object.keys(out).filter(function (k, _, __) {
+    if (!out[k] ||
+      typeof out[k] !== 'object' ||
+      Array.isArray(out[k])) {
+      return false
+    }
+    // see if the parent section is also an object.
+    // if so, add it to that, and mark this one for deletion
+    var parts = dotSplit(k)
+    var p = out
+    var l = parts.pop()
+    var nl = l.replace(/\\\./g, '.')
+    parts.forEach(function (part, _, __) {
+      if (!p[part] || typeof p[part] !== 'object') p[part] = {}
+      p = p[part]
+    })
+    if (p === out && nl === l) {
+      return false
+    }
+    p[nl] = out[k]
+    return true
+  }).forEach(function (del, _, __) {
+    delete out[del]
+  })
+
+  return out
+}
+
+function isQuoted (val) {
+  return (val.charAt(0) === '"' && val.slice(-1) === '"') ||
+    (val.charAt(0) === "'" && val.slice(-1) === "'")
+}
+
+function safe (val) {
+  return (typeof val !== 'string' ||
+    val.match(/[=\r\n]/) ||
+    val.match(/^\[/) ||
+    (val.length > 1 &&
+     isQuoted(val)) ||
+    val !== val.trim())
+      ? JSON.stringify(val)
+      : val.replace(/;/g, '\\;').replace(/#/g, '\\#')
+}
+
+function unsafe (val, doUnesc) {
+  val = (val || '').trim()
+  if (isQuoted(val)) {
+    // remove the single quotes before calling JSON.parse
+    if (val.charAt(0) === "'") {
+      val = val.substr(1, val.length - 2)
+    }
+    try { val = JSON.parse(val) } catch (_) {}
+  } else {
+    // walk the val to find the first not-escaped ; character
+    var esc = false
+    var unesc = ''
+    for (var i = 0, l = val.length; i < l; i++) {
+      var c = val.charAt(i)
+      if (esc) {
+        if ('\\;#'.indexOf(c) !== -1) {
+          unesc += c
+        } else {
+          unesc += '\\' + c
+        }
+        esc = false
+      } else if (';#'.indexOf(c) !== -1) {
+        break
+      } else if (c === '\\') {
+        esc = true
+      } else {
+        unesc += c
+      }
+    }
+    if (esc) {
+      unesc += '\\'
+    }
+    return unesc.trim()
+  }
+  return val
+}
diff --git a/input_devices/mag/node_modules/ini/package.json b/input_devices/mag/node_modules/ini/package.json
new file mode 100644
index 00000000..f41f76ee
--- /dev/null
+++ b/input_devices/mag/node_modules/ini/package.json
@@ -0,0 +1,91 @@
+{
+  "_args": [
+    [
+      "ini@~1.3.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/rc"
+    ]
+  ],
+  "_from": "ini@>=1.3.0 <1.4.0",
+  "_id": "ini@1.3.5",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ini",
+  "_nodeVersion": "8.9.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/ini-1.3.5.tgz_1511302634290_0.6889052151236683"
+  },
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ini",
+    "raw": "ini@~1.3.0",
+    "rawSpec": "~1.3.0",
+    "scope": null,
+    "spec": ">=1.3.0 <1.4.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/rc"
+  ],
+  "_resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+  "_shasum": "eee25f56db1c9ec6085e0c22778083f596abf927",
+  "_shrinkwrap": null,
+  "_spec": "ini@~1.3.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/rc",
+  "author": {
+    "email": "i@izs.me",
+    "name": "Isaac Z. Schlueter",
+    "url": "http://blog.izs.me/"
+  },
+  "bugs": {
+    "url": "https://github.com/isaacs/ini/issues"
+  },
+  "dependencies": {},
+  "description": "An ini encoder/decoder for node",
+  "devDependencies": {
+    "standard": "^10.0.3",
+    "tap": "^10.7.3 || 11"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+    "shasum": "eee25f56db1c9ec6085e0c22778083f596abf927",
+    "tarball": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz"
+  },
+  "engines": {
+    "node": "*"
+  },
+  "files": [
+    "ini.js"
+  ],
+  "gitHead": "738eca59d77d8cfdddf5c477c17a0d8f8fbfe0fd",
+  "homepage": "https://github.com/isaacs/ini#readme",
+  "license": "ISC",
+  "main": "ini.js",
+  "maintainers": [
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    }
+  ],
+  "name": "ini",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/ini.git"
+  },
+  "scripts": {
+    "postpublish": "git push origin --all; git push origin --tags",
+    "postversion": "npm publish",
+    "pretest": "standard ini.js",
+    "preversion": "npm test",
+    "test": "tap test/*.js --100 -J"
+  },
+  "version": "1.3.5"
+}
diff --git a/input_devices/mag/node_modules/is-accessor-descriptor/LICENSE b/input_devices/mag/node_modules/is-accessor-descriptor/LICENSE
new file mode 100644
index 00000000..e33d14b7
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-accessor-descriptor/README.md b/input_devices/mag/node_modules/is-accessor-descriptor/README.md
new file mode 100644
index 00000000..d198e1f0
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/README.md
@@ -0,0 +1,144 @@
+# is-accessor-descriptor [![NPM version](https://img.shields.io/npm/v/is-accessor-descriptor.svg?style=flat)](https://www.npmjs.com/package/is-accessor-descriptor) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-accessor-descriptor.svg?style=flat)](https://npmjs.org/package/is-accessor-descriptor) [![NPM total downloads](https://img.shields.io/npm/dt/is-accessor-descriptor.svg?style=flat)](https://npmjs.org/package/is-accessor-descriptor) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-accessor-descriptor.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-accessor-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-accessor-descriptor
+```
+
+## Usage
+
+```js
+var isAccessor = require('is-accessor-descriptor');
+
+isAccessor({get: function() {}});
+//=> true
+```
+
+You may also pass an object and property name to check if the property is an accessor:
+
+```js
+isAccessor(foo, 'bar');
+```
+
+## Examples
+
+`false` when not an object
+
+```js
+isAccessor('a')
+isAccessor(null)
+isAccessor([])
+//=> false
+```
+
+`true` when the object has valid properties
+
+and the properties all have the correct JavaScript types:
+
+```js
+isAccessor({get: noop, set: noop})
+isAccessor({get: noop})
+isAccessor({set: noop})
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isAccessor({get: noop, set: noop, bar: 'baz'})
+isAccessor({get: noop, writable: true})
+isAccessor({get: noop, value: true})
+//=> false
+```
+
+`false` when an accessor is not a function
+
+```js
+isAccessor({get: noop, set: 'baz'})
+isAccessor({get: 'foo', set: noop})
+isAccessor({get: 'foo', bar: 'baz'})
+isAccessor({get: 'foo', set: 'baz'})
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isAccessor({get: noop, set: noop, enumerable: 'foo'})
+isAccessor({set: noop, configurable: 'foo'})
+isAccessor({get: noop, configurable: 'foo'})
+//=> false
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.")
+* [is-data-descriptor](https://www.npmjs.com/package/is-data-descriptor): Returns true if a value has the characteristics of a valid JavaScript data descriptor. | [homepage](https://github.com/jonschlinkert/is-data-descriptor "Returns true if a value has the characteristics of a valid JavaScript data descriptor.")
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://github.com/jonschlinkert/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.")
+* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 22 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 2 | [realityking](https://github.com/realityking) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on November 01, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-accessor-descriptor/index.js b/input_devices/mag/node_modules/is-accessor-descriptor/index.js
new file mode 100644
index 00000000..d2e6fe8b
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/index.js
@@ -0,0 +1,69 @@
+/*!
+ * is-accessor-descriptor <https://github.com/jonschlinkert/is-accessor-descriptor>
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+// accessor descriptor properties
+var accessor = {
+  get: 'function',
+  set: 'function',
+  configurable: 'boolean',
+  enumerable: 'boolean'
+};
+
+function isAccessorDescriptor(obj, prop) {
+  if (typeof prop === 'string') {
+    var val = Object.getOwnPropertyDescriptor(obj, prop);
+    return typeof val !== 'undefined';
+  }
+
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+
+  if (has(obj, 'value') || has(obj, 'writable')) {
+    return false;
+  }
+
+  if (!has(obj, 'get') || typeof obj.get !== 'function') {
+    return false;
+  }
+
+  // tldr: it's valid to have "set" be undefined
+  // "set" might be undefined if `Object.getOwnPropertyDescriptor`
+  // was used to get the value, and only `get` was defined by the user
+  if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') {
+    return false;
+  }
+
+  for (var key in obj) {
+    if (!accessor.hasOwnProperty(key)) {
+      continue;
+    }
+
+    if (typeOf(obj[key]) === accessor[key]) {
+      continue;
+    }
+
+    if (typeof obj[key] !== 'undefined') {
+      return false;
+    }
+  }
+  return true;
+}
+
+function has(obj, key) {
+  return {}.hasOwnProperty.call(obj, key);
+}
+
+/**
+ * Expose `isAccessorDescriptor`
+ */
+
+module.exports = isAccessorDescriptor;
diff --git a/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/CHANGELOG.md b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/CHANGELOG.md
new file mode 100644
index 00000000..fb30b06d
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/CHANGELOG.md
@@ -0,0 +1,157 @@
+# Release history
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<details>
+  <summary><strong>Guiding Principles</strong></summary>
+
+- Changelogs are for humans, not machines.
+- There should be an entry for every single version.
+- The same types of changes should be grouped.
+- Versions and sections should be linkable.
+- The latest version comes first.
+- The release date of each versions is displayed.
+- Mention whether you follow Semantic Versioning.
+
+</details>
+
+<details>
+  <summary><strong>Types of changes</strong></summary>
+
+Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_):
+
+- `Added` for new features.
+- `Changed` for changes in existing functionality.
+- `Deprecated` for soon-to-be removed features.
+- `Removed` for now removed features.
+- `Fixed` for any bug fixes.
+- `Security` in case of vulnerabilities.
+
+</details>
+
+## [6.0.0] - 2017-10-13
+
+- refactor code to be more performant
+- refactor benchmarks
+
+## [5.1.0] - 2017-10-13
+
+**Added**
+
+- Merge pull request #15 from aretecode/patch-1
+- adds support and tests for string & array iterators
+
+**Changed**
+
+- updates benchmarks
+
+## [5.0.2] - 2017-08-02
+
+- Merge pull request #14 from struct78/master
+- Added `undefined` check
+
+## [5.0.0] - 2017-06-21
+
+- Merge pull request #12 from aretecode/iterator
+- Set Iterator + Map Iterator
+- streamline `isbuffer`, minor edits
+
+## [4.0.0] - 2017-05-19
+
+- Merge pull request #8 from tunnckoCore/master
+- update deps
+
+## [3.2.2] - 2017-05-16
+
+- fix version
+
+## [3.2.1] - 2017-05-16
+
+- add browserify
+
+## [3.2.0] - 2017-04-25
+
+- Merge pull request #10 from ksheedlo/unrequire-buffer
+- add `promise` support and tests
+- Remove unnecessary `Buffer` check
+
+## [3.1.0] - 2016-12-07
+
+- Merge pull request #7 from laggingreflex/err
+- add support for `error` and tests
+- run update
+
+## [3.0.4] - 2016-07-29
+
+- move tests
+- run update
+
+## [3.0.3] - 2016-05-03
+
+- fix prepublish script
+- remove unused dep
+
+## [3.0.0] - 2015-11-17
+
+- add typed array support
+- Merge pull request #5 from miguelmota/typed-arrays
+- adds new tests
+
+## [2.0.1] - 2015-08-21
+
+- use `is-buffer` module
+
+## [2.0.0] - 2015-05-31
+
+- Create fallback for `Array.isArray` if used as a browser package
+- Merge pull request #2 from dtothefp/patch-1
+- Merge pull request #3 from pdehaan/patch-1
+- Merge branch 'master' of https://github.com/chorks/kind-of into chorks-master
+- optimizations, mostly date and regex
+
+## [1.1.0] - 2015-02-09
+
+- adds `buffer` support
+- adds tests for `buffer`
+
+## [1.0.0] - 2015-01-19
+
+- update benchmarks
+- optimizations based on benchmarks
+
+## [0.1.2] - 2014-10-26
+
+- return `typeof` value if it's not an object. very slight speed improvement
+- use `.slice`
+- adds benchmarks
+
+## [0.1.0] - 2014-9-26
+
+- first commit
+
+[6.0.0]: https://github.com/jonschlinkert/kind-of/compare/5.1.0...6.0.0
+[5.1.0]: https://github.com/jonschlinkert/kind-of/compare/5.0.2...5.1.0
+[5.0.2]: https://github.com/jonschlinkert/kind-of/compare/5.0.1...5.0.2
+[5.0.1]: https://github.com/jonschlinkert/kind-of/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/jonschlinkert/kind-of/compare/4.0.0...5.0.0
+[4.0.0]: https://github.com/jonschlinkert/kind-of/compare/3.2.2...4.0.0
+[3.2.2]: https://github.com/jonschlinkert/kind-of/compare/3.2.1...3.2.2
+[3.2.1]: https://github.com/jonschlinkert/kind-of/compare/3.2.0...3.2.1
+[3.2.0]: https://github.com/jonschlinkert/kind-of/compare/3.1.0...3.2.0
+[3.1.0]: https://github.com/jonschlinkert/kind-of/compare/3.0.4...3.1.0
+[3.0.4]: https://github.com/jonschlinkert/kind-of/compare/3.0.3...3.0.4
+[3.0.3]: https://github.com/jonschlinkert/kind-of/compare/3.0.0...3.0.3
+[3.0.0]: https://github.com/jonschlinkert/kind-of/compare/2.0.1...3.0.0
+[2.0.1]: https://github.com/jonschlinkert/kind-of/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/jonschlinkert/kind-of/compare/1.1.0...2.0.0
+[1.1.0]: https://github.com/jonschlinkert/kind-of/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...1.0.0
+[0.1.2]: https://github.com/jonschlinkert/kind-of/compare/0.1.0...0.1.2
+[0.1.0]: https://github.com/jonschlinkert/kind-of/commit/2fae09b0b19b1aadb558e9be39f0c3ef6034eb87
+
+[Unreleased]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...HEAD
+[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog
+
diff --git a/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md
new file mode 100644
index 00000000..4b0d4a81
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md
@@ -0,0 +1,365 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, es6, and browser ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(new Error('error'));
+//=> 'error'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'generatorfunction'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+
+```bash
+# arguments (32 bytes)
+  kind-of x 17,024,098 ops/sec ±1.90% (86 runs sampled)
+  lib-type-of x 11,926,235 ops/sec ±1.34% (83 runs sampled)
+  lib-typeof x 9,245,257 ops/sec ±1.22% (87 runs sampled)
+
+  fastest is kind-of (by 161% avg)
+
+# array (22 bytes)
+  kind-of x 17,196,492 ops/sec ±1.07% (88 runs sampled)
+  lib-type-of x 8,838,283 ops/sec ±1.02% (87 runs sampled)
+  lib-typeof x 8,677,848 ops/sec ±0.87% (87 runs sampled)
+
+  fastest is kind-of (by 196% avg)
+
+# boolean (24 bytes)
+  kind-of x 16,841,600 ops/sec ±1.10% (86 runs sampled)
+  lib-type-of x 8,096,787 ops/sec ±0.95% (87 runs sampled)
+  lib-typeof x 8,423,345 ops/sec ±1.15% (86 runs sampled)
+
+  fastest is kind-of (by 204% avg)
+
+# buffer (38 bytes)
+  kind-of x 14,848,060 ops/sec ±1.05% (86 runs sampled)
+  lib-type-of x 3,671,577 ops/sec ±1.49% (87 runs sampled)
+  lib-typeof x 8,360,236 ops/sec ±1.24% (86 runs sampled)
+
+  fastest is kind-of (by 247% avg)
+
+# date (30 bytes)
+  kind-of x 16,067,761 ops/sec ±1.58% (86 runs sampled)
+  lib-type-of x 8,954,436 ops/sec ±1.40% (87 runs sampled)
+  lib-typeof x 8,488,307 ops/sec ±1.51% (84 runs sampled)
+
+  fastest is kind-of (by 184% avg)
+
+# error (36 bytes)
+  kind-of x 9,634,090 ops/sec ±1.12% (89 runs sampled)
+  lib-type-of x 7,735,624 ops/sec ±1.32% (86 runs sampled)
+  lib-typeof x 7,442,160 ops/sec ±1.11% (90 runs sampled)
+
+  fastest is kind-of (by 127% avg)
+
+# function (34 bytes)
+  kind-of x 10,031,494 ops/sec ±1.27% (86 runs sampled)
+  lib-type-of x 9,502,757 ops/sec ±1.17% (89 runs sampled)
+  lib-typeof x 8,278,985 ops/sec ±1.08% (88 runs sampled)
+
+  fastest is kind-of (by 113% avg)
+
+# null (24 bytes)
+  kind-of x 18,159,808 ops/sec ±1.92% (86 runs sampled)
+  lib-type-of x 12,927,635 ops/sec ±1.01% (88 runs sampled)
+  lib-typeof x 7,958,234 ops/sec ±1.21% (89 runs sampled)
+
+  fastest is kind-of (by 174% avg)
+
+# number (22 bytes)
+  kind-of x 17,846,779 ops/sec ±0.91% (85 runs sampled)
+  lib-type-of x 3,316,636 ops/sec ±1.19% (86 runs sampled)
+  lib-typeof x 2,329,477 ops/sec ±2.21% (85 runs sampled)
+
+  fastest is kind-of (by 632% avg)
+
+# object-plain (47 bytes)
+  kind-of x 7,085,155 ops/sec ±1.05% (88 runs sampled)
+  lib-type-of x 8,870,930 ops/sec ±1.06% (83 runs sampled)
+  lib-typeof x 8,716,024 ops/sec ±1.05% (87 runs sampled)
+
+  fastest is lib-type-of (by 112% avg)
+
+# regex (25 bytes)
+  kind-of x 14,196,052 ops/sec ±1.65% (84 runs sampled)
+  lib-type-of x 9,554,164 ops/sec ±1.25% (88 runs sampled)
+  lib-typeof x 8,359,691 ops/sec ±1.07% (87 runs sampled)
+
+  fastest is kind-of (by 158% avg)
+
+# string (33 bytes)
+  kind-of x 16,131,428 ops/sec ±1.41% (85 runs sampled)
+  lib-type-of x 7,273,172 ops/sec ±1.05% (87 runs sampled)
+  lib-typeof x 7,382,635 ops/sec ±1.17% (85 runs sampled)
+
+  fastest is kind-of (by 220% avg)
+
+# symbol (34 bytes)
+  kind-of x 17,011,537 ops/sec ±1.24% (86 runs sampled)
+  lib-type-of x 3,492,454 ops/sec ±1.23% (89 runs sampled)
+  lib-typeof x 7,471,235 ops/sec ±2.48% (87 runs sampled)
+
+  fastest is kind-of (by 310% avg)
+
+# template-strings (36 bytes)
+  kind-of x 15,434,250 ops/sec ±1.46% (83 runs sampled)
+  lib-type-of x 7,157,907 ops/sec ±0.97% (87 runs sampled)
+  lib-typeof x 7,517,986 ops/sec ±0.92% (86 runs sampled)
+
+  fastest is kind-of (by 210% avg)
+
+# undefined (29 bytes)
+  kind-of x 19,167,115 ops/sec ±1.71% (87 runs sampled)
+  lib-type-of x 15,477,740 ops/sec ±1.63% (85 runs sampled)
+  lib-typeof x 19,075,495 ops/sec ±1.17% (83 runs sampled)
+
+  fastest is lib-typeof,kind-of
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of seems to be more consistently "correct" than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly identifies instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 98 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike-old](https://github.com/charlike-old) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on December 01, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js
new file mode 100644
index 00000000..aa2bb394
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js
@@ -0,0 +1,129 @@
+var toString = Object.prototype.toString;
+
+module.exports = function kindOf(val) {
+  if (val === void 0) return 'undefined';
+  if (val === null) return 'null';
+
+  var type = typeof val;
+  if (type === 'boolean') return 'boolean';
+  if (type === 'string') return 'string';
+  if (type === 'number') return 'number';
+  if (type === 'symbol') return 'symbol';
+  if (type === 'function') {
+    return isGeneratorFn(val) ? 'generatorfunction' : 'function';
+  }
+
+  if (isArray(val)) return 'array';
+  if (isBuffer(val)) return 'buffer';
+  if (isArguments(val)) return 'arguments';
+  if (isDate(val)) return 'date';
+  if (isError(val)) return 'error';
+  if (isRegexp(val)) return 'regexp';
+
+  switch (ctorName(val)) {
+    case 'Symbol': return 'symbol';
+    case 'Promise': return 'promise';
+
+    // Set, Map, WeakSet, WeakMap
+    case 'WeakMap': return 'weakmap';
+    case 'WeakSet': return 'weakset';
+    case 'Map': return 'map';
+    case 'Set': return 'set';
+
+    // 8-bit typed arrays
+    case 'Int8Array': return 'int8array';
+    case 'Uint8Array': return 'uint8array';
+    case 'Uint8ClampedArray': return 'uint8clampedarray';
+
+    // 16-bit typed arrays
+    case 'Int16Array': return 'int16array';
+    case 'Uint16Array': return 'uint16array';
+
+    // 32-bit typed arrays
+    case 'Int32Array': return 'int32array';
+    case 'Uint32Array': return 'uint32array';
+    case 'Float32Array': return 'float32array';
+    case 'Float64Array': return 'float64array';
+  }
+
+  if (isGeneratorObj(val)) {
+    return 'generator';
+  }
+
+  // Non-plain objects
+  type = toString.call(val);
+  switch (type) {
+    case '[object Object]': return 'object';
+    // iterators
+    case '[object Map Iterator]': return 'mapiterator';
+    case '[object Set Iterator]': return 'setiterator';
+    case '[object String Iterator]': return 'stringiterator';
+    case '[object Array Iterator]': return 'arrayiterator';
+  }
+
+  // other
+  return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
+};
+
+function ctorName(val) {
+  return val.constructor ? val.constructor.name : null;
+}
+
+function isArray(val) {
+  if (Array.isArray) return Array.isArray(val);
+  return val instanceof Array;
+}
+
+function isError(val) {
+  return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
+}
+
+function isDate(val) {
+  if (val instanceof Date) return true;
+  return typeof val.toDateString === 'function'
+    && typeof val.getDate === 'function'
+    && typeof val.setDate === 'function';
+}
+
+function isRegexp(val) {
+  if (val instanceof RegExp) return true;
+  return typeof val.flags === 'string'
+    && typeof val.ignoreCase === 'boolean'
+    && typeof val.multiline === 'boolean'
+    && typeof val.global === 'boolean';
+}
+
+function isGeneratorFn(name, val) {
+  return ctorName(name) === 'GeneratorFunction';
+}
+
+function isGeneratorObj(val) {
+  return typeof val.throw === 'function'
+    && typeof val.return === 'function'
+    && typeof val.next === 'function';
+}
+
+function isArguments(val) {
+  try {
+    if (typeof val.length === 'number' && typeof val.callee === 'function') {
+      return true;
+    }
+  } catch (err) {
+    if (err.message.indexOf('callee') !== -1) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  if (val.constructor && typeof val.constructor.isBuffer === 'function') {
+    return val.constructor.isBuffer(val);
+  }
+  return false;
+}
diff --git a/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json
new file mode 100644
index 00000000..bc6c79d6
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json
@@ -0,0 +1,176 @@
+{
+  "_args": [
+    [
+      "kind-of@^6.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-accessor-descriptor"
+    ]
+  ],
+  "_from": "kind-of@>=6.0.0 <7.0.0",
+  "_id": "kind-of@6.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-accessor-descriptor/kind-of",
+  "_nodeVersion": "9.1.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-6.0.2.tgz_1512153086430_0.774781379615888"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^6.0.0",
+    "rawSpec": "^6.0.0",
+    "scope": null,
+    "spec": ">=6.0.0 <7.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/is-accessor-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+  "_shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^6.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-accessor-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "benchmarked": "^2.0.0",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^4.0.1",
+    "write": "^1.0.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+    "shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "1491da72e8d276479f5f6198a9e79c1379c5d0c7",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "6.0.2"
+}
diff --git a/input_devices/mag/node_modules/is-accessor-descriptor/package.json b/input_devices/mag/node_modules/is-accessor-descriptor/package.json
new file mode 100644
index 00000000..4820824f
--- /dev/null
+++ b/input_devices/mag/node_modules/is-accessor-descriptor/package.json
@@ -0,0 +1,138 @@
+{
+  "_args": [
+    [
+      "is-accessor-descriptor@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "is-accessor-descriptor@>=1.0.0 <2.0.0",
+  "_id": "is-accessor-descriptor@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-accessor-descriptor",
+  "_nodeVersion": "8.7.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-accessor-descriptor-1.0.0.tgz_1509516773874_0.014908343320712447"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-accessor-descriptor",
+    "raw": "is-accessor-descriptor@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+  "_shasum": "169c2f6d3df1f992618072365c9b0ea1f6878656",
+  "_shrinkwrap": null,
+  "_spec": "is-accessor-descriptor@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-accessor-descriptor/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Rouven Weßling",
+      "url": "www.rouvenwessling.de"
+    }
+  ],
+  "dependencies": {
+    "kind-of": "^6.0.0"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+    "shasum": "169c2f6d3df1f992618072365c9b0ea1f6878656",
+    "tarball": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "22b0a2617ccbebd131247c29e3700ca860d37d06",
+  "homepage": "https://github.com/jonschlinkert/is-accessor-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-accessor-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-accessor-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "is-plain-object",
+        "isobject"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/is-buffer/LICENSE b/input_devices/mag/node_modules/is-buffer/LICENSE
new file mode 100644
index 00000000..0c068cee
--- /dev/null
+++ b/input_devices/mag/node_modules/is-buffer/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Feross Aboukhadijeh
+
+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/input_devices/mag/node_modules/is-buffer/README.md b/input_devices/mag/node_modules/is-buffer/README.md
new file mode 100644
index 00000000..cce0a8cf
--- /dev/null
+++ b/input_devices/mag/node_modules/is-buffer/README.md
@@ -0,0 +1,53 @@
+# is-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
+
+[travis-image]: https://img.shields.io/travis/feross/is-buffer/master.svg
+[travis-url]: https://travis-ci.org/feross/is-buffer
+[npm-image]: https://img.shields.io/npm/v/is-buffer.svg
+[npm-url]: https://npmjs.org/package/is-buffer
+[downloads-image]: https://img.shields.io/npm/dm/is-buffer.svg
+[downloads-url]: https://npmjs.org/package/is-buffer
+[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
+[standard-url]: https://standardjs.com
+
+#### Determine if an object is a [`Buffer`](http://nodejs.org/api/buffer.html) (including the [browserify Buffer](https://github.com/feross/buffer))
+
+[![saucelabs][saucelabs-image]][saucelabs-url]
+
+[saucelabs-image]: https://saucelabs.com/browser-matrix/is-buffer.svg
+[saucelabs-url]: https://saucelabs.com/u/is-buffer
+
+## Why not use `Buffer.isBuffer`?
+
+This module lets you check if an object is a `Buffer` without using `Buffer.isBuffer` (which includes the whole [buffer](https://github.com/feross/buffer) module in [browserify](http://browserify.org/)).
+
+It's future-proof and works in node too!
+
+## install
+
+```bash
+npm install is-buffer
+```
+
+## usage
+
+```js
+var isBuffer = require('is-buffer')
+
+isBuffer(new Buffer(4)) // true
+
+isBuffer(undefined) // false
+isBuffer(null) // false
+isBuffer('') // false
+isBuffer(true) // false
+isBuffer(false) // false
+isBuffer(0) // false
+isBuffer(1) // false
+isBuffer(1.0) // false
+isBuffer('string') // false
+isBuffer({}) // false
+isBuffer(function foo () {}) // false
+```
+
+## license
+
+MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org).
diff --git a/input_devices/mag/node_modules/is-buffer/index.js b/input_devices/mag/node_modules/is-buffer/index.js
new file mode 100644
index 00000000..9cce3965
--- /dev/null
+++ b/input_devices/mag/node_modules/is-buffer/index.js
@@ -0,0 +1,21 @@
+/*!
+ * Determine if an object is a Buffer
+ *
+ * @author   Feross Aboukhadijeh <https://feross.org>
+ * @license  MIT
+ */
+
+// The _isBuffer check is for Safari 5-7 support, because it's missing
+// Object.prototype.constructor. Remove this eventually
+module.exports = function (obj) {
+  return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
+}
+
+function isBuffer (obj) {
+  return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
+}
+
+// For Node v0.10 support. Remove this eventually.
+function isSlowBuffer (obj) {
+  return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
+}
diff --git a/input_devices/mag/node_modules/is-buffer/package.json b/input_devices/mag/node_modules/is-buffer/package.json
new file mode 100644
index 00000000..a2a1e344
--- /dev/null
+++ b/input_devices/mag/node_modules/is-buffer/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "is-buffer@^1.1.5",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/kind-of"
+    ]
+  ],
+  "_from": "is-buffer@>=1.1.5 <2.0.0",
+  "_id": "is-buffer@1.1.6",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-buffer",
+  "_nodeVersion": "8.6.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-buffer-1.1.6.tgz_1508967388794_0.03916449216194451"
+  },
+  "_npmUser": {
+    "email": "feross@feross.org",
+    "name": "feross"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-buffer",
+    "raw": "is-buffer@^1.1.5",
+    "rawSpec": "^1.1.5",
+    "scope": null,
+    "spec": ">=1.1.5 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/kind-of",
+    "/readline-utils",
+    "/static-extend/is-accessor-descriptor/kind-of",
+    "/static-extend/is-data-descriptor/kind-of"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+  "_shasum": "efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be",
+  "_shrinkwrap": null,
+  "_spec": "is-buffer@^1.1.5",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/kind-of",
+  "author": {
+    "email": "feross@feross.org",
+    "name": "Feross Aboukhadijeh",
+    "url": "http://feross.org/"
+  },
+  "bugs": {
+    "url": "https://github.com/feross/is-buffer/issues"
+  },
+  "dependencies": {},
+  "description": "Determine if an object is a Buffer",
+  "devDependencies": {
+    "standard": "*",
+    "tape": "^4.0.0",
+    "zuul": "^3.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+    "shasum": "efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be",
+    "tarball": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz"
+  },
+  "gitHead": "1e84e7ee31cf6b660b12500f3111a05501da387f",
+  "homepage": "https://github.com/feross/is-buffer#readme",
+  "keywords": [
+    "arraybuffer",
+    "browser",
+    "browser buffer",
+    "browserify",
+    "buffer",
+    "buffers",
+    "core buffer",
+    "dataview",
+    "float32array",
+    "float64array",
+    "int16array",
+    "int32array",
+    "type",
+    "typed array",
+    "uint32array"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "feross",
+      "email": "feross@feross.org"
+    }
+  ],
+  "name": "is-buffer",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/feross/is-buffer.git"
+  },
+  "scripts": {
+    "test": "standard && npm run test-node && npm run test-browser",
+    "test-browser": "zuul -- test/*.js",
+    "test-browser-local": "zuul --local -- test/*.js",
+    "test-node": "tape test/*.js"
+  },
+  "testling": {
+    "files": "test/*.js"
+  },
+  "version": "1.1.6"
+}
diff --git a/input_devices/mag/node_modules/is-buffer/test/basic.js b/input_devices/mag/node_modules/is-buffer/test/basic.js
new file mode 100644
index 00000000..be4f8e43
--- /dev/null
+++ b/input_devices/mag/node_modules/is-buffer/test/basic.js
@@ -0,0 +1,24 @@
+var isBuffer = require('../')
+var test = require('tape')
+
+test('is-buffer', function (t) {
+  t.equal(isBuffer(Buffer.alloc(4)), true, 'new Buffer(4)')
+  t.equal(isBuffer(Buffer.allocUnsafeSlow(100)), true, 'SlowBuffer(100)')
+
+  t.equal(isBuffer(undefined), false, 'undefined')
+  t.equal(isBuffer(null), false, 'null')
+  t.equal(isBuffer(''), false, 'empty string')
+  t.equal(isBuffer(true), false, 'true')
+  t.equal(isBuffer(false), false, 'false')
+  t.equal(isBuffer(0), false, '0')
+  t.equal(isBuffer(1), false, '1')
+  t.equal(isBuffer(1.0), false, '1.0')
+  t.equal(isBuffer('string'), false, 'string')
+  t.equal(isBuffer({}), false, '{}')
+  t.equal(isBuffer([]), false, '[]')
+  t.equal(isBuffer(function foo () {}), false, 'function foo () {}')
+  t.equal(isBuffer({ isBuffer: null }), false, '{ isBuffer: null }')
+  t.equal(isBuffer({ isBuffer: function () { throw new Error() } }), false, '{ isBuffer: function () { throw new Error() } }')
+
+  t.end()
+})
diff --git a/input_devices/mag/node_modules/is-data-descriptor/LICENSE b/input_devices/mag/node_modules/is-data-descriptor/LICENSE
new file mode 100644
index 00000000..e33d14b7
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-data-descriptor/README.md b/input_devices/mag/node_modules/is-data-descriptor/README.md
new file mode 100644
index 00000000..42b07144
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/README.md
@@ -0,0 +1,161 @@
+# is-data-descriptor [![NPM version](https://img.shields.io/npm/v/is-data-descriptor.svg?style=flat)](https://www.npmjs.com/package/is-data-descriptor) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-data-descriptor.svg?style=flat)](https://npmjs.org/package/is-data-descriptor) [![NPM total downloads](https://img.shields.io/npm/dt/is-data-descriptor.svg?style=flat)](https://npmjs.org/package/is-data-descriptor) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-data-descriptor.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-data-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript data descriptor.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-data-descriptor
+```
+
+## Usage
+
+```js
+var isDataDesc = require('is-data-descriptor');
+```
+
+## Examples
+
+`true` when the descriptor has valid properties with valid values.
+
+```js
+// `value` can be anything
+isDataDesc({value: 'foo'})
+isDataDesc({value: function() {}})
+isDataDesc({value: true})
+//=> true
+```
+
+`false` when not an object
+
+```js
+isDataDesc('a')
+//=> false
+isDataDesc(null)
+//=> false
+isDataDesc([])
+//=> false
+```
+
+`false` when the object has invalid properties
+
+```js
+isDataDesc({value: 'foo', bar: 'baz'})
+//=> false
+isDataDesc({value: 'foo', bar: 'baz'})
+//=> false
+isDataDesc({value: 'foo', get: function(){}})
+//=> false
+isDataDesc({get: function(){}, value: 'foo'})
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDataDesc({value: 'foo', enumerable: 'foo'})
+//=> false
+isDataDesc({value: 'foo', configurable: 'foo'})
+//=> false
+isDataDesc({value: 'foo', writable: 'foo'})
+//=> false
+```
+
+## Valid properties
+
+The only valid data descriptor properties are the following:
+
+* `configurable` (required)
+* `enumerable` (required)
+* `value` (optional)
+* `writable` (optional)
+
+To be a valid data descriptor, either `value` or `writable` must be defined.
+
+**Invalid properties**
+
+A descriptor may have additional _invalid_ properties (an error will **not** be thrown).
+
+```js
+var foo = {};
+
+Object.defineProperty(foo, 'bar', {
+  enumerable: true,
+  whatever: 'blah', // invalid, but doesn't cause an error
+  get: function() {
+    return 'baz';
+  }
+});
+
+console.log(foo.bar);
+//=> 'baz'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.")
+* [is-data-descriptor](https://www.npmjs.com/package/is-data-descriptor): Returns true if a value has the characteristics of a valid JavaScript data descriptor. | [homepage](https://github.com/jonschlinkert/is-data-descriptor "Returns true if a value has the characteristics of a valid JavaScript data descriptor.")
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://github.com/jonschlinkert/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 21 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 2 | [realityking](https://github.com/realityking) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on November 01, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-data-descriptor/index.js b/input_devices/mag/node_modules/is-data-descriptor/index.js
new file mode 100644
index 00000000..cfeae361
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/index.js
@@ -0,0 +1,49 @@
+/*!
+ * is-data-descriptor <https://github.com/jonschlinkert/is-data-descriptor>
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+module.exports = function isDataDescriptor(obj, prop) {
+  // data descriptor properties
+  var data = {
+    configurable: 'boolean',
+    enumerable: 'boolean',
+    writable: 'boolean'
+  };
+
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+
+  if (typeof prop === 'string') {
+    var val = Object.getOwnPropertyDescriptor(obj, prop);
+    return typeof val !== 'undefined';
+  }
+
+  if (!('value' in obj) && !('writable' in obj)) {
+    return false;
+  }
+
+  for (var key in obj) {
+    if (key === 'value') continue;
+
+    if (!data.hasOwnProperty(key)) {
+      continue;
+    }
+
+    if (typeOf(obj[key]) === data[key]) {
+      continue;
+    }
+
+    if (typeof obj[key] !== 'undefined') {
+      return false;
+    }
+  }
+  return true;
+};
diff --git a/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/CHANGELOG.md b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/CHANGELOG.md
new file mode 100644
index 00000000..fb30b06d
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/CHANGELOG.md
@@ -0,0 +1,157 @@
+# Release history
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<details>
+  <summary><strong>Guiding Principles</strong></summary>
+
+- Changelogs are for humans, not machines.
+- There should be an entry for every single version.
+- The same types of changes should be grouped.
+- Versions and sections should be linkable.
+- The latest version comes first.
+- The release date of each versions is displayed.
+- Mention whether you follow Semantic Versioning.
+
+</details>
+
+<details>
+  <summary><strong>Types of changes</strong></summary>
+
+Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_):
+
+- `Added` for new features.
+- `Changed` for changes in existing functionality.
+- `Deprecated` for soon-to-be removed features.
+- `Removed` for now removed features.
+- `Fixed` for any bug fixes.
+- `Security` in case of vulnerabilities.
+
+</details>
+
+## [6.0.0] - 2017-10-13
+
+- refactor code to be more performant
+- refactor benchmarks
+
+## [5.1.0] - 2017-10-13
+
+**Added**
+
+- Merge pull request #15 from aretecode/patch-1
+- adds support and tests for string & array iterators
+
+**Changed**
+
+- updates benchmarks
+
+## [5.0.2] - 2017-08-02
+
+- Merge pull request #14 from struct78/master
+- Added `undefined` check
+
+## [5.0.0] - 2017-06-21
+
+- Merge pull request #12 from aretecode/iterator
+- Set Iterator + Map Iterator
+- streamline `isbuffer`, minor edits
+
+## [4.0.0] - 2017-05-19
+
+- Merge pull request #8 from tunnckoCore/master
+- update deps
+
+## [3.2.2] - 2017-05-16
+
+- fix version
+
+## [3.2.1] - 2017-05-16
+
+- add browserify
+
+## [3.2.0] - 2017-04-25
+
+- Merge pull request #10 from ksheedlo/unrequire-buffer
+- add `promise` support and tests
+- Remove unnecessary `Buffer` check
+
+## [3.1.0] - 2016-12-07
+
+- Merge pull request #7 from laggingreflex/err
+- add support for `error` and tests
+- run update
+
+## [3.0.4] - 2016-07-29
+
+- move tests
+- run update
+
+## [3.0.3] - 2016-05-03
+
+- fix prepublish script
+- remove unused dep
+
+## [3.0.0] - 2015-11-17
+
+- add typed array support
+- Merge pull request #5 from miguelmota/typed-arrays
+- adds new tests
+
+## [2.0.1] - 2015-08-21
+
+- use `is-buffer` module
+
+## [2.0.0] - 2015-05-31
+
+- Create fallback for `Array.isArray` if used as a browser package
+- Merge pull request #2 from dtothefp/patch-1
+- Merge pull request #3 from pdehaan/patch-1
+- Merge branch 'master' of https://github.com/chorks/kind-of into chorks-master
+- optimizations, mostly date and regex
+
+## [1.1.0] - 2015-02-09
+
+- adds `buffer` support
+- adds tests for `buffer`
+
+## [1.0.0] - 2015-01-19
+
+- update benchmarks
+- optimizations based on benchmarks
+
+## [0.1.2] - 2014-10-26
+
+- return `typeof` value if it's not an object. very slight speed improvement
+- use `.slice`
+- adds benchmarks
+
+## [0.1.0] - 2014-9-26
+
+- first commit
+
+[6.0.0]: https://github.com/jonschlinkert/kind-of/compare/5.1.0...6.0.0
+[5.1.0]: https://github.com/jonschlinkert/kind-of/compare/5.0.2...5.1.0
+[5.0.2]: https://github.com/jonschlinkert/kind-of/compare/5.0.1...5.0.2
+[5.0.1]: https://github.com/jonschlinkert/kind-of/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/jonschlinkert/kind-of/compare/4.0.0...5.0.0
+[4.0.0]: https://github.com/jonschlinkert/kind-of/compare/3.2.2...4.0.0
+[3.2.2]: https://github.com/jonschlinkert/kind-of/compare/3.2.1...3.2.2
+[3.2.1]: https://github.com/jonschlinkert/kind-of/compare/3.2.0...3.2.1
+[3.2.0]: https://github.com/jonschlinkert/kind-of/compare/3.1.0...3.2.0
+[3.1.0]: https://github.com/jonschlinkert/kind-of/compare/3.0.4...3.1.0
+[3.0.4]: https://github.com/jonschlinkert/kind-of/compare/3.0.3...3.0.4
+[3.0.3]: https://github.com/jonschlinkert/kind-of/compare/3.0.0...3.0.3
+[3.0.0]: https://github.com/jonschlinkert/kind-of/compare/2.0.1...3.0.0
+[2.0.1]: https://github.com/jonschlinkert/kind-of/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/jonschlinkert/kind-of/compare/1.1.0...2.0.0
+[1.1.0]: https://github.com/jonschlinkert/kind-of/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...1.0.0
+[0.1.2]: https://github.com/jonschlinkert/kind-of/compare/0.1.0...0.1.2
+[0.1.0]: https://github.com/jonschlinkert/kind-of/commit/2fae09b0b19b1aadb558e9be39f0c3ef6034eb87
+
+[Unreleased]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...HEAD
+[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog
+
diff --git a/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/README.md b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/README.md
new file mode 100644
index 00000000..4b0d4a81
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/README.md
@@ -0,0 +1,365 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, es6, and browser ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(new Error('error'));
+//=> 'error'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'generatorfunction'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+
+```bash
+# arguments (32 bytes)
+  kind-of x 17,024,098 ops/sec ±1.90% (86 runs sampled)
+  lib-type-of x 11,926,235 ops/sec ±1.34% (83 runs sampled)
+  lib-typeof x 9,245,257 ops/sec ±1.22% (87 runs sampled)
+
+  fastest is kind-of (by 161% avg)
+
+# array (22 bytes)
+  kind-of x 17,196,492 ops/sec ±1.07% (88 runs sampled)
+  lib-type-of x 8,838,283 ops/sec ±1.02% (87 runs sampled)
+  lib-typeof x 8,677,848 ops/sec ±0.87% (87 runs sampled)
+
+  fastest is kind-of (by 196% avg)
+
+# boolean (24 bytes)
+  kind-of x 16,841,600 ops/sec ±1.10% (86 runs sampled)
+  lib-type-of x 8,096,787 ops/sec ±0.95% (87 runs sampled)
+  lib-typeof x 8,423,345 ops/sec ±1.15% (86 runs sampled)
+
+  fastest is kind-of (by 204% avg)
+
+# buffer (38 bytes)
+  kind-of x 14,848,060 ops/sec ±1.05% (86 runs sampled)
+  lib-type-of x 3,671,577 ops/sec ±1.49% (87 runs sampled)
+  lib-typeof x 8,360,236 ops/sec ±1.24% (86 runs sampled)
+
+  fastest is kind-of (by 247% avg)
+
+# date (30 bytes)
+  kind-of x 16,067,761 ops/sec ±1.58% (86 runs sampled)
+  lib-type-of x 8,954,436 ops/sec ±1.40% (87 runs sampled)
+  lib-typeof x 8,488,307 ops/sec ±1.51% (84 runs sampled)
+
+  fastest is kind-of (by 184% avg)
+
+# error (36 bytes)
+  kind-of x 9,634,090 ops/sec ±1.12% (89 runs sampled)
+  lib-type-of x 7,735,624 ops/sec ±1.32% (86 runs sampled)
+  lib-typeof x 7,442,160 ops/sec ±1.11% (90 runs sampled)
+
+  fastest is kind-of (by 127% avg)
+
+# function (34 bytes)
+  kind-of x 10,031,494 ops/sec ±1.27% (86 runs sampled)
+  lib-type-of x 9,502,757 ops/sec ±1.17% (89 runs sampled)
+  lib-typeof x 8,278,985 ops/sec ±1.08% (88 runs sampled)
+
+  fastest is kind-of (by 113% avg)
+
+# null (24 bytes)
+  kind-of x 18,159,808 ops/sec ±1.92% (86 runs sampled)
+  lib-type-of x 12,927,635 ops/sec ±1.01% (88 runs sampled)
+  lib-typeof x 7,958,234 ops/sec ±1.21% (89 runs sampled)
+
+  fastest is kind-of (by 174% avg)
+
+# number (22 bytes)
+  kind-of x 17,846,779 ops/sec ±0.91% (85 runs sampled)
+  lib-type-of x 3,316,636 ops/sec ±1.19% (86 runs sampled)
+  lib-typeof x 2,329,477 ops/sec ±2.21% (85 runs sampled)
+
+  fastest is kind-of (by 632% avg)
+
+# object-plain (47 bytes)
+  kind-of x 7,085,155 ops/sec ±1.05% (88 runs sampled)
+  lib-type-of x 8,870,930 ops/sec ±1.06% (83 runs sampled)
+  lib-typeof x 8,716,024 ops/sec ±1.05% (87 runs sampled)
+
+  fastest is lib-type-of (by 112% avg)
+
+# regex (25 bytes)
+  kind-of x 14,196,052 ops/sec ±1.65% (84 runs sampled)
+  lib-type-of x 9,554,164 ops/sec ±1.25% (88 runs sampled)
+  lib-typeof x 8,359,691 ops/sec ±1.07% (87 runs sampled)
+
+  fastest is kind-of (by 158% avg)
+
+# string (33 bytes)
+  kind-of x 16,131,428 ops/sec ±1.41% (85 runs sampled)
+  lib-type-of x 7,273,172 ops/sec ±1.05% (87 runs sampled)
+  lib-typeof x 7,382,635 ops/sec ±1.17% (85 runs sampled)
+
+  fastest is kind-of (by 220% avg)
+
+# symbol (34 bytes)
+  kind-of x 17,011,537 ops/sec ±1.24% (86 runs sampled)
+  lib-type-of x 3,492,454 ops/sec ±1.23% (89 runs sampled)
+  lib-typeof x 7,471,235 ops/sec ±2.48% (87 runs sampled)
+
+  fastest is kind-of (by 310% avg)
+
+# template-strings (36 bytes)
+  kind-of x 15,434,250 ops/sec ±1.46% (83 runs sampled)
+  lib-type-of x 7,157,907 ops/sec ±0.97% (87 runs sampled)
+  lib-typeof x 7,517,986 ops/sec ±0.92% (86 runs sampled)
+
+  fastest is kind-of (by 210% avg)
+
+# undefined (29 bytes)
+  kind-of x 19,167,115 ops/sec ±1.71% (87 runs sampled)
+  lib-type-of x 15,477,740 ops/sec ±1.63% (85 runs sampled)
+  lib-typeof x 19,075,495 ops/sec ±1.17% (83 runs sampled)
+
+  fastest is lib-typeof,kind-of
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of seems to be more consistently "correct" than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly identifies instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 98 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike-old](https://github.com/charlike-old) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on December 01, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/index.js b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/index.js
new file mode 100644
index 00000000..aa2bb394
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/index.js
@@ -0,0 +1,129 @@
+var toString = Object.prototype.toString;
+
+module.exports = function kindOf(val) {
+  if (val === void 0) return 'undefined';
+  if (val === null) return 'null';
+
+  var type = typeof val;
+  if (type === 'boolean') return 'boolean';
+  if (type === 'string') return 'string';
+  if (type === 'number') return 'number';
+  if (type === 'symbol') return 'symbol';
+  if (type === 'function') {
+    return isGeneratorFn(val) ? 'generatorfunction' : 'function';
+  }
+
+  if (isArray(val)) return 'array';
+  if (isBuffer(val)) return 'buffer';
+  if (isArguments(val)) return 'arguments';
+  if (isDate(val)) return 'date';
+  if (isError(val)) return 'error';
+  if (isRegexp(val)) return 'regexp';
+
+  switch (ctorName(val)) {
+    case 'Symbol': return 'symbol';
+    case 'Promise': return 'promise';
+
+    // Set, Map, WeakSet, WeakMap
+    case 'WeakMap': return 'weakmap';
+    case 'WeakSet': return 'weakset';
+    case 'Map': return 'map';
+    case 'Set': return 'set';
+
+    // 8-bit typed arrays
+    case 'Int8Array': return 'int8array';
+    case 'Uint8Array': return 'uint8array';
+    case 'Uint8ClampedArray': return 'uint8clampedarray';
+
+    // 16-bit typed arrays
+    case 'Int16Array': return 'int16array';
+    case 'Uint16Array': return 'uint16array';
+
+    // 32-bit typed arrays
+    case 'Int32Array': return 'int32array';
+    case 'Uint32Array': return 'uint32array';
+    case 'Float32Array': return 'float32array';
+    case 'Float64Array': return 'float64array';
+  }
+
+  if (isGeneratorObj(val)) {
+    return 'generator';
+  }
+
+  // Non-plain objects
+  type = toString.call(val);
+  switch (type) {
+    case '[object Object]': return 'object';
+    // iterators
+    case '[object Map Iterator]': return 'mapiterator';
+    case '[object Set Iterator]': return 'setiterator';
+    case '[object String Iterator]': return 'stringiterator';
+    case '[object Array Iterator]': return 'arrayiterator';
+  }
+
+  // other
+  return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
+};
+
+function ctorName(val) {
+  return val.constructor ? val.constructor.name : null;
+}
+
+function isArray(val) {
+  if (Array.isArray) return Array.isArray(val);
+  return val instanceof Array;
+}
+
+function isError(val) {
+  return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
+}
+
+function isDate(val) {
+  if (val instanceof Date) return true;
+  return typeof val.toDateString === 'function'
+    && typeof val.getDate === 'function'
+    && typeof val.setDate === 'function';
+}
+
+function isRegexp(val) {
+  if (val instanceof RegExp) return true;
+  return typeof val.flags === 'string'
+    && typeof val.ignoreCase === 'boolean'
+    && typeof val.multiline === 'boolean'
+    && typeof val.global === 'boolean';
+}
+
+function isGeneratorFn(name, val) {
+  return ctorName(name) === 'GeneratorFunction';
+}
+
+function isGeneratorObj(val) {
+  return typeof val.throw === 'function'
+    && typeof val.return === 'function'
+    && typeof val.next === 'function';
+}
+
+function isArguments(val) {
+  try {
+    if (typeof val.length === 'number' && typeof val.callee === 'function') {
+      return true;
+    }
+  } catch (err) {
+    if (err.message.indexOf('callee') !== -1) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  if (val.constructor && typeof val.constructor.isBuffer === 'function') {
+    return val.constructor.isBuffer(val);
+  }
+  return false;
+}
diff --git a/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/package.json b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/package.json
new file mode 100644
index 00000000..ed7974a9
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/node_modules/kind-of/package.json
@@ -0,0 +1,176 @@
+{
+  "_args": [
+    [
+      "kind-of@^6.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-data-descriptor"
+    ]
+  ],
+  "_from": "kind-of@>=6.0.0 <7.0.0",
+  "_id": "kind-of@6.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-data-descriptor/kind-of",
+  "_nodeVersion": "9.1.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-6.0.2.tgz_1512153086430_0.774781379615888"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^6.0.0",
+    "rawSpec": "^6.0.0",
+    "scope": null,
+    "spec": ">=6.0.0 <7.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/is-data-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+  "_shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^6.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-data-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "benchmarked": "^2.0.0",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^4.0.1",
+    "write": "^1.0.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+    "shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "1491da72e8d276479f5f6198a9e79c1379c5d0c7",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "6.0.2"
+}
diff --git a/input_devices/mag/node_modules/is-data-descriptor/package.json b/input_devices/mag/node_modules/is-data-descriptor/package.json
new file mode 100644
index 00000000..c6fca49f
--- /dev/null
+++ b/input_devices/mag/node_modules/is-data-descriptor/package.json
@@ -0,0 +1,137 @@
+{
+  "_args": [
+    [
+      "is-data-descriptor@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "is-data-descriptor@>=1.0.0 <2.0.0",
+  "_id": "is-data-descriptor@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-data-descriptor",
+  "_nodeVersion": "8.7.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-data-descriptor-1.0.0.tgz_1509518030206_0.015712385065853596"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-data-descriptor",
+    "raw": "is-data-descriptor@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+  "_shasum": "d84876321d0e7add03990406abbbbd36ba9268c7",
+  "_shrinkwrap": null,
+  "_spec": "is-data-descriptor@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-data-descriptor/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Rouven Weßling",
+      "url": "www.rouvenwessling.de"
+    }
+  ],
+  "dependencies": {
+    "kind-of": "^6.0.0"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript data descriptor.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+    "shasum": "d84876321d0e7add03990406abbbbd36ba9268c7",
+    "tarball": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "42dcba2627fe655daa21aec843ca8de849f26cd6",
+  "homepage": "https://github.com/jonschlinkert/is-data-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-data-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-data-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/is-descriptor/LICENSE b/input_devices/mag/node_modules/is-descriptor/LICENSE
new file mode 100644
index 00000000..c0d7f136
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-descriptor/README.md b/input_devices/mag/node_modules/is-descriptor/README.md
new file mode 100644
index 00000000..658e5330
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/README.md
@@ -0,0 +1,193 @@
+# is-descriptor [![NPM version](https://img.shields.io/npm/v/is-descriptor.svg?style=flat)](https://www.npmjs.com/package/is-descriptor) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-descriptor.svg?style=flat)](https://npmjs.org/package/is-descriptor) [![NPM total downloads](https://img.shields.io/npm/dt/is-descriptor.svg?style=flat)](https://npmjs.org/package/is-descriptor) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-descriptor.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-descriptor
+```
+
+## Usage
+
+```js
+var isDescriptor = require('is-descriptor');
+
+isDescriptor({value: 'foo'})
+//=> true
+isDescriptor({get: function(){}, set: function(){}})
+//=> true
+isDescriptor({get: 'foo', set: function(){}})
+//=> false
+```
+
+You may also check for a descriptor by passing an object as the first argument and property name (`string`) as the second argument.
+
+```js
+var obj = {};
+obj.foo = 'abc';
+
+Object.defineProperty(obj, 'bar', {
+  value: 'xyz'
+});
+
+isDescriptor(obj, 'foo');
+//=> true
+isDescriptor(obj, 'bar');
+//=> true
+```
+
+## Examples
+
+### value type
+
+`false` when not an object
+
+```js
+isDescriptor('a');
+//=> false
+isDescriptor(null);
+//=> false
+isDescriptor([]);
+//=> false
+```
+
+### data descriptor
+
+`true` when the object has valid properties with valid values.
+
+```js
+isDescriptor({value: 'foo'});
+//=> true
+isDescriptor({value: noop});
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isDescriptor({value: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({value: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({value: 'foo', get: noop});
+//=> false
+isDescriptor({get: noop, value: noop});
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDescriptor({value: 'foo', enumerable: 'foo'});
+//=> false
+isDescriptor({value: 'foo', configurable: 'foo'});
+//=> false
+isDescriptor({value: 'foo', writable: 'foo'});
+//=> false
+```
+
+### accessor descriptor
+
+`true` when the object has valid properties with valid values.
+
+```js
+isDescriptor({get: noop, set: noop});
+//=> true
+isDescriptor({get: noop});
+//=> true
+isDescriptor({set: noop});
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isDescriptor({get: noop, set: noop, bar: 'baz'});
+//=> false
+isDescriptor({get: noop, writable: true});
+//=> false
+isDescriptor({get: noop, value: true});
+//=> false
+```
+
+`false` when an accessor is not a function
+
+```js
+isDescriptor({get: noop, set: 'baz'});
+//=> false
+isDescriptor({get: 'foo', set: noop});
+//=> false
+isDescriptor({get: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({get: 'foo', set: 'baz'});
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDescriptor({get: noop, set: noop, enumerable: 'foo'});
+//=> false
+isDescriptor({set: noop, configurable: 'foo'});
+//=> false
+isDescriptor({get: noop, configurable: 'foo'});
+//=> false
+```
+
+## About
+
+### Related projects
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.")
+* [is-data-descriptor](https://www.npmjs.com/package/is-data-descriptor): Returns true if a value has the characteristics of a valid JavaScript data descriptor. | [homepage](https://github.com/jonschlinkert/is-data-descriptor "Returns true if a value has the characteristics of a valid JavaScript data descriptor.")
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://github.com/jonschlinkert/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 24 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [doowb](https://github.com/doowb) |
+| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 22, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-descriptor/index.js b/input_devices/mag/node_modules/is-descriptor/index.js
new file mode 100644
index 00000000..c9b91d76
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/index.js
@@ -0,0 +1,22 @@
+/*!
+ * is-descriptor <https://github.com/jonschlinkert/is-descriptor>
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+var isAccessor = require('is-accessor-descriptor');
+var isData = require('is-data-descriptor');
+
+module.exports = function isDescriptor(obj, key) {
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+  if ('get' in obj) {
+    return isAccessor(obj, key);
+  }
+  return isData(obj, key);
+};
diff --git a/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/CHANGELOG.md b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/CHANGELOG.md
new file mode 100644
index 00000000..fb30b06d
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/CHANGELOG.md
@@ -0,0 +1,157 @@
+# Release history
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<details>
+  <summary><strong>Guiding Principles</strong></summary>
+
+- Changelogs are for humans, not machines.
+- There should be an entry for every single version.
+- The same types of changes should be grouped.
+- Versions and sections should be linkable.
+- The latest version comes first.
+- The release date of each versions is displayed.
+- Mention whether you follow Semantic Versioning.
+
+</details>
+
+<details>
+  <summary><strong>Types of changes</strong></summary>
+
+Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_):
+
+- `Added` for new features.
+- `Changed` for changes in existing functionality.
+- `Deprecated` for soon-to-be removed features.
+- `Removed` for now removed features.
+- `Fixed` for any bug fixes.
+- `Security` in case of vulnerabilities.
+
+</details>
+
+## [6.0.0] - 2017-10-13
+
+- refactor code to be more performant
+- refactor benchmarks
+
+## [5.1.0] - 2017-10-13
+
+**Added**
+
+- Merge pull request #15 from aretecode/patch-1
+- adds support and tests for string & array iterators
+
+**Changed**
+
+- updates benchmarks
+
+## [5.0.2] - 2017-08-02
+
+- Merge pull request #14 from struct78/master
+- Added `undefined` check
+
+## [5.0.0] - 2017-06-21
+
+- Merge pull request #12 from aretecode/iterator
+- Set Iterator + Map Iterator
+- streamline `isbuffer`, minor edits
+
+## [4.0.0] - 2017-05-19
+
+- Merge pull request #8 from tunnckoCore/master
+- update deps
+
+## [3.2.2] - 2017-05-16
+
+- fix version
+
+## [3.2.1] - 2017-05-16
+
+- add browserify
+
+## [3.2.0] - 2017-04-25
+
+- Merge pull request #10 from ksheedlo/unrequire-buffer
+- add `promise` support and tests
+- Remove unnecessary `Buffer` check
+
+## [3.1.0] - 2016-12-07
+
+- Merge pull request #7 from laggingreflex/err
+- add support for `error` and tests
+- run update
+
+## [3.0.4] - 2016-07-29
+
+- move tests
+- run update
+
+## [3.0.3] - 2016-05-03
+
+- fix prepublish script
+- remove unused dep
+
+## [3.0.0] - 2015-11-17
+
+- add typed array support
+- Merge pull request #5 from miguelmota/typed-arrays
+- adds new tests
+
+## [2.0.1] - 2015-08-21
+
+- use `is-buffer` module
+
+## [2.0.0] - 2015-05-31
+
+- Create fallback for `Array.isArray` if used as a browser package
+- Merge pull request #2 from dtothefp/patch-1
+- Merge pull request #3 from pdehaan/patch-1
+- Merge branch 'master' of https://github.com/chorks/kind-of into chorks-master
+- optimizations, mostly date and regex
+
+## [1.1.0] - 2015-02-09
+
+- adds `buffer` support
+- adds tests for `buffer`
+
+## [1.0.0] - 2015-01-19
+
+- update benchmarks
+- optimizations based on benchmarks
+
+## [0.1.2] - 2014-10-26
+
+- return `typeof` value if it's not an object. very slight speed improvement
+- use `.slice`
+- adds benchmarks
+
+## [0.1.0] - 2014-9-26
+
+- first commit
+
+[6.0.0]: https://github.com/jonschlinkert/kind-of/compare/5.1.0...6.0.0
+[5.1.0]: https://github.com/jonschlinkert/kind-of/compare/5.0.2...5.1.0
+[5.0.2]: https://github.com/jonschlinkert/kind-of/compare/5.0.1...5.0.2
+[5.0.1]: https://github.com/jonschlinkert/kind-of/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/jonschlinkert/kind-of/compare/4.0.0...5.0.0
+[4.0.0]: https://github.com/jonschlinkert/kind-of/compare/3.2.2...4.0.0
+[3.2.2]: https://github.com/jonschlinkert/kind-of/compare/3.2.1...3.2.2
+[3.2.1]: https://github.com/jonschlinkert/kind-of/compare/3.2.0...3.2.1
+[3.2.0]: https://github.com/jonschlinkert/kind-of/compare/3.1.0...3.2.0
+[3.1.0]: https://github.com/jonschlinkert/kind-of/compare/3.0.4...3.1.0
+[3.0.4]: https://github.com/jonschlinkert/kind-of/compare/3.0.3...3.0.4
+[3.0.3]: https://github.com/jonschlinkert/kind-of/compare/3.0.0...3.0.3
+[3.0.0]: https://github.com/jonschlinkert/kind-of/compare/2.0.1...3.0.0
+[2.0.1]: https://github.com/jonschlinkert/kind-of/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/jonschlinkert/kind-of/compare/1.1.0...2.0.0
+[1.1.0]: https://github.com/jonschlinkert/kind-of/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...1.0.0
+[0.1.2]: https://github.com/jonschlinkert/kind-of/compare/0.1.0...0.1.2
+[0.1.0]: https://github.com/jonschlinkert/kind-of/commit/2fae09b0b19b1aadb558e9be39f0c3ef6034eb87
+
+[Unreleased]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...HEAD
+[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog
+
diff --git a/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/README.md b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/README.md
new file mode 100644
index 00000000..4b0d4a81
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/README.md
@@ -0,0 +1,365 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, es6, and browser ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(new Error('error'));
+//=> 'error'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'generatorfunction'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+
+```bash
+# arguments (32 bytes)
+  kind-of x 17,024,098 ops/sec ±1.90% (86 runs sampled)
+  lib-type-of x 11,926,235 ops/sec ±1.34% (83 runs sampled)
+  lib-typeof x 9,245,257 ops/sec ±1.22% (87 runs sampled)
+
+  fastest is kind-of (by 161% avg)
+
+# array (22 bytes)
+  kind-of x 17,196,492 ops/sec ±1.07% (88 runs sampled)
+  lib-type-of x 8,838,283 ops/sec ±1.02% (87 runs sampled)
+  lib-typeof x 8,677,848 ops/sec ±0.87% (87 runs sampled)
+
+  fastest is kind-of (by 196% avg)
+
+# boolean (24 bytes)
+  kind-of x 16,841,600 ops/sec ±1.10% (86 runs sampled)
+  lib-type-of x 8,096,787 ops/sec ±0.95% (87 runs sampled)
+  lib-typeof x 8,423,345 ops/sec ±1.15% (86 runs sampled)
+
+  fastest is kind-of (by 204% avg)
+
+# buffer (38 bytes)
+  kind-of x 14,848,060 ops/sec ±1.05% (86 runs sampled)
+  lib-type-of x 3,671,577 ops/sec ±1.49% (87 runs sampled)
+  lib-typeof x 8,360,236 ops/sec ±1.24% (86 runs sampled)
+
+  fastest is kind-of (by 247% avg)
+
+# date (30 bytes)
+  kind-of x 16,067,761 ops/sec ±1.58% (86 runs sampled)
+  lib-type-of x 8,954,436 ops/sec ±1.40% (87 runs sampled)
+  lib-typeof x 8,488,307 ops/sec ±1.51% (84 runs sampled)
+
+  fastest is kind-of (by 184% avg)
+
+# error (36 bytes)
+  kind-of x 9,634,090 ops/sec ±1.12% (89 runs sampled)
+  lib-type-of x 7,735,624 ops/sec ±1.32% (86 runs sampled)
+  lib-typeof x 7,442,160 ops/sec ±1.11% (90 runs sampled)
+
+  fastest is kind-of (by 127% avg)
+
+# function (34 bytes)
+  kind-of x 10,031,494 ops/sec ±1.27% (86 runs sampled)
+  lib-type-of x 9,502,757 ops/sec ±1.17% (89 runs sampled)
+  lib-typeof x 8,278,985 ops/sec ±1.08% (88 runs sampled)
+
+  fastest is kind-of (by 113% avg)
+
+# null (24 bytes)
+  kind-of x 18,159,808 ops/sec ±1.92% (86 runs sampled)
+  lib-type-of x 12,927,635 ops/sec ±1.01% (88 runs sampled)
+  lib-typeof x 7,958,234 ops/sec ±1.21% (89 runs sampled)
+
+  fastest is kind-of (by 174% avg)
+
+# number (22 bytes)
+  kind-of x 17,846,779 ops/sec ±0.91% (85 runs sampled)
+  lib-type-of x 3,316,636 ops/sec ±1.19% (86 runs sampled)
+  lib-typeof x 2,329,477 ops/sec ±2.21% (85 runs sampled)
+
+  fastest is kind-of (by 632% avg)
+
+# object-plain (47 bytes)
+  kind-of x 7,085,155 ops/sec ±1.05% (88 runs sampled)
+  lib-type-of x 8,870,930 ops/sec ±1.06% (83 runs sampled)
+  lib-typeof x 8,716,024 ops/sec ±1.05% (87 runs sampled)
+
+  fastest is lib-type-of (by 112% avg)
+
+# regex (25 bytes)
+  kind-of x 14,196,052 ops/sec ±1.65% (84 runs sampled)
+  lib-type-of x 9,554,164 ops/sec ±1.25% (88 runs sampled)
+  lib-typeof x 8,359,691 ops/sec ±1.07% (87 runs sampled)
+
+  fastest is kind-of (by 158% avg)
+
+# string (33 bytes)
+  kind-of x 16,131,428 ops/sec ±1.41% (85 runs sampled)
+  lib-type-of x 7,273,172 ops/sec ±1.05% (87 runs sampled)
+  lib-typeof x 7,382,635 ops/sec ±1.17% (85 runs sampled)
+
+  fastest is kind-of (by 220% avg)
+
+# symbol (34 bytes)
+  kind-of x 17,011,537 ops/sec ±1.24% (86 runs sampled)
+  lib-type-of x 3,492,454 ops/sec ±1.23% (89 runs sampled)
+  lib-typeof x 7,471,235 ops/sec ±2.48% (87 runs sampled)
+
+  fastest is kind-of (by 310% avg)
+
+# template-strings (36 bytes)
+  kind-of x 15,434,250 ops/sec ±1.46% (83 runs sampled)
+  lib-type-of x 7,157,907 ops/sec ±0.97% (87 runs sampled)
+  lib-typeof x 7,517,986 ops/sec ±0.92% (86 runs sampled)
+
+  fastest is kind-of (by 210% avg)
+
+# undefined (29 bytes)
+  kind-of x 19,167,115 ops/sec ±1.71% (87 runs sampled)
+  lib-type-of x 15,477,740 ops/sec ±1.63% (85 runs sampled)
+  lib-typeof x 19,075,495 ops/sec ±1.17% (83 runs sampled)
+
+  fastest is lib-typeof,kind-of
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of seems to be more consistently "correct" than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly identifies instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 98 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike-old](https://github.com/charlike-old) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on December 01, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/index.js b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/index.js
new file mode 100644
index 00000000..aa2bb394
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/index.js
@@ -0,0 +1,129 @@
+var toString = Object.prototype.toString;
+
+module.exports = function kindOf(val) {
+  if (val === void 0) return 'undefined';
+  if (val === null) return 'null';
+
+  var type = typeof val;
+  if (type === 'boolean') return 'boolean';
+  if (type === 'string') return 'string';
+  if (type === 'number') return 'number';
+  if (type === 'symbol') return 'symbol';
+  if (type === 'function') {
+    return isGeneratorFn(val) ? 'generatorfunction' : 'function';
+  }
+
+  if (isArray(val)) return 'array';
+  if (isBuffer(val)) return 'buffer';
+  if (isArguments(val)) return 'arguments';
+  if (isDate(val)) return 'date';
+  if (isError(val)) return 'error';
+  if (isRegexp(val)) return 'regexp';
+
+  switch (ctorName(val)) {
+    case 'Symbol': return 'symbol';
+    case 'Promise': return 'promise';
+
+    // Set, Map, WeakSet, WeakMap
+    case 'WeakMap': return 'weakmap';
+    case 'WeakSet': return 'weakset';
+    case 'Map': return 'map';
+    case 'Set': return 'set';
+
+    // 8-bit typed arrays
+    case 'Int8Array': return 'int8array';
+    case 'Uint8Array': return 'uint8array';
+    case 'Uint8ClampedArray': return 'uint8clampedarray';
+
+    // 16-bit typed arrays
+    case 'Int16Array': return 'int16array';
+    case 'Uint16Array': return 'uint16array';
+
+    // 32-bit typed arrays
+    case 'Int32Array': return 'int32array';
+    case 'Uint32Array': return 'uint32array';
+    case 'Float32Array': return 'float32array';
+    case 'Float64Array': return 'float64array';
+  }
+
+  if (isGeneratorObj(val)) {
+    return 'generator';
+  }
+
+  // Non-plain objects
+  type = toString.call(val);
+  switch (type) {
+    case '[object Object]': return 'object';
+    // iterators
+    case '[object Map Iterator]': return 'mapiterator';
+    case '[object Set Iterator]': return 'setiterator';
+    case '[object String Iterator]': return 'stringiterator';
+    case '[object Array Iterator]': return 'arrayiterator';
+  }
+
+  // other
+  return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
+};
+
+function ctorName(val) {
+  return val.constructor ? val.constructor.name : null;
+}
+
+function isArray(val) {
+  if (Array.isArray) return Array.isArray(val);
+  return val instanceof Array;
+}
+
+function isError(val) {
+  return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
+}
+
+function isDate(val) {
+  if (val instanceof Date) return true;
+  return typeof val.toDateString === 'function'
+    && typeof val.getDate === 'function'
+    && typeof val.setDate === 'function';
+}
+
+function isRegexp(val) {
+  if (val instanceof RegExp) return true;
+  return typeof val.flags === 'string'
+    && typeof val.ignoreCase === 'boolean'
+    && typeof val.multiline === 'boolean'
+    && typeof val.global === 'boolean';
+}
+
+function isGeneratorFn(name, val) {
+  return ctorName(name) === 'GeneratorFunction';
+}
+
+function isGeneratorObj(val) {
+  return typeof val.throw === 'function'
+    && typeof val.return === 'function'
+    && typeof val.next === 'function';
+}
+
+function isArguments(val) {
+  try {
+    if (typeof val.length === 'number' && typeof val.callee === 'function') {
+      return true;
+    }
+  } catch (err) {
+    if (err.message.indexOf('callee') !== -1) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  if (val.constructor && typeof val.constructor.isBuffer === 'function') {
+    return val.constructor.isBuffer(val);
+  }
+  return false;
+}
diff --git a/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/package.json b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/package.json
new file mode 100644
index 00000000..13a5fc93
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/node_modules/kind-of/package.json
@@ -0,0 +1,176 @@
+{
+  "_args": [
+    [
+      "kind-of@^6.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "kind-of@>=6.0.2 <7.0.0",
+  "_id": "kind-of@6.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-descriptor/kind-of",
+  "_nodeVersion": "9.1.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-6.0.2.tgz_1512153086430_0.774781379615888"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^6.0.2",
+    "rawSpec": "^6.0.2",
+    "scope": null,
+    "spec": ">=6.0.2 <7.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+  "_shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^6.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "benchmarked": "^2.0.0",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^4.0.1",
+    "write": "^1.0.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+    "shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "1491da72e8d276479f5f6198a9e79c1379c5d0c7",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "6.0.2"
+}
diff --git a/input_devices/mag/node_modules/is-descriptor/package.json b/input_devices/mag/node_modules/is-descriptor/package.json
new file mode 100644
index 00000000..336910cb
--- /dev/null
+++ b/input_devices/mag/node_modules/is-descriptor/package.json
@@ -0,0 +1,143 @@
+{
+  "_args": [
+    [
+      "is-descriptor@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/define-property"
+    ]
+  ],
+  "_from": "is-descriptor@>=1.0.0 <2.0.0",
+  "_id": "is-descriptor@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-descriptor",
+  "_nodeVersion": "9.1.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-descriptor-1.0.2.tgz_1514502694043_0.9101065774448216"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-descriptor",
+    "raw": "is-descriptor@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/define-property",
+    "/prompt-choices/define-property"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+  "_shasum": "3b159746a66604b04f8c81524ba365c5f14d86ec",
+  "_shrinkwrap": null,
+  "_spec": "is-descriptor@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/define-property",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-descriptor/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "url": "https://github.com/wtgtybhertgeghgtwtg"
+    }
+  ],
+  "dependencies": {
+    "is-accessor-descriptor": "^1.0.0",
+    "is-data-descriptor": "^1.0.0",
+    "kind-of": "^6.0.2"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+    "shasum": "3b159746a66604b04f8c81524ba365c5f14d86ec",
+    "tarball": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "324635c990dc7f1e6d169deecd19769dea72114c",
+  "homepage": "https://github.com/jonschlinkert/is-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/is-extendable/LICENSE b/input_devices/mag/node_modules/is-extendable/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/is-extendable/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-extendable/README.md b/input_devices/mag/node_modules/is-extendable/README.md
new file mode 100644
index 00000000..e4cfaebc
--- /dev/null
+++ b/input_devices/mag/node_modules/is-extendable/README.md
@@ -0,0 +1,72 @@
+# is-extendable [![NPM version](https://badge.fury.io/js/is-extendable.svg)](http://badge.fury.io/js/is-extendable)
+
+> Returns true if a value is any of the object types: array, regexp, plain object, function or date. This is useful for determining if a value can be extended, e.g. "can the value have keys?"
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i is-extendable --save
+```
+
+## Usage
+
+```js
+var isExtendable = require('is-extendable');
+```
+
+Returns true if the value is any of the following:
+
+* `array`
+* `regexp`
+* `plain object`
+* `function`
+* `date`
+* `error`
+
+## Notes
+
+All objects in JavaScript can have keys, but it's a pain to check for this, since we ether need to verify that the value is not `null` or `undefined` and:
+
+* the value is not a primitive, or
+* that the object is an `object`, `function`
+
+Also note that an `extendable` object is not the same as an [extensible object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible), which is one that (in es6) is not sealed, frozen, or marked as non-extensible using `preventExtensions`.
+
+## Related projects
+
+* [assign-deep](https://github.com/jonschlinkert/assign-deep): Deeply assign the enumerable properties of source objects to a destination object.
+* [extend-shallow](https://github.com/jonschlinkert/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util.
+* [isobject](https://github.com/jonschlinkert/isobject): Returns true if the value is an object and not an array or null.
+* [is-plain-object](https://github.com/jonschlinkert/is-plain-object): Returns true if an object was created by the `Object` constructor.
+* [is-equal-shallow](https://github.com/jonschlinkert/is-equal-shallow): Does a shallow comparison of two objects, returning false if the keys or values differ.
+* [kind-of](https://github.com/jonschlinkert/kind-of): Get the native type of a value.
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/is-extendable/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on July 04, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-extendable/index.js b/input_devices/mag/node_modules/is-extendable/index.js
new file mode 100644
index 00000000..4ee71a44
--- /dev/null
+++ b/input_devices/mag/node_modules/is-extendable/index.js
@@ -0,0 +1,13 @@
+/*!
+ * is-extendable <https://github.com/jonschlinkert/is-extendable>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+module.exports = function isExtendable(val) {
+  return typeof val !== 'undefined' && val !== null
+    && (typeof val === 'object' || typeof val === 'function');
+};
diff --git a/input_devices/mag/node_modules/is-extendable/package.json b/input_devices/mag/node_modules/is-extendable/package.json
new file mode 100644
index 00000000..663b1ae6
--- /dev/null
+++ b/input_devices/mag/node_modules/is-extendable/package.json
@@ -0,0 +1,108 @@
+{
+  "_args": [
+    [
+      "is-extendable@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/shallow-clone"
+    ]
+  ],
+  "_from": "is-extendable@>=0.1.1 <0.2.0",
+  "_id": "is-extendable@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-extendable",
+  "_nodeVersion": "0.12.4",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-extendable",
+    "raw": "is-extendable@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/extend-shallow",
+    "/mixin-object",
+    "/shallow-clone"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+  "_shasum": "62b110e289a471418e3ec36a617d472e301dfc89",
+  "_shrinkwrap": null,
+  "_spec": "is-extendable@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/shallow-clone",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-extendable/issues"
+  },
+  "dependencies": {},
+  "description": "Returns true if a value is any of the object types: array, regexp, plain object, function or date. This is useful for determining if a value can be extended, e.g. \"can the value have keys?\"",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "62b110e289a471418e3ec36a617d472e301dfc89",
+    "tarball": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "c36a0732e6a76931c6f66c5931d1f3e54fa44380",
+  "homepage": "https://github.com/jonschlinkert/is-extendable",
+  "keywords": [
+    "array",
+    "assign",
+    "check",
+    "date",
+    "extend",
+    "extensible",
+    "function",
+    "is",
+    "object",
+    "regex",
+    "test"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-extendable",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-extendable.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verbiage": {
+    "related": {
+      "list": [
+        "assign-deep",
+        "extend-shallow",
+        "is-equal-shallow",
+        "is-extendable",
+        "is-plain-object",
+        "isobject",
+        "kind-of"
+      ]
+    }
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/is-fullwidth-code-point/index.js b/input_devices/mag/node_modules/is-fullwidth-code-point/index.js
new file mode 100644
index 00000000..a7d3e385
--- /dev/null
+++ b/input_devices/mag/node_modules/is-fullwidth-code-point/index.js
@@ -0,0 +1,46 @@
+'use strict';
+var numberIsNan = require('number-is-nan');
+
+module.exports = function (x) {
+	if (numberIsNan(x)) {
+		return false;
+	}
+
+	// https://github.com/nodejs/io.js/blob/cff7300a578be1b10001f2d967aaedc88aee6402/lib/readline.js#L1369
+
+	// code points are derived from:
+	// http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt
+	if (x >= 0x1100 && (
+		x <= 0x115f ||  // Hangul Jamo
+		0x2329 === x || // LEFT-POINTING ANGLE BRACKET
+		0x232a === x || // RIGHT-POINTING ANGLE BRACKET
+		// CJK Radicals Supplement .. Enclosed CJK Letters and Months
+		(0x2e80 <= x && x <= 0x3247 && x !== 0x303f) ||
+		// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
+		0x3250 <= x && x <= 0x4dbf ||
+		// CJK Unified Ideographs .. Yi Radicals
+		0x4e00 <= x && x <= 0xa4c6 ||
+		// Hangul Jamo Extended-A
+		0xa960 <= x && x <= 0xa97c ||
+		// Hangul Syllables
+		0xac00 <= x && x <= 0xd7a3 ||
+		// CJK Compatibility Ideographs
+		0xf900 <= x && x <= 0xfaff ||
+		// Vertical Forms
+		0xfe10 <= x && x <= 0xfe19 ||
+		// CJK Compatibility Forms .. Small Form Variants
+		0xfe30 <= x && x <= 0xfe6b ||
+		// Halfwidth and Fullwidth Forms
+		0xff01 <= x && x <= 0xff60 ||
+		0xffe0 <= x && x <= 0xffe6 ||
+		// Kana Supplement
+		0x1b000 <= x && x <= 0x1b001 ||
+		// Enclosed Ideographic Supplement
+		0x1f200 <= x && x <= 0x1f251 ||
+		// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
+		0x20000 <= x && x <= 0x3fffd)) {
+		return true;
+	}
+
+	return false;
+}
diff --git a/input_devices/mag/node_modules/is-fullwidth-code-point/license b/input_devices/mag/node_modules/is-fullwidth-code-point/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/is-fullwidth-code-point/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/is-fullwidth-code-point/package.json b/input_devices/mag/node_modules/is-fullwidth-code-point/package.json
new file mode 100644
index 00000000..97270a63
--- /dev/null
+++ b/input_devices/mag/node_modules/is-fullwidth-code-point/package.json
@@ -0,0 +1,100 @@
+{
+  "_args": [
+    [
+      "is-fullwidth-code-point@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/string-width"
+    ]
+  ],
+  "_from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+  "_id": "is-fullwidth-code-point@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-fullwidth-code-point",
+  "_nodeVersion": "0.12.5",
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.11.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-fullwidth-code-point",
+    "raw": "is-fullwidth-code-point@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/string-width"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+  "_shasum": "ef9e31386f031a7f0d643af82fde50c457ef00cb",
+  "_shrinkwrap": null,
+  "_spec": "is-fullwidth-code-point@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/string-width",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/is-fullwidth-code-point/issues"
+  },
+  "dependencies": {
+    "number-is-nan": "^1.0.0"
+  },
+  "description": "Check if the character represented by a given Unicode code point is fullwidth",
+  "devDependencies": {
+    "ava": "0.0.4",
+    "code-point-at": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "ef9e31386f031a7f0d643af82fde50c457ef00cb",
+    "tarball": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "f2152d357f41f82785436d428e4f8ede143b7548",
+  "homepage": "https://github.com/sindresorhus/is-fullwidth-code-point",
+  "keywords": [
+    "char",
+    "character",
+    "check",
+    "code",
+    "codepoint",
+    "detect",
+    "full",
+    "full-width",
+    "fullwidth",
+    "is",
+    "point",
+    "str",
+    "string",
+    "unicode",
+    "width"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "is-fullwidth-code-point",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/is-fullwidth-code-point.git"
+  },
+  "scripts": {
+    "test": "node test.js"
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/is-fullwidth-code-point/readme.md b/input_devices/mag/node_modules/is-fullwidth-code-point/readme.md
new file mode 100644
index 00000000..4936464b
--- /dev/null
+++ b/input_devices/mag/node_modules/is-fullwidth-code-point/readme.md
@@ -0,0 +1,39 @@
+# is-fullwidth-code-point [![Build Status](https://travis-ci.org/sindresorhus/is-fullwidth-code-point.svg?branch=master)](https://travis-ci.org/sindresorhus/is-fullwidth-code-point)
+
+> Check if the character represented by a given [Unicode code point](https://en.wikipedia.org/wiki/Code_point) is [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms)
+
+
+## Install
+
+```
+$ npm install --save is-fullwidth-code-point
+```
+
+
+## Usage
+
+```js
+var isFullwidthCodePoint = require('is-fullwidth-code-point');
+
+isFullwidthCodePoint('谢'.codePointAt());
+//=> true
+
+isFullwidthCodePoint('a'.codePointAt());
+//=> false
+```
+
+
+## API
+
+### isFullwidthCodePoint(input)
+
+#### input
+
+Type: `number`
+
+[Code point](https://en.wikipedia.org/wiki/Code_point) of a character.
+
+
+## License
+
+MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/is-number/LICENSE b/input_devices/mag/node_modules/is-number/LICENSE
new file mode 100644
index 00000000..d32ab442
--- /dev/null
+++ b/input_devices/mag/node_modules/is-number/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2018, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-number/README.md b/input_devices/mag/node_modules/is-number/README.md
new file mode 100644
index 00000000..9570020a
--- /dev/null
+++ b/input_devices/mag/node_modules/is-number/README.md
@@ -0,0 +1,152 @@
+# is-number [![NPM version](https://img.shields.io/npm/v/is-number.svg?style=flat)](https://www.npmjs.com/package/is-number) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![NPM total downloads](https://img.shields.io/npm/dt/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-number.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-number)
+
+> Returns true if the value is a number. comprehensive tests.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-number
+```
+
+## Why is this needed?
+
+This library provides a fast, simple way of checking whether a value is a number, whether defined as a string or number by the user.
+
+It's easy to check for a number in JavaScript, all we need to do is `typeof value === 'number'`. But sometimes that's not enough. For example, `typeof NaN` returns `number`, and there are many use cases where it's possible or necessary for a numerical value to be defined as a string, like in parsers or regex matches where it's not possible for the value to be defined as a number.
+
+## Usage
+
+To understand some of the rationale behind the decisions made in this library (and to learn about some oddities of number evaluation in JavaScript), [see this gist](https://gist.github.com/jonschlinkert/e30c70c713da325d0e81).
+
+```js
+const isNumber = require('is-number');
+```
+
+### true
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber(5e3);               // true
+isNumber(0xff);              // true
+isNumber(-1.1);              // true
+isNumber(0);                 // true
+isNumber(1);                 // true
+isNumber(1.1);               // true
+isNumber(10);                // true
+isNumber(10.10);             // true
+isNumber(100);               // true
+isNumber('-1.1');            // true
+isNumber('0');               // true
+isNumber('012');             // true
+isNumber('0xff');            // true
+isNumber('1');               // true
+isNumber('1.1');             // true
+isNumber('10');              // true
+isNumber('10.10');           // true
+isNumber('100');             // true
+isNumber('5e3');             // true
+isNumber(parseInt('012'));   // true
+isNumber(parseFloat('012')); // true
+```
+
+### False
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber('foo');             // false
+isNumber([1]);               // false
+isNumber([]);                // false
+isNumber(function () {});    // false
+isNumber(Infinity);          // false
+isNumber(NaN);               // false
+isNumber(new Buffer('abc')); // false
+isNumber(null);              // false
+isNumber(undefined);         // false
+isNumber({abc: 'abc'});      // false
+```
+
+## Release history
+
+### 6.0.0
+
+* optimizations, thanks to @benaadams.
+
+### 5.0.0
+
+**Breaking changes**
+
+* removed support for `instanceof Number` and `instanceof String`
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 47 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 5 | [charlike-old](https://github.com/charlike-old) |
+| 1 | [benaadams](https://github.com/benaadams) |
+| 1 | [realityking](https://github.com/realityking) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
+* [GitHub Profile](https://github.com/jonschlinkert)
+* [Twitter Profile](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on March 31, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-number/index.js b/input_devices/mag/node_modules/is-number/index.js
new file mode 100644
index 00000000..a1ea391e
--- /dev/null
+++ b/input_devices/mag/node_modules/is-number/index.js
@@ -0,0 +1,31 @@
+/*!
+ * is-number <https://github.com/jonschlinkert/is-number>
+ *
+ * Copyright (c) 2014-2018, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+module.exports = function isNumber(num) {
+  var number = +num;
+
+  if ((number - number) !== 0) {
+    // Discard Infinity and NaN
+    return false;
+  }
+
+  if (number === num) {
+    return true;
+  }
+
+  if (typeof num === 'string') {
+    // String parsed, both a non-empty whitespace string and an empty string
+    // will have been coerced to 0. If 0 trim the string and see if its empty.
+    if (number === 0 && num.trim() === '') {
+      return false;
+    }
+    return true;
+  }
+  return false;
+};
diff --git a/input_devices/mag/node_modules/is-number/package.json b/input_devices/mag/node_modules/is-number/package.json
new file mode 100644
index 00000000..d72da993
--- /dev/null
+++ b/input_devices/mag/node_modules/is-number/package.json
@@ -0,0 +1,154 @@
+{
+  "_args": [
+    [
+      "is-number@^6.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "is-number@>=6.0.0 <7.0.0",
+  "_id": "is-number@6.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-number",
+  "_nodeVersion": "9.9.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-number_6.0.0_1522515759840_0.005598684369539919"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.8.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-number",
+    "raw": "is-number@^6.0.0",
+    "rawSpec": "^6.0.0",
+    "scope": null,
+    "spec": ">=6.0.0 <7.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz",
+  "_shasum": "e6d15ad31fc262887cccf217ae5f9316f81b1995",
+  "_shrinkwrap": null,
+  "_spec": "is-number@^6.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-number/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Olsten Larck",
+      "url": "https://i.am.charlike.online"
+    },
+    {
+      "name": "Rouven Weßling",
+      "url": "www.rouvenwessling.de"
+    }
+  ],
+  "dependencies": {},
+  "description": "Returns true if the value is a number. comprehensive tests.",
+  "devDependencies": {
+    "benchmarked": "^2.0.0",
+    "chalk": "^2.1.0",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==",
+    "shasum": "e6d15ad31fc262887cccf217ae5f9316f81b1995",
+    "tarball": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz",
+    "unpackedSize": 8960
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "b0953635829711e7dceec0eaa92bc56521a546eb",
+  "homepage": "https://github.com/jonschlinkert/is-number",
+  "keywords": [
+    "check",
+    "coerce",
+    "coercion",
+    "integer",
+    "is",
+    "is-nan",
+    "is-num",
+    "is-number",
+    "istype",
+    "kind",
+    "math",
+    "nan",
+    "num",
+    "number",
+    "numeric",
+    "test",
+    "type",
+    "typeof",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "realityking",
+      "email": "me@rouvenwessling.de"
+    }
+  ],
+  "name": "is-number",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-number.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-plain-object",
+        "is-primitive",
+        "isobject",
+        "kind-of"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "6.0.0"
+}
diff --git a/input_devices/mag/node_modules/is-plain-object/LICENSE b/input_devices/mag/node_modules/is-plain-object/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/is-plain-object/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-plain-object/README.md b/input_devices/mag/node_modules/is-plain-object/README.md
new file mode 100644
index 00000000..1f9d0c82
--- /dev/null
+++ b/input_devices/mag/node_modules/is-plain-object/README.md
@@ -0,0 +1,104 @@
+# is-plain-object [![NPM version](https://img.shields.io/npm/v/is-plain-object.svg?style=flat)](https://www.npmjs.com/package/is-plain-object) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-plain-object.svg?style=flat)](https://npmjs.org/package/is-plain-object) [![NPM total downloads](https://img.shields.io/npm/dt/is-plain-object.svg?style=flat)](https://npmjs.org/package/is-plain-object) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-plain-object.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-plain-object)
+
+> Returns true if an object was created by the `Object` constructor.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-plain-object
+```
+
+Use [isobject](https://github.com/jonschlinkert/isobject) if you only want to check if the value is an object and not an array or null.
+
+## Usage
+
+```js
+var isPlainObject = require('is-plain-object');
+```
+
+**true** when created by the `Object` constructor.
+
+```js
+isPlainObject(Object.create({}));
+//=> true
+isPlainObject(Object.create(Object.prototype));
+//=> true
+isPlainObject({foo: 'bar'});
+//=> true
+isPlainObject({});
+//=> true
+```
+
+**false** when not created by the `Object` constructor.
+
+```js
+isPlainObject(1);
+//=> false
+isPlainObject(['foo', 'bar']);
+//=> false
+isPlainObject([]);
+//=> false
+isPlainObject(new Foo);
+//=> false
+isPlainObject(null);
+//=> false
+isPlainObject(Object.create(null));
+//=> false
+```
+
+## About
+
+### Related projects
+
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 17 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 6 | [stevenvachon](https://github.com/stevenvachon) |
+| 3 | [onokumus](https://github.com/onokumus) |
+| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 11, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-plain-object/index.d.ts b/input_devices/mag/node_modules/is-plain-object/index.d.ts
new file mode 100644
index 00000000..74a44e97
--- /dev/null
+++ b/input_devices/mag/node_modules/is-plain-object/index.d.ts
@@ -0,0 +1,5 @@
+export = isPlainObject;
+
+declare function isPlainObject(o: any): boolean;
+
+declare namespace isPlainObject {}
diff --git a/input_devices/mag/node_modules/is-plain-object/index.js b/input_devices/mag/node_modules/is-plain-object/index.js
new file mode 100644
index 00000000..c3284849
--- /dev/null
+++ b/input_devices/mag/node_modules/is-plain-object/index.js
@@ -0,0 +1,37 @@
+/*!
+ * is-plain-object <https://github.com/jonschlinkert/is-plain-object>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var isObject = require('isobject');
+
+function isObjectObject(o) {
+  return isObject(o) === true
+    && Object.prototype.toString.call(o) === '[object Object]';
+}
+
+module.exports = function isPlainObject(o) {
+  var ctor,prot;
+
+  if (isObjectObject(o) === false) return false;
+
+  // If has modified constructor
+  ctor = o.constructor;
+  if (typeof ctor !== 'function') return false;
+
+  // If has modified prototype
+  prot = ctor.prototype;
+  if (isObjectObject(prot) === false) return false;
+
+  // If constructor does not have an Object-specific method
+  if (prot.hasOwnProperty('isPrototypeOf') === false) {
+    return false;
+  }
+
+  // Most likely a plain Object
+  return true;
+};
diff --git a/input_devices/mag/node_modules/is-plain-object/package.json b/input_devices/mag/node_modules/is-plain-object/package.json
new file mode 100644
index 00000000..427df769
--- /dev/null
+++ b/input_devices/mag/node_modules/is-plain-object/package.json
@@ -0,0 +1,154 @@
+{
+  "_args": [
+    [
+      "is-plain-object@^2.0.4",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep"
+    ]
+  ],
+  "_from": "is-plain-object@>=2.0.4 <3.0.0",
+  "_id": "is-plain-object@2.0.4",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-plain-object",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-plain-object-2.0.4.tgz_1499812869259_0.27965074591338634"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-plain-object",
+    "raw": "is-plain-object@^2.0.4",
+    "rawSpec": "^2.0.4",
+    "scope": null,
+    "spec": ">=2.0.4 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/clone-deep",
+    "/set-value"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+  "_shasum": "2c163b3fafb1b606d9d17928f05c2a1c38e07677",
+  "_shrinkwrap": null,
+  "_spec": "is-plain-object@^2.0.4",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-plain-object/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Osman Nuri Okumuş",
+      "url": "http://onokumus.com"
+    },
+    {
+      "name": "Steven Vachon",
+      "url": "https://svachon.com"
+    },
+    {
+      "url": "https://github.com/wtgtybhertgeghgtwtg"
+    }
+  ],
+  "dependencies": {
+    "isobject": "^3.0.1"
+  },
+  "description": "Returns true if an object was created by the `Object` constructor.",
+  "devDependencies": {
+    "browserify": "^14.4.0",
+    "chai": "^4.0.2",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.4.2",
+    "mocha-phantomjs": "^4.1.0",
+    "phantomjs": "^2.1.7",
+    "uglify-js": "^3.0.24"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+    "shasum": "2c163b3fafb1b606d9d17928f05c2a1c38e07677",
+    "tarball": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.d.ts",
+    "index.js"
+  ],
+  "gitHead": "81345df0d1700a5c285f379cbdca0e273388910d",
+  "homepage": "https://github.com/jonschlinkert/is-plain-object",
+  "keywords": [
+    "check",
+    "is",
+    "is-object",
+    "isobject",
+    "javascript",
+    "kind",
+    "kind-of",
+    "object",
+    "plain",
+    "type",
+    "typeof",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "stevenvachon",
+      "email": "contact@svachon.com"
+    }
+  ],
+  "name": "is-plain-object",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-plain-object.git"
+  },
+  "scripts": {
+    "browserify": "browserify index.js --standalone isPlainObject | uglifyjs --compress --mangle -o browser/is-plain-object.js",
+    "test": "npm run test_node && npm run browserify && npm run test_browser",
+    "test_browser": "mocha-phantomjs test/browser.html",
+    "test_node": "mocha"
+  },
+  "types": "index.d.ts",
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-number",
+        "isobject",
+        "kind-of"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.0.4"
+}
diff --git a/input_devices/mag/node_modules/is-windows/LICENSE b/input_devices/mag/node_modules/is-windows/LICENSE
new file mode 100644
index 00000000..f8de0630
--- /dev/null
+++ b/input_devices/mag/node_modules/is-windows/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2018, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/is-windows/README.md b/input_devices/mag/node_modules/is-windows/README.md
new file mode 100644
index 00000000..485bfdec
--- /dev/null
+++ b/input_devices/mag/node_modules/is-windows/README.md
@@ -0,0 +1,95 @@
+# is-windows [![NPM version](https://img.shields.io/npm/v/is-windows.svg?style=flat)](https://www.npmjs.com/package/is-windows) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-windows.svg?style=flat)](https://npmjs.org/package/is-windows) [![NPM total downloads](https://img.shields.io/npm/dt/is-windows.svg?style=flat)](https://npmjs.org/package/is-windows) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-windows.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-windows)
+
+> Returns true if the platform is windows. UMD module, works with node.js, commonjs, browser, AMD, electron, etc.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-windows
+```
+
+## Heads up!
+
+As of `v0.2.0` this module always returns a function.
+
+## Node.js usage
+
+```js
+var isWindows = require('is-windows');
+
+console.log(isWindows());
+//=> returns true if the platform is windows
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-absolute](https://www.npmjs.com/package/is-absolute): Returns true if a file path is absolute. Does not rely on the path module… [more](https://github.com/jonschlinkert/is-absolute) | [homepage](https://github.com/jonschlinkert/is-absolute "Returns true if a file path is absolute. Does not rely on the path module and can be used as a polyfill for node.js native `path.isAbolute`.")
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-relative](https://www.npmjs.com/package/is-relative): Returns `true` if the path appears to be relative. | [homepage](https://github.com/jonschlinkert/is-relative "Returns `true` if the path appears to be relative.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+* [window-size](https://www.npmjs.com/package/window-size): Reliable way to get the height and width of terminal/console, since it's not calculated or… [more](https://github.com/jonschlinkert/window-size) | [homepage](https://github.com/jonschlinkert/window-size "Reliable way to get the height and width of terminal/console, since it's not calculated or updated the same way on all platforms, environments and node.js versions.")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 11 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 4 | [doowb](https://github.com/doowb) |
+| 1 | [SimenB](https://github.com/SimenB) |
+| 1 | [gucong3000](https://github.com/gucong3000) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on February 14, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/is-windows/index.js b/input_devices/mag/node_modules/is-windows/index.js
new file mode 100644
index 00000000..55d43e09
--- /dev/null
+++ b/input_devices/mag/node_modules/is-windows/index.js
@@ -0,0 +1,27 @@
+/*!
+ * is-windows <https://github.com/jonschlinkert/is-windows>
+ *
+ * Copyright © 2015-2018, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+(function(factory) {
+  if (exports && typeof exports === 'object' && typeof module !== 'undefined') {
+    module.exports = factory();
+  } else if (typeof define === 'function' && define.amd) {
+    define([], factory);
+  } else if (typeof window !== 'undefined') {
+    window.isWindows = factory();
+  } else if (typeof global !== 'undefined') {
+    global.isWindows = factory();
+  } else if (typeof self !== 'undefined') {
+    self.isWindows = factory();
+  } else {
+    this.isWindows = factory();
+  }
+})(function() {
+  'use strict';
+  return function isWindows() {
+    return process && (process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE));
+  };
+});
diff --git a/input_devices/mag/node_modules/is-windows/package.json b/input_devices/mag/node_modules/is-windows/package.json
new file mode 100644
index 00000000..6411f2c7
--- /dev/null
+++ b/input_devices/mag/node_modules/is-windows/package.json
@@ -0,0 +1,147 @@
+{
+  "_args": [
+    [
+      "is-windows@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/radio-symbol"
+    ]
+  ],
+  "_from": "is-windows@>=1.0.1 <2.0.0",
+  "_id": "is-windows@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/is-windows",
+  "_nodeVersion": "9.5.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-windows_1.0.2_1518593802371_0.8807568142517928"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-windows",
+    "raw": "is-windows@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/radio-symbol",
+    "/readline-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+  "_shasum": "d1850eb9791ecd18e6182ce12a30f396634bb19d",
+  "_shrinkwrap": null,
+  "_spec": "is-windows@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/radio-symbol",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-windows/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Simen Bekkhus",
+      "url": "https://github.com/SimenB"
+    },
+    {
+      "name": "刘祺",
+      "url": "gucong.co.cc"
+    }
+  ],
+  "dependencies": {},
+  "description": "Returns true if the platform is windows. UMD module, works with node.js, commonjs, browser, AMD, electron, etc.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+    "shasum": "d1850eb9791ecd18e6182ce12a30f396634bb19d",
+    "tarball": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+    "unpackedSize": 7963
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "4dcfff4ed9e36ad761a1a24d3899c832382d7254",
+  "homepage": "https://github.com/jonschlinkert/is-windows",
+  "keywords": [
+    "check",
+    "cywin",
+    "is",
+    "is-windows",
+    "nix",
+    "operating system",
+    "os",
+    "platform",
+    "process",
+    "unix",
+    "win",
+    "win32",
+    "windows"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-windows",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-windows.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-absolute",
+        "is-glob",
+        "is-relative",
+        "isobject",
+        "window-size"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/.npmignore b/input_devices/mag/node_modules/isarray/.npmignore
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/.npmignore
rename to input_devices/mag/node_modules/isarray/.npmignore
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/.travis.yml b/input_devices/mag/node_modules/isarray/.travis.yml
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/.travis.yml
rename to input_devices/mag/node_modules/isarray/.travis.yml
diff --git a/input_devices/mag/node_modules/isarray/Makefile b/input_devices/mag/node_modules/isarray/Makefile
new file mode 100644
index 00000000..787d56e1
--- /dev/null
+++ b/input_devices/mag/node_modules/isarray/Makefile
@@ -0,0 +1,6 @@
+
+test:
+	@node_modules/.bin/tape test.js
+
+.PHONY: test
+
diff --git a/input_devices/mag/node_modules/isarray/README.md b/input_devices/mag/node_modules/isarray/README.md
new file mode 100644
index 00000000..16d2c59c
--- /dev/null
+++ b/input_devices/mag/node_modules/isarray/README.md
@@ -0,0 +1,60 @@
+
+# isarray
+
+`Array#isArray` for older browsers.
+
+[![build status](https://secure.travis-ci.org/juliangruber/isarray.svg)](http://travis-ci.org/juliangruber/isarray)
+[![downloads](https://img.shields.io/npm/dm/isarray.svg)](https://www.npmjs.org/package/isarray)
+
+[![browser support](https://ci.testling.com/juliangruber/isarray.png)
+](https://ci.testling.com/juliangruber/isarray)
+
+## Usage
+
+```js
+var isArray = require('isarray');
+
+console.log(isArray([])); // => true
+console.log(isArray({})); // => false
+```
+
+## Installation
+
+With [npm](http://npmjs.org) do
+
+```bash
+$ npm install isarray
+```
+
+Then bundle for the browser with
+[browserify](https://github.com/substack/browserify).
+
+With [component](http://component.io) do
+
+```bash
+$ component install juliangruber/isarray
+```
+
+## License
+
+(MIT)
+
+Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
+
+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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/component.json b/input_devices/mag/node_modules/isarray/component.json
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/component.json
rename to input_devices/mag/node_modules/isarray/component.json
diff --git a/input_devices/mag/node_modules/isarray/index.js b/input_devices/mag/node_modules/isarray/index.js
new file mode 100644
index 00000000..a57f6349
--- /dev/null
+++ b/input_devices/mag/node_modules/isarray/index.js
@@ -0,0 +1,5 @@
+var toString = {}.toString;
+
+module.exports = Array.isArray || function (arr) {
+  return toString.call(arr) == '[object Array]';
+};
diff --git a/input_devices/mag/node_modules/isarray/package.json b/input_devices/mag/node_modules/isarray/package.json
new file mode 100644
index 00000000..5a34e52a
--- /dev/null
+++ b/input_devices/mag/node_modules/isarray/package.json
@@ -0,0 +1,96 @@
+{
+  "_args": [
+    [
+      "isarray@~1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream"
+    ]
+  ],
+  "_from": "isarray@>=1.0.0 <1.1.0",
+  "_id": "isarray@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/isarray",
+  "_nodeVersion": "5.1.0",
+  "_npmUser": {
+    "email": "julian@juliangruber.com",
+    "name": "juliangruber"
+  },
+  "_npmVersion": "3.3.12",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "isarray",
+    "raw": "isarray@~1.0.0",
+    "rawSpec": "~1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <1.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readable-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+  "_shasum": "bb935d48582cba168c06834957a54a3e07124f11",
+  "_shrinkwrap": null,
+  "_spec": "isarray@~1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream",
+  "author": {
+    "email": "mail@juliangruber.com",
+    "name": "Julian Gruber",
+    "url": "http://juliangruber.com"
+  },
+  "bugs": {
+    "url": "https://github.com/juliangruber/isarray/issues"
+  },
+  "dependencies": {},
+  "description": "Array#isArray for older browsers",
+  "devDependencies": {
+    "tape": "~2.13.4"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "bb935d48582cba168c06834957a54a3e07124f11",
+    "tarball": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
+  },
+  "gitHead": "2a23a281f369e9ae06394c0fb4d2381355a6ba33",
+  "homepage": "https://github.com/juliangruber/isarray",
+  "keywords": [
+    "array",
+    "browser",
+    "isarray"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "juliangruber",
+      "email": "julian@juliangruber.com"
+    }
+  ],
+  "name": "isarray",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/juliangruber/isarray.git"
+  },
+  "scripts": {
+    "test": "tape test.js"
+  },
+  "testling": {
+    "browsers": [
+      "android-browser/4.2..latest",
+      "chrome/22..latest",
+      "chrome/canary",
+      "firefox/17..latest",
+      "firefox/nightly",
+      "ie/8..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest",
+      "opera/12..latest",
+      "opera/next",
+      "safari/5.1..latest"
+    ],
+    "files": "test.js"
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/isarray/test.js b/input_devices/mag/node_modules/isarray/test.js
new file mode 100644
index 00000000..e0c3444d
--- /dev/null
+++ b/input_devices/mag/node_modules/isarray/test.js
@@ -0,0 +1,20 @@
+var isArray = require('./');
+var test = require('tape');
+
+test('is array', function(t){
+  t.ok(isArray([]));
+  t.notOk(isArray({}));
+  t.notOk(isArray(null));
+  t.notOk(isArray(false));
+
+  var obj = {};
+  obj[0] = true;
+  t.notOk(isArray(obj));
+
+  var arr = [];
+  arr.foo = 'bar';
+  t.ok(isArray(arr));
+
+  t.end();
+});
+
diff --git a/input_devices/mag/node_modules/isobject/LICENSE b/input_devices/mag/node_modules/isobject/LICENSE
new file mode 100644
index 00000000..943e71d0
--- /dev/null
+++ b/input_devices/mag/node_modules/isobject/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/isobject/README.md b/input_devices/mag/node_modules/isobject/README.md
new file mode 100644
index 00000000..d01feaa4
--- /dev/null
+++ b/input_devices/mag/node_modules/isobject/README.md
@@ -0,0 +1,122 @@
+# isobject [![NPM version](https://img.shields.io/npm/v/isobject.svg?style=flat)](https://www.npmjs.com/package/isobject) [![NPM monthly downloads](https://img.shields.io/npm/dm/isobject.svg?style=flat)](https://npmjs.org/package/isobject)  [![NPM total downloads](https://img.shields.io/npm/dt/isobject.svg?style=flat)](https://npmjs.org/package/isobject) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/isobject.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/isobject)
+
+> Returns true if the value is an object and not an array or null.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save isobject
+```
+
+Install with [yarn](https://yarnpkg.com):
+
+```sh
+$ yarn add isobject
+```
+
+Use [is-plain-object](https://github.com/jonschlinkert/is-plain-object) if you want only objects that are created by the `Object` constructor.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install isobject
+```
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install isobject
+```
+
+## Usage
+
+```js
+var isObject = require('isobject');
+```
+
+**True**
+
+All of the following return `true`:
+
+```js
+isObject({});
+isObject(Object.create({}));
+isObject(Object.create(Object.prototype));
+isObject(Object.create(null));
+isObject({});
+isObject(new Foo);
+isObject(/foo/);
+```
+
+**False**
+
+All of the following return `false`:
+
+```js
+isObject();
+isObject(function () {});
+isObject(1);
+isObject([]);
+isObject(undefined);
+isObject(null);
+```
+
+## About
+
+### Related projects
+
+* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow "Extend an object with the properties of additional objects. node.js/javascript util.")
+* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+* [merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep "Recursively merge values in a javascript object.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** |  
+| --- | --- |  
+| 29 | [jonschlinkert](https://github.com/jonschlinkert) |  
+| 4  | [doowb](https://github.com/doowb) |  
+| 1  | [magnudae](https://github.com/magnudae) |  
+| 1  | [LeSuisse](https://github.com/LeSuisse) |  
+| 1  | [tmcw](https://github.com/tmcw) |  
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on June 30, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/isobject/index.d.ts b/input_devices/mag/node_modules/isobject/index.d.ts
new file mode 100644
index 00000000..55f81c27
--- /dev/null
+++ b/input_devices/mag/node_modules/isobject/index.d.ts
@@ -0,0 +1,5 @@
+export = isObject;
+
+declare function isObject(val: any): boolean;
+
+declare namespace isObject {}
diff --git a/input_devices/mag/node_modules/isobject/index.js b/input_devices/mag/node_modules/isobject/index.js
new file mode 100644
index 00000000..2d59958b
--- /dev/null
+++ b/input_devices/mag/node_modules/isobject/index.js
@@ -0,0 +1,12 @@
+/*!
+ * isobject <https://github.com/jonschlinkert/isobject>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+module.exports = function isObject(val) {
+  return val != null && typeof val === 'object' && Array.isArray(val) === false;
+};
diff --git a/input_devices/mag/node_modules/isobject/package.json b/input_devices/mag/node_modules/isobject/package.json
new file mode 100644
index 00000000..bcaa55aa
--- /dev/null
+++ b/input_devices/mag/node_modules/isobject/package.json
@@ -0,0 +1,154 @@
+{
+  "_args": [
+    [
+      "isobject@^3.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question"
+    ]
+  ],
+  "_from": "isobject@>=3.0.1 <4.0.0",
+  "_id": "isobject@3.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/isobject",
+  "_nodeVersion": "6.10.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/isobject-3.0.1.tgz_1498846769653_0.28330610087141395"
+  },
+  "_npmUser": {
+    "email": "brian.woodward@gmail.com",
+    "name": "doowb"
+  },
+  "_npmVersion": "4.6.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "isobject",
+    "raw": "isobject@^3.0.1",
+    "rawSpec": "^3.0.1",
+    "scope": null,
+    "spec": ">=3.0.1 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/is-plain-object",
+    "/object-visit",
+    "/prompt-choices/define-property",
+    "/prompt-question",
+    "/toggle-array"
+  ],
+  "_resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+  "_shasum": "4e431e92b11a9731636aa1f9c8d1ccbcfdab78df",
+  "_shrinkwrap": null,
+  "_spec": "isobject@^3.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/isobject/issues"
+  },
+  "contributors": [
+    {
+      "url": "https://github.com/LeSuisse"
+    },
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Magnús Dæhlen",
+      "url": "https://github.com/magnudae"
+    },
+    {
+      "name": "Tom MacWright",
+      "url": "https://macwright.org"
+    }
+  ],
+  "dependencies": {},
+  "description": "Returns true if the value is an object and not an array or null.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.9",
+    "mocha": "^2.4.5"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "4e431e92b11a9731636aa1f9c8d1ccbcfdab78df",
+    "tarball": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.d.ts",
+    "index.js"
+  ],
+  "gitHead": "7ad1fc405d19f144a21e2bfe947fa82801baa7aa",
+  "homepage": "https://github.com/jonschlinkert/isobject",
+  "keywords": [
+    "check",
+    "is",
+    "is-object",
+    "isobject",
+    "kind",
+    "kind-of",
+    "kindof",
+    "native",
+    "object",
+    "type",
+    "typeof",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "isobject",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/isobject.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "types": "index.d.ts",
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "extend-shallow",
+        "is-plain-object",
+        "kind-of",
+        "merge-deep"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.0.1"
+}
diff --git a/input_devices/mag/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..d734237b
--- /dev/null
+++ b/input_devices/mag/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/kind-of/README.md b/input_devices/mag/node_modules/kind-of/README.md
new file mode 100644
index 00000000..6a9df36d
--- /dev/null
+++ b/input_devices/mag/node_modules/kind-of/README.md
@@ -0,0 +1,261 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+## Install
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+
+## About
+
+### Related projects
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 59 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 16, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/kind-of/index.js b/input_devices/mag/node_modules/kind-of/index.js
new file mode 100644
index 00000000..b52c2917
--- /dev/null
+++ b/input_devices/mag/node_modules/kind-of/index.js
@@ -0,0 +1,116 @@
+var isBuffer = require('is-buffer');
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  // primitivies
+  if (typeof val === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (typeof val === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (typeof val === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (typeof val === 'function' || val instanceof Function) {
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  var type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
diff --git a/input_devices/mag/node_modules/kind-of/package.json b/input_devices/mag/node_modules/kind-of/package.json
new file mode 100644
index 00000000..2d3b2ffd
--- /dev/null
+++ b/input_devices/mag/node_modules/kind-of/package.json
@@ -0,0 +1,176 @@
+{
+  "_args": [
+    [
+      "kind-of@^3.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/to-object-path"
+    ]
+  ],
+  "_from": "kind-of@>=3.0.2 <4.0.0",
+  "_id": "kind-of@3.2.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/kind-of",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/kind-of-3.2.2.tgz_1494958899918_0.23780996026471257"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.5.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^3.0.2",
+    "rawSpec": "^3.0.2",
+    "scope": null,
+    "spec": ">=3.0.2 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/arr-swap/is-number",
+    "/object-copy",
+    "/object-copy/is-accessor-descriptor",
+    "/object-copy/is-data-descriptor",
+    "/readline-utils/is-number",
+    "/to-object-path",
+    "/window-size/is-number"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+  "_shasum": "31ea21a734bab9bbb0f32466d893aea51e4a3c64",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^3.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/to-object-path",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    }
+  ],
+  "dependencies": {
+    "is-buffer": "^1.1.5"
+  },
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.0.0",
+    "browserify": "^14.3.0",
+    "glob": "^7.1.1",
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.3.0",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "31ea21a734bab9bbb0f32466d893aea51e4a3c64",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "0ffe67cf12f5396047c1bacf04232b7deeb24063",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.2.2"
+}
diff --git a/input_devices/mag/node_modules/koalas/LICENSE b/input_devices/mag/node_modules/koalas/LICENSE
new file mode 100644
index 00000000..59898a10
--- /dev/null
+++ b/input_devices/mag/node_modules/koalas/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013, 2017, Brian Woodward
+
+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/input_devices/mag/node_modules/koalas/README.md b/input_devices/mag/node_modules/koalas/README.md
new file mode 100644
index 00000000..4f1f3f6a
--- /dev/null
+++ b/input_devices/mag/node_modules/koalas/README.md
@@ -0,0 +1,91 @@
+# koalas [![NPM version](https://img.shields.io/npm/v/koalas.svg?style=flat)](https://www.npmjs.com/package/koalas) [![NPM monthly downloads](https://img.shields.io/npm/dm/koalas.svg?style=flat)](https://npmjs.org/package/koalas)  [![NPM total downloads](https://img.shields.io/npm/dt/koalas.svg?style=flat)](https://npmjs.org/package/koalas) [![Linux Build Status](https://img.shields.io/travis/doowb/koalas.svg?style=flat&label=Travis)](https://travis-ci.org/doowb/koalas) [![Windows Build Status](https://img.shields.io/appveyor/ci/doowb/koalas.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/doowb/koalas)
+
+> Coalesce for JavaScript. Returns the first value that is not undefined or null.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save koalas
+```
+
+## Usage
+
+```js
+var koalas = require('koalas');
+```
+
+## API
+
+### [koalas](index.js#L27)
+
+Coalesce function to find the first valid value. A valid value is one that is not undefined, not null and not NaN (not a number). If no values are valid, then the last argument is returned.
+
+**Params**
+
+* `arguments` **{Mixed}**: Pass in any amount of arguments.
+* `returns` **{Mixed}**: First valid value.
+
+**Example**
+
+```js
+console.log(koalas(undefined, null, NaN, 'a', 'b'));
+//=> 'a'
+
+console.log(koalas(undefined, null, NaN, {a: 'b'}, 'b'));
+//=> {a: 'b'}
+
+console.log(koalas(undefined, null, NaN, ['a', 'b', 'c'], {a: 'b'}, 'b'));
+//=> ['a', 'b', 'c']
+
+console.log(koalas(undefined, NaN, null));
+//=> null
+```
+
+## About
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 39 | [doowb](https://github.com/doowb) |
+| 1 | [jonschlinkert](https://github.com/jonschlinkert) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Brian Woodward**
+
+* [github/doowb](https://github.com/doowb)
+* [twitter/doowb](https://twitter.com/doowb)
+
+### License
+
+Copyright © 2017, [Brian Woodward](https://github.com/doowb).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.3, on April 18, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/koalas/index.js b/input_devices/mag/node_modules/koalas/index.js
new file mode 100644
index 00000000..785d042d
--- /dev/null
+++ b/input_devices/mag/node_modules/koalas/index.js
@@ -0,0 +1,58 @@
+'use strict';
+
+/**
+ * Coalesce function to find the first valid value.
+ * A valid value is one that is not undefined, not null and not NaN (not a number).
+ * If no values are valid, then the last argument is returned.
+ *
+ * ```js
+ * console.log(koalas(undefined, null, NaN, 'a', 'b'));
+ * //=> 'a'
+ *
+ * console.log(koalas(undefined, null, NaN, {a: 'b'}, 'b'));
+ * //=> {a: 'b'}
+ *
+ * console.log(koalas(undefined, null, NaN, ['a', 'b', 'c'], {a: 'b'}, 'b'));
+ * //=> ['a', 'b', 'c']
+ *
+ * console.log(koalas(undefined, NaN, null));
+ * //=> null
+ * ```
+ * @name koalas
+ * @param {Mixed} `arguments` Pass in any amount of arguments.
+ * @return {Mixed} First valid value.
+ * @api public
+ */
+
+function koalas() {
+  var len = arguments.length;
+  var arg;
+  for (var i = 0; i < len; i++) {
+    arg = arguments[i];
+    if (hasValue(arg)) {
+      return arg;
+    }
+  }
+  return arg;
+}
+
+/**
+ * Check to see if a value actually has a valid value:
+ *  - not undefined
+ *  - not null
+ *  - not NaN (not a number)
+ *
+ * @param  {*} `val` value to check
+ * @return {Boolean} returns `true` if the `val` has a valid value
+ */
+
+function hasValue(val) {
+  // eslint-disable-next-line no-self-compare
+  return val != null && val === val;
+}
+
+/**
+ * Expose koalas
+ */
+
+module.exports = koalas;
diff --git a/input_devices/mag/node_modules/koalas/package.json b/input_devices/mag/node_modules/koalas/package.json
new file mode 100644
index 00000000..8a1d6783
--- /dev/null
+++ b/input_devices/mag/node_modules/koalas/package.json
@@ -0,0 +1,133 @@
+{
+  "_args": [
+    [
+      "koalas@^1.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "koalas@>=1.0.2 <2.0.0",
+  "_id": "koalas@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/koalas",
+  "_nodeVersion": "6.10.1",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/koalas-1.0.2.tgz_1492608526077_0.8102033603936434"
+  },
+  "_npmUser": {
+    "email": "brian.woodward@gmail.com",
+    "name": "doowb"
+  },
+  "_npmVersion": "3.10.10",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "koalas",
+    "raw": "koalas@^1.0.2",
+    "rawSpec": "^1.0.2",
+    "scope": null,
+    "spec": ">=1.0.2 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base",
+    "/prompt-choices",
+    "/prompt-question",
+    "/readline-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/koalas/-/koalas-1.0.2.tgz",
+  "_shasum": "318433f074235db78fae5661a02a8ca53ee295cd",
+  "_shrinkwrap": null,
+  "_spec": "koalas@^1.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "author": {
+    "name": "Brian Woodward",
+    "url": "https://github.com/doowb"
+  },
+  "bugs": {
+    "url": "https://github.com/doowb/koalas/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "email": "brian.woodward@gmail.com",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {},
+  "description": "Coalesce for JavaScript. Returns the first value that is not undefined or null.",
+  "devDependencies": {
+    "gulp": "github:gulpjs/gulp#4.0",
+    "gulp-eslint": "^3.0.1",
+    "gulp-format-md": "^0.1.11",
+    "gulp-istanbul": "^1.1.1",
+    "gulp-mocha": "^3.0.1",
+    "mocha": "^3.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "318433f074235db78fae5661a02a8ca53ee295cd",
+    "tarball": "https://registry.npmjs.org/koalas/-/koalas-1.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "d40db3625b8479160b85718e2bf5cbf34cbfb809",
+  "homepage": "https://github.com/doowb/koalas",
+  "keywords": [
+    "check",
+    "isnull",
+    "kind",
+    "koala",
+    "koalas",
+    "null",
+    "type",
+    "type-of",
+    "typeof",
+    "undefined",
+    "util",
+    "utility",
+    "utils",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "koalas",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/doowb/koalas.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/lazy-cache/LICENSE b/input_devices/mag/node_modules/lazy-cache/LICENSE
new file mode 100644
index 00000000..1e49edf8
--- /dev/null
+++ b/input_devices/mag/node_modules/lazy-cache/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2016, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/lazy-cache/README.md b/input_devices/mag/node_modules/lazy-cache/README.md
new file mode 100644
index 00000000..14463180
--- /dev/null
+++ b/input_devices/mag/node_modules/lazy-cache/README.md
@@ -0,0 +1,195 @@
+# lazy-cache [![NPM version](https://img.shields.io/npm/v/lazy-cache.svg?style=flat)](https://www.npmjs.com/package/lazy-cache) [![NPM monthly downloads](https://img.shields.io/npm/dm/lazy-cache.svg?style=flat)](https://npmjs.org/package/lazy-cache)  [![NPM total downloads](https://img.shields.io/npm/dt/lazy-cache.svg?style=flat)](https://npmjs.org/package/lazy-cache) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/lazy-cache.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/lazy-cache)
+
+> Cache requires to be lazy-loaded when needed.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save lazy-cache
+```
+
+## Heads up!
+
+It's suprising how many libraries are in the average dependency tree that don't belong there for one reason or another. Either because they were accidentally listed as `dependencies` instead of `devDepedencies`, or they are required in a file as variables, but the variable is never actually used (poor linting), and so on. Or because the maintainer made the decision to add the deps, even though they will never ([or can't ever](https://github.com/felixge/node-dateformat/issues/36)) be used by 99.9% of users.
+
+Worse, many libraries like chalk and [shelljs](https://github.com/eslint/eslint/issues/7316) actually execute code when `require()` is called!? (shelljs was modifying the `String.prototype`, and chalk loops over some objects to dynamically create methods). In other words, they do something like this:
+
+```js
+// in the main export of a library, if you do this it will
+// automatically modify the String.prototype _globally_, 
+// the moment node.js loads the dependency tree
+String.prototype.foo = function() {};
+
+// same if you do something like this
+// (dont' do this, ever. wrap this kind of code in a function
+// and allow implementors to decide when to call it)
+while (foo) {
+  // do stuff
+}
+```
+
+In any case, just having these libraries in your dependency tree somewhere means that their code will excecute the moment you run your application _even if the libraries are never called by your application or any other code anywhere in the tree_.
+
+**solution**
+
+lazy-cache doesn't use any "magic", it uses native, plain-vanilla, tried and true javascript getters to call node's `require()` system.
+
+**Faster, safer code**
+
+There main advantage to this, the main is that `require`s are loaded on demand, so only code that is actually used will ever be loaded. As a result, applications will load faster (sometimes much faster - we've seen load times drop from ~1 second to less than 50 milliseconds).
+
+Moreover, in some cases this also avoids inadvertently loading libraries that execute code or modifies globals, etc.
+
+**webpack users**
+
+If you use webpack and are experiencing issues with lazy-cache, this is a known bug caused by webpack, not lazy-cache. There is a solution though, you can use [unlazy-loader](https://github.com/doowb/unlazy-loader), a webpack loader that _fixes the webpack bug_.
+
+## Usage
+
+```js
+var utils = require('lazy-cache')(require);
+```
+
+**Use as a property on `lazy`**
+
+The module is also added as a property to the `lazy` function so it can be called without having to call a function first.
+
+```js
+var utils = require('lazy-cache')(require);
+
+// `npm install glob`
+utils('glob');
+
+// glob sync
+console.log(utils.glob.sync('*.js'));
+
+// glob async
+utils.glob('*.js', function (err, files) {
+  console.log(files);
+});
+```
+
+**Use as a function**
+
+```js
+var utils = require('lazy-cache')(require);
+var glob = utils('glob');
+
+// `glob` is a now a function that may be called when needed
+glob().sync('foo/*.js');
+```
+
+## Aliases
+
+An alias may be passed as the second argument if you don't want to use the automatically camel-cased variable name.
+
+**Example**
+
+```js
+var utils = require('lazy-cache')(require);
+
+// alias `ansi-yellow` as `yellow`
+utils('ansi-yellow', 'yellow');
+console.log(utils.yellow('foo'));
+```
+
+Dot notation may also be used in the alias to create an object hierarchy.
+
+**Example**
+
+```js
+var utils = require('lazy-cache')(require);
+utils('ansi-cyan', 'color.cyan');
+utils('ansi-yellow', 'color.yellow');
+utils('ansi-magenta', 'color.magenta');
+console.log(utils.color.cyan('foo'));
+console.log(utils.color.yellow('bar'));
+console.log(utils.color.magenta('baz'));
+```
+
+## Browserify usage
+
+**Example**
+
+```js
+var utils = require('lazy-cache')(require);
+// temporarily re-assign `require` to trick browserify
+var fn = require;
+require = utils;
+// list module dependencies (here, `require` is actually `lazy-cache`)
+require('glob');
+require = fn; // restore the native `require` function
+
+/**
+ * Now you can use glob with the `utils.glob` variable
+ */
+
+// sync
+console.log(utils.glob.sync('*.js'));
+
+// async
+utils.glob('*.js', function (err, files) {
+  console.log(files.join('\n'));
+});
+```
+
+## Kill switch
+
+To force lazy-cache to immediately invoke all dependencies, do:
+
+```js
+process.env.UNLAZY = true;
+```
+
+## About
+
+### Related projects
+
+[lint-deps](https://www.npmjs.com/package/lint-deps): CLI tool that tells you when dependencies are missing from package.json and offers you a… [more](https://github.com/jonschlinkert/lint-deps) | [homepage](https://github.com/jonschlinkert/lint-deps "CLI tool that tells you when dependencies are missing from package.json and offers you a choice to install them. Also tells you when dependencies are listed in package.json but are not being used anywhere in your project. Node.js command line tool and API")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor**<br/> | 
+| --- | --- |
+| 31 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 27 | [doowb](https://github.com/doowb) |
+
+### Building docs
+
+_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
+
+To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
+
+```sh
+$ npm install -g verb verb-generate-readme && verb
+```
+
+### Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm install -d && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT license](https://github.com/jonschlinkert/lazy-cache/blob/master/LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.2.0, on November 07, 2016._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/lazy-cache/index.js b/input_devices/mag/node_modules/lazy-cache/index.js
new file mode 100644
index 00000000..751fcbb5
--- /dev/null
+++ b/input_devices/mag/node_modules/lazy-cache/index.js
@@ -0,0 +1,73 @@
+'use strict';
+
+var set = require('set-getter');
+
+/**
+ * Cache results of the first function call to ensure only calling once.
+ *
+ * ```js
+ * var utils = require('lazy-cache')(require);
+ * // cache the call to `require('ansi-yellow')`
+ * utils('ansi-yellow', 'yellow');
+ * // use `ansi-yellow`
+ * console.log(utils.yellow('this is yellow'));
+ * ```
+ *
+ * @param  {Function} `fn` Function that will be called only once.
+ * @return {Function} Function that can be called to get the cached function
+ * @api public
+ */
+
+function lazyCache(requireFn) {
+  var cache = {};
+
+  return function proxy(name, alias) {
+    var key = alias;
+
+    // camel-case the module `name` if `alias` is not defined
+    if (typeof key !== 'string') {
+      key = camelcase(name);
+    }
+
+    // create a getter to lazily invoke the module the first time it's called
+    function getter() {
+      return cache[key] || (cache[key] = requireFn(name));
+    }
+
+    // trip the getter if `process.env.UNLAZY` is defined
+    if (unlazy(process.env)) {
+      getter();
+    }
+
+    set(proxy, key, getter);
+    return getter;
+  };
+}
+
+/**
+ * Return true if `process.env.LAZY` is true, or travis is running.
+ */
+
+function unlazy(env) {
+  return env.UNLAZY === 'true' || env.UNLAZY === true || env.TRAVIS;
+}
+
+/**
+ * Camelcase the the given module `name`.
+ */
+
+function camelcase(str) {
+  if (str.length === 1) {
+    return str.toLowerCase();
+  }
+  str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase();
+  return str.replace(/[\W_]+(\w|$)/g, function(_, ch) {
+    return ch.toUpperCase();
+  });
+}
+
+/**
+ * Expose `lazyCache`
+ */
+
+module.exports = lazyCache;
diff --git a/input_devices/mag/node_modules/lazy-cache/package.json b/input_devices/mag/node_modules/lazy-cache/package.json
new file mode 100644
index 00000000..82ff37f5
--- /dev/null
+++ b/input_devices/mag/node_modules/lazy-cache/package.json
@@ -0,0 +1,139 @@
+{
+  "_args": [
+    [
+      "lazy-cache@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors"
+    ]
+  ],
+  "_from": "lazy-cache@>=2.0.1 <3.0.0",
+  "_id": "lazy-cache@2.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/lazy-cache",
+  "_nodeVersion": "6.7.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/lazy-cache-2.0.2.tgz_1478577911105_0.547785654431209"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.10.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "lazy-cache",
+    "raw": "lazy-cache@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": null,
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/ansi-colors"
+  ],
+  "_resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz",
+  "_shasum": "b9190a4f913354694840859f8a8f7084d8822264",
+  "_shrinkwrap": null,
+  "_spec": "lazy-cache@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/ansi-colors",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/lazy-cache/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "email": "brian.woodward@gmail.com",
+      "url": "https://github.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "set-getter": "^0.1.0"
+  },
+  "description": "Cache requires to be lazy-loaded when needed.",
+  "devDependencies": {
+    "ansi-cyan": "^0.1.1",
+    "ansi-magenta": "^0.1.1",
+    "ansi-yellow": "^0.1.1",
+    "glob": "^7.0.3",
+    "gulp-format-md": "^0.1.8",
+    "mocha": "^2.4.5",
+    "object.omit": "^2.0.0",
+    "object.pick": "^1.1.2"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "b9190a4f913354694840859f8a8f7084d8822264",
+    "tarball": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ca0579a0687f9a7d915d9ecf53a93af7ad72762d",
+  "homepage": "https://github.com/jonschlinkert/lazy-cache",
+  "keywords": [
+    "cache",
+    "caching",
+    "dependencies",
+    "dependency",
+    "lazy",
+    "require",
+    "requires"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "lazy-cache",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/lazy-cache.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "lint-deps"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.0.2"
+}
diff --git a/input_devices/mag/node_modules/log-ok/LICENSE b/input_devices/mag/node_modules/log-ok/LICENSE
new file mode 100644
index 00000000..e28e6032
--- /dev/null
+++ b/input_devices/mag/node_modules/log-ok/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/log-ok/index.js b/input_devices/mag/node_modules/log-ok/index.js
new file mode 100644
index 00000000..452e15ab
--- /dev/null
+++ b/input_devices/mag/node_modules/log-ok/index.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var check = require('success-symbol');
+var green = require('ansi-green');
+
+module.exports = function() {
+  var args = [].slice.call(arguments);
+  var msg = args[0];
+  var ok = green(check);
+
+  if (typeof msg === 'string') {
+    var match = /^(\s+)(.*)/.exec(msg);
+    if (match) {
+      ok = match[1] + ok;
+      args[0] = match[2];
+    }
+  }
+
+  console.log.bind(console, ok).apply(console, args);
+};
diff --git a/input_devices/mag/node_modules/log-ok/package.json b/input_devices/mag/node_modules/log-ok/package.json
new file mode 100644
index 00000000..5c648a5e
--- /dev/null
+++ b/input_devices/mag/node_modules/log-ok/package.json
@@ -0,0 +1,115 @@
+{
+  "_args": [
+    [
+      "log-ok@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils"
+    ]
+  ],
+  "_from": "log-ok@>=0.1.1 <0.2.0",
+  "_id": "log-ok@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/log-ok",
+  "_nodeVersion": "6.2.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/log-ok-0.1.1.tgz_1466357697518_0.597567250020802"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.8.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "log-ok",
+    "raw": "log-ok@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/log-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/log-ok/-/log-ok-0.1.1.tgz",
+  "_shasum": "bea3dd36acd0b8a7240d78736b5b97c65444a334",
+  "_shrinkwrap": null,
+  "_spec": "log-ok@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/log-ok/issues"
+  },
+  "dependencies": {
+    "ansi-green": "^0.1.1",
+    "success-symbol": "^0.1.0"
+  },
+  "description": "just `console.log` prefixed with a green check",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.9",
+    "mocha": "^2.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "bea3dd36acd0b8a7240d78736b5b97c65444a334",
+    "tarball": "https://registry.npmjs.org/log-ok/-/log-ok-0.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "59edddc6de212f0a339d1903a0e941e46ca36fcc",
+  "homepage": "https://github.com/jonschlinkert/log-ok",
+  "keywords": [
+    "log",
+    "ok"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "log-ok",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/log-ok.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-readme-generator"
+    ],
+    "related": {
+      "list": [
+        "ansi-colors",
+        "log-utils"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/log-utils/LICENSE b/input_devices/mag/node_modules/log-utils/LICENSE
new file mode 100644
index 00000000..e28e6032
--- /dev/null
+++ b/input_devices/mag/node_modules/log-utils/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/log-utils/index.js b/input_devices/mag/node_modules/log-utils/index.js
new file mode 100644
index 00000000..c7187c5d
--- /dev/null
+++ b/input_devices/mag/node_modules/log-utils/index.js
@@ -0,0 +1,224 @@
+/*!
+ * log-utils <https://github.com/jonschlinkert/log-utils>
+ *
+ * Copyright (c) 2016, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var readline = require('readline');
+var log = require('ansi-colors');
+var fn = require;
+require = log;
+
+/**
+ * Utils
+ */
+
+require('error-symbol');
+require('info-symbol');
+require('success-symbol', 'check');
+require('warning-symbol');
+require('time-stamp');
+require = fn;
+
+/**
+ * Expose `colors` and `symbols`
+ */
+
+log.colors = require('ansi-colors');
+log.symbol = {};
+
+/**
+ * Error symbol.
+ *
+ * ```js
+ * console.log(log.symbol.error);
+ * //=> ✖
+ * ```
+ * @name .symbol.error
+ * @api public
+ */
+
+getter(log.symbol, 'error', function() {
+  return log.errorSymbol;
+});
+
+/**
+ * Info symbol.
+ *
+ * ```js
+ * console.log(log.symbol.info);
+ * //=> ℹ
+ * ```
+ * @name .symbol.info
+ * @api public
+ */
+
+getter(log.symbol, 'info', function() {
+  return log.infoSymbol;
+});
+
+/**
+ * Success symbol.
+ *
+ * ```js
+ * console.log(log.symbol.success);
+ * //=> ✔
+ * ```
+ * @name .symbol.success
+ * @api public
+ */
+
+getter(log.symbol, 'success', function() {
+  return log.check;
+});
+
+/**
+ * Warning symbol.
+ *
+ * ```js
+ * console.log(log.symbol.warning);
+ * //=> ⚠
+ * ```
+ * @name .symbol.warning
+ * @api public
+ */
+
+getter(log.symbol, 'warning', function() {
+  return log.warningSymbol;
+});
+
+/**
+ * Get a red error symbol.
+ *
+ * ```js
+ * console.log(log.error);
+ * //=> ✖
+ * ```
+ * @name .error
+ * @api public
+ */
+
+getter(log, 'error', function() {
+  return log.red(log.symbol.error);
+});
+
+/**
+ * Get a cyan info symbol.
+ *
+ * ```js
+ * console.log(log.info);
+ * //=> ℹ
+ * ```
+ * @name .info
+ * @api public
+ */
+
+getter(log, 'info', function() {
+  return log.cyan(log.symbol.info);
+});
+
+/**
+ * Get a green success symbol.
+ *
+ * ```js
+ * console.log(log.success);
+ * //=> ✔
+ * ```
+ * @name .success
+ * @api public
+ */
+
+getter(log, 'success', function() {
+  return log.green(log.symbol.success);
+});
+
+/**
+ * Get a yellow warning symbol.
+ *
+ * ```js
+ * console.log(log.warning);
+ * //=> ⚠
+ * ```
+ * @name .warning
+ * @api public
+ */
+
+getter(log, 'warning', function() {
+  return log.yellow(log.symbol.warning);
+});
+
+/**
+ * Get a formatted timestamp.
+ *
+ * ```js
+ * console.log(log.timestamp);
+ * //=> [15:27:46]
+ * ```
+ * @name .timestamp
+ * @api public
+ */
+
+getter(log, 'timestamp', function() {
+  return '[' + log.gray(log.timeStamp('HH:mm:ss')) + ']';
+});
+
+/**
+ * Log a white success message prefixed by a green check.
+ *
+ * ```js
+ * log.ok('Alright!');
+ * //=> '✔ Alright!'
+ * ```
+ * @name .ok
+ * @api public
+ */
+
+log.ok = require('log-ok');
+
+/**
+ * Make the given text bold and underlined.
+ *
+ * ```js
+ * console.log(log.heading('foo'));
+ * // or
+ * console.log(log.heading('foo', 'bar'));
+ * ```
+ * @name .heading
+ * @api public
+ */
+
+log.heading = function() {
+  var args = [].concat.apply([], [].slice.call(arguments));
+  var len = args.length;
+  var idx = -1;
+  var headings = [];
+  while (++idx < len) {
+    var str = args[idx];
+    if (typeof str === 'string') {
+      headings.push(log.bold(log.underline(str)));
+    }
+  }
+  return headings.join(' ');
+};
+
+/**
+ * Utility for defining a getter
+ */
+
+function getter(obj, prop, fn) {
+  Object.defineProperty(obj, prop, {
+    configurable: true,
+    enumerable: true,
+    get: fn
+  });
+}
+
+/**
+ * Expose `log`
+ */
+
+module.exports = log;
+
diff --git a/input_devices/mag/node_modules/log-utils/package.json b/input_devices/mag/node_modules/log-utils/package.json
new file mode 100644
index 00000000..bead1eae
--- /dev/null
+++ b/input_devices/mag/node_modules/log-utils/package.json
@@ -0,0 +1,153 @@
+{
+  "_args": [
+    [
+      "log-utils@^0.2.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "log-utils@>=0.2.1 <0.3.0",
+  "_id": "log-utils@0.2.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/log-utils",
+  "_nodeVersion": "6.2.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/log-utils-0.2.1.tgz_1468242600154_0.7743242129217833"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.8.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "log-utils",
+    "raw": "log-utils@^0.2.1",
+    "rawSpec": "^0.2.1",
+    "scope": null,
+    "spec": ">=0.2.1 <0.3.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base",
+    "/prompt-choices",
+    "/terminal-paginator"
+  ],
+  "_resolved": "https://registry.npmjs.org/log-utils/-/log-utils-0.2.1.tgz",
+  "_shasum": "a4c217a0dd9a50515d9b920206091ab3d4e031cf",
+  "_shrinkwrap": null,
+  "_spec": "log-utils@^0.2.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/log-utils/issues"
+  },
+  "dependencies": {
+    "ansi-colors": "^0.2.0",
+    "error-symbol": "^0.1.0",
+    "info-symbol": "^0.1.0",
+    "log-ok": "^0.1.1",
+    "success-symbol": "^0.1.0",
+    "time-stamp": "^1.0.1",
+    "warning-symbol": "^0.1.0"
+  },
+  "description": "Basic logging utils: colors, symbols and timestamp.",
+  "devDependencies": {
+    "clear-require": "^1.0.1",
+    "gulp-format-md": "^0.1.7",
+    "mocha": "^2.4.5",
+    "verb-generate-readme": "^0.1.21"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a4c217a0dd9a50515d9b920206091ab3d4e031cf",
+    "tarball": "https://registry.npmjs.org/log-utils/-/log-utils-0.2.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "LICENSE",
+    "README.md",
+    "index.js"
+  ],
+  "gitHead": "0e1ef356203db7589c082627e6d31bd3a31414ae",
+  "homepage": "https://github.com/jonschlinkert/log-utils",
+  "keywords": [
+    "ansi",
+    "chalk",
+    "check",
+    "checkmark",
+    "cli",
+    "color",
+    "colors",
+    "command",
+    "console",
+    "cyan",
+    "error",
+    "green",
+    "info",
+    "line",
+    "log",
+    "red",
+    "stamp",
+    "success",
+    "terminal",
+    "time",
+    "time-stamp",
+    "timestamp",
+    "util",
+    "utility",
+    "utils",
+    "warn",
+    "warning",
+    "yellow"
+  ],
+  "license": "MIT",
+  "lintDeps": {
+    "ignore": []
+  },
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "log-utils",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/log-utils.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "ansi-colors",
+      "time-diff",
+      "verb",
+      "verb-readme-generator"
+    ],
+    "related": {
+      "list": [
+        "ansi-colors",
+        "error-symbol",
+        "info-symbol",
+        "success-symbol",
+        "warning-symbol"
+      ]
+    }
+  },
+  "version": "0.2.1"
+}
diff --git a/input_devices/mag/node_modules/map-visit/LICENSE b/input_devices/mag/node_modules/map-visit/LICENSE
new file mode 100644
index 00000000..83b56e70
--- /dev/null
+++ b/input_devices/mag/node_modules/map-visit/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/map-visit/README.md b/input_devices/mag/node_modules/map-visit/README.md
new file mode 100644
index 00000000..5ab02d45
--- /dev/null
+++ b/input_devices/mag/node_modules/map-visit/README.md
@@ -0,0 +1,155 @@
+# map-visit [![NPM version](https://img.shields.io/npm/v/map-visit.svg?style=flat)](https://www.npmjs.com/package/map-visit) [![NPM monthly downloads](https://img.shields.io/npm/dm/map-visit.svg?style=flat)](https://npmjs.org/package/map-visit)  [![NPM total downloads](https://img.shields.io/npm/dt/map-visit.svg?style=flat)](https://npmjs.org/package/map-visit) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/map-visit.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/map-visit)
+
+> Map `visit` over an array of objects.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save map-visit
+```
+
+## Usage
+
+```js
+var mapVisit = require('map-visit');
+```
+
+## What does this do?
+
+**Assign/Merge/Extend vs. Visit**
+
+Let's say you want to add a `set` method to your application that will:
+
+* set key-value pairs on a `data` object
+* extend objects onto the `data` object
+* extend arrays of objects onto the data object
+
+**Example using `extend`**
+
+Here is one way to accomplish this using Lo-Dash's `extend` (comparable to `Object.assign`):
+
+```js
+var _ = require('lodash');
+
+var obj = {
+  data: {},
+  set: function (key, value) {
+    if (Array.isArray(key)) {
+      _.extend.apply(_, [obj.data].concat(key));
+    } else if (typeof key === 'object') {
+      _.extend(obj.data, key);
+    } else {
+      obj.data[key] = value;
+    }
+  }
+};
+
+obj.set('a', 'a');
+obj.set([{b: 'b'}, {c: 'c'}]);
+obj.set({d: {e: 'f'}});
+
+console.log(obj.data);
+//=> {a: 'a', b: 'b', c: 'c', d: { e: 'f' }}
+```
+
+The above approach works fine for most use cases. However, **if you also want to emit an event** each time a property is added to the `data` object, or you want more control over what happens as the object is extended, a better approach would be to use `visit`.
+
+**Example using `visit`**
+
+In this approach:
+
+* when an array is passed to `set`, the `mapVisit` library calls the `set` method on each object in the array.
+* when an object is passed, `visit` calls `set` on each property in the object.
+
+As a result, the `data` event will be emitted every time a property is added to `data` (events are just an example, you can use this approach to perform any necessary logic every time the method is called).
+
+```js
+var mapVisit = require('map-visit');
+var visit = require('object-visit');
+
+var obj = {
+  data: {},
+  set: function (key, value) {
+    if (Array.isArray(key)) {
+      mapVisit(obj, 'set', key);
+    } else if (typeof key === 'object') {
+      visit(obj, 'set', key);
+    } else {
+      // simulate an event-emitter
+      console.log('emit', key, value);
+      obj.data[key] = value;
+    }
+  }
+};
+
+obj.set('a', 'a');
+obj.set([{b: 'b'}, {c: 'c'}]);
+obj.set({d: {e: 'f'}});
+obj.set({g: 'h', i: 'j', k: 'l'});
+
+console.log(obj.data);
+//=> {a: 'a', b: 'b', c: 'c', d: { e: 'f' }, g: 'h', i: 'j', k: 'l'}
+
+// events would look something like:
+// emit a a
+// emit b b
+// emit c c
+// emit d { e: 'f' }
+// emit g h
+// emit i j
+// emit k l
+```
+
+## About
+
+### Related projects
+
+* [collection-visit](https://www.npmjs.com/package/collection-visit): Visit a method over the items in an object, or map visit over the objects… [more](https://github.com/jonschlinkert/collection-visit) | [homepage](https://github.com/jonschlinkert/collection-visit "Visit a method over the items in an object, or map visit over the objects in an array.")
+* [object-visit](https://www.npmjs.com/package/object-visit): Call a specified method on each value in the given object. | [homepage](https://github.com/jonschlinkert/object-visit "Call a specified method on each value in the given object.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 15 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 7 | [doowb](https://github.com/doowb) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.5.0, on April 09, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/map-visit/index.js b/input_devices/mag/node_modules/map-visit/index.js
new file mode 100644
index 00000000..bc54ccc4
--- /dev/null
+++ b/input_devices/mag/node_modules/map-visit/index.js
@@ -0,0 +1,37 @@
+'use strict';
+
+var util = require('util');
+var visit = require('object-visit');
+
+/**
+ * Map `visit` over an array of objects.
+ *
+ * @param  {Object} `collection` The context in which to invoke `method`
+ * @param  {String} `method` Name of the method to call on `collection`
+ * @param  {Object} `arr` Array of objects.
+ */
+
+module.exports = function mapVisit(collection, method, val) {
+  if (isObject(val)) {
+    return visit.apply(null, arguments);
+  }
+
+  if (!Array.isArray(val)) {
+    throw new TypeError('expected an array: ' + util.inspect(val));
+  }
+
+  var args = [].slice.call(arguments, 3);
+
+  for (var i = 0; i < val.length; i++) {
+    var ele = val[i];
+    if (isObject(ele)) {
+      visit.apply(null, [collection, method, ele].concat(args));
+    } else {
+      collection[method].apply(collection, [ele].concat(args));
+    }
+  }
+};
+
+function isObject(val) {
+  return val && (typeof val === 'function' || (!Array.isArray(val) && typeof val === 'object'));
+}
diff --git a/input_devices/mag/node_modules/map-visit/package.json b/input_devices/mag/node_modules/map-visit/package.json
new file mode 100644
index 00000000..0ae04509
--- /dev/null
+++ b/input_devices/mag/node_modules/map-visit/package.json
@@ -0,0 +1,144 @@
+{
+  "_args": [
+    [
+      "map-visit@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/collection-visit"
+    ]
+  ],
+  "_from": "map-visit@>=1.0.0 <2.0.0",
+  "_id": "map-visit@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/map-visit",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/map-visit-1.0.0.tgz_1491774214052_0.825954457744956"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.1.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "map-visit",
+    "raw": "map-visit@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/collection-visit"
+  ],
+  "_resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+  "_shasum": "ecdca8f13144e660f1b5bd41f12f3479d98dfb8f",
+  "_shrinkwrap": null,
+  "_spec": "map-visit@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/collection-visit",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/map-visit/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "email": "brian.woodward@gmail.com",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "object-visit": "^1.0.0"
+  },
+  "description": "Map `visit` over an array of objects.",
+  "devDependencies": {
+    "clone-deep": "^0.2.4",
+    "extend-shallow": "^2.0.1",
+    "gulp-format-md": "^0.1.12",
+    "lodash": "^4.17.4",
+    "mocha": "^3.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "ecdca8f13144e660f1b5bd41f12f3479d98dfb8f",
+    "tarball": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "73bcd8385c9520c595a825486f19623a5e0550f0",
+  "homepage": "https://github.com/jonschlinkert/map-visit",
+  "keywords": [
+    "array",
+    "arrays",
+    "function",
+    "helper",
+    "invoke",
+    "key",
+    "map",
+    "method",
+    "object",
+    "objects",
+    "value",
+    "visit",
+    "visitor"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "map-visit",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/map-visit.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-generate-readme"
+    ],
+    "related": {
+      "list": [
+        "collection-visit",
+        "object-visit"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/mimic-response/index.js b/input_devices/mag/node_modules/mimic-response/index.js
new file mode 100644
index 00000000..d5e33be4
--- /dev/null
+++ b/input_devices/mag/node_modules/mimic-response/index.js
@@ -0,0 +1,32 @@
+'use strict';
+
+// We define these manually to ensure they're always copied
+// even if they would move up the prototype chain
+// https://nodejs.org/api/http.html#http_class_http_incomingmessage
+const knownProps = [
+	'destroy',
+	'setTimeout',
+	'socket',
+	'headers',
+	'trailers',
+	'rawHeaders',
+	'statusCode',
+	'httpVersion',
+	'httpVersionMinor',
+	'httpVersionMajor',
+	'rawTrailers',
+	'statusMessage'
+];
+
+module.exports = (fromStream, toStream) => {
+	const fromProps = new Set(Object.keys(fromStream).concat(knownProps));
+
+	for (const prop of fromProps) {
+		// Don't overwrite existing properties
+		if (prop in toStream) {
+			continue;
+		}
+
+		toStream[prop] = typeof fromStream[prop] === 'function' ? fromStream[prop].bind(fromStream) : fromStream[prop];
+	}
+};
diff --git a/input_devices/mag/node_modules/mimic-response/license b/input_devices/mag/node_modules/mimic-response/license
new file mode 100644
index 00000000..e7af2f77
--- /dev/null
+++ b/input_devices/mag/node_modules/mimic-response/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/mimic-response/package.json b/input_devices/mag/node_modules/mimic-response/package.json
new file mode 100644
index 00000000..7e8f7994
--- /dev/null
+++ b/input_devices/mag/node_modules/mimic-response/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "mimic-response@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/decompress-response"
+    ]
+  ],
+  "_from": "mimic-response@>=1.0.0 <2.0.0",
+  "_id": "mimic-response@1.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/mimic-response",
+  "_nodeVersion": "8.11.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/mimic-response_1.0.1_1531308307178_0.4318628271748308"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "mimic-response",
+    "raw": "mimic-response@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/decompress-response"
+  ],
+  "_resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+  "_shasum": "4923538878eef42063cb8a3e3b0798781487ab1b",
+  "_shrinkwrap": null,
+  "_spec": "mimic-response@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/decompress-response",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/mimic-response/issues"
+  },
+  "dependencies": {},
+  "description": "Mimic a Node.js HTTP response stream",
+  "devDependencies": {
+    "ava": "*",
+    "create-test-server": "^0.1.0",
+    "pify": "^3.0.0",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRekTCRA9TVsSAnZWagAA3jYQAIIPznt0xQK2f0PlPwFp\nPGY3XFk5wsB6jA0+n4BaeLD3NdQ2zN2wP/ydMnLCY4KbcMhcsRNMapq7C5+J\n28aUasU7ljgoD2HH892XTSH3TlDze9ExbFFXNphlF+p4o+rKVD1xlk6abvSX\n04kgFTIcpL5oBztEPLNEDLWh48Z++hLNcsDcQk+6Mrw69N2Tbl8bJBjnPSnf\nnKAeZe8PqRFKzTXkl1bNiE+jLNp07pX/sUkA/6QBxisk+IcadW5uFZG0GtzZ\neAE7kJdp3yT64flZn8KmD5oHY4UmwyECA4CWEuyfau4ROBlqMEfr4U/1slTf\nuscm7iTx1/6x+/T4PSgytvQxqFx/iJ4FZCQrW8Vb807kntobpnYHU0Yj/AfE\nPuHVIiSvrpE+xUjyaMxA2/A/yBA46NSza3sPBd+rWmJJvY5CjdShIksu66Hx\nfra4BXMu4GcZlNgXJEwbj/jkY8xuVFMyr1YDkkGKQ30A6BHdEObayAxpSSpN\nOpVE0CXeiFgxiL+yPP+oEdStpT9VcUF0Jh1pGsSN6hOGPMYqJqVSs+mhAwkx\nUEkmu9zUOK4WxieYPRKBpvCkewe738Di0tc6d9nI8TCx/5ie4jE7ZTtI0s1L\nNkWmxtDXXD11LWLSn2R2DCSapjSzcbH/00EZIFg6BuuOzb0wQRM5JyYzY9B1\nhQ5F\r\n=+pqq\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "4923538878eef42063cb8a3e3b0798781487ab1b",
+    "tarball": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+    "unpackedSize": 3584
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "687b4544afddca3d3e9e61a455ca5efe0e27851e",
+  "homepage": "https://github.com/sindresorhus/mimic-response#readme",
+  "keywords": [
+    "core",
+    "get",
+    "http",
+    "https",
+    "mimic",
+    "request",
+    "response",
+    "stream"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "mimic-response",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/mimic-response.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "1.0.1"
+}
diff --git a/input_devices/mag/node_modules/mimic-response/readme.md b/input_devices/mag/node_modules/mimic-response/readme.md
new file mode 100644
index 00000000..e07ec661
--- /dev/null
+++ b/input_devices/mag/node_modules/mimic-response/readme.md
@@ -0,0 +1,54 @@
+# mimic-response [![Build Status](https://travis-ci.org/sindresorhus/mimic-response.svg?branch=master)](https://travis-ci.org/sindresorhus/mimic-response)
+
+> Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
+
+
+## Install
+
+```
+$ npm install mimic-response
+```
+
+
+## Usage
+
+```js
+const stream = require('stream');
+const mimicResponse = require('mimic-response');
+
+const responseStream = getHttpResponseStream();
+const myStream = new stream.PassThrough();
+
+mimicResponse(responseStream, myStream);
+
+console.log(myStream.statusCode);
+//=> 200
+```
+
+
+## API
+
+### mimicResponse(from, to)
+
+#### from
+
+Type: `Stream`
+
+[Node.js HTTP response stream.](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
+
+#### to
+
+Type: `Stream`
+
+Any stream.
+
+
+## Related
+
+- [mimic-fn](https://github.com/sindresorhus/mimic-fn) - Make a function mimic another one
+- [clone-response](https://github.com/lukechilds/clone-response) - Clone a Node.js response stream
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/minimist/.travis.yml b/input_devices/mag/node_modules/minimist/.travis.yml
new file mode 100644
index 00000000..74c57bf1
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
+  - "0.12"
+  - "iojs"
+before_install:
+  - npm install -g npm@~1.4.6
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/LICENSE b/input_devices/mag/node_modules/minimist/LICENSE
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/LICENSE
rename to input_devices/mag/node_modules/minimist/LICENSE
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/example/parse.js b/input_devices/mag/node_modules/minimist/example/parse.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/example/parse.js
rename to input_devices/mag/node_modules/minimist/example/parse.js
diff --git a/input_devices/mag/node_modules/minimist/index.js b/input_devices/mag/node_modules/minimist/index.js
new file mode 100644
index 00000000..6a0559d5
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/index.js
@@ -0,0 +1,236 @@
+module.exports = function (args, opts) {
+    if (!opts) opts = {};
+    
+    var flags = { bools : {}, strings : {}, unknownFn: null };
+
+    if (typeof opts['unknown'] === 'function') {
+        flags.unknownFn = opts['unknown'];
+    }
+
+    if (typeof opts['boolean'] === 'boolean' && opts['boolean']) {
+      flags.allBools = true;
+    } else {
+      [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
+          flags.bools[key] = true;
+      });
+    }
+    
+    var aliases = {};
+    Object.keys(opts.alias || {}).forEach(function (key) {
+        aliases[key] = [].concat(opts.alias[key]);
+        aliases[key].forEach(function (x) {
+            aliases[x] = [key].concat(aliases[key].filter(function (y) {
+                return x !== y;
+            }));
+        });
+    });
+
+    [].concat(opts.string).filter(Boolean).forEach(function (key) {
+        flags.strings[key] = true;
+        if (aliases[key]) {
+            flags.strings[aliases[key]] = true;
+        }
+     });
+
+    var defaults = opts['default'] || {};
+    
+    var argv = { _ : [] };
+    Object.keys(flags.bools).forEach(function (key) {
+        setArg(key, defaults[key] === undefined ? false : defaults[key]);
+    });
+    
+    var notFlags = [];
+
+    if (args.indexOf('--') !== -1) {
+        notFlags = args.slice(args.indexOf('--')+1);
+        args = args.slice(0, args.indexOf('--'));
+    }
+
+    function argDefined(key, arg) {
+        return (flags.allBools && /^--[^=]+$/.test(arg)) ||
+            flags.strings[key] || flags.bools[key] || aliases[key];
+    }
+
+    function setArg (key, val, arg) {
+        if (arg && flags.unknownFn && !argDefined(key, arg)) {
+            if (flags.unknownFn(arg) === false) return;
+        }
+
+        var value = !flags.strings[key] && isNumber(val)
+            ? Number(val) : val
+        ;
+        setKey(argv, key.split('.'), value);
+        
+        (aliases[key] || []).forEach(function (x) {
+            setKey(argv, x.split('.'), value);
+        });
+    }
+
+    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 || flags.bools[key] || typeof o[key] === 'boolean') {
+            o[key] = value;
+        }
+        else if (Array.isArray(o[key])) {
+            o[key].push(value);
+        }
+        else {
+            o[key] = [ o[key], value ];
+        }
+    }
+    
+    function aliasIsBoolean(key) {
+      return aliases[key].some(function (x) {
+          return flags.bools[x];
+      });
+    }
+
+    for (var i = 0; i < args.length; i++) {
+        var arg = args[i];
+        
+        if (/^--.+=/.test(arg)) {
+            // 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]*)$/);
+            var key = m[1];
+            var value = m[2];
+            if (flags.bools[key]) {
+                value = value !== 'false';
+            }
+            setArg(key, value, arg);
+        }
+        else if (/^--no-.+/.test(arg)) {
+            var key = arg.match(/^--no-(.+)/)[1];
+            setArg(key, false, arg);
+        }
+        else if (/^--.+/.test(arg)) {
+            var key = arg.match(/^--(.+)/)[1];
+            var next = args[i + 1];
+            if (next !== undefined && !/^-/.test(next)
+            && !flags.bools[key]
+            && !flags.allBools
+            && (aliases[key] ? !aliasIsBoolean(key) : true)) {
+                setArg(key, next, arg);
+                i++;
+            }
+            else if (/^(true|false)$/.test(next)) {
+                setArg(key, next === 'true', arg);
+                i++;
+            }
+            else {
+                setArg(key, flags.strings[key] ? '' : true, arg);
+            }
+        }
+        else if (/^-[^-]+/.test(arg)) {
+            var letters = arg.slice(1,-1).split('');
+            
+            var broken = false;
+            for (var j = 0; j < letters.length; j++) {
+                var next = arg.slice(j+2);
+                
+                if (next === '-') {
+                    setArg(letters[j], next, arg)
+                    continue;
+                }
+                
+                if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
+                    setArg(letters[j], next.split('=')[1], arg);
+                    broken = true;
+                    break;
+                }
+                
+                if (/[A-Za-z]/.test(letters[j])
+                && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
+                    setArg(letters[j], next, arg);
+                    broken = true;
+                    break;
+                }
+                
+                if (letters[j+1] && letters[j+1].match(/\W/)) {
+                    setArg(letters[j], arg.slice(j+2), arg);
+                    broken = true;
+                    break;
+                }
+                else {
+                    setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
+                }
+            }
+            
+            var key = arg.slice(-1)[0];
+            if (!broken && key !== '-') {
+                if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
+                && !flags.bools[key]
+                && (aliases[key] ? !aliasIsBoolean(key) : true)) {
+                    setArg(key, args[i+1], arg);
+                    i++;
+                }
+                else if (args[i+1] && /true|false/.test(args[i+1])) {
+                    setArg(key, args[i+1] === 'true', arg);
+                    i++;
+                }
+                else {
+                    setArg(key, flags.strings[key] ? '' : true, arg);
+                }
+            }
+        }
+        else {
+            if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
+                argv._.push(
+                    flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
+                );
+            }
+            if (opts.stopEarly) {
+                argv._.push.apply(argv._, args.slice(i + 1));
+                break;
+            }
+        }
+    }
+    
+    Object.keys(defaults).forEach(function (key) {
+        if (!hasKey(argv, key.split('.'))) {
+            setKey(argv, key.split('.'), defaults[key]);
+            
+            (aliases[key] || []).forEach(function (x) {
+                setKey(argv, x.split('.'), defaults[key]);
+            });
+        }
+    });
+    
+    if (opts['--']) {
+        argv['--'] = new Array();
+        notFlags.forEach(function(key) {
+            argv['--'].push(key);
+        });
+    }
+    else {
+        notFlags.forEach(function(key) {
+            argv._.push(key);
+        });
+    }
+
+    return argv;
+};
+
+function hasKey (obj, keys) {
+    var o = obj;
+    keys.slice(0,-1).forEach(function (key) {
+        o = (o[key] || {});
+    });
+
+    var key = keys[keys.length - 1];
+    return key in o;
+}
+
+function isNumber (x) {
+    if (typeof x === 'number') return true;
+    if (/^0x[0-9a-f]+$/i.test(x)) return true;
+    return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
+}
+
diff --git a/input_devices/mag/node_modules/minimist/package.json b/input_devices/mag/node_modules/minimist/package.json
new file mode 100644
index 00000000..bea395ac
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/package.json
@@ -0,0 +1,98 @@
+{
+  "_args": [
+    [
+      "minimist@^1.2.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "minimist@>=1.2.0 <2.0.0",
+  "_id": "minimist@1.2.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/minimist",
+  "_nodeVersion": "2.4.0",
+  "_npmUser": {
+    "email": "substack@gmail.com",
+    "name": "substack"
+  },
+  "_npmVersion": "3.2.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "minimist",
+    "raw": "minimist@^1.2.0",
+    "rawSpec": "^1.2.0",
+    "scope": null,
+    "spec": ">=1.2.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install",
+    "/rc"
+  ],
+  "_resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+  "_shasum": "a35008b20f41383eec1fb914f4cd5df79a264284",
+  "_shrinkwrap": null,
+  "_spec": "minimist@^1.2.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "mail@substack.net",
+    "name": "James Halliday",
+    "url": "http://substack.net"
+  },
+  "bugs": {
+    "url": "https://github.com/substack/minimist/issues"
+  },
+  "dependencies": {},
+  "description": "parse argument options",
+  "devDependencies": {
+    "covert": "^1.0.0",
+    "tap": "~0.4.0",
+    "tape": "^3.5.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a35008b20f41383eec1fb914f4cd5df79a264284",
+    "tarball": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz"
+  },
+  "gitHead": "dc624482fcfec5bc669c68cdb861f00573ed4e64",
+  "homepage": "https://github.com/substack/minimist",
+  "keywords": [
+    "argv",
+    "getopt",
+    "optimist",
+    "parser"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "substack",
+      "email": "mail@substack.net"
+    }
+  ],
+  "name": "minimist",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/substack/minimist.git"
+  },
+  "scripts": {
+    "coverage": "covert test/*.js",
+    "test": "tap test/*.js"
+  },
+  "testling": {
+    "browsers": [
+      "chrome/10",
+      "chrome/latest",
+      "ff/5",
+      "firefox/latest",
+      "ie/6..latest",
+      "opera/12",
+      "safari/5.1",
+      "safari/latest"
+    ],
+    "files": "test/*.js"
+  },
+  "version": "1.2.0"
+}
diff --git a/input_devices/mag/node_modules/minimist/readme.markdown b/input_devices/mag/node_modules/minimist/readme.markdown
new file mode 100644
index 00000000..30a74cf8
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/readme.markdown
@@ -0,0 +1,91 @@
+# minimist
+
+parse argument options
+
+This module is the guts of optimist's argument parser without all the
+fanciful decoration.
+
+[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)
+
+[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)
+
+# example
+
+``` js
+var argv = require('minimist')(process.argv.slice(2));
+console.dir(argv);
+```
+
+```
+$ node example/parse.js -a beep -b boop
+{ _: [], a: 'beep', b: 'boop' }
+```
+
+```
+$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
+{ _: [ 'foo', 'bar', 'baz' ],
+  x: 3,
+  y: 4,
+  n: 5,
+  a: true,
+  b: true,
+  c: true,
+  beep: 'boop' }
+```
+
+# methods
+
+``` js
+var parseArgs = require('minimist')
+```
+
+## var argv = parseArgs(args, opts={})
+
+Return an argument object `argv` populated with the array arguments from `args`.
+
+`argv._` contains all the arguments that didn't have an option associated with
+them.
+
+Numeric-looking arguments will be returned as numbers unless `opts.string` or
+`opts.boolean` is set for that argument name.
+
+Any arguments after `'--'` will not be parsed and will end up in `argv._`.
+
+options can be:
+
+* `opts.string` - a string or array of strings argument names to always treat as
+strings
+* `opts.boolean` - a boolean, string or array of strings to always treat as
+booleans. if `true` will treat all double hyphenated arguments without equal signs
+as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`)
+* `opts.alias` - an object mapping string names to strings or arrays of string
+argument names to use as aliases
+* `opts.default` - an object mapping string argument names to default values
+* `opts.stopEarly` - when true, populate `argv._` with everything after the
+first non-option
+* `opts['--']` - when true, populate `argv._` with everything before the `--`
+and `argv['--']` with everything after the `--`. Here's an example:
+* `opts.unknown` - a function which is invoked with a command line parameter not
+defined in the `opts` configuration object. If the function returns `false`, the
+unknown option is not added to `argv`.
+
+```
+> require('./')('one two three -- four five --six'.split(' '), { '--': true })
+{ _: [ 'one', 'two', 'three' ],
+  '--': [ 'four', 'five', '--six' ] }
+```
+
+Note that with `opts['--']` set, parsing for arguments still stops after the
+`--`.
+
+# install
+
+With [npm](https://npmjs.org) do:
+
+```
+npm install minimist
+```
+
+# license
+
+MIT
diff --git a/input_devices/mag/node_modules/minimist/test/all_bool.js b/input_devices/mag/node_modules/minimist/test/all_bool.js
new file mode 100644
index 00000000..ac835483
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/all_bool.js
@@ -0,0 +1,32 @@
+var parse = require('../');
+var test = require('tape');
+
+test('flag boolean true (default all --args to boolean)', function (t) {
+    var argv = parse(['moo', '--honk', 'cow'], {
+        boolean: true
+    });
+    
+    t.deepEqual(argv, {
+        honk: true,
+        _: ['moo', 'cow']
+    });
+    
+    t.deepEqual(typeof argv.honk, 'boolean');
+    t.end();
+});
+
+test('flag boolean true only affects double hyphen arguments without equals signs', function (t) {
+    var argv = parse(['moo', '--honk', 'cow', '-p', '55', '--tacos=good'], {
+        boolean: true
+    });
+    
+    t.deepEqual(argv, {
+        honk: true,
+        tacos: 'good',
+        p: 55,
+        _: ['moo', 'cow']
+    });
+    
+    t.deepEqual(typeof argv.honk, 'boolean');
+    t.end();
+});
diff --git a/input_devices/mag/node_modules/minimist/test/bool.js b/input_devices/mag/node_modules/minimist/test/bool.js
new file mode 100644
index 00000000..14b0717c
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/bool.js
@@ -0,0 +1,166 @@
+var parse = require('../');
+var test = require('tape');
+
+test('flag boolean default false', function (t) {
+    var argv = parse(['moo'], {
+        boolean: ['t', 'verbose'],
+        default: { verbose: false, t: false }
+    });
+    
+    t.deepEqual(argv, {
+        verbose: false,
+        t: false,
+        _: ['moo']
+    });
+    
+    t.deepEqual(typeof argv.verbose, 'boolean');
+    t.deepEqual(typeof argv.t, 'boolean');
+    t.end();
+
+});
+
+test('boolean groups', function (t) {
+    var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], {
+        boolean: ['x','y','z']
+    });
+    
+    t.deepEqual(argv, {
+        x : true,
+        y : false,
+        z : true,
+        _ : [ 'one', 'two', 'three' ]
+    });
+    
+    t.deepEqual(typeof argv.x, 'boolean');
+    t.deepEqual(typeof argv.y, 'boolean');
+    t.deepEqual(typeof argv.z, 'boolean');
+    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 = parse(aliased, {
+        boolean: 'herp',
+        alias: { h: 'herp' }
+    });
+    var propertyArgv = parse(regular, {
+        boolean: 'herp',
+        alias: { h: 'herp' }
+    });
+    var expected = {
+        herp: true,
+        h: true,
+        '_': [ 'derp' ]
+    };
+    
+    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 = {
+        alias: { 'h': 'herp' },
+        boolean: 'herp'
+    };
+    var aliasedArgv = parse(aliased, opts);
+    var propertyArgv = parse(regular, opts);
+    var expected = {
+        herp: true,
+        h: true,
+        '_': [ 'derp' ]
+    };
+    t.same(aliasedArgv, expected);
+    t.same(propertyArgv, expected);
+    t.end();
+});
+
+test('boolean and alias array with options hash', function (t) {
+    var aliased = [ '-h', 'derp' ];
+    var regular = [ '--herp', 'derp' ];
+    var alt = [ '--harp', 'derp' ];
+    var opts = {
+        alias: { 'h': ['herp', 'harp'] },
+        boolean: 'h'
+    };
+    var aliasedArgv = parse(aliased, opts);
+    var propertyArgv = parse(regular, opts);
+    var altPropertyArgv = parse(alt, opts);
+    var expected = {
+        harp: true,
+        herp: true,
+        h: true,
+        '_': [ 'derp' ]
+    };
+    t.same(aliasedArgv, expected);
+    t.same(propertyArgv, expected);
+    t.same(altPropertyArgv, expected);
+    t.end();
+});
+
+test('boolean and alias using explicit true', function (t) {
+    var aliased = [ '-h', 'true' ];
+    var regular = [ '--herp',  'true' ];
+    var opts = {
+        alias: { h: 'herp' },
+        boolean: 'h'
+    };
+    var aliasedArgv = parse(aliased, opts);
+    var propertyArgv = parse(regular, opts);
+    var expected = {
+        herp: true,
+        h: true,
+        '_': [ ]
+    };
+
+    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 = parse(['--boool', '--other=true'], {
+        boolean: 'boool'
+    });
+
+    t.same(parsed.boool, true);
+    t.same(parsed.other, 'true');
+
+    parsed = parse(['--boool', '--other=false'], {
+        boolean: 'boool'
+    });
+    
+    t.same(parsed.boool, true);
+    t.same(parsed.other, 'false');
+    t.end();
+});
+
+test('boolean --boool=true', function (t) {
+    var parsed = parse(['--boool=true'], {
+        default: {
+            boool: false
+        },
+        boolean: ['boool']
+    });
+
+    t.same(parsed.boool, true);
+    t.end();
+});
+
+test('boolean --boool=false', function (t) {
+    var parsed = parse(['--boool=false'], {
+        default: {
+          boool: true
+        },
+        boolean: ['boool']
+    });
+
+    t.same(parsed.boool, false);
+    t.end();
+});
diff --git a/input_devices/mag/node_modules/minimist/test/dash.js b/input_devices/mag/node_modules/minimist/test/dash.js
new file mode 100644
index 00000000..5a4fa5be
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/dash.js
@@ -0,0 +1,31 @@
+var parse = require('../');
+var test = require('tape');
+
+test('-', function (t) {
+    t.plan(5);
+    t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] });
+    t.deepEqual(parse([ '-' ]), { _: [ '-' ] });
+    t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] });
+    t.deepEqual(
+        parse([ '-b', '-' ], { boolean: 'b' }),
+        { b: true, _: [ '-' ] }
+    );
+    t.deepEqual(
+        parse([ '-s', '-' ], { string: 's' }),
+        { s: '-', _: [] }
+    );
+});
+
+test('-a -- b', function (t) {
+    t.plan(3);
+    t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] });
+    t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
+    t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
+});
+
+test('move arguments after the -- into their own `--` array', function(t) {
+    t.plan(1);
+    t.deepEqual(
+        parse([ '--name', 'John', 'before', '--', 'after' ], { '--': true }),
+        { name: 'John', _: [ 'before' ], '--': [ 'after' ] });
+});
diff --git a/input_devices/mag/node_modules/minimist/test/default_bool.js b/input_devices/mag/node_modules/minimist/test/default_bool.js
new file mode 100644
index 00000000..780a3112
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/default_bool.js
@@ -0,0 +1,35 @@
+var test = require('tape');
+var parse = require('../');
+
+test('boolean default true', function (t) {
+    var argv = parse([], {
+        boolean: 'sometrue',
+        default: { sometrue: true }
+    });
+    t.equal(argv.sometrue, true);
+    t.end();
+});
+
+test('boolean default false', function (t) {
+    var argv = parse([], {
+        boolean: 'somefalse',
+        default: { somefalse: false }
+    });
+    t.equal(argv.somefalse, false);
+    t.end();
+});
+
+test('boolean default to null', function (t) {
+    var argv = parse([], {
+        boolean: 'maybe',
+        default: { maybe: null }
+    });
+    t.equal(argv.maybe, null);
+    var argv = parse(['--maybe'], {
+        boolean: 'maybe',
+        default: { maybe: null }
+    });
+    t.equal(argv.maybe, true);
+    t.end();
+
+})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/dotted.js b/input_devices/mag/node_modules/minimist/test/dotted.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/dotted.js
rename to input_devices/mag/node_modules/minimist/test/dotted.js
diff --git a/input_devices/mag/node_modules/minimist/test/kv_short.js b/input_devices/mag/node_modules/minimist/test/kv_short.js
new file mode 100644
index 00000000..f813b305
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/kv_short.js
@@ -0,0 +1,16 @@
+var parse = require('../');
+var test = require('tape');
+
+test('short -k=v' , function (t) {
+    t.plan(1);
+    
+    var argv = parse([ '-b=123' ]);
+    t.deepEqual(argv, { b: 123, _: [] });
+});
+
+test('multi short -k=v' , function (t) {
+    t.plan(1);
+    
+    var argv = parse([ '-a=whatever', '-b=robots' ]);
+    t.deepEqual(argv, { a: 'whatever', b: 'robots', _: [] });
+});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/long.js b/input_devices/mag/node_modules/minimist/test/long.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/long.js
rename to input_devices/mag/node_modules/minimist/test/long.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/num.js b/input_devices/mag/node_modules/minimist/test/num.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/num.js
rename to input_devices/mag/node_modules/minimist/test/num.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/parse.js b/input_devices/mag/node_modules/minimist/test/parse.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/parse.js
rename to input_devices/mag/node_modules/minimist/test/parse.js
diff --git a/input_devices/mag/node_modules/minimist/test/parse_modified.js b/input_devices/mag/node_modules/minimist/test/parse_modified.js
new file mode 100644
index 00000000..ab620dc5
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/parse_modified.js
@@ -0,0 +1,9 @@
+var parse = require('../');
+var test = require('tape');
+
+test('parse with modifier functions' , function (t) {
+    t.plan(1);
+    
+    var argv = parse([ '-b', '123' ], { boolean: 'b' });
+    t.deepEqual(argv, { b: true, _: [123] });
+});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/short.js b/input_devices/mag/node_modules/minimist/test/short.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/short.js
rename to input_devices/mag/node_modules/minimist/test/short.js
diff --git a/input_devices/mag/node_modules/minimist/test/stop_early.js b/input_devices/mag/node_modules/minimist/test/stop_early.js
new file mode 100644
index 00000000..bdf9fbcb
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/stop_early.js
@@ -0,0 +1,15 @@
+var parse = require('../');
+var test = require('tape');
+
+test('stops parsing on the first non-option when stopEarly is set', function (t) {
+    var argv = parse(['--aaa', 'bbb', 'ccc', '--ddd'], {
+        stopEarly: true
+    });
+
+    t.deepEqual(argv, {
+        aaa: 'bbb',
+        _: ['ccc', '--ddd']
+    });
+
+    t.end();
+});
diff --git a/input_devices/mag/node_modules/minimist/test/unknown.js b/input_devices/mag/node_modules/minimist/test/unknown.js
new file mode 100644
index 00000000..462a36bd
--- /dev/null
+++ b/input_devices/mag/node_modules/minimist/test/unknown.js
@@ -0,0 +1,102 @@
+var parse = require('../');
+var test = require('tape');
+
+test('boolean and alias is not unknown', function (t) {
+    var unknown = [];
+    function unknownFn(arg) {
+        unknown.push(arg);
+        return false;
+    }
+    var aliased = [ '-h', 'true', '--derp', 'true' ];
+    var regular = [ '--herp',  'true', '-d', 'true' ];
+    var opts = {
+        alias: { h: 'herp' },
+        boolean: 'h',
+        unknown: unknownFn
+    };
+    var aliasedArgv = parse(aliased, opts);
+    var propertyArgv = parse(regular, opts);
+
+    t.same(unknown, ['--derp', '-d']);
+    t.end();
+});
+
+test('flag boolean true any double hyphen argument is not unknown', function (t) {
+    var unknown = [];
+    function unknownFn(arg) {
+        unknown.push(arg);
+        return false;
+    }
+    var argv = parse(['--honk', '--tacos=good', 'cow', '-p', '55'], {
+        boolean: true,
+        unknown: unknownFn
+    });
+    t.same(unknown, ['--tacos=good', 'cow', '-p']);
+    t.same(argv, {
+        honk: true,
+        _: []
+    });
+    t.end();
+});
+
+test('string and alias is not unknown', function (t) {
+    var unknown = [];
+    function unknownFn(arg) {
+        unknown.push(arg);
+        return false;
+    }
+    var aliased = [ '-h', 'hello', '--derp', 'goodbye' ];
+    var regular = [ '--herp',  'hello', '-d', 'moon' ];
+    var opts = {
+        alias: { h: 'herp' },
+        string: 'h',
+        unknown: unknownFn
+    };
+    var aliasedArgv = parse(aliased, opts);
+    var propertyArgv = parse(regular, opts);
+
+    t.same(unknown, ['--derp', '-d']);
+    t.end();
+});
+
+test('default and alias is not unknown', function (t) {
+    var unknown = [];
+    function unknownFn(arg) {
+        unknown.push(arg);
+        return false;
+    }
+    var aliased = [ '-h', 'hello' ];
+    var regular = [ '--herp',  'hello' ];
+    var opts = {
+        default: { 'h': 'bar' },
+        alias: { 'h': 'herp' },
+        unknown: unknownFn
+    };
+    var aliasedArgv = parse(aliased, opts);
+    var propertyArgv = parse(regular, opts);
+
+    t.same(unknown, []);
+    t.end();
+    unknownFn(); // exercise fn for 100% coverage
+});
+
+test('value following -- is not unknown', function (t) {
+    var unknown = [];
+    function unknownFn(arg) {
+        unknown.push(arg);
+        return false;
+    }
+    var aliased = [ '--bad', '--', 'good', 'arg' ];
+    var opts = {
+        '--': true,
+        unknown: unknownFn
+    };
+    var argv = parse(aliased, opts);
+
+    t.same(unknown, ['--bad']);
+    t.same(argv, {
+        '--': ['good', 'arg'],
+        '_': []
+    })
+    t.end();
+});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/whitespace.js b/input_devices/mag/node_modules/minimist/test/whitespace.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/whitespace.js
rename to input_devices/mag/node_modules/minimist/test/whitespace.js
diff --git a/input_devices/mag/node_modules/mixin-object/LICENSE b/input_devices/mag/node_modules/mixin-object/LICENSE
new file mode 100644
index 00000000..fa30c4cb
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/mixin-object/README.md b/input_devices/mag/node_modules/mixin-object/README.md
new file mode 100644
index 00000000..65538535
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/README.md
@@ -0,0 +1,75 @@
+# mixin-object [![NPM version](https://badge.fury.io/js/mixin-object.svg)](http://badge.fury.io/js/mixin-object)
+
+> Mixin the own and inherited properties of other objects onto the first object. Pass an empty object as the first arg to shallow clone.
+
+If you only want to combine own-properties, use [extend-shallow](https://github.com/jonschlinkert/extend-shallow).
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i mixin-object --save
+```
+
+Install with [bower](http://bower.io/)
+
+```sh
+$ bower install mixin-object --save
+```
+
+## Usage
+
+```js
+var mixin = require('mixin-object');
+
+var obj = {c: 'c'};
+var foo = mixin({a: 'a'}, {b: 'b'});
+console.log(foo);
+//=> {c: 'c', a: 'a', b: 'b'}
+console.log(obj);
+//=> {c: 'c'}
+
+mixin({}, {a: 'a'}, {b: 'b'});
+//=> {a: 'a', b: 'b'}
+```
+
+## Related
+
+* [assign-deep](https://github.com/jonschlinkert/assign-deep): Deeply assign the enumerable properties of source objects to a destination object.
+* [defaults-deep](https://github.com/jonschlinkert/defaults-deep): Like `extend` but recursively copies only the missing properties/values to the target object.
+* [extend-shallow](https://github.com/jonschlinkert/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util.
+* [for-own](https://github.com/jonschlinkert/for-own): Iterate over the own enumerable properties of an object, and return an object with properties… [more](https://github.com/jonschlinkert/for-own)
+* [for-in](https://github.com/jonschlinkert/for-in): Iterate over the own and inherited enumerable properties of an objecte, and return an object… [more](https://github.com/jonschlinkert/for-in)
+* [isobject](https://github.com/jonschlinkert/isobject): Returns true if the value is an object and not an array or null.
+* [is-plain-object](https://github.com/jonschlinkert/is-plain-object): Returns true if an object was created by the `Object` constructor.
+* [mixin-deep](https://github.com/jonschlinkert/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone.
+* [merge-deep](https://github.com/jonschlinkert/merge-deep): Recursively merge values in a javascript object.
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/mixin-object/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2014-2015 [Jon Schlinkert](https://github.com/jonschlinkert)
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on July 05, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/mixin-object/index.js b/input_devices/mag/node_modules/mixin-object/index.js
new file mode 100644
index 00000000..fca0107c
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/index.js
@@ -0,0 +1,36 @@
+'use strict';
+
+var isObject = require('is-extendable');
+var forIn = require('for-in');
+
+function mixin(target, objects) {
+  if (!isObject(target)) {
+    throw new TypeError('mixin-object expects the first argument to be an object.');
+  }
+  var len = arguments.length, i = 0;
+  while (++i < len) {
+    var obj = arguments[i];
+    if (isObject(obj)) {
+      forIn(obj, copy, target);
+    }
+  }
+  return target;
+}
+
+/**
+ * copy properties from the source object to the
+ * target object.
+ *
+ * @param  {*} `value`
+ * @param  {String} `key`
+ */
+
+function copy(value, key) {
+  this[key] = value;
+}
+
+/**
+ * Expose `mixin`
+ */
+
+module.exports = mixin;
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/mixin-object/node_modules/for-in/LICENSE b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/LICENSE
new file mode 100644
index 00000000..d734237b
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/mixin-object/node_modules/for-in/README.md b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/README.md
new file mode 100644
index 00000000..11736306
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/README.md
@@ -0,0 +1,85 @@
+# for-in [![NPM version](https://img.shields.io/npm/v/for-in.svg?style=flat)](https://www.npmjs.com/package/for-in) [![NPM monthly downloads](https://img.shields.io/npm/dm/for-in.svg?style=flat)](https://npmjs.org/package/for-in)  [![NPM total downloads](https://img.shields.io/npm/dt/for-in.svg?style=flat)](https://npmjs.org/package/for-in) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/for-in.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/for-in)
+
+> Iterate over the own and inherited enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save for-in
+```
+
+## Usage
+
+```js
+var forIn = require('for-in');
+
+var obj = {a: 'foo', b: 'bar', c: 'baz'};
+var values = [];
+var keys = [];
+
+forIn(obj, function (value, key, o) {
+  keys.push(key);
+  values.push(value);
+});
+
+console.log(keys);
+//=> ['a', 'b', 'c'];
+
+console.log(values);
+//=> ['foo', 'bar', 'baz'];
+```
+
+## About
+
+### Related projects
+
+* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten)
+* [collection-map](https://www.npmjs.com/package/collection-map): Returns an array of mapped values from an array or object. | [homepage](https://github.com/jonschlinkert/collection-map)
+* [for-own](https://www.npmjs.com/package/for-own): Iterate over the own enumerable properties of an object, and return an object with properties… [more](https://github.com/jonschlinkert/for-own) | [homepage](https://github.com/jonschlinkert/for-own)
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** |  
+| --- | --- |  
+| 11 | [jonschlinkert](https://github.com/jonschlinkert) |  
+| 2  | [paulirish](https://github.com/paulirish) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 26, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/mixin-object/node_modules/for-in/index.js b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/index.js
new file mode 100644
index 00000000..0b5f95f0
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/index.js
@@ -0,0 +1,16 @@
+/*!
+ * for-in <https://github.com/jonschlinkert/for-in>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+module.exports = function forIn(obj, fn, thisArg) {
+  for (var key in obj) {
+    if (fn.call(thisArg, obj[key], key, obj) === false) {
+      break;
+    }
+  }
+};
diff --git a/input_devices/mag/node_modules/mixin-object/node_modules/for-in/package.json b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/package.json
new file mode 100644
index 00000000..43950f8f
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/node_modules/for-in/package.json
@@ -0,0 +1,135 @@
+{
+  "_args": [
+    [
+      "for-in@^0.1.3",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/mixin-object"
+    ]
+  ],
+  "_from": "for-in@>=0.1.3 <0.2.0",
+  "_id": "for-in@0.1.8",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/mixin-object/for-in",
+  "_nodeVersion": "7.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/for-in-0.1.8.tgz_1488163817403_0.749103807611391"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.1.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "for-in",
+    "raw": "for-in@^0.1.3",
+    "rawSpec": "^0.1.3",
+    "scope": null,
+    "spec": ">=0.1.3 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/mixin-object"
+  ],
+  "_resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
+  "_shasum": "d8773908e31256109952b1fdb9b3fa867d2775e1",
+  "_shrinkwrap": null,
+  "_spec": "for-in@^0.1.3",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/mixin-object",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/for-in/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Paul Irish",
+      "url": "http://paulirish.com"
+    }
+  ],
+  "dependencies": {},
+  "description": "Iterate over the own and inherited enumerable properties of an object, and return an object with properties that evaluate to true from the callback. Exit early by returning `false`. JavaScript/Node.js",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "shasum": "d8773908e31256109952b1fdb9b3fa867d2775e1",
+    "tarball": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "243e4877c0d9421c05353f03e9f019e157f807dd",
+  "homepage": "https://github.com/jonschlinkert/for-in",
+  "keywords": [
+    "for",
+    "for-in",
+    "for-own",
+    "has",
+    "has-own",
+    "hasOwn",
+    "in",
+    "key",
+    "keys",
+    "object",
+    "own",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "for-in",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/for-in.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "arr-flatten",
+        "collection-map",
+        "for-own"
+      ]
+    },
+    "run": true,
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.1.8"
+}
diff --git a/input_devices/mag/node_modules/mixin-object/package.json b/input_devices/mag/node_modules/mixin-object/package.json
new file mode 100644
index 00000000..f9226593
--- /dev/null
+++ b/input_devices/mag/node_modules/mixin-object/package.json
@@ -0,0 +1,115 @@
+{
+  "_args": [
+    [
+      "mixin-object@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/shallow-clone"
+    ]
+  ],
+  "_from": "mixin-object@>=2.0.1 <3.0.0",
+  "_id": "mixin-object@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/mixin-object",
+  "_nodeVersion": "0.12.4",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "mixin-object",
+    "raw": "mixin-object@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": null,
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/shallow-clone"
+  ],
+  "_resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
+  "_shasum": "4fb949441dab182540f1fe035ba60e1947a5e57e",
+  "_shrinkwrap": null,
+  "_spec": "mixin-object@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/shallow-clone",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/mixin-object/issues"
+  },
+  "dependencies": {
+    "for-in": "^0.1.3",
+    "is-extendable": "^0.1.1"
+  },
+  "description": "Mixin the own and inherited properties of other objects onto the first object. Pass an empty object as the first arg to shallow clone.",
+  "devDependencies": {
+    "mocha": "^2.2.5",
+    "should": "^7.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "4fb949441dab182540f1fe035ba60e1947a5e57e",
+    "tarball": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "d01616d67f22220ef32c754c09d5caad46402b5a",
+  "homepage": "https://github.com/jonschlinkert/mixin-object",
+  "keywords": [
+    "assign",
+    "copy",
+    "extend",
+    "key",
+    "merge",
+    "mixin",
+    "object",
+    "objects",
+    "prop",
+    "properties",
+    "property",
+    "shallow",
+    "util",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "mixin-object",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/mixin-object.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verbiage": {
+    "related": {
+      "list": [
+        "assign-deep",
+        "defaults-deep",
+        "extend-shallow",
+        "for-in",
+        "for-own",
+        "is-plain-object",
+        "isobject",
+        "merge-deep",
+        "mixin-deep"
+      ]
+    }
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/mkdirp/.travis.yml b/input_devices/mag/node_modules/mkdirp/.travis.yml
new file mode 100644
index 00000000..74c57bf1
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
+  - "0.12"
+  - "iojs"
+before_install:
+  - npm install -g npm@~1.4.6
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/LICENSE b/input_devices/mag/node_modules/mkdirp/LICENSE
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/LICENSE
rename to input_devices/mag/node_modules/mkdirp/LICENSE
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/bin/cmd.js b/input_devices/mag/node_modules/mkdirp/bin/cmd.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/bin/cmd.js
rename to input_devices/mag/node_modules/mkdirp/bin/cmd.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/bin/usage.txt b/input_devices/mag/node_modules/mkdirp/bin/usage.txt
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/bin/usage.txt
rename to input_devices/mag/node_modules/mkdirp/bin/usage.txt
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/examples/pow.js b/input_devices/mag/node_modules/mkdirp/examples/pow.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/examples/pow.js
rename to input_devices/mag/node_modules/mkdirp/examples/pow.js
diff --git a/input_devices/mag/node_modules/mkdirp/index.js b/input_devices/mag/node_modules/mkdirp/index.js
new file mode 100644
index 00000000..6ce241b5
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/index.js
@@ -0,0 +1,98 @@
+var path = require('path');
+var fs = require('fs');
+var _0777 = parseInt('0777', 8);
+
+module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
+
+function mkdirP (p, opts, f, made) {
+    if (typeof opts === 'function') {
+        f = opts;
+        opts = {};
+    }
+    else if (!opts || typeof opts !== 'object') {
+        opts = { mode: opts };
+    }
+    
+    var mode = opts.mode;
+    var xfs = opts.fs || fs;
+    
+    if (mode === undefined) {
+        mode = _0777 & (~process.umask());
+    }
+    if (!made) made = null;
+    
+    var cb = f || function () {};
+    p = path.resolve(p);
+    
+    xfs.mkdir(p, mode, function (er) {
+        if (!er) {
+            made = made || p;
+            return cb(null, made);
+        }
+        switch (er.code) {
+            case 'ENOENT':
+                mkdirP(path.dirname(p), opts, function (er, made) {
+                    if (er) cb(er, made);
+                    else mkdirP(p, opts, cb, made);
+                });
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                xfs.stat(p, function (er2, stat) {
+                    // if the stat fails, then that's super weird.
+                    // let the original error be the failure reason.
+                    if (er2 || !stat.isDirectory()) cb(er, made)
+                    else cb(null, made);
+                });
+                break;
+        }
+    });
+}
+
+mkdirP.sync = function sync (p, opts, made) {
+    if (!opts || typeof opts !== 'object') {
+        opts = { mode: opts };
+    }
+    
+    var mode = opts.mode;
+    var xfs = opts.fs || fs;
+    
+    if (mode === undefined) {
+        mode = _0777 & (~process.umask());
+    }
+    if (!made) made = null;
+
+    p = path.resolve(p);
+
+    try {
+        xfs.mkdirSync(p, mode);
+        made = made || p;
+    }
+    catch (err0) {
+        switch (err0.code) {
+            case 'ENOENT' :
+                made = sync(path.dirname(p), opts, made);
+                sync(p, opts, made);
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                var stat;
+                try {
+                    stat = xfs.statSync(p);
+                }
+                catch (err1) {
+                    throw err0;
+                }
+                if (!stat.isDirectory()) throw err0;
+                break;
+        }
+    }
+
+    return made;
+};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/.travis.yml b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/.travis.yml
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/.travis.yml
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/.travis.yml
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/LICENSE b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/LICENSE
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/LICENSE
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/LICENSE
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/example/parse.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/example/parse.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/example/parse.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/example/parse.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/index.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/index.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/index.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/index.js
diff --git a/input_devices/mag/node_modules/mkdirp/node_modules/minimist/package.json b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/package.json
new file mode 100644
index 00000000..e054e209
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/package.json
@@ -0,0 +1,93 @@
+{
+  "_args": [
+    [
+      "minimist@0.0.8",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/mkdirp"
+    ]
+  ],
+  "_from": "minimist@0.0.8",
+  "_id": "minimist@0.0.8",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/mkdirp/minimist",
+  "_npmUser": {
+    "email": "mail@substack.net",
+    "name": "substack"
+  },
+  "_npmVersion": "1.4.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "minimist",
+    "raw": "minimist@0.0.8",
+    "rawSpec": "0.0.8",
+    "scope": null,
+    "spec": "0.0.8",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/mkdirp"
+  ],
+  "_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+  "_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
+  "_shrinkwrap": null,
+  "_spec": "minimist@0.0.8",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/mkdirp",
+  "author": {
+    "email": "mail@substack.net",
+    "name": "James Halliday",
+    "url": "http://substack.net"
+  },
+  "bugs": {
+    "url": "https://github.com/substack/minimist/issues"
+  },
+  "dependencies": {},
+  "description": "parse argument options",
+  "devDependencies": {
+    "tap": "~0.4.0",
+    "tape": "~1.0.4"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
+    "tarball": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
+  },
+  "homepage": "https://github.com/substack/minimist",
+  "keywords": [
+    "argv",
+    "getopt",
+    "optimist",
+    "parser"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "substack",
+      "email": "mail@substack.net"
+    }
+  ],
+  "name": "minimist",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/substack/minimist.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "testling": {
+    "browsers": [
+      "chrome/10",
+      "chrome/latest",
+      "ff/5",
+      "firefox/latest",
+      "ie/6..latest",
+      "opera/12",
+      "safari/5.1",
+      "safari/latest"
+    ],
+    "files": "test/*.js"
+  },
+  "version": "0.0.8"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/readme.markdown b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/readme.markdown
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/readme.markdown
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/readme.markdown
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/dash.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/dash.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/dash.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/dash.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/default_bool.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/default_bool.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/default_bool.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/default_bool.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/dotted.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/dotted.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/dotted.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/dotted.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/long.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/long.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/long.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/long.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/parse.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/parse.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/parse.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/parse.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/parse_modified.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/parse_modified.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/test/parse_modified.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/parse_modified.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/short.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/short.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/short.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/short.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/whitespace.js b/input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/whitespace.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/whitespace.js
rename to input_devices/mag/node_modules/mkdirp/node_modules/minimist/test/whitespace.js
diff --git a/input_devices/mag/node_modules/mkdirp/package.json b/input_devices/mag/node_modules/mkdirp/package.json
new file mode 100644
index 00000000..9b32b6e8
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/package.json
@@ -0,0 +1,86 @@
+{
+  "_args": [
+    [
+      "mkdirp@^0.5.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "mkdirp@>=0.5.1 <0.6.0",
+  "_id": "mkdirp@0.5.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/mkdirp",
+  "_nodeVersion": "2.0.0",
+  "_npmUser": {
+    "email": "substack@gmail.com",
+    "name": "substack"
+  },
+  "_npmVersion": "2.9.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "mkdirp",
+    "raw": "mkdirp@^0.5.1",
+    "rawSpec": "^0.5.1",
+    "scope": null,
+    "spec": ">=0.5.1 <0.6.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install",
+    "/tar-fs"
+  ],
+  "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+  "_shasum": "30057438eac6cf7f8c4767f38648d6697d75c903",
+  "_shrinkwrap": null,
+  "_spec": "mkdirp@^0.5.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "mail@substack.net",
+    "name": "James Halliday",
+    "url": "http://substack.net"
+  },
+  "bin": {
+    "mkdirp": "bin/cmd.js"
+  },
+  "bugs": {
+    "url": "https://github.com/substack/node-mkdirp/issues"
+  },
+  "dependencies": {
+    "minimist": "0.0.8"
+  },
+  "description": "Recursively mkdir, like `mkdir -p`",
+  "devDependencies": {
+    "mock-fs": "2 >=2.7.0",
+    "tap": "1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "30057438eac6cf7f8c4767f38648d6697d75c903",
+    "tarball": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz"
+  },
+  "gitHead": "d4eff0f06093aed4f387e88e9fc301cb76beedc7",
+  "homepage": "https://github.com/substack/node-mkdirp#readme",
+  "keywords": [
+    "directory",
+    "mkdir"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "substack",
+      "email": "mail@substack.net"
+    }
+  ],
+  "name": "mkdirp",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/substack/node-mkdirp.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "version": "0.5.1"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/readme.markdown b/input_devices/mag/node_modules/mkdirp/readme.markdown
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/readme.markdown
rename to input_devices/mag/node_modules/mkdirp/readme.markdown
diff --git a/input_devices/mag/node_modules/mkdirp/test/chmod.js b/input_devices/mag/node_modules/mkdirp/test/chmod.js
new file mode 100644
index 00000000..6a404b93
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/chmod.js
@@ -0,0 +1,41 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+var _0744 = parseInt('0744', 8);
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    ps.push(dir);
+}
+
+var file = ps.join('/');
+
+test('chmod-pre', function (t) {
+    var mode = _0744
+    mkdirp(file, mode, function (er) {
+        t.ifError(er, 'should not error');
+        fs.stat(file, function (er, stat) {
+            t.ifError(er, 'should exist');
+            t.ok(stat && stat.isDirectory(), 'should be directory');
+            t.equal(stat && stat.mode & _0777, mode, 'should be 0744');
+            t.end();
+        });
+    });
+});
+
+test('chmod', function (t) {
+    var mode = _0755
+    mkdirp(file, mode, function (er) {
+        t.ifError(er, 'should not error');
+        fs.stat(file, function (er, stat) {
+            t.ifError(er, 'should exist');
+            t.ok(stat && stat.isDirectory(), 'should be directory');
+            t.end();
+        });
+    });
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/clobber.js b/input_devices/mag/node_modules/mkdirp/test/clobber.js
new file mode 100644
index 00000000..2433b9ad
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/clobber.js
@@ -0,0 +1,38 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+var _0755 = parseInt('0755', 8);
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    ps.push(dir);
+}
+
+var file = ps.join('/');
+
+// a file in the way
+var itw = ps.slice(0, 3).join('/');
+
+
+test('clobber-pre', function (t) {
+    console.error("about to write to "+itw)
+    fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
+
+    fs.stat(itw, function (er, stat) {
+        t.ifError(er)
+        t.ok(stat && stat.isFile(), 'should be file')
+        t.end()
+    })
+})
+
+test('clobber', function (t) {
+    t.plan(2);
+    mkdirp(file, _0755, function (err) {
+        t.ok(err);
+        t.equal(err.code, 'ENOTDIR');
+        t.end();
+    });
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/mkdirp.js b/input_devices/mag/node_modules/mkdirp/test/mkdirp.js
new file mode 100644
index 00000000..eaa8921c
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/mkdirp.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('woo', function (t) {
+    t.plan(5);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var file = '/tmp/' + [x,y,z].join('/');
+    
+    mkdirp(file, _0755, function (err) {
+        t.ifError(err);
+        exists(file, function (ex) {
+            t.ok(ex, 'file created');
+            fs.stat(file, function (err, stat) {
+                t.ifError(err);
+                t.equal(stat.mode & _0777, _0755);
+                t.ok(stat.isDirectory(), 'target not a directory');
+            })
+        })
+    });
+});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/opts_fs.js b/input_devices/mag/node_modules/mkdirp/test/opts_fs.js
similarity index 81%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/opts_fs.js
rename to input_devices/mag/node_modules/mkdirp/test/opts_fs.js
index f1fbeca1..97186b62 100644
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/opts_fs.js
+++ b/input_devices/mag/node_modules/mkdirp/test/opts_fs.js
@@ -2,6 +2,8 @@ var mkdirp = require('../');
 var path = require('path');
 var test = require('tap').test;
 var mockfs = require('mock-fs');
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
 
 test('opts.fs', function (t) {
     t.plan(5);
@@ -13,13 +15,13 @@ test('opts.fs', function (t) {
     var file = '/beep/boop/' + [x,y,z].join('/');
     var xfs = mockfs.fs();
     
-    mkdirp(file, { fs: xfs, mode: 0755 }, function (err) {
+    mkdirp(file, { fs: xfs, mode: _0755 }, function (err) {
         t.ifError(err);
         xfs.exists(file, function (ex) {
             t.ok(ex, 'created file');
             xfs.stat(file, function (err, stat) {
                 t.ifError(err);
-                t.equal(stat.mode & 0777, 0755);
+                t.equal(stat.mode & _0777, _0755);
                 t.ok(stat.isDirectory(), 'target not a directory');
             });
         });
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/opts_fs_sync.js b/input_devices/mag/node_modules/mkdirp/test/opts_fs_sync.js
similarity index 81%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/opts_fs_sync.js
rename to input_devices/mag/node_modules/mkdirp/test/opts_fs_sync.js
index 224b5064..6c370aa6 100644
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/opts_fs_sync.js
+++ b/input_devices/mag/node_modules/mkdirp/test/opts_fs_sync.js
@@ -2,6 +2,8 @@ var mkdirp = require('../');
 var path = require('path');
 var test = require('tap').test;
 var mockfs = require('mock-fs');
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
 
 test('opts.fs sync', function (t) {
     t.plan(4);
@@ -13,12 +15,12 @@ test('opts.fs sync', function (t) {
     var file = '/beep/boop/' + [x,y,z].join('/');
     var xfs = mockfs.fs();
     
-    mkdirp.sync(file, { fs: xfs, mode: 0755 });
+    mkdirp.sync(file, { fs: xfs, mode: _0755 });
     xfs.exists(file, function (ex) {
         t.ok(ex, 'created file');
         xfs.stat(file, function (err, stat) {
             t.ifError(err);
-            t.equal(stat.mode & 0777, 0755);
+            t.equal(stat.mode & _0777, _0755);
             t.ok(stat.isDirectory(), 'target not a directory');
         });
     });
diff --git a/input_devices/mag/node_modules/mkdirp/test/perm.js b/input_devices/mag/node_modules/mkdirp/test/perm.js
new file mode 100644
index 00000000..fbce44b8
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/perm.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('async perm', function (t) {
+    t.plan(5);
+    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
+    
+    mkdirp(file, _0755, function (err) {
+        t.ifError(err);
+        exists(file, function (ex) {
+            t.ok(ex, 'file created');
+            fs.stat(file, function (err, stat) {
+                t.ifError(err);
+                t.equal(stat.mode & _0777, _0755);
+                t.ok(stat.isDirectory(), 'target not a directory');
+            })
+        })
+    });
+});
+
+test('async root perm', function (t) {
+    mkdirp('/tmp', _0755, function (err) {
+        if (err) t.fail(err);
+        t.end();
+    });
+    t.end();
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/perm_sync.js b/input_devices/mag/node_modules/mkdirp/test/perm_sync.js
new file mode 100644
index 00000000..398229fe
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/perm_sync.js
@@ -0,0 +1,36 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('sync perm', function (t) {
+    t.plan(4);
+    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
+    
+    mkdirp.sync(file, _0755);
+    exists(file, function (ex) {
+        t.ok(ex, 'file created');
+        fs.stat(file, function (err, stat) {
+            t.ifError(err);
+            t.equal(stat.mode & _0777, _0755);
+            t.ok(stat.isDirectory(), 'target not a directory');
+        });
+    });
+});
+
+test('sync root perm', function (t) {
+    t.plan(3);
+    
+    var file = '/tmp';
+    mkdirp.sync(file, _0755);
+    exists(file, function (ex) {
+        t.ok(ex, 'file created');
+        fs.stat(file, function (err, stat) {
+            t.ifError(err);
+            t.ok(stat.isDirectory(), 'target not a directory');
+        })
+    });
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/race.js b/input_devices/mag/node_modules/mkdirp/test/race.js
new file mode 100644
index 00000000..b0b9e183
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/race.js
@@ -0,0 +1,37 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('race', function (t) {
+    t.plan(10);
+    var ps = [ '', 'tmp' ];
+    
+    for (var i = 0; i < 25; i++) {
+        var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+        ps.push(dir);
+    }
+    var file = ps.join('/');
+    
+    var res = 2;
+    mk(file);
+    
+    mk(file);
+    
+    function mk (file, cb) {
+        mkdirp(file, _0755, function (err) {
+            t.ifError(err);
+            exists(file, function (ex) {
+                t.ok(ex, 'file created');
+                fs.stat(file, function (err, stat) {
+                    t.ifError(err);
+                    t.equal(stat.mode & _0777, _0755);
+                    t.ok(stat.isDirectory(), 'target not a directory');
+                });
+            })
+        });
+    }
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/rel.js b/input_devices/mag/node_modules/mkdirp/test/rel.js
new file mode 100644
index 00000000..4ddb3427
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/rel.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('rel', function (t) {
+    t.plan(5);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var cwd = process.cwd();
+    process.chdir('/tmp');
+    
+    var file = [x,y,z].join('/');
+    
+    mkdirp(file, _0755, function (err) {
+        t.ifError(err);
+        exists(file, function (ex) {
+            t.ok(ex, 'file created');
+            fs.stat(file, function (err, stat) {
+                t.ifError(err);
+                process.chdir(cwd);
+                t.equal(stat.mode & _0777, _0755);
+                t.ok(stat.isDirectory(), 'target not a directory');
+            })
+        })
+    });
+});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/return.js b/input_devices/mag/node_modules/mkdirp/test/return.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/return.js
rename to input_devices/mag/node_modules/mkdirp/test/return.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/return_sync.js b/input_devices/mag/node_modules/mkdirp/test/return_sync.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/return_sync.js
rename to input_devices/mag/node_modules/mkdirp/test/return_sync.js
diff --git a/input_devices/mag/node_modules/mkdirp/test/root.js b/input_devices/mag/node_modules/mkdirp/test/root.js
new file mode 100644
index 00000000..9e7d079d
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/root.js
@@ -0,0 +1,19 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+var _0755 = parseInt('0755', 8);
+
+test('root', function (t) {
+    // '/' on unix, 'c:/' on windows.
+    var file = path.resolve('/');
+
+    mkdirp(file, _0755, function (err) {
+        if (err) throw err
+        fs.stat(file, function (er, stat) {
+            if (er) throw er
+            t.ok(stat.isDirectory(), 'target is a directory');
+            t.end();
+        })
+    });
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/sync.js b/input_devices/mag/node_modules/mkdirp/test/sync.js
new file mode 100644
index 00000000..8c8dc938
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/sync.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('sync', function (t) {
+    t.plan(4);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+    var file = '/tmp/' + [x,y,z].join('/');
+
+    try {
+        mkdirp.sync(file, _0755);
+    } catch (err) {
+        t.fail(err);
+        return t.end();
+    }
+
+    exists(file, function (ex) {
+        t.ok(ex, 'file created');
+        fs.stat(file, function (err, stat) {
+            t.ifError(err);
+            t.equal(stat.mode & _0777, _0755);
+            t.ok(stat.isDirectory(), 'target not a directory');
+        });
+    });
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/umask.js b/input_devices/mag/node_modules/mkdirp/test/umask.js
new file mode 100644
index 00000000..2033c63a
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/umask.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('implicit mode from umask', function (t) {
+    t.plan(5);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var file = '/tmp/' + [x,y,z].join('/');
+    
+    mkdirp(file, function (err) {
+        t.ifError(err);
+        exists(file, function (ex) {
+            t.ok(ex, 'file created');
+            fs.stat(file, function (err, stat) {
+                t.ifError(err);
+                t.equal(stat.mode & _0777, _0777 & (~process.umask()));
+                t.ok(stat.isDirectory(), 'target not a directory');
+            });
+        })
+    });
+});
diff --git a/input_devices/mag/node_modules/mkdirp/test/umask_sync.js b/input_devices/mag/node_modules/mkdirp/test/umask_sync.js
new file mode 100644
index 00000000..11a76147
--- /dev/null
+++ b/input_devices/mag/node_modules/mkdirp/test/umask_sync.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var exists = fs.exists || path.exists;
+var test = require('tap').test;
+var _0777 = parseInt('0777', 8);
+var _0755 = parseInt('0755', 8);
+
+test('umask sync modes', function (t) {
+    t.plan(4);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+    var file = '/tmp/' + [x,y,z].join('/');
+
+    try {
+        mkdirp.sync(file);
+    } catch (err) {
+        t.fail(err);
+        return t.end();
+    }
+
+    exists(file, function (ex) {
+        t.ok(ex, 'file created');
+        fs.stat(file, function (err, stat) {
+            t.ifError(err);
+            t.equal(stat.mode & _0777, (_0777 & (~process.umask())));
+            t.ok(stat.isDirectory(), 'target not a directory');
+        });
+    });
+});
diff --git a/input_devices/mag/node_modules/ms/index.js b/input_devices/mag/node_modules/ms/index.js
new file mode 100644
index 00000000..72297501
--- /dev/null
+++ b/input_devices/mag/node_modules/ms/index.js
@@ -0,0 +1,162 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var w = d * 7;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+  options = options || {};
+  var type = typeof val;
+  if (type === 'string' && val.length > 0) {
+    return parse(val);
+  } else if (type === 'number' && isNaN(val) === false) {
+    return options.long ? fmtLong(val) : fmtShort(val);
+  }
+  throw new Error(
+    'val is not a non-empty string or a valid number. val=' +
+      JSON.stringify(val)
+  );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  str = String(str);
+  if (str.length > 100) {
+    return;
+  }
+  var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
+    str
+  );
+  if (!match) {
+    return;
+  }
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'yrs':
+    case 'yr':
+    case 'y':
+      return n * y;
+    case 'weeks':
+    case 'week':
+    case 'w':
+      return n * w;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'hrs':
+    case 'hr':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'mins':
+    case 'min':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 'secs':
+    case 'sec':
+    case 's':
+      return n * s;
+    case 'milliseconds':
+    case 'millisecond':
+    case 'msecs':
+    case 'msec':
+    case 'ms':
+      return n;
+    default:
+      return undefined;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+  var msAbs = Math.abs(ms);
+  if (msAbs >= d) {
+    return Math.round(ms / d) + 'd';
+  }
+  if (msAbs >= h) {
+    return Math.round(ms / h) + 'h';
+  }
+  if (msAbs >= m) {
+    return Math.round(ms / m) + 'm';
+  }
+  if (msAbs >= s) {
+    return Math.round(ms / s) + 's';
+  }
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+  var msAbs = Math.abs(ms);
+  if (msAbs >= d) {
+    return plural(ms, msAbs, d, 'day');
+  }
+  if (msAbs >= h) {
+    return plural(ms, msAbs, h, 'hour');
+  }
+  if (msAbs >= m) {
+    return plural(ms, msAbs, m, 'minute');
+  }
+  if (msAbs >= s) {
+    return plural(ms, msAbs, s, 'second');
+  }
+  return ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, msAbs, n, name) {
+  var isPlural = msAbs >= n * 1.5;
+  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
+}
diff --git a/input_devices/mag/node_modules/ms/license.md b/input_devices/mag/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/input_devices/mag/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/input_devices/mag/node_modules/ms/package.json b/input_devices/mag/node_modules/ms/package.json
new file mode 100644
index 00000000..0a1b20da
--- /dev/null
+++ b/input_devices/mag/node_modules/ms/package.json
@@ -0,0 +1,102 @@
+{
+  "_args": [
+    [
+      "ms@^2.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/debug"
+    ]
+  ],
+  "_from": "ms@>=2.1.1 <3.0.0",
+  "_id": "ms@2.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ms",
+  "_nodeVersion": "9.2.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/ms-2.1.1.tgz_1512066615982_0.7117063472978771"
+  },
+  "_npmUser": {
+    "email": "leo@zeit.co",
+    "name": "leo"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ms",
+    "raw": "ms@^2.1.1",
+    "rawSpec": "^2.1.1",
+    "scope": null,
+    "spec": ">=2.1.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/debug"
+  ],
+  "_resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+  "_shasum": "30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a",
+  "_shrinkwrap": null,
+  "_spec": "ms@^2.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/debug",
+  "bugs": {
+    "url": "https://github.com/zeit/ms/issues"
+  },
+  "dependencies": {},
+  "description": "Tiny millisecond conversion utility",
+  "devDependencies": {
+    "eslint": "4.12.1",
+    "expect.js": "0.3.1",
+    "husky": "0.14.3",
+    "lint-staged": "5.0.0",
+    "mocha": "4.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+    "shasum": "30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a",
+    "tarball": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz"
+  },
+  "eslintConfig": {
+    "env": {
+      "es6": true,
+      "node": true
+    },
+    "extends": "eslint:recommended"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "fe0bae301a6c41f68a01595658a4f4f0dcba0e84",
+  "homepage": "https://github.com/zeit/ms#readme",
+  "license": "MIT",
+  "lint-staged": {
+    "*.js": [
+      "git add",
+      "npm run lint",
+      "prettier --single-quote --write"
+    ]
+  },
+  "main": "./index",
+  "maintainers": [
+    {
+      "name": "leo",
+      "email": "leo@zeit.co"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "name": "ms",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zeit/ms.git"
+  },
+  "scripts": {
+    "lint": "eslint lib/* bin/*",
+    "precommit": "lint-staged",
+    "test": "mocha tests.js"
+  },
+  "version": "2.1.1"
+}
diff --git a/input_devices/mag/node_modules/ms/readme.md b/input_devices/mag/node_modules/ms/readme.md
new file mode 100644
index 00000000..bb767293
--- /dev/null
+++ b/input_devices/mag/node_modules/ms/readme.md
@@ -0,0 +1,60 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days')  // 172800000
+ms('1d')      // 86400000
+ms('10h')     // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h')      // 7200000
+ms('1m')      // 60000
+ms('5s')      // 5000
+ms('1y')      // 31557600000
+ms('100')     // 100
+ms('-3 days') // -259200000
+ms('-1h')     // -3600000
+ms('-200')    // -200
+```
+
+### Convert from Milliseconds
+
+```js
+ms(60000)             // "1m"
+ms(2 * 60000)         // "2m"
+ms(-3 * 60000)        // "-3m"
+ms(ms('10 hours'))    // "10h"
+```
+
+### Time Format Written-Out
+
+```js
+ms(60000, { long: true })             // "1 minute"
+ms(2 * 60000, { long: true })         // "2 minutes"
+ms(-3 * 60000, { long: true })        // "-3 minutes"
+ms(ms('10 hours'), { long: true })    // "10 hours"
+```
+
+## Features
+
+- Works both in [Node.js](https://nodejs.org) and in the browser
+- If a number is supplied to `ms`, a string with a unit is returned
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`)
+- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned
+
+## Related Packages
+
+- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time.
+
+## Caught a Bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/input_devices/mag/node_modules/mute-stream/.nyc_output/33508.json b/input_devices/mag/node_modules/mute-stream/.nyc_output/33508.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/.nyc_output/33508.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/mute-stream/.nyc_output/33510.json b/input_devices/mag/node_modules/mute-stream/.nyc_output/33510.json
new file mode 100644
index 00000000..1d044423
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/.nyc_output/33510.json
@@ -0,0 +1 @@
+{"./mute.js":{"path":"./mute.js","s":{"1":1,"2":1,"3":1,"4":7,"5":7,"6":7,"7":7,"8":7,"9":7,"10":7,"11":7,"12":1,"13":1,"14":1,"15":10,"16":1,"17":6,"18":1,"19":1,"20":5,"21":1,"22":1,"23":8,"24":1,"25":2,"26":1,"27":5,"28":1,"29":5,"30":1,"31":2,"32":2,"33":1,"34":2,"35":2,"36":1,"37":2,"38":2,"39":1,"40":25,"41":13,"42":5,"43":8,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":8,"51":0,"52":0,"53":0,"54":8,"55":20,"56":1,"57":2,"58":2,"59":0,"60":2,"61":2,"62":0,"63":2,"64":1,"65":3,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":1,"73":1,"74":1},"b":{"1":[7,5],"2":[7,7],"3":[3,5],"4":[3,2],"5":[4,1],"6":[0,1],"7":[4,1],"8":[0,1],"9":[2,0],"10":[2,0],"11":[13,12],"12":[5,8],"13":[0,8],"14":[0,0],"15":[0,8],"16":[8,0,0],"17":[2,0],"18":[0,2],"19":[2,1],"20":[0,2],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0]},"f":{"1":7,"2":10,"3":6,"4":5,"5":8,"6":2,"7":5,"8":5,"9":2,"10":2,"11":2,"12":25,"13":2,"14":3,"15":0},"fnMap":{"1":{"name":"MuteStream","line":7,"loc":{"start":{"line":7,"column":0},"end":{"line":7,"column":27}}},"2":{"name":"(anonymous_2)","line":29,"loc":{"start":{"line":29,"column":28},"end":{"line":29,"column":40}}},"3":{"name":"(anonymous_3)","line":33,"loc":{"start":{"line":33,"column":30},"end":{"line":33,"column":42}}},"4":{"name":"onPipe","line":44,"loc":{"start":{"line":44,"column":0},"end":{"line":44,"column":22}}},"5":{"name":"getIsTTY","line":55,"loc":{"start":{"line":55,"column":0},"end":{"line":55,"column":21}}},"6":{"name":"setIsTTY","line":63,"loc":{"start":{"line":63,"column":0},"end":{"line":63,"column":26}}},"7":{"name":"(anonymous_7)","line":73,"loc":{"start":{"line":73,"column":7},"end":{"line":73,"column":19}}},"8":{"name":"(anonymous_8)","line":80,"loc":{"start":{"line":80,"column":7},"end":{"line":80,"column":19}}},"9":{"name":"(anonymous_9)","line":87,"loc":{"start":{"line":87,"column":28},"end":{"line":87,"column":53}}},"10":{"name":"(anonymous_10)","line":92,"loc":{"start":{"line":92,"column":29},"end":{"line":92,"column":41}}},"11":{"name":"(anonymous_11)","line":96,"loc":{"start":{"line":96,"column":30},"end":{"line":96,"column":42}}},"12":{"name":"(anonymous_12)","line":100,"loc":{"start":{"line":100,"column":29},"end":{"line":100,"column":42}}},"13":{"name":"(anonymous_13)","line":124,"loc":{"start":{"line":124,"column":27},"end":{"line":124,"column":40}}},"14":{"name":"proxy","line":136,"loc":{"start":{"line":136,"column":0},"end":{"line":136,"column":20}}},"15":{"name":"(anonymous_15)","line":136,"loc":{"start":{"line":136,"column":29},"end":{"line":136,"column":41}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":27}},"3":{"start":{"line":7,"column":0},"end":{"line":20,"column":1}},"4":{"start":{"line":8,"column":2},"end":{"line":8,"column":20}},"5":{"start":{"line":9,"column":2},"end":{"line":9,"column":19}},"6":{"start":{"line":10,"column":2},"end":{"line":10,"column":38}},"7":{"start":{"line":11,"column":2},"end":{"line":11,"column":20}},"8":{"start":{"line":12,"column":2},"end":{"line":12,"column":31}},"9":{"start":{"line":13,"column":2},"end":{"line":13,"column":29}},"10":{"start":{"line":18,"column":2},"end":{"line":18,"column":36}},"11":{"start":{"line":19,"column":2},"end":{"line":19,"column":26}},"12":{"start":{"line":22,"column":0},"end":{"line":22,"column":54}},"13":{"start":{"line":24,"column":0},"end":{"line":27,"column":2}},"14":{"start":{"line":29,"column":0},"end":{"line":31,"column":1}},"15":{"start":{"line":30,"column":2},"end":{"line":30,"column":19}},"16":{"start":{"line":33,"column":0},"end":{"line":35,"column":1}},"17":{"start":{"line":34,"column":2},"end":{"line":34,"column":20}},"18":{"start":{"line":37,"column":0},"end":{"line":42,"column":2}},"19":{"start":{"line":44,"column":0},"end":{"line":46,"column":1}},"20":{"start":{"line":45,"column":2},"end":{"line":45,"column":17}},"21":{"start":{"line":48,"column":0},"end":{"line":53,"column":2}},"22":{"start":{"line":55,"column":0},"end":{"line":60,"column":1}},"23":{"start":{"line":56,"column":2},"end":{"line":59,"column":9}},"24":{"start":{"line":63,"column":0},"end":{"line":70,"column":1}},"25":{"start":{"line":64,"column":2},"end":{"line":69,"column":4}},"26":{"start":{"line":72,"column":0},"end":{"line":77,"column":44}},"27":{"start":{"line":74,"column":4},"end":{"line":76,"column":23}},"28":{"start":{"line":79,"column":0},"end":{"line":84,"column":44}},"29":{"start":{"line":81,"column":4},"end":{"line":83,"column":23}},"30":{"start":{"line":87,"column":0},"end":{"line":90,"column":1}},"31":{"start":{"line":88,"column":2},"end":{"line":88,"column":19}},"32":{"start":{"line":89,"column":2},"end":{"line":89,"column":56}},"33":{"start":{"line":92,"column":0},"end":{"line":94,"column":1}},"34":{"start":{"line":93,"column":2},"end":{"line":93,"column":41}},"35":{"start":{"line":93,"column":17},"end":{"line":93,"column":41}},"36":{"start":{"line":96,"column":0},"end":{"line":98,"column":1}},"37":{"start":{"line":97,"column":2},"end":{"line":97,"column":42}},"38":{"start":{"line":97,"column":17},"end":{"line":97,"column":42}},"39":{"start":{"line":100,"column":0},"end":{"line":122,"column":1}},"40":{"start":{"line":101,"column":2},"end":{"line":120,"column":3}},"41":{"start":{"line":102,"column":4},"end":{"line":102,"column":34}},"42":{"start":{"line":102,"column":23},"end":{"line":102,"column":34}},"43":{"start":{"line":103,"column":4},"end":{"line":119,"column":5}},"44":{"start":{"line":104,"column":6},"end":{"line":108,"column":7}},"45":{"start":{"line":105,"column":8},"end":{"line":105,"column":42}},"46":{"start":{"line":106,"column":8},"end":{"line":106,"column":42}},"47":{"start":{"line":107,"column":8},"end":{"line":107,"column":29}},"48":{"start":{"line":109,"column":6},"end":{"line":109,"column":29}},"49":{"start":{"line":110,"column":6},"end":{"line":110,"column":33}},"50":{"start":{"line":112,"column":6},"end":{"line":117,"column":7}},"51":{"start":{"line":114,"column":8},"end":{"line":114,"column":32}},"52":{"start":{"line":115,"column":8},"end":{"line":115,"column":39}},"53":{"start":{"line":116,"column":8},"end":{"line":116,"column":41}},"54":{"start":{"line":118,"column":6},"end":{"line":118,"column":50}},"55":{"start":{"line":121,"column":2},"end":{"line":121,"column":22}},"56":{"start":{"line":124,"column":0},"end":{"line":134,"column":1}},"57":{"start":{"line":125,"column":2},"end":{"line":131,"column":3}},"58":{"start":{"line":126,"column":4},"end":{"line":130,"column":5}},"59":{"start":{"line":127,"column":6},"end":{"line":127,"column":50}},"60":{"start":{"line":129,"column":6},"end":{"line":129,"column":14}},"61":{"start":{"line":132,"column":2},"end":{"line":132,"column":29}},"62":{"start":{"line":132,"column":9},"end":{"line":132,"column":29}},"63":{"start":{"line":133,"column":2},"end":{"line":133,"column":18}},"64":{"start":{"line":136,"column":0},"end":{"line":141,"column":2}},"65":{"start":{"line":136,"column":22},"end":{"line":141,"column":1}},"66":{"start":{"line":137,"column":2},"end":{"line":137,"column":20}},"67":{"start":{"line":138,"column":2},"end":{"line":138,"column":19}},"68":{"start":{"line":139,"column":2},"end":{"line":139,"column":43}},"69":{"start":{"line":139,"column":18},"end":{"line":139,"column":43}},"70":{"start":{"line":140,"column":2},"end":{"line":140,"column":43}},"71":{"start":{"line":140,"column":18},"end":{"line":140,"column":43}},"72":{"start":{"line":143,"column":0},"end":{"line":143,"column":47}},"73":{"start":{"line":144,"column":0},"end":{"line":144,"column":55}},"74":{"start":{"line":145,"column":0},"end":{"line":145,"column":43}}},"branchMap":{"1":{"line":9,"type":"binary-expr","locations":[{"start":{"line":9,"column":9},"end":{"line":9,"column":13}},{"start":{"line":9,"column":17},"end":{"line":9,"column":19}}]},"2":{"line":18,"type":"binary-expr","locations":[{"start":{"line":18,"column":17},"end":{"line":18,"column":28}},{"start":{"line":18,"column":32},"end":{"line":18,"column":36}}]},"3":{"line":56,"type":"cond-expr","locations":[{"start":{"line":56,"column":25},"end":{"line":56,"column":41}},{"start":{"line":57,"column":10},"end":{"line":58,"column":15}}]},"4":{"line":57,"type":"cond-expr","locations":[{"start":{"line":57,"column":24},"end":{"line":57,"column":39}},{"start":{"line":58,"column":10},"end":{"line":58,"column":15}}]},"5":{"line":74,"type":"cond-expr","locations":[{"start":{"line":74,"column":25},"end":{"line":74,"column":40}},{"start":{"line":75,"column":12},"end":{"line":76,"column":21}}]},"6":{"line":75,"type":"cond-expr","locations":[{"start":{"line":75,"column":24},"end":{"line":75,"column":38}},{"start":{"line":76,"column":12},"end":{"line":76,"column":21}}]},"7":{"line":81,"type":"cond-expr","locations":[{"start":{"line":81,"column":25},"end":{"line":81,"column":43}},{"start":{"line":82,"column":12},"end":{"line":83,"column":21}}]},"8":{"line":82,"type":"cond-expr","locations":[{"start":{"line":82,"column":24},"end":{"line":82,"column":41}},{"start":{"line":83,"column":12},"end":{"line":83,"column":21}}]},"9":{"line":93,"type":"if","locations":[{"start":{"line":93,"column":2},"end":{"line":93,"column":2}},{"start":{"line":93,"column":2},"end":{"line":93,"column":2}}]},"10":{"line":97,"type":"if","locations":[{"start":{"line":97,"column":2},"end":{"line":97,"column":2}},{"start":{"line":97,"column":2},"end":{"line":97,"column":2}}]},"11":{"line":101,"type":"if","locations":[{"start":{"line":101,"column":2},"end":{"line":101,"column":2}},{"start":{"line":101,"column":2},"end":{"line":101,"column":2}}]},"12":{"line":102,"type":"if","locations":[{"start":{"line":102,"column":4},"end":{"line":102,"column":4}},{"start":{"line":102,"column":4},"end":{"line":102,"column":4}}]},"13":{"line":103,"type":"if","locations":[{"start":{"line":103,"column":4},"end":{"line":103,"column":4}},{"start":{"line":103,"column":4},"end":{"line":103,"column":4}}]},"14":{"line":104,"type":"if","locations":[{"start":{"line":104,"column":6},"end":{"line":104,"column":6}},{"start":{"line":104,"column":6},"end":{"line":104,"column":6}}]},"15":{"line":112,"type":"if","locations":[{"start":{"line":112,"column":6},"end":{"line":112,"column":6}},{"start":{"line":112,"column":6},"end":{"line":112,"column":6}}]},"16":{"line":112,"type":"binary-expr","locations":[{"start":{"line":112,"column":10},"end":{"line":112,"column":22}},{"start":{"line":112,"column":26},"end":{"line":112,"column":42}},{"start":{"line":113,"column":10},"end":{"line":113,"column":39}}]},"17":{"line":125,"type":"if","locations":[{"start":{"line":125,"column":2},"end":{"line":125,"column":2}},{"start":{"line":125,"column":2},"end":{"line":125,"column":2}}]},"18":{"line":126,"type":"if","locations":[{"start":{"line":126,"column":4},"end":{"line":126,"column":4}},{"start":{"line":126,"column":4},"end":{"line":126,"column":4}}]},"19":{"line":126,"type":"binary-expr","locations":[{"start":{"line":126,"column":8},"end":{"line":126,"column":9}},{"start":{"line":126,"column":13},"end":{"line":126,"column":25}}]},"20":{"line":132,"type":"if","locations":[{"start":{"line":132,"column":2},"end":{"line":132,"column":2}},{"start":{"line":132,"column":2},"end":{"line":132,"column":2}}]},"21":{"line":139,"type":"if","locations":[{"start":{"line":139,"column":2},"end":{"line":139,"column":2}},{"start":{"line":139,"column":2},"end":{"line":139,"column":2}}]},"22":{"line":139,"type":"binary-expr","locations":[{"start":{"line":139,"column":6},"end":{"line":139,"column":7}},{"start":{"line":139,"column":11},"end":{"line":139,"column":16}}]},"23":{"line":140,"type":"if","locations":[{"start":{"line":140,"column":2},"end":{"line":140,"column":2}},{"start":{"line":140,"column":2},"end":{"line":140,"column":2}}]},"24":{"line":140,"type":"binary-expr","locations":[{"start":{"line":140,"column":6},"end":{"line":140,"column":7}},{"start":{"line":140,"column":11},"end":{"line":140,"column":16}}]}}}}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/mute-stream/.travis.yml b/input_devices/mag/node_modules/mute-stream/.travis.yml
new file mode 100644
index 00000000..99f2bbf5
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/.travis.yml
@@ -0,0 +1,9 @@
+language: node_js
+language: node_js
+node_js:
+  - '0.8'
+  - '0.10'
+  - '0.12'
+  - 'iojs'
+before_install:
+  - npm install -g npm@latest
diff --git a/input_devices/mag/node_modules/mute-stream/LICENSE b/input_devices/mag/node_modules/mute-stream/LICENSE
new file mode 100644
index 00000000..19129e31
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/mute-stream/README.md b/input_devices/mag/node_modules/mute-stream/README.md
new file mode 100644
index 00000000..8ab1238e
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/README.md
@@ -0,0 +1,68 @@
+# mute-stream
+
+Bytes go in, but they don't come out (when muted).
+
+This is a basic pass-through stream, but when muted, the bytes are
+silently dropped, rather than being passed through.
+
+## Usage
+
+```javascript
+var MuteStream = require('mute-stream')
+
+var ms = new MuteStream(options)
+
+ms.pipe(process.stdout)
+ms.write('foo') // writes 'foo' to stdout
+ms.mute()
+ms.write('bar') // does not write 'bar'
+ms.unmute()
+ms.write('baz') // writes 'baz' to stdout
+
+// can also be used to mute incoming data
+var ms = new MuteStream
+input.pipe(ms)
+
+ms.on('data', function (c) {
+  console.log('data: ' + c)
+})
+
+input.emit('data', 'foo') // logs 'foo'
+ms.mute()
+input.emit('data', 'bar') // does not log 'bar'
+ms.unmute()
+input.emit('data', 'baz') // logs 'baz'
+```
+
+## Options
+
+All options are optional.
+
+* `replace` Set to a string to replace each character with the
+  specified string when muted.  (So you can show `****` instead of the
+  password, for example.)
+
+* `prompt` If you are using a replacement char, and also using a
+  prompt with a readline stream (as for a `Password: *****` input),
+  then specify what the prompt is so that backspace will work
+  properly.  Otherwise, pressing backspace will overwrite the prompt
+  with the replacement character, which is weird.
+
+## ms.mute()
+
+Set `muted` to `true`.  Turns `.write()` into a no-op.
+
+## ms.unmute()
+
+Set `muted` to `false`
+
+## ms.isTTY
+
+True if the pipe destination is a TTY, or if the incoming pipe source is
+a TTY.
+
+## Other stream methods...
+
+The other standard readable and writable stream methods are all
+available.  The MuteStream object acts as a facade to its pipe source
+and destination.
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/index.html b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/index.html
new file mode 100644
index 00000000..de0934d6
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/index.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Code coverage report for __root__/</title>
+    <meta charset="utf-8" />
+    <link rel="stylesheet" href="../prettify.css" />
+    <link rel="stylesheet" href="../base.css" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <style type='text/css'>
+        .coverage-summary .sorter {
+            background-image: url(../sort-arrow-sprite.png);
+        }
+    </style>
+</head>
+<body>
+<div class='wrapper'>
+  <div class='pad1'>
+    <h1>
+      <a href="../index.html">all files</a> __root__/
+    </h1>
+    <div class='clearfix'>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">77.03% </span>
+        <span class="quiet">Statements</span>
+        <span class='fraction'>57/74</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">57.14% </span>
+        <span class="quiet">Branches</span>
+        <span class='fraction'>28/49</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">93.33% </span>
+        <span class="quiet">Functions</span>
+        <span class='fraction'>14/15</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">79.1% </span>
+        <span class="quiet">Lines</span>
+        <span class='fraction'>53/67</span>
+      </div>
+    </div>
+  </div>
+  <div class='status-line medium'></div>
+<div class="pad1">
+<table class="coverage-summary">
+<thead>
+<tr>
+   <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
+   <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
+   <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
+   <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
+   <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
+   <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
+   <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
+</tr>
+</thead>
+<tbody><tr>
+	<td class="file medium" data-value="mute.js"><a href="mute.js.html">mute.js</a></td>
+	<td data-value="77.03" class="pic medium"><div class="chart"><div class="cover-fill" style="width: 77%;"></div><div class="cover-empty" style="width:23%;"></div></div></td>
+	<td data-value="77.03" class="pct medium">77.03%</td>
+	<td data-value="74" class="abs medium">57/74</td>
+	<td data-value="57.14" class="pct medium">57.14%</td>
+	<td data-value="49" class="abs medium">28/49</td>
+	<td data-value="93.33" class="pct high">93.33%</td>
+	<td data-value="15" class="abs high">14/15</td>
+	<td data-value="79.1" class="pct medium">79.1%</td>
+	<td data-value="67" class="abs medium">53/67</td>
+	</tr>
+
+</tbody>
+</table>
+</div><div class='push'></div><!-- for sticky footer -->
+</div><!-- /wrapper -->
+<div class='footer quiet pad2 space-top1 center small'>
+  Code coverage
+  generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Fri Feb 12 2016 22:19:00 GMT-0800 (PST)
+</div>
+</div>
+<script src="../prettify.js"></script>
+<script>
+window.onload = function () {
+        if (typeof prettyPrint === 'function') {
+            prettyPrint();
+        }
+};
+</script>
+<script src="../sorter.js"></script>
+</body>
+</html>
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/mute.js.html b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/mute.js.html
new file mode 100644
index 00000000..375a8326
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/__root__/mute.js.html
@@ -0,0 +1,500 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Code coverage report for mute.js</title>
+    <meta charset="utf-8" />
+    <link rel="stylesheet" href="../prettify.css" />
+    <link rel="stylesheet" href="../base.css" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <style type='text/css'>
+        .coverage-summary .sorter {
+            background-image: url(../sort-arrow-sprite.png);
+        }
+    </style>
+</head>
+<body>
+<div class='wrapper'>
+  <div class='pad1'>
+    <h1>
+      <a href="../index.html">all files</a> / <a href="index.html">__root__/</a> mute.js
+    </h1>
+    <div class='clearfix'>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">77.03% </span>
+        <span class="quiet">Statements</span>
+        <span class='fraction'>57/74</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">57.14% </span>
+        <span class="quiet">Branches</span>
+        <span class='fraction'>28/49</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">93.33% </span>
+        <span class="quiet">Functions</span>
+        <span class='fraction'>14/15</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">79.1% </span>
+        <span class="quiet">Lines</span>
+        <span class='fraction'>53/67</span>
+      </div>
+    </div>
+  </div>
+  <div class='status-line medium'></div>
+<pre><table class="coverage">
+<tr><td class="line-count quiet">1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146</td><td class="line-coverage quiet"><span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-yes">7×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">10×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">6×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">5×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">8×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">5×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">5×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">25×</span>
+<span class="cline-any cline-yes">13×</span>
+<span class="cline-any cline-yes">8×</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">8×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">8×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">20×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-yes">2×</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">3×</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-yes">1×</span>
+<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">var Stream = require('stream')
+&nbsp;
+module.exports = MuteStream
+&nbsp;
+// var out = new MuteStream(process.stdout)
+// argument auto-pipes
+function MuteStream (opts) {
+  Stream.apply(this)
+  opts = opts || {}
+  this.writable = this.readable = true
+  this.muted = false
+  this.on('pipe', this._onpipe)
+  this.replace = opts.replace
+&nbsp;
+  // For readline-type situations
+  // This much at the start of a line being redrawn after a ctrl char
+  // is seen (such as backspace) won't be redrawn as the replacement
+  this._prompt = opts.prompt || null
+  this._hadControl = false
+}
+&nbsp;
+MuteStream.prototype = Object.create(Stream.prototype)
+&nbsp;
+Object.defineProperty(MuteStream.prototype, 'constructor', {
+  value: MuteStream,
+  enumerable: false
+})
+&nbsp;
+MuteStream.prototype.mute = function () {
+  this.muted = true
+}
+&nbsp;
+MuteStream.prototype.unmute = function () {
+  this.muted = false
+}
+&nbsp;
+Object.defineProperty(MuteStream.prototype, '_onpipe', {
+  value: onPipe,
+  enumerable: false,
+  writable: true,
+  configurable: true
+})
+&nbsp;
+function onPipe (src) {
+  this._src = src
+}
+&nbsp;
+Object.defineProperty(MuteStream.prototype, 'isTTY', {
+  get: getIsTTY,
+  set: setIsTTY,
+  enumerable: true,
+  configurable: true
+})
+&nbsp;
+function getIsTTY () {
+  return( (this._dest) ? this._dest.isTTY
+        : (this._src) ? this._src.isTTY
+        : false
+        )
+}
+&nbsp;
+// basically just get replace the getter/setter with a regular value
+function setIsTTY (isTTY) {
+  Object.defineProperty(this, 'isTTY', {
+    value: isTTY,
+    enumerable: true,
+    writable: true,
+    configurable: true
+  })
+}
+&nbsp;
+Object.defineProperty(MuteStream.prototype, 'rows', {
+  get: function () {
+    return( this._dest ? this._dest.rows
+          : this._src ? <span class="branch-0 cbranch-no" title="branch not covered" >this._src.rows</span>
+          : undefined )
+  }, enumerable: true, configurable: true })
+&nbsp;
+Object.defineProperty(MuteStream.prototype, 'columns', {
+  get: function () {
+    return( this._dest ? this._dest.columns
+          : this._src ? <span class="branch-0 cbranch-no" title="branch not covered" >this._src.columns</span>
+          : undefined )
+  }, enumerable: true, configurable: true })
+&nbsp;
+&nbsp;
+MuteStream.prototype.pipe = function (dest, options) {
+  this._dest = dest
+  return Stream.prototype.pipe.call(this, dest, options)
+}
+&nbsp;
+MuteStream.prototype.pause = function () {
+  <span class="missing-if-branch" title="else path not taken" >E</span>if (this._src) return this._src.pause()
+}
+&nbsp;
+MuteStream.prototype.resume = function () {
+  <span class="missing-if-branch" title="else path not taken" >E</span>if (this._src) return this._src.resume()
+}
+&nbsp;
+MuteStream.prototype.write = function (c) {
+  if (this.muted) {
+    if (!this.replace) return true
+    <span class="missing-if-branch" title="if path not taken" >I</span>if (c.match(/^\u001b/)) {
+<span class="cstat-no" title="statement not covered" >      if(c.indexOf(this._prompt) === 0) {</span>
+<span class="cstat-no" title="statement not covered" >        c = c.substr(this._prompt.length);</span>
+<span class="cstat-no" title="statement not covered" >        c = c.replace(/./g, this.replace);</span>
+<span class="cstat-no" title="statement not covered" >        c = this._prompt + c;</span>
+      }
+<span class="cstat-no" title="statement not covered" >      this._hadControl = true</span>
+<span class="cstat-no" title="statement not covered" >      return this.emit('data', c)</span>
+    } else {
+      <span class="missing-if-branch" title="if path not taken" >I</span>if (this._prompt &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >this._hadControl </span>&amp;&amp;
+<span class="branch-2 cbranch-no" title="branch not covered" >          c.indexOf(this._prompt) === 0)</span> {
+<span class="cstat-no" title="statement not covered" >        this._hadControl = false</span>
+<span class="cstat-no" title="statement not covered" >        this.emit('data', this._prompt)</span>
+<span class="cstat-no" title="statement not covered" >        c = c.substr(this._prompt.length)</span>
+      }
+      c = c.toString().replace(/./g, this.replace)
+    }
+  }
+  this.emit('data', c)
+}
+&nbsp;
+MuteStream.prototype.end = function (c) {
+  <span class="missing-if-branch" title="else path not taken" >E</span>if (this.muted) {
+    <span class="missing-if-branch" title="if path not taken" >I</span>if (c &amp;&amp; this.replace) {
+<span class="cstat-no" title="statement not covered" >      c = c.toString().replace(/./g, this.replace)</span>
+    } else {
+      c = null
+    }
+  }
+  <span class="missing-if-branch" title="if path not taken" >I</span>if (c) <span class="cstat-no" title="statement not covered" >this.emit('data', c)</span>
+  this.emit('end')
+}
+&nbsp;
+function proxy (fn) { return <span class="fstat-no" title="function not covered" >function () {</span>
+<span class="cstat-no" title="statement not covered" >  var d = this._dest</span>
+<span class="cstat-no" title="statement not covered" >  var s = this._src</span>
+<span class="cstat-no" title="statement not covered" >  if (d &amp;&amp; d[fn]) <span class="cstat-no" title="statement not covered" >d[fn].apply(d, arguments)</span></span>
+<span class="cstat-no" title="statement not covered" >  if (s &amp;&amp; s[fn]) <span class="cstat-no" title="statement not covered" >s[fn].apply(s, arguments)</span></span>
+}}
+&nbsp;
+MuteStream.prototype.destroy = proxy('destroy')
+MuteStream.prototype.destroySoon = proxy('destroySoon')
+MuteStream.prototype.close = proxy('close')
+&nbsp;</pre></td></tr>
+</table></pre>
+<div class='push'></div><!-- for sticky footer -->
+</div><!-- /wrapper -->
+<div class='footer quiet pad2 space-top1 center small'>
+  Code coverage
+  generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Fri Feb 12 2016 22:19:00 GMT-0800 (PST)
+</div>
+</div>
+<script src="../prettify.js"></script>
+<script>
+window.onload = function () {
+        if (typeof prettyPrint === 'function') {
+            prettyPrint();
+        }
+};
+</script>
+<script src="../sorter.js"></script>
+</body>
+</html>
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/base.css b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/base.css
new file mode 100644
index 00000000..0c0571da
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/base.css
@@ -0,0 +1,212 @@
+body, html {
+  margin:0; padding: 0;
+  height: 100%;
+}
+body {
+    font-family: Helvetica Neue, Helvetica, Arial;
+    font-size: 14px;
+    color:#333;
+}
+.small { font-size: 12px;; }
+*, *:after, *:before {
+  -webkit-box-sizing:border-box;
+     -moz-box-sizing:border-box;
+          box-sizing:border-box;
+  }
+h1 { font-size: 20px; margin: 0;}
+h2 { font-size: 14px; }
+pre {
+    font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
+    margin: 0;
+    padding: 0;
+    -moz-tab-size: 2;
+    -o-tab-size:  2;
+    tab-size: 2;
+}
+a { color:#0074D9; text-decoration:none; }
+a:hover { text-decoration:underline; }
+.strong { font-weight: bold; }
+.space-top1 { padding: 10px 0 0 0; }
+.pad2y { padding: 20px 0; }
+.pad1y { padding: 10px 0; }
+.pad2x { padding: 0 20px; }
+.pad2 { padding: 20px; }
+.pad1 { padding: 10px; }
+.space-left2 { padding-left:55px; }
+.space-right2 { padding-right:20px; }
+.center { text-align:center; }
+.clearfix { display:block; }
+.clearfix:after {
+  content:'';
+  display:block;
+  height:0;
+  clear:both;
+  visibility:hidden;
+  }
+.fl { float: left; }
+@media only screen and (max-width:640px) {
+  .col3 { width:100%; max-width:100%; }
+  .hide-mobile { display:none!important; }
+}
+
+.quiet {
+  color: #7f7f7f;
+  color: rgba(0,0,0,0.5);
+}
+.quiet a { opacity: 0.7; }
+
+.fraction {
+  font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
+  font-size: 10px;
+  color: #555;
+  background: #E8E8E8;
+  padding: 4px 5px;
+  border-radius: 3px;
+  vertical-align: middle;
+}
+
+div.path a:link, div.path a:visited { color: #333; }
+table.coverage {
+  border-collapse: collapse;
+  margin: 10px 0 0 0;
+  padding: 0;
+}
+
+table.coverage td {
+  margin: 0;
+  padding: 0;
+  vertical-align: top;
+}
+table.coverage td.line-count {
+    text-align: right;
+    padding: 0 5px 0 20px;
+}
+table.coverage td.line-coverage {
+    text-align: right;
+    padding-right: 10px;
+    min-width:20px;
+}
+
+table.coverage td span.cline-any {
+    display: inline-block;
+    padding: 0 5px;
+    width: 100%;
+}
+.missing-if-branch {
+    display: inline-block;
+    margin-right: 5px;
+    border-radius: 3px;
+    position: relative;
+    padding: 0 4px;
+    background: #333;
+    color: yellow;
+}
+
+.skip-if-branch {
+    display: none;
+    margin-right: 10px;
+    position: relative;
+    padding: 0 4px;
+    background: #ccc;
+    color: white;
+}
+.missing-if-branch .typ, .skip-if-branch .typ {
+    color: inherit !important;
+}
+.coverage-summary {
+  border-collapse: collapse;
+  width: 100%;
+}
+.coverage-summary tr { border-bottom: 1px solid #bbb; }
+.keyline-all { border: 1px solid #ddd; }
+.coverage-summary td, .coverage-summary th { padding: 10px; }
+.coverage-summary tbody { border: 1px solid #bbb; }
+.coverage-summary td { border-right: 1px solid #bbb; }
+.coverage-summary td:last-child { border-right: none; }
+.coverage-summary th {
+  text-align: left;
+  font-weight: normal;
+  white-space: nowrap;
+}
+.coverage-summary th.file { border-right: none !important; }
+.coverage-summary th.pct { }
+.coverage-summary th.pic,
+.coverage-summary th.abs,
+.coverage-summary td.pct,
+.coverage-summary td.abs { text-align: right; }
+.coverage-summary td.file { white-space: nowrap;  }
+.coverage-summary td.pic { min-width: 120px !important;  }
+.coverage-summary tfoot td { }
+
+.coverage-summary .sorter {
+    height: 10px;
+    width: 7px;
+    display: inline-block;
+    margin-left: 0.5em;
+    background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
+}
+.coverage-summary .sorted .sorter {
+    background-position: 0 -20px;
+}
+.coverage-summary .sorted-desc .sorter {
+    background-position: 0 -10px;
+}
+.status-line {  height: 10px; }
+/* dark red */
+.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
+.low .chart { border:1px solid #C21F39 }
+/* medium red */
+.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
+/* light red */
+.low, .cline-no { background:#FCE1E5 }
+/* light green */
+.high, .cline-yes { background:rgb(230,245,208) }
+/* medium green */
+.cstat-yes { background:rgb(161,215,106) }
+/* dark green */
+.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
+.high .chart { border:1px solid rgb(77,146,33) }
+
+
+.medium .chart { border:1px solid #666; }
+.medium .cover-fill { background: #666; }
+
+.cbranch-no { background:  yellow !important; color: #111; }
+
+.cstat-skip { background: #ddd; color: #111; }
+.fstat-skip { background: #ddd; color: #111 !important; }
+.cbranch-skip { background: #ddd !important; color: #111; }
+
+span.cline-neutral { background: #eaeaea; }
+.medium { background: #eaeaea; }
+
+.cover-fill, .cover-empty {
+  display:inline-block;
+  height: 12px;
+}
+.chart {
+  line-height: 0;
+}
+.cover-empty {
+    background: white;
+}
+.cover-full {
+    border-right: none !important;
+}
+pre.prettyprint {
+    border: none !important;
+    padding: 0 !important;
+    margin: 0 !important;
+}
+.com { color: #999 !important; }
+.ignore-none { color: #999; font-weight: normal; }
+
+.wrapper {
+  min-height: 100%;
+  height: auto !important;
+  height: 100%;
+  margin: 0 auto -48px;
+}
+.footer, .push {
+  height: 48px;
+}
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/index.html b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/index.html
new file mode 100644
index 00000000..17d7a760
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/index.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Code coverage report for All files</title>
+    <meta charset="utf-8" />
+    <link rel="stylesheet" href="prettify.css" />
+    <link rel="stylesheet" href="base.css" />
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <style type='text/css'>
+        .coverage-summary .sorter {
+            background-image: url(sort-arrow-sprite.png);
+        }
+    </style>
+</head>
+<body>
+<div class='wrapper'>
+  <div class='pad1'>
+    <h1>
+      /
+    </h1>
+    <div class='clearfix'>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">77.03% </span>
+        <span class="quiet">Statements</span>
+        <span class='fraction'>57/74</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">57.14% </span>
+        <span class="quiet">Branches</span>
+        <span class='fraction'>28/49</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">93.33% </span>
+        <span class="quiet">Functions</span>
+        <span class='fraction'>14/15</span>
+      </div>
+      <div class='fl pad1y space-right2'>
+        <span class="strong">79.1% </span>
+        <span class="quiet">Lines</span>
+        <span class='fraction'>53/67</span>
+      </div>
+    </div>
+  </div>
+  <div class='status-line medium'></div>
+<div class="pad1">
+<table class="coverage-summary">
+<thead>
+<tr>
+   <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
+   <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
+   <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
+   <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
+   <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
+   <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
+   <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
+   <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
+</tr>
+</thead>
+<tbody><tr>
+	<td class="file medium" data-value="__root__/"><a href="__root__/index.html">__root__/</a></td>
+	<td data-value="77.03" class="pic medium"><div class="chart"><div class="cover-fill" style="width: 77%;"></div><div class="cover-empty" style="width:23%;"></div></div></td>
+	<td data-value="77.03" class="pct medium">77.03%</td>
+	<td data-value="74" class="abs medium">57/74</td>
+	<td data-value="57.14" class="pct medium">57.14%</td>
+	<td data-value="49" class="abs medium">28/49</td>
+	<td data-value="93.33" class="pct high">93.33%</td>
+	<td data-value="15" class="abs high">14/15</td>
+	<td data-value="79.1" class="pct medium">79.1%</td>
+	<td data-value="67" class="abs medium">53/67</td>
+	</tr>
+
+</tbody>
+</table>
+</div><div class='push'></div><!-- for sticky footer -->
+</div><!-- /wrapper -->
+<div class='footer quiet pad2 space-top1 center small'>
+  Code coverage
+  generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Fri Feb 12 2016 22:19:00 GMT-0800 (PST)
+</div>
+</div>
+<script src="prettify.js"></script>
+<script>
+window.onload = function () {
+        if (typeof prettyPrint === 'function') {
+            prettyPrint();
+        }
+};
+</script>
+<script src="sorter.js"></script>
+</body>
+</html>
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.css b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.css
new file mode 100644
index 00000000..b317a7cd
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.css
@@ -0,0 +1 @@
+.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.js b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.js
new file mode 100644
index 00000000..ef51e038
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/prettify.js
@@ -0,0 +1 @@
+window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.ignoreCase){ac=true}else{if(/[a-z]/i.test(ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){S=true;ac=false;break}}}var Y={b:8,t:9,n:10,v:11,f:12,r:13};function ab(ah){var ag=ah.charCodeAt(0);if(ag!==92){return ag}var af=ah.charAt(1);ag=Y[af];if(ag){return ag}else{if("0"<=af&&af<="7"){return parseInt(ah.substring(1),8)}else{if(af==="u"||af==="x"){return parseInt(ah.substring(2),16)}else{return ah.charCodeAt(1)}}}}function T(af){if(af<32){return(af<16?"\\x0":"\\x")+af.toString(16)}var ag=String.fromCharCode(af);if(ag==="\\"||ag==="-"||ag==="["||ag==="]"){ag="\\"+ag}return ag}function X(am){var aq=am.substring(1,am.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));var ak=[];var af=[];var ao=aq[0]==="^";for(var ar=ao?1:0,aj=aq.length;ar<aj;++ar){var ah=aq[ar];if(/\\[bdsw]/i.test(ah)){ak.push(ah)}else{var ag=ab(ah);var al;if(ar+2<aj&&"-"===aq[ar+1]){al=ab(aq[ar+2]);ar+=2}else{al=ag}af.push([ag,al]);if(!(al<65||ag>122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;ar<af.length;++ar){var at=af[ar];if(at[0]<=ap[1]+1){ap[1]=Math.max(ap[1],at[1])}else{ai.push(ap=at)}}var an=["["];if(ao){an.push("^")}an.push.apply(an,ak);for(var ar=0;ar<ai.length;++ar){var at=ai[ar];an.push(T(at[0]));if(at[1]>at[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){an[af]=-1}}}}for(var ak=1;ak<an.length;++ak){if(-1===an[ak]){an[ak]=++ad}}for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am;if(an[am]===undefined){aj[ak]="(?:"}}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){aj[ak]="\\"+an[am]}}}}for(var ak=0,am=0;ak<ah;++ak){if("^"===aj[ak]&&"^"!==aj[ak+1]){aj[ak]=""}}if(al.ignoreCase&&S){for(var ak=0;ak<ah;++ak){var ag=aj[ak];var ai=ag.charAt(0);if(ag.length>=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.global||ae.multiline){throw new Error(""+ae)}aa.push("(?:"+W(ae)+")")}return new RegExp(aa.join("|"),ac?"gi":"g")}function a(V){var U=/(?:^|\s)nocode(?:\s|$)/;var X=[];var T=0;var Z=[];var W=0;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=document.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Y=S&&"pre"===S.substring(0,3);function aa(ab){switch(ab.nodeType){case 1:if(U.test(ab.className)){return}for(var ae=ab.firstChild;ae;ae=ae.nextSibling){aa(ae)}var ad=ab.nodeName;if("BR"===ad||"LI"===ad){X[W]="\n";Z[W<<1]=T++;Z[(W++<<1)|1]=ab}break;case 3:case 4:var ac=ab.nodeValue;if(ac.length){if(!Y){ac=ac.replace(/[ \t\r\n]+/g," ")}else{ac=ac.replace(/\r\n?/g,"\n")}X[W]=ac;Z[W<<1]=T;T+=ac.length;Z[(W++<<1)|1]=ab}break}}aa(V);return{sourceCode:X.join("").replace(/\n$/,""),spans:Z}}function B(S,U,W,T){if(!U){return}var V={sourceCode:U,basePos:S};W(V);T.push.apply(T,V.decorations)}var v=/\S/;function o(S){var V=undefined;for(var U=S.firstChild;U;U=U.nextSibling){var T=U.nodeType;V=(T===1)?(V?S:U):(T===3)?(v.test(U.nodeValue)?S:V):V}return V===S?undefined:V}function g(U,T){var S={};var V;(function(){var ad=U.concat(T);var ah=[];var ag={};for(var ab=0,Z=ad.length;ab<Z;++ab){var Y=ad[ab];var ac=Y[3];if(ac){for(var ae=ac.length;--ae>=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae<aq;++ae){var ag=an[ae];var ap=aj[ag];var ai=void 0;var am;if(typeof ap==="string"){am=false}else{var aa=S[ag.charAt(0)];if(aa){ai=ag.match(aa[1]);ap=aa[0]}else{for(var ao=0;ao<X;++ao){aa=T[ao];ai=ag.match(aa[1]);if(ai){ap=aa[0];break}}if(!ai){ap=F}}am=ap.length>=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y<W.length;++Y){ae(W[Y])}if(ag===(ag|0)){W[0].setAttribute("value",ag)}var aa=ac.createElement("OL");aa.className="linenums";var X=Math.max(0,((ag-1))|0)||0;for(var Y=0,T=W.length;Y<T;++Y){af=W[Y];af.className="L"+((Y+X)%10);if(!af.firstChild){af.appendChild(ac.createTextNode("\xA0"))}aa.appendChild(af)}V.appendChild(aa)}function D(ac){var aj=/\bMSIE\b/.test(navigator.userAgent);var am=/\n/g;var al=ac.sourceCode;var an=al.length;var V=0;var aa=ac.spans;var T=aa.length;var ah=0;var X=ac.decorations;var Y=X.length;var Z=0;X[Y]=an;var ar,aq;for(aq=ar=0;aq<Y;){if(X[aq]!==X[aq+2]){X[ar++]=X[aq++];X[ar++]=X[aq++]}else{aq+=2}}Y=ar;for(aq=ar=0;aq<Y;){var at=X[aq];var ab=X[aq+1];var W=aq+2;while(W+2<=Y&&X[W+1]===ab){W+=2}X[ar++]=at;X[ar++]=ab;aq=W}Y=X.length=ar;var ae=null;while(ah<T){var af=aa[ah];var S=aa[ah+2]||an;var ag=X[Z];var ap=X[Z+2]||an;var W=Math.min(S,ap);var ak=aa[ah+1];var U;if(ak.nodeType!==1&&(U=al.substring(V,W))){if(aj){U=U.replace(am,"\r")}ak.nodeValue=U;var ai=ak.ownerDocument;var ao=ai.createElement("SPAN");ao.className=X[Z+1];var ad=ak.parentNode;ad.replaceChild(ao,ak);ao.appendChild(ak);if(V<S){aa[ah+1]=ak=ai.createTextNode(al.substring(W,S));ad.insertBefore(ak,ao.nextSibling)}}V=W;if(V>=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*</.test(S)?"default-markup":"default-code"}return t[T]}c(K,["default-code"]);c(g([],[[F,/^[^<?]+/],[E,/^<!\w[^>]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa<ac.length;++aa){for(var Z=0,V=ac[aa].length;Z<V;++Z){T.push(ac[aa][Z])}}ac=null;var W=Date;if(!W.now){W={now:function(){return +(new Date)}}}var X=0;var S;var ab=/\blang(?:uage)?-([\w.]+)(?!\S)/;var ae=/\bprettyprint\b/;function U(){var ag=(window.PR_SHOULD_USE_CONTINUATION?W.now()+250:Infinity);for(;X<T.length&&W.now()<ag;X++){var aj=T[X];var ai=aj.className;if(ai.indexOf("prettyprint")>=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X<T.length){setTimeout(U,250)}else{if(ad){ad()}}}U()}window.prettyPrintOne=y;window.prettyPrint=b;window.PR={createSimpleLexer:g,registerLangHandler:c,sourceDecorator:i,PR_ATTRIB_NAME:P,PR_ATTRIB_VALUE:n,PR_COMMENT:j,PR_DECLARATION:E,PR_KEYWORD:z,PR_LITERAL:G,PR_NOCODE:N,PR_PLAIN:F,PR_PUNCTUATION:L,PR_SOURCE:J,PR_STRING:C,PR_TAG:m,PR_TYPE:O}})();PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^<script\b[^>]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]);
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/sort-arrow-sprite.png b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/sort-arrow-sprite.png
new file mode 100644
index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3
GIT binary patch
literal 209
zcmeAS@N?(olHy`uVBq!ia0y~yU|?rpV36iuV_;y|;5OBmfq_A?#5JNMI6tkVJh3R1
z!7(L2DOJHUH!(dmC^a#qvhZZ84Fdy1v8Rh;NX4x^L5_R}6gZgo9r-{1!E6ba-5Xf%
zq(%$#UgEmqk>(b`*UOu}kTva^=&Iw!;$1E&JZ>w?H|n0Au|c|n>!5-}9?Ru)_M5)i
z{$aOvJ+j@Yq@>UB?#NPgp~xQ-r`mh`&j_2Ou*qSS^zwr5AKDq186tmJIF%>sbTBY5
OFnGH9xvX<aXaWF!+epL!

literal 0
HcmV?d00001

diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/sorter.js b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/sorter.js
new file mode 100644
index 00000000..6c5034e4
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov-report/sorter.js
@@ -0,0 +1,158 @@
+var addSorting = (function () {
+    "use strict";
+    var cols,
+        currentSort = {
+            index: 0,
+            desc: false
+        };
+
+    // returns the summary table element
+    function getTable() { return document.querySelector('.coverage-summary'); }
+    // returns the thead element of the summary table
+    function getTableHeader() { return getTable().querySelector('thead tr'); }
+    // returns the tbody element of the summary table
+    function getTableBody() { return getTable().querySelector('tbody'); }
+    // returns the th element for nth column
+    function getNthColumn(n) { return getTableHeader().querySelectorAll('th')[n]; }
+
+    // loads all columns
+    function loadColumns() {
+        var colNodes = getTableHeader().querySelectorAll('th'),
+            colNode,
+            cols = [],
+            col,
+            i;
+
+        for (i = 0; i < colNodes.length; i += 1) {
+            colNode = colNodes[i];
+            col = {
+                key: colNode.getAttribute('data-col'),
+                sortable: !colNode.getAttribute('data-nosort'),
+                type: colNode.getAttribute('data-type') || 'string'
+            };
+            cols.push(col);
+            if (col.sortable) {
+                col.defaultDescSort = col.type === 'number';
+                colNode.innerHTML = colNode.innerHTML + '<span class="sorter"></span>';
+            }
+        }
+        return cols;
+    }
+    // attaches a data attribute to every tr element with an object
+    // of data values keyed by column name
+    function loadRowData(tableRow) {
+        var tableCols = tableRow.querySelectorAll('td'),
+            colNode,
+            col,
+            data = {},
+            i,
+            val;
+        for (i = 0; i < tableCols.length; i += 1) {
+            colNode = tableCols[i];
+            col = cols[i];
+            val = colNode.getAttribute('data-value');
+            if (col.type === 'number') {
+                val = Number(val);
+            }
+            data[col.key] = val;
+        }
+        return data;
+    }
+    // loads all row data
+    function loadData() {
+        var rows = getTableBody().querySelectorAll('tr'),
+            i;
+
+        for (i = 0; i < rows.length; i += 1) {
+            rows[i].data = loadRowData(rows[i]);
+        }
+    }
+    // sorts the table using the data for the ith column
+    function sortByIndex(index, desc) {
+        var key = cols[index].key,
+            sorter = function (a, b) {
+                a = a.data[key];
+                b = b.data[key];
+                return a < b ? -1 : a > b ? 1 : 0;
+            },
+            finalSorter = sorter,
+            tableBody = document.querySelector('.coverage-summary tbody'),
+            rowNodes = tableBody.querySelectorAll('tr'),
+            rows = [],
+            i;
+
+        if (desc) {
+            finalSorter = function (a, b) {
+                return -1 * sorter(a, b);
+            };
+        }
+
+        for (i = 0; i < rowNodes.length; i += 1) {
+            rows.push(rowNodes[i]);
+            tableBody.removeChild(rowNodes[i]);
+        }
+
+        rows.sort(finalSorter);
+
+        for (i = 0; i < rows.length; i += 1) {
+            tableBody.appendChild(rows[i]);
+        }
+    }
+    // removes sort indicators for current column being sorted
+    function removeSortIndicators() {
+        var col = getNthColumn(currentSort.index),
+            cls = col.className;
+
+        cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
+        col.className = cls;
+    }
+    // adds sort indicators for current column being sorted
+    function addSortIndicators() {
+        getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted';
+    }
+    // adds event listeners for all sorter widgets
+    function enableUI() {
+        var i,
+            el,
+            ithSorter = function ithSorter(i) {
+                var col = cols[i];
+
+                return function () {
+                    var desc = col.defaultDescSort;
+
+                    if (currentSort.index === i) {
+                        desc = !currentSort.desc;
+                    }
+                    sortByIndex(i, desc);
+                    removeSortIndicators();
+                    currentSort.index = i;
+                    currentSort.desc = desc;
+                    addSortIndicators();
+                };
+            };
+        for (i =0 ; i < cols.length; i += 1) {
+            if (cols[i].sortable) {
+                // add the click event handler on the th so users
+                // dont have to click on those tiny arrows
+                el = getNthColumn(i).querySelector('.sorter').parentElement;
+                if (el.addEventListener) {
+                    el.addEventListener('click', ithSorter(i));
+                } else {
+                    el.attachEvent('onclick', ithSorter(i));
+                }
+            }
+        }
+    }
+    // adds sorting functionality to the UI
+    return function () {
+        if (!getTable()) {
+            return;
+        }
+        cols = loadColumns();
+        loadData(cols);
+        addSortIndicators();
+        enableUI();
+    };
+})();
+
+window.addEventListener('load', addSorting);
diff --git a/input_devices/mag/node_modules/mute-stream/coverage/lcov.info b/input_devices/mag/node_modules/mute-stream/coverage/lcov.info
new file mode 100644
index 00000000..5f2a58e4
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/coverage/lcov.info
@@ -0,0 +1,155 @@
+TN:
+SF:./mute.js
+FN:7,MuteStream
+FN:29,(anonymous_2)
+FN:33,(anonymous_3)
+FN:44,onPipe
+FN:55,getIsTTY
+FN:63,setIsTTY
+FN:73,(anonymous_7)
+FN:80,(anonymous_8)
+FN:87,(anonymous_9)
+FN:92,(anonymous_10)
+FN:96,(anonymous_11)
+FN:100,(anonymous_12)
+FN:124,(anonymous_13)
+FN:136,proxy
+FN:136,(anonymous_15)
+FNF:15
+FNH:14
+FNDA:7,MuteStream
+FNDA:10,(anonymous_2)
+FNDA:6,(anonymous_3)
+FNDA:5,onPipe
+FNDA:8,getIsTTY
+FNDA:2,setIsTTY
+FNDA:5,(anonymous_7)
+FNDA:5,(anonymous_8)
+FNDA:2,(anonymous_9)
+FNDA:2,(anonymous_10)
+FNDA:2,(anonymous_11)
+FNDA:25,(anonymous_12)
+FNDA:2,(anonymous_13)
+FNDA:3,proxy
+FNDA:0,(anonymous_15)
+DA:1,1
+DA:3,1
+DA:7,1
+DA:8,7
+DA:9,7
+DA:10,7
+DA:11,7
+DA:12,7
+DA:13,7
+DA:18,7
+DA:19,7
+DA:22,1
+DA:24,1
+DA:29,1
+DA:30,10
+DA:33,1
+DA:34,6
+DA:37,1
+DA:44,1
+DA:45,5
+DA:48,1
+DA:55,1
+DA:56,8
+DA:63,1
+DA:64,2
+DA:72,1
+DA:74,5
+DA:79,1
+DA:81,5
+DA:87,1
+DA:88,2
+DA:89,2
+DA:92,1
+DA:93,2
+DA:96,1
+DA:97,2
+DA:100,1
+DA:101,25
+DA:102,13
+DA:103,8
+DA:104,0
+DA:105,0
+DA:106,0
+DA:107,0
+DA:109,0
+DA:110,0
+DA:112,8
+DA:114,0
+DA:115,0
+DA:116,0
+DA:118,8
+DA:121,20
+DA:124,1
+DA:125,2
+DA:126,2
+DA:127,0
+DA:129,2
+DA:132,2
+DA:133,2
+DA:136,3
+DA:137,0
+DA:138,0
+DA:139,0
+DA:140,0
+DA:143,1
+DA:144,1
+DA:145,1
+LF:67
+LH:53
+BRDA:9,1,0,7
+BRDA:9,1,1,5
+BRDA:18,2,0,7
+BRDA:18,2,1,7
+BRDA:56,3,0,3
+BRDA:56,3,1,5
+BRDA:57,4,0,3
+BRDA:57,4,1,2
+BRDA:74,5,0,4
+BRDA:74,5,1,1
+BRDA:75,6,0,0
+BRDA:75,6,1,1
+BRDA:81,7,0,4
+BRDA:81,7,1,1
+BRDA:82,8,0,0
+BRDA:82,8,1,1
+BRDA:93,9,0,2
+BRDA:93,9,1,0
+BRDA:97,10,0,2
+BRDA:97,10,1,0
+BRDA:101,11,0,13
+BRDA:101,11,1,12
+BRDA:102,12,0,5
+BRDA:102,12,1,8
+BRDA:103,13,0,0
+BRDA:103,13,1,8
+BRDA:104,14,0,0
+BRDA:104,14,1,0
+BRDA:112,15,0,0
+BRDA:112,15,1,8
+BRDA:112,16,0,8
+BRDA:112,16,1,0
+BRDA:112,16,2,0
+BRDA:125,17,0,2
+BRDA:125,17,1,0
+BRDA:126,18,0,0
+BRDA:126,18,1,2
+BRDA:126,19,0,2
+BRDA:126,19,1,1
+BRDA:132,20,0,0
+BRDA:132,20,1,2
+BRDA:139,21,0,0
+BRDA:139,21,1,0
+BRDA:139,22,0,0
+BRDA:139,22,1,0
+BRDA:140,23,0,0
+BRDA:140,23,1,0
+BRDA:140,24,0,0
+BRDA:140,24,1,0
+BRF:49
+BRH:28
+end_of_record
diff --git a/input_devices/mag/node_modules/mute-stream/mute.js b/input_devices/mag/node_modules/mute-stream/mute.js
new file mode 100644
index 00000000..a24fc099
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/mute.js
@@ -0,0 +1,145 @@
+var Stream = require('stream')
+
+module.exports = MuteStream
+
+// var out = new MuteStream(process.stdout)
+// argument auto-pipes
+function MuteStream (opts) {
+  Stream.apply(this)
+  opts = opts || {}
+  this.writable = this.readable = true
+  this.muted = false
+  this.on('pipe', this._onpipe)
+  this.replace = opts.replace
+
+  // For readline-type situations
+  // This much at the start of a line being redrawn after a ctrl char
+  // is seen (such as backspace) won't be redrawn as the replacement
+  this._prompt = opts.prompt || null
+  this._hadControl = false
+}
+
+MuteStream.prototype = Object.create(Stream.prototype)
+
+Object.defineProperty(MuteStream.prototype, 'constructor', {
+  value: MuteStream,
+  enumerable: false
+})
+
+MuteStream.prototype.mute = function () {
+  this.muted = true
+}
+
+MuteStream.prototype.unmute = function () {
+  this.muted = false
+}
+
+Object.defineProperty(MuteStream.prototype, '_onpipe', {
+  value: onPipe,
+  enumerable: false,
+  writable: true,
+  configurable: true
+})
+
+function onPipe (src) {
+  this._src = src
+}
+
+Object.defineProperty(MuteStream.prototype, 'isTTY', {
+  get: getIsTTY,
+  set: setIsTTY,
+  enumerable: true,
+  configurable: true
+})
+
+function getIsTTY () {
+  return( (this._dest) ? this._dest.isTTY
+        : (this._src) ? this._src.isTTY
+        : false
+        )
+}
+
+// basically just get replace the getter/setter with a regular value
+function setIsTTY (isTTY) {
+  Object.defineProperty(this, 'isTTY', {
+    value: isTTY,
+    enumerable: true,
+    writable: true,
+    configurable: true
+  })
+}
+
+Object.defineProperty(MuteStream.prototype, 'rows', {
+  get: function () {
+    return( this._dest ? this._dest.rows
+          : this._src ? this._src.rows
+          : undefined )
+  }, enumerable: true, configurable: true })
+
+Object.defineProperty(MuteStream.prototype, 'columns', {
+  get: function () {
+    return( this._dest ? this._dest.columns
+          : this._src ? this._src.columns
+          : undefined )
+  }, enumerable: true, configurable: true })
+
+
+MuteStream.prototype.pipe = function (dest, options) {
+  this._dest = dest
+  return Stream.prototype.pipe.call(this, dest, options)
+}
+
+MuteStream.prototype.pause = function () {
+  if (this._src) return this._src.pause()
+}
+
+MuteStream.prototype.resume = function () {
+  if (this._src) return this._src.resume()
+}
+
+MuteStream.prototype.write = function (c) {
+  if (this.muted) {
+    if (!this.replace) return true
+    if (c.match(/^\u001b/)) {
+      if(c.indexOf(this._prompt) === 0) {
+        c = c.substr(this._prompt.length);
+        c = c.replace(/./g, this.replace);
+        c = this._prompt + c;
+      }
+      this._hadControl = true
+      return this.emit('data', c)
+    } else {
+      if (this._prompt && this._hadControl &&
+          c.indexOf(this._prompt) === 0) {
+        this._hadControl = false
+        this.emit('data', this._prompt)
+        c = c.substr(this._prompt.length)
+      }
+      c = c.toString().replace(/./g, this.replace)
+    }
+  }
+  this.emit('data', c)
+}
+
+MuteStream.prototype.end = function (c) {
+  if (this.muted) {
+    if (c && this.replace) {
+      c = c.toString().replace(/./g, this.replace)
+    } else {
+      c = null
+    }
+  }
+  if (c) this.emit('data', c)
+  this.emit('end')
+}
+
+function proxy (fn) { return function () {
+  var d = this._dest
+  var s = this._src
+  if (d && d[fn]) d[fn].apply(d, arguments)
+  if (s && s[fn]) s[fn].apply(s, arguments)
+}}
+
+MuteStream.prototype.destroy = proxy('destroy')
+MuteStream.prototype.destroySoon = proxy('destroySoon')
+MuteStream.prototype.close = proxy('close')
diff --git a/input_devices/mag/node_modules/mute-stream/package.json b/input_devices/mag/node_modules/mute-stream/package.json
new file mode 100644
index 00000000..aaa15e1e
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/package.json
@@ -0,0 +1,98 @@
+{
+  "_args": [
+    [
+      "mute-stream@0.0.7",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-utils"
+    ]
+  ],
+  "_from": "mute-stream@0.0.7",
+  "_id": "mute-stream@0.0.7",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/mute-stream",
+  "_nodeVersion": "8.0.0-pre",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/mute-stream-0.0.7.tgz_1483483671377_0.22980716335587204"
+  },
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "3.10.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "mute-stream",
+    "raw": "mute-stream@0.0.7",
+    "rawSpec": "0.0.7",
+    "scope": null,
+    "spec": "0.0.7",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/readline-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+  "_shasum": "3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab",
+  "_shrinkwrap": null,
+  "_spec": "mute-stream@0.0.7",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-utils",
+  "author": {
+    "email": "i@izs.me",
+    "name": "Isaac Z. Schlueter",
+    "url": "http://blog.izs.me/"
+  },
+  "bugs": {
+    "url": "https://github.com/isaacs/mute-stream/issues"
+  },
+  "dependencies": {},
+  "description": "Bytes go in, but they don't come out (when muted).",
+  "devDependencies": {
+    "tap": "^5.4.4"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "dist": {
+    "shasum": "3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab",
+    "tarball": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz"
+  },
+  "gitHead": "304d9f7b277175b03c5ae828c326a211e3139778",
+  "homepage": "https://github.com/isaacs/mute-stream#readme",
+  "keywords": [
+    "mute",
+    "pipe",
+    "stream"
+  ],
+  "license": "ISC",
+  "main": "mute.js",
+  "maintainers": [
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    },
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    },
+    {
+      "name": "othiym23",
+      "email": "ogd@aoaioxxysz.net"
+    },
+    {
+      "name": "zkat",
+      "email": "kat@sykosomatic.org"
+    }
+  ],
+  "name": "mute-stream",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/mute-stream.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js --cov"
+  },
+  "version": "0.0.7"
+}
diff --git a/input_devices/mag/node_modules/mute-stream/test/basic.js b/input_devices/mag/node_modules/mute-stream/test/basic.js
new file mode 100644
index 00000000..41f9e10c
--- /dev/null
+++ b/input_devices/mag/node_modules/mute-stream/test/basic.js
@@ -0,0 +1,207 @@
+var Stream = require('stream')
+var tap = require('tap')
+var MS = require('../mute.js')
+
+// some marker objects
+var END = {}
+var PAUSE = {}
+var RESUME = {}
+
+function PassThrough () {
+  Stream.call(this)
+  this.readable = this.writable = true
+}
+
+PassThrough.prototype = Object.create(Stream.prototype, {
+  constructor: {
+    value: PassThrough
+  },
+  write: {
+    value: function (c) {
+      this.emit('data', c)
+      return true
+    }
+  },
+  end: {
+    value: function (c) {
+      if (c) this.write(c)
+      this.emit('end')
+    }
+  },
+  pause: {
+    value: function () {
+      this.emit('pause')
+    }
+  },
+  resume: {
+    value: function () {
+      this.emit('resume')
+    }
+  }
+})
+
+tap.test('incoming', function (t) {
+  var ms = new MS
+  var str = new PassThrough
+  str.pipe(ms)
+
+  var expect = ['foo', 'boo', END]
+  ms.on('data', function (c) {
+    t.equal(c, expect.shift())
+  })
+  ms.on('end', function () {
+    t.equal(END, expect.shift())
+    t.end()
+  })
+  str.write('foo')
+  ms.mute()
+  str.write('bar')
+  ms.unmute()
+  str.write('boo')
+  ms.mute()
+  str.write('blaz')
+  str.end('grelb')
+})
+
+tap.test('outgoing', function (t) {
+  var ms = new MS
+  var str = new PassThrough
+  ms.pipe(str)
+
+  var expect = ['foo', 'boo', END]
+  str.on('data', function (c) {
+    t.equal(c, expect.shift())
+  })
+  str.on('end', function () {
+    t.equal(END, expect.shift())
+    t.end()
+  })
+
+  ms.write('foo')
+  ms.mute()
+  ms.write('bar')
+  ms.unmute()
+  ms.write('boo')
+  ms.mute()
+  ms.write('blaz')
+  ms.end('grelb')
+})
+
+tap.test('isTTY', function (t) {
+  var str = new PassThrough
+  str.isTTY = true
+  str.columns=80
+  str.rows=24
+
+  var ms = new MS
+  t.equal(ms.isTTY, false)
+  t.equal(ms.columns, undefined)
+  t.equal(ms.rows, undefined)
+  ms.pipe(str)
+  t.equal(ms.isTTY, true)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
+  str.isTTY = false
+  t.equal(ms.isTTY, false)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
+  str.isTTY = true
+  t.equal(ms.isTTY, true)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
+  ms.isTTY = false
+  t.equal(ms.isTTY, false)
+  t.equal(ms.columns, 80)
+  t.equal(ms.rows, 24)
+
+  ms = new MS
+  t.equal(ms.isTTY, false)
+  str.pipe(ms)
+  t.equal(ms.isTTY, true)
+  str.isTTY = false
+  t.equal(ms.isTTY, false)
+  str.isTTY = true
+  t.equal(ms.isTTY, true)
+  ms.isTTY = false
+  t.equal(ms.isTTY, false)
+
+  t.end()
+})
+
+tap.test('pause/resume incoming', function (t) {
+  var str = new PassThrough
+  var ms = new MS
+  str.on('pause', function () {
+    t.equal(PAUSE, expect.shift())
+  })
+  str.on('resume', function () {
+    t.equal(RESUME, expect.shift())
+  })
+  var expect = [PAUSE, RESUME, PAUSE, RESUME]
+  str.pipe(ms)
+  ms.pause()
+  ms.resume()
+  ms.pause()
+  ms.resume()
+  t.equal(expect.length, 0, 'saw all events')
+  t.end()
+})
+
+tap.test('replace with *', function (t) {
+  var str = new PassThrough
+  var ms = new MS({replace: '*'})
+  str.pipe(ms)
+  var expect = ['foo', '*****', 'bar', '***', 'baz', 'boo', '**', '****']
+
+  ms.on('data', function (c) {
+    t.equal(c, expect.shift())
+  })
+
+  str.write('foo')
+  ms.mute()
+  str.write('12345')
+  ms.unmute()
+  str.write('bar')
+  ms.mute()
+  str.write('baz')
+  ms.unmute()
+  str.write('baz')
+  str.write('boo')
+  ms.mute()
+  str.write('xy')
+  str.write('xyzΩ')
+
+  t.equal(expect.length, 0)
+  t.end()
+})
+
+tap.test('replace with ~YARG~', function (t) {
+  var str = new PassThrough
+  var ms = new MS({replace: '~YARG~'})
+  str.pipe(ms)
+  var expect = ['foo', '~YARG~~YARG~~YARG~~YARG~~YARG~', 'bar',
+                '~YARG~~YARG~~YARG~', 'baz', 'boo', '~YARG~~YARG~',
+                '~YARG~~YARG~~YARG~~YARG~']
+
+  ms.on('data', function (c) {
+    t.equal(c, expect.shift())
+  })
+
+  // also throw some unicode in there, just for good measure.
+  str.write('foo')
+  ms.mute()
+  str.write('ΩΩ')
+  ms.unmute()
+  str.write('bar')
+  ms.mute()
+  str.write('Ω')
+  ms.unmute()
+  str.write('baz')
+  str.write('boo')
+  ms.mute()
+  str.write('Ω')
+  str.write('ΩΩ')
+
+  t.equal(expect.length, 0)
+  t.end()
+})
diff --git a/input_devices/mag/node_modules/nan/CHANGELOG.md b/input_devices/mag/node_modules/nan/CHANGELOG.md
new file mode 100644
index 00000000..10d3ee6f
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/CHANGELOG.md
@@ -0,0 +1,503 @@
+# NAN ChangeLog
+
+**Version 2.11.1: current Node 10.11.0, Node 0.12: 0.12.18, Node 0.10: 0.10.48, iojs: 3.3.1**
+
+### 2.11.1 Sep 29 2018
+
+- Fix: adapt to V8 7.0 24a22c3b25eeeec2016c6ec239bdd6169e985447
+
+### 2.11.0 Aug 25 2018
+
+  - Removal: remove `FunctionCallbackInfo::Callee` for nodejs `>= 10` 1a56c0a6efd4fac944cb46c30912a8e023bda7d4
+  - Bugfix: Fix `AsyncProgressWorkerBase::WorkProgress` sends invalid data b0c764d1dab11e9f8b37ffb81e2560a4498aad5e
+  - Feature: Introduce `GetCurrentEventLoop` b4911b0bb1f6d47d860e10ec014d941c51efac5e
+  - Feature: Add `NAN_MODULE_WORKER_ENABLED` macro as a replacement for `NAN_MODULE` b058fb047d18a58250e66ae831444441c1f2ac7a
+
+### 2.10.0 Mar 16 2018
+
+  - Deprecation: Deprecate `MakeCallback` 5e92b19a59e194241d6a658bd6ff7bfbda372950
+  - Feature: add `Nan::Call` overload 4482e1242fe124d166fc1a5b2be3c1cc849fe452
+  - Feature: add more `Nan::Call` overloads 8584e63e6d04c7d2eb8c4a664e4ef57d70bf672b
+  - Feature: Fix deprecation warnings for Node 10 1caf258243b0602ed56922bde74f1c91b0cbcb6a
+
+### 2.9.2 Feb 22 2018
+
+  - Bugfix: Bandaid for async hooks 212bd2f849be14ef1b02fc85010b053daa24252b
+
+### 2.9.1 Feb 22 2018
+
+  - Bugfix: Avoid deprecation warnings in deprecated `Nan::Callback::operator()` 372b14d91289df4604b0f81780709708c45a9aa4
+  - Bugfix: Avoid deprecation warnings in `Nan::JSON` 3bc294bce0b7d0a3ee4559926303e5ed4866fda2
+
+### 2.9.0 Feb 22 2018
+
+  - Deprecation: Deprecate legacy `Callback::Call` 6dd5fa690af61ca3523004b433304c581b3ea309
+  - Feature: introduce `AsyncResource` class 90c0a179c0d8cb5fd26f1a7d2b1d6231eb402d48o
+  - Feature: Add context aware `Nan::Callback::Call` functions 7169e09fb088418b6e388222e88b4c13f07ebaee
+  - Feature: Make `AsyncWorker` context aware 066ba21a6fb9e2b5230c9ed3a6fc51f1211736a4
+  - Feature: add `Callback` overload to `Nan::Call` 5328daf66e202658c1dc0d916c3aaba99b3cc606
+  - Bugfix: fix warning: suggest parentheses around `&&` within `||` b2bb63d68b8ae623a526b542764e1ac82319cb2c
+  - Bugfix: Fix compilation on io.js 3 d06114dba0a522fb436f0c5f47b994210968cd7b
+
+### 2.8.0 Nov 15 2017
+
+  - Deprecation: Deprecate `Nan::ForceSet` in favor of `Nan::DefineOwnProperty()` 95cbb976d6fbbba88ba0f86dd188223a8591b4e7
+  - Feature: Add `Nan::AsyncProgressQueueWorker` a976636ecc2ef617d1b061ce4a6edf39923691cb
+  - Feature: Add `Nan::DefineOwnProperty()` 95cbb976d6fbbba88ba0f86dd188223a8591b4e7
+  - Bugfix: Fix compiling on io.js 1 & 2 82705a64503ce60c62e98df5bd02972bba090900
+  - Bugfix: Use DefineOwnProperty instead of ForceSet 95cbb976d6fbbba88ba0f86dd188223a8591b4e7
+
+### 2.7.0 Aug 30 2017
+
+  - Feature: Add `Nan::To<v8::Function>()` overload. b93280670c9f6da42ed4cf6cbf085ffdd87bd65b
+  - Bugfix: Fix ternary in `Nan::MaybeLocal<T>::FromMaybe<S>()`. 79a26f7d362e756a9524e672a82c3d603b542867
+
+### 2.6.2 Apr 12 2017
+
+  - Bugfix: Fix v8::JSON::Parse() deprecation warning. 87f6a3c65815fa062296a994cc863e2fa124867d
+
+### 2.6.1 Apr 6 2017
+
+  - Bugfix: nan_json.h: fix build breakage in Node 6 ac8d47dc3c10bfbf3f15a6b951633120c0ee6d51
+
+### 2.6.0 Apr 6 2017
+
+  - Feature: nan: add support for JSON::Parse & Stringify b533226c629cce70e1932a873bb6f849044a56c5
+
+### 2.5.1 Jan 23 2017
+
+  - Bugfix: Fix disappearing handle for private value 6a80995694f162ef63dbc9948fbefd45d4485aa0
+  - Bugfix: Add missing scopes a93b8bae6bc7d32a170db6e89228b7f60ee57112
+  - Bugfix: Use string::data instead of string::front in NewOneByteString d5f920371e67e1f3b268295daee6e83af86b6e50
+
+### 2.5.0 Dec 21 2016
+
+  - Feature: Support Private accessors a86255cb357e8ad8ccbf1f6a4a901c921e39a178
+  - Bugfix: Abort in delete operators that shouldn't be called 0fe38215ff8581703967dfd26c12793feb960018
+
+### 2.4.0 Jul 10 2016
+
+  - Feature: Rewrite Callback to add Callback::Reset c4cf44d61f8275cd5f7b0c911d7a806d4004f649
+  - Feature: AsyncProgressWorker: add template types for .send 1242c9a11a7ed481c8f08ec06316385cacc513d0
+  - Bugfix: Add constness to old Persistent comparison operators bd43cb9982c7639605d60fd073efe8cae165d9b2
+
+### 2.3.5 May 31 2016
+
+  - Bugfix: Replace NAN_INLINE with 'inline' keyword. 71819d8725f822990f439479c9aba3b240804909
+
+### 2.3.4 May 31 2016
+
+  - Bugfix: Remove V8 deprecation warnings 0592fb0a47f3a1c7763087ebea8e1138829f24f9
+  - Bugfix: Fix new versions not to use WeakCallbackInfo::IsFirstPass 615c19d9e03d4be2049c10db0151edbc3b229246
+  - Bugfix: Make ObjectWrap::handle() const d19af99595587fe7a26bd850af6595c2a7145afc
+  - Bugfix: Fix compilation errors related to 0592fb0a47f3a1c7763087ebea8e1138829f24f9 e9191c525b94f652718325e28610a1adcf90fed8
+
+### 2.3.3 May 4 2016
+
+  - Bugfix: Refactor SetMethod() to deal with v8::Templates (#566) b9083cf6d5de6ebe6bcb49c7502fbb7c0d9ddda8
+
+### 2.3.2 Apr 27 2016
+
+  - Bugfix: Fix compilation on outdated versions due to Handle removal f8b7c875d04d425a41dfd4f3f8345bc3a11e6c52
+
+### 2.3.1 Apr 27 2016
+
+  - Bugfix: Don't use deprecated v8::Template::Set() in SetMethod a90951e9ea70fa1b3836af4b925322919159100e
+
+### 2.3.0 Apr 27 2016
+
+  - Feature: added Signal() for invoking async callbacks without sending data from AsyncProgressWorker d8adba45f20e077d00561b20199133620c990b38
+  - Bugfix: Don't use deprecated v8::Template::Set() 00dacf0a4b86027415867fa7f1059acc499dcece
+
+### 2.2.1 Mar 29 2016
+
+  - Bugfix: Use NewFromUnsigned in ReturnValue<T>::Set(uint32_t i) for pre_12 3a18f9bdce29826e0e4c217854bc476918241a58
+  - Performance: Remove unneeeded nullptr checks b715ef44887931c94f0d1605b3b1a4156eebece9
+
+### 2.2.0 Jan 9 2016
+
+  - Feature: Add Function::Call wrapper 4c157474dacf284d125c324177b45aa5dabc08c6
+  - Feature: Rename GC*logueCallback to GCCallback for > 4.0 3603435109f981606d300eb88004ca101283acec
+  - Bugfix: Fix Global::Pass for old versions 367e82a60fbaa52716232cc89db1cc3f685d77d9
+  - Bugfix: Remove weird MaybeLocal wrapping of what already is a MaybeLocal 23b4590db10c2ba66aee2338aebe9751c4cb190b
+
+### 2.1.0 Oct 8 2015
+
+  - Deprecation: Deprecate NanErrnoException in favor of ErrnoException 0af1ca4cf8b3f0f65ed31bc63a663ab3319da55c
+  - Feature: added helper class for accessing contents of typedarrays 17b51294c801e534479d5463697a73462d0ca555
+  - Feature: [Maybe types] Add MakeMaybe(...) 48d7b53d9702b0c7a060e69ea10fea8fb48d814d
+  - Feature: new: allow utf16 string with length 66ac6e65c8ab9394ef588adfc59131b3b9d8347b
+  - Feature: Introduce SetCallHandler and SetCallAsFunctionHandler 7764a9a115d60ba10dc24d86feb0fbc9b4f75537
+  - Bugfix: Enable creating Locals from Globals under Node 0.10. 9bf9b8b190821af889790fdc18ace57257e4f9ff
+  - Bugfix: Fix issue #462 where PropertyCallbackInfo data is not stored safely. 55f50adedd543098526c7b9f4fffd607d3f9861f
+
+### 2.0.9 Sep 8 2015
+
+  - Bugfix: EscapableHandleScope in Nan::NewBuffer for Node 0.8 and 0.10 b1654d7
+
+### 2.0.8 Aug 28 2015
+
+  - Work around duplicate linking bug in clang 11902da
+
+### 2.0.7 Aug 26 2015
+
+  - Build: Repackage
+
+### 2.0.6 Aug 26 2015
+
+  - Bugfix: Properly handle null callback in FunctionTemplate factory 6e99cb1
+  - Bugfix: Remove unused static std::map instances 525bddc
+  - Bugfix: Make better use of maybe versions of APIs bfba85b
+  - Bugfix: Fix shadowing issues with handle in ObjectWrap 0a9072d
+
+### 2.0.5 Aug 10 2015
+
+  - Bugfix: Reimplement weak callback in ObjectWrap 98d38c1
+  - Bugfix: Make sure callback classes are not assignable, copyable or movable 81f9b1d
+
+### 2.0.4 Aug 6 2015
+
+  - Build: Repackage
+
+### 2.0.3 Aug 6 2015
+
+  - Bugfix: Don't use clang++ / g++ syntax extension. 231450e
+
+### 2.0.2 Aug 6 2015
+
+  - Build: Repackage
+
+### 2.0.1 Aug 6 2015
+
+  - Bugfix: Add workaround for missing REPLACE_INVALID_UTF8 60d6687
+  - Bugfix: Reimplement ObjectWrap from scratch to prevent memory leaks 6484601
+  - Bugfix: Fix Persistent leak in FunctionCallbackInfo and PropertyCallbackInfo 641ef5f
+  - Bugfix: Add missing overload for Nan::NewInstance that takes argc/argv 29450ed
+
+### 2.0.0 Jul 31 2015
+
+  - Change: Renamed identifiers with leading underscores	b5932b4
+  - Change: Replaced NanObjectWrapHandle with class NanObjectWrap	464f1e1
+  - Change: Replace NanScope and NanEscpableScope macros with classes	47751c4
+  - Change: Rename NanNewBufferHandle to NanNewBuffer	6745f99
+  - Change: Rename NanBufferUse to NanNewBuffer	3e8b0a5
+  - Change: Rename NanNewBuffer to NanCopyBuffer	d6af78d
+  - Change: Remove Nan prefix from all names	72d1f67
+  - Change: Update Buffer API for new upstream changes	d5d3291
+  - Change: Rename Scope and EscapableScope to HandleScope and EscapableHandleScope	21a7a6a
+  - Change: Get rid of Handles	 e6c0daf
+  - Feature: Support io.js 3 with V8 4.4
+  - Feature: Introduce NanPersistent	7fed696
+  - Feature: Introduce NanGlobal	4408da1
+  - Feature: Added NanTryCatch	10f1ca4
+  - Feature: Update for V8 v4.3	4b6404a
+  - Feature: Introduce NanNewOneByteString	c543d32
+  - Feature: Introduce namespace Nan	67ed1b1
+  - Removal: Remove NanLocker and NanUnlocker	dd6e401
+  - Removal: Remove string converters, except NanUtf8String, which now follows the node implementation b5d00a9
+  - Removal: Remove NanReturn* macros	d90a25c
+  - Removal: Remove HasInstance	e8f84fe
+
+
+### 1.9.0 Jul 31 2015
+
+  - Feature: Added `NanFatalException` 81d4a2c
+  - Feature: Added more error types 4265f06
+  - Feature: Added dereference and function call operators to NanCallback c4b2ed0
+  - Feature: Added indexed GetFromPersistent and SaveToPersistent edd510c
+  - Feature: Added more overloads of SaveToPersistent and GetFromPersistent 8b1cef6
+  - Feature: Added NanErrnoException dd87d9e
+  - Correctness: Prevent assign, copy, and move for classes that do not support it 1f55c59, 4b808cb, c96d9b2, fba4a29, 3357130
+  - Deprecation: Deprecate `NanGetPointerSafe` and `NanSetPointerSafe` 81d4a2c
+  - Deprecation: Deprecate `NanBooleanOptionValue` and `NanUInt32OptionValue` 0ad254b
+
+### 1.8.4 Apr 26 2015
+
+  - Build: Repackage
+
+### 1.8.3 Apr 26 2015
+
+  - Bugfix: Include missing header 1af8648
+
+### 1.8.2 Apr 23 2015
+
+  - Build: Repackage
+
+### 1.8.1 Apr 23 2015
+
+  - Bugfix: NanObjectWrapHandle should take a pointer 155f1d3
+
+### 1.8.0 Apr 23 2015
+
+  - Feature: Allow primitives with NanReturnValue 2e4475e
+  - Feature: Added comparison operators to NanCallback 55b075e
+  - Feature: Backport thread local storage 15bb7fa
+  - Removal: Remove support for signatures with arguments 8a2069d
+  - Correcteness: Replaced NanObjectWrapHandle macro with function 0bc6d59
+
+### 1.7.0 Feb 28 2015
+
+  - Feature: Made NanCallback::Call accept optional target 8d54da7
+  - Feature: Support atom-shell 0.21 0b7f1bb
+
+### 1.6.2 Feb 6 2015
+
+  - Bugfix: NanEncode: fix argument type for node::Encode on io.js 2be8639
+
+### 1.6.1 Jan 23 2015
+
+  - Build: version bump
+
+### 1.5.3 Jan 23 2015
+
+  - Build: repackage
+
+### 1.6.0 Jan 23 2015
+
+ - Deprecated `NanNewContextHandle` in favor of `NanNew<Context>` 49259af
+ - Support utility functions moved in newer v8 versions (Node 0.11.15, io.js 1.0) a0aa179
+ - Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite` 75e6fb9
+
+### 1.5.2 Jan 23 2015
+
+  - Bugfix: Fix non-inline definition build error with clang++ 21d96a1, 60fadd4
+  - Bugfix: Readded missing String constructors 18d828f
+  - Bugfix: Add overload handling NanNew<FunctionTemplate>(..) 5ef813b
+  - Bugfix: Fix uv_work_cb versioning 997e4ae
+  - Bugfix: Add function factory and test 4eca89c
+  - Bugfix: Add object template factory and test cdcb951
+  - Correctness: Lifted an io.js related typedef c9490be
+  - Correctness: Make explicit downcasts of String lengths 00074e6
+  - Windows: Limit the scope of disabled warning C4530 83d7deb
+
+### 1.5.1 Jan 15 2015
+
+  - Build: version bump
+
+### 1.4.3 Jan 15 2015
+
+  - Build: version bump
+
+### 1.4.2 Jan 15 2015
+
+  - Feature: Support io.js 0dbc5e8
+
+### 1.5.0 Jan 14 2015
+
+ - Feature: Support io.js b003843
+ - Correctness: Improved NanNew internals 9cd4f6a
+ - Feature: Implement progress to NanAsyncWorker 8d6a160
+
+### 1.4.1 Nov 8 2014
+
+ - Bugfix: Handle DEBUG definition correctly
+ - Bugfix: Accept int as Boolean
+
+### 1.4.0 Nov 1 2014
+
+ - Feature: Added NAN_GC_CALLBACK 6a5c245
+ - Performance: Removed unnecessary local handle creation 18a7243, 41fe2f8
+ - Correctness: Added constness to references in NanHasInstance 02c61cd
+ - Warnings: Fixed spurious warnings from -Wundef and -Wshadow, 541b122, 99d8cb6
+ - Windoze: Shut Visual Studio up when compiling 8d558c1
+ - License: Switch to plain MIT from custom hacked MIT license 11de983
+ - Build: Added test target to Makefile e232e46
+ - Performance: Removed superfluous scope in NanAsyncWorker f4b7821
+ - Sugar/Feature: Added NanReturnThis() and NanReturnHolder() shorthands 237a5ff, d697208
+ - Feature: Added suitable overload of NanNew for v8::Integer::NewFromUnsigned b27b450
+
+### 1.3.0 Aug 2 2014
+
+ - Added NanNew<v8::String, std::string>(std::string)
+ - Added NanNew<v8::String, std::string&>(std::string&)
+ - Added NanAsciiString helper class
+ - Added NanUtf8String helper class
+ - Added NanUcs2String helper class
+ - Deprecated NanRawString()
+ - Deprecated NanCString()
+ - Added NanGetIsolateData(v8::Isolate *isolate)
+ - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value>* argv)
+ - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::String> symbol, int argc, v8::Handle<v8::Value>* argv)
+ - Added NanMakeCallback(v8::Handle<v8::Object> target, const char* method, int argc, v8::Handle<v8::Value>* argv)
+ - Added NanSetTemplate(v8::Handle<v8::Template> templ, v8::Handle<v8::String> name , v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
+ - Added NanSetPrototypeTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
+ - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, const char *name, v8::Handle<v8::Data> value)
+ - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
+
+### 1.2.0 Jun 5 2014
+
+ - Add NanSetPrototypeTemplate
+ - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class,
+     introduced _NanWeakCallbackDispatcher
+ - Removed -Wno-unused-local-typedefs from test builds
+ - Made test builds Windows compatible ('Sleep()')
+
+### 1.1.2 May 28 2014
+
+ - Release to fix more stuff-ups in 1.1.1
+
+### 1.1.1 May 28 2014
+
+ - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0
+
+### 1.1.0 May 25 2014
+
+ - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead
+ - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]),
+     (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*,
+     v8::String::ExternalAsciiStringResource*
+ - Deprecate NanSymbol()
+ - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker
+
+### 1.0.0 May 4 2014
+
+ - Heavy API changes for V8 3.25 / Node 0.11.13
+ - Use cpplint.py
+ - Removed NanInitPersistent
+ - Removed NanPersistentToLocal
+ - Removed NanFromV8String
+ - Removed NanMakeWeak
+ - Removed NanNewLocal
+ - Removed NAN_WEAK_CALLBACK_OBJECT
+ - Removed NAN_WEAK_CALLBACK_DATA
+ - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions
+ - Introduce NanUndefined, NanNull, NanTrue and NanFalse
+ - Introduce NanEscapableScope and NanEscapeScope
+ - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node)
+ - Introduce NanMakeCallback for node::MakeCallback
+ - Introduce NanSetTemplate
+ - Introduce NanGetCurrentContext
+ - Introduce NanCompileScript and NanRunScript
+ - Introduce NanAdjustExternalMemory
+ - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback
+ - Introduce NanGetHeapStatistics
+ - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent()
+
+### 0.8.0 Jan 9 2014
+
+ - NanDispose -> NanDisposePersistent, deprecate NanDispose
+ - Extract _NAN_*_RETURN_TYPE, pull up NAN_*()
+
+### 0.7.1 Jan 9 2014
+
+ - Fixes to work against debug builds of Node
+ - Safer NanPersistentToLocal (avoid reinterpret_cast)
+ - Speed up common NanRawString case by only extracting flattened string when necessary
+
+### 0.7.0 Dec 17 2013
+
+ - New no-arg form of NanCallback() constructor.
+ - NanCallback#Call takes Handle rather than Local
+ - Removed deprecated NanCallback#Run method, use NanCallback#Call instead
+ - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS
+ - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call()
+ - Introduce NanRawString() for char* (or appropriate void*) from v8::String
+     (replacement for NanFromV8String)
+ - Introduce NanCString() for null-terminated char* from v8::String
+
+### 0.6.0 Nov 21 2013
+
+ - Introduce NanNewLocal<T>(v8::Handle<T> value) for use in place of
+     v8::Local<T>::New(...) since v8 started requiring isolate in Node 0.11.9
+
+### 0.5.2 Nov 16 2013
+
+ - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public
+
+### 0.5.1 Nov 12 2013
+
+ - Use node::MakeCallback() instead of direct v8::Function::Call()
+
+### 0.5.0 Nov 11 2013
+
+ - Added @TooTallNate as collaborator
+ - New, much simpler, "include_dirs" for binding.gyp
+ - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros
+
+### 0.4.4 Nov 2 2013
+
+ - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+
+
+### 0.4.3 Nov 2 2013
+
+ - Include node_object_wrap.h, removed from node.h for Node 0.11.8.
+
+### 0.4.2 Nov 2 2013
+
+ - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for
+     Node 0.11.8 release.
+
+### 0.4.1 Sep 16 2013
+
+ - Added explicit `#include <uv.h>` as it was removed from node.h for v0.11.8
+
+### 0.4.0 Sep 2 2013
+
+ - Added NAN_INLINE and NAN_DEPRECATED and made use of them
+ - Added NanError, NanTypeError and NanRangeError
+ - Cleaned up code
+
+### 0.3.2 Aug 30 2013
+
+ - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent
+     in NanAsyncWorker
+
+### 0.3.1 Aug 20 2013
+
+ - fix "not all control paths return a value" compile warning on some platforms
+
+### 0.3.0 Aug 19 2013
+
+ - Made NAN work with NPM
+ - Lots of fixes to NanFromV8String, pulling in features from new Node core
+ - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API
+ - Added optional error number argument for NanThrowError()
+ - Added NanInitPersistent()
+ - Added NanReturnNull() and NanReturnEmptyString()
+ - Added NanLocker and NanUnlocker
+ - Added missing scopes
+ - Made sure to clear disposed Persistent handles
+ - Changed NanAsyncWorker to allocate error messages on the heap
+ - Changed NanThrowError(Local<Value>) to NanThrowError(Handle<Value>)
+ - Fixed leak in NanAsyncWorker when errmsg is used
+
+### 0.2.2 Aug 5 2013
+
+ - Fixed usage of undefined variable with node::BASE64 in NanFromV8String()
+
+### 0.2.1 Aug 5 2013
+
+ - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for
+     NanFromV8String()
+
+### 0.2.0 Aug 5 2013
+
+ - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR,
+     NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY
+ - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS,
+     _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS,
+     _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS,
+     _NAN_PROPERTY_QUERY_ARGS
+ - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer
+ - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT,
+     NAN_WEAK_CALLBACK_DATA, NanMakeWeak
+ - Renamed THROW_ERROR to _NAN_THROW_ERROR
+ - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*)
+ - Added NanBufferUse(char*, uint32_t)
+ - Added NanNewContextHandle(v8::ExtensionConfiguration*,
+       v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
+ - Fixed broken NanCallback#GetFunction()
+ - Added optional encoding and size arguments to NanFromV8String()
+ - Added NanGetPointerSafe() and NanSetPointerSafe()
+ - Added initial test suite (to be expanded)
+ - Allow NanUInt32OptionValue to convert any Number object
+
+### 0.1.0 Jul 21 2013
+
+ - Added `NAN_GETTER`, `NAN_SETTER`
+ - Added `NanThrowError` with single Local<Value> argument
+ - Added `NanNewBufferHandle` with single uint32_t argument
+ - Added `NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)`
+ - Added `Local<Function> NanCallback#GetFunction()`
+ - Added `NanCallback#Call(int, Local<Value>[])`
+ - Deprecated `NanCallback#Run(int, Local<Value>[])` in favour of Call
diff --git a/input_devices/mag/node_modules/nan/LICENSE.md b/input_devices/mag/node_modules/nan/LICENSE.md
new file mode 100644
index 00000000..dddd13d5
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/LICENSE.md
@@ -0,0 +1,13 @@
+The MIT License (MIT)
+=====================
+
+Copyright (c) 2018 NAN contributors
+-----------------------------------
+
+*NAN contributors listed at <https://github.com/nodejs/nan#contributors>*
+
+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/input_devices/mag/node_modules/nan/README.md b/input_devices/mag/node_modules/nan/README.md
new file mode 100644
index 00000000..d002fe12
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/README.md
@@ -0,0 +1,456 @@
+Native Abstractions for Node.js
+===============================
+
+**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10.**
+
+***Current version: 2.11.1***
+
+*(See [CHANGELOG.md](https://github.com/nodejs/nan/blob/master/CHANGELOG.md) for complete ChangeLog)*
+
+[![NPM](https://nodei.co/npm/nan.png?downloads=true&downloadRank=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6&height=3)](https://nodei.co/npm/nan/)
+
+[![Build Status](https://api.travis-ci.org/nodejs/nan.svg?branch=master)](http://travis-ci.org/nodejs/nan)
+[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan)
+
+Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.12 to 4.0, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle.
+
+This project also contains some helper utilities that make addon development a bit more pleasant.
+
+ * **[News & Updates](#news)**
+ * **[Usage](#usage)**
+ * **[Example](#example)**
+ * **[API](#api)**
+ * **[Tests](#tests)**
+ * **[Knowns issues](#issues)**
+ * **[Governance & Contributing](#governance)**
+
+<a name="news"></a>
+
+## News & Updates
+
+<a name="usage"></a>
+
+## Usage
+
+Simply add **NAN** as a dependency in the *package.json* of your Node addon:
+
+``` bash
+$ npm install --save nan
+```
+
+Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include <nan.h>` in your *.cpp* files:
+
+``` python
+"include_dirs" : [
+    "<!(node -e \"require('nan')\")"
+]
+```
+
+This works like a `-I<path-to-NAN>` when compiling your addon.
+
+<a name="example"></a>
+
+## Example
+
+Just getting started with Nan? Take a look at the **[Node Add-on Examples](https://github.com/nodejs/node-addon-examples)**.
+
+Refer to a [quick-start **Nan** Boilerplate](https://github.com/fcanas/node-native-boilerplate) for a ready-to-go project that utilizes basic Nan functionality.
+
+For a simpler example, see the **[async pi estimation example](https://github.com/nodejs/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**.
+
+Yet another example is **[nan-example-eol](https://github.com/CodeCharmLtd/nan-example-eol)**. It shows newline detection implemented as a native addon.
+
+Also take a look at our comprehensive **[C++ test suite](https://github.com/nodejs/nan/tree/master/test/cpp)** which has a plethora of code snippets for your pasting pleasure.
+
+<a name="api"></a>
+
+## API
+
+Additional to the NAN documentation below, please consult:
+
+* [The V8 Getting Started * Guide](https://github.com/v8/v8/wiki/Getting%20Started%20with%20Embedding)
+* [The V8 Embedders * Guide](https://github.com/v8/v8/wiki/Embedder%27s%20Guide)
+* [V8 API Documentation](http://v8docs.nodesource.com/)
+* [Node Add-on Documentation](https://nodejs.org/api/addons.html)
+
+<!-- START API -->
+
+### JavaScript-accessible methods
+
+A _template_ is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated from JavaScript. See the V8 Embedders Guide section on [Templates](https://github.com/v8/v8/wiki/Embedder%27s-Guide#templates) for further information.
+
+In order to expose functionality to JavaScript via a template, you must provide it to V8 in a form that it understands. Across the versions of V8 supported by NAN, JavaScript-accessible method signatures vary widely, NAN fully abstracts method declaration and provides you with an interface that is similar to the most recent V8 API but is backward-compatible with older versions that still use the now-deceased `v8::Argument` type.
+
+* **Method argument types**
+ - <a href="doc/methods.md#api_nan_function_callback_info"><b><code>Nan::FunctionCallbackInfo</code></b></a>
+ - <a href="doc/methods.md#api_nan_property_callback_info"><b><code>Nan::PropertyCallbackInfo</code></b></a>
+ - <a href="doc/methods.md#api_nan_return_value"><b><code>Nan::ReturnValue</code></b></a>
+* **Method declarations**
+ - <a href="doc/methods.md#api_nan_method"><b>Method declaration</b></a>
+ - <a href="doc/methods.md#api_nan_getter"><b>Getter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_setter"><b>Setter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_property_getter"><b>Property getter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_property_setter"><b>Property setter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_property_enumerator"><b>Property enumerator declaration</b></a>
+ - <a href="doc/methods.md#api_nan_property_deleter"><b>Property deleter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_property_query"><b>Property query declaration</b></a>
+ - <a href="doc/methods.md#api_nan_index_getter"><b>Index getter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_index_setter"><b>Index setter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_index_enumerator"><b>Index enumerator declaration</b></a>
+ - <a href="doc/methods.md#api_nan_index_deleter"><b>Index deleter declaration</b></a>
+ - <a href="doc/methods.md#api_nan_index_query"><b>Index query declaration</b></a>
+* Method and template helpers
+ - <a href="doc/methods.md#api_nan_set_method"><b><code>Nan::SetMethod()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_prototype_method"><b><code>Nan::SetPrototypeMethod()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_accessor"><b><code>Nan::SetAccessor()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_named_property_handler"><b><code>Nan::SetNamedPropertyHandler()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_indexed_property_handler"><b><code>Nan::SetIndexedPropertyHandler()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_template"><b><code>Nan::SetTemplate()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_prototype_template"><b><code>Nan::SetPrototypeTemplate()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_instance_template"><b><code>Nan::SetInstanceTemplate()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_call_handler"><b><code>Nan::SetCallHandler()</code></b></a>
+ - <a href="doc/methods.md#api_nan_set_call_as_function_handler"><b><code>Nan::SetCallAsFunctionHandler()</code></b></a>
+
+### Scopes
+
+A _local handle_ is a pointer to an object. All V8 objects are accessed using handles, they are necessary because of the way the V8 garbage collector works.
+
+A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope.
+
+The creation of `HandleScope` objects is different across the supported versions of V8. Therefore, NAN provides its own implementations that can be used safely across these.
+
+ - <a href="doc/scopes.md#api_nan_handle_scope"><b><code>Nan::HandleScope</code></b></a>
+ - <a href="doc/scopes.md#api_nan_escapable_handle_scope"><b><code>Nan::EscapableHandleScope</code></b></a>
+
+Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://github.com/v8/v8/wiki/Embedder%27s%20Guide#handles-and-garbage-collection).
+
+### Persistent references
+
+An object reference that is independent of any `HandleScope` is a _persistent_ reference. Where a `Local` handle only lives as long as the `HandleScope` in which it was allocated, a `Persistent` handle remains valid until it is explicitly disposed.
+
+Due to the evolution of the V8 API, it is necessary for NAN to provide a wrapper implementation of the `Persistent` classes to supply compatibility across the V8 versions supported.
+
+ - <a href="doc/persistent.md#api_nan_persistent_base"><b><code>Nan::PersistentBase & v8::PersistentBase</code></b></a>
+ - <a href="doc/persistent.md#api_nan_non_copyable_persistent_traits"><b><code>Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits</code></b></a>
+ - <a href="doc/persistent.md#api_nan_copyable_persistent_traits"><b><code>Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits</code></b></a>
+ - <a href="doc/persistent.md#api_nan_persistent"><b><code>Nan::Persistent</code></b></a>
+ - <a href="doc/persistent.md#api_nan_global"><b><code>Nan::Global</code></b></a>
+ - <a href="doc/persistent.md#api_nan_weak_callback_info"><b><code>Nan::WeakCallbackInfo</code></b></a>
+ - <a href="doc/persistent.md#api_nan_weak_callback_type"><b><code>Nan::WeakCallbackType</code></b></a>
+
+Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://developers.google.com/v8/embed#handles).
+
+### New
+
+NAN provides a `Nan::New()` helper for the creation of new JavaScript objects in a way that's compatible across the supported versions of V8.
+
+ - <a href="doc/new.md#api_nan_new"><b><code>Nan::New()</code></b></a>
+ - <a href="doc/new.md#api_nan_undefined"><b><code>Nan::Undefined()</code></b></a>
+ - <a href="doc/new.md#api_nan_null"><b><code>Nan::Null()</code></b></a>
+ - <a href="doc/new.md#api_nan_true"><b><code>Nan::True()</code></b></a>
+ - <a href="doc/new.md#api_nan_false"><b><code>Nan::False()</code></b></a>
+ - <a href="doc/new.md#api_nan_empty_string"><b><code>Nan::EmptyString()</code></b></a>
+
+
+### Converters
+
+NAN contains functions that convert `v8::Value`s to other `v8::Value` types and native types. Since type conversion is not guaranteed to succeed, they return `Nan::Maybe` types. These converters can be used in place of `value->ToX()` and `value->XValue()` (where `X` is one of the types, e.g. `Boolean`) in a way that provides a consistent interface across V8 versions. Newer versions of V8 use the new `v8::Maybe` and `v8::MaybeLocal` types for these conversions, older versions don't have this functionality so it is provided by NAN.
+
+ - <a href="doc/converters.md#api_nan_to"><b><code>Nan::To()</code></b></a>
+
+### Maybe Types
+
+The `Nan::MaybeLocal` and `Nan::Maybe` types are monads that encapsulate `v8::Local` handles that _may be empty_.
+
+* **Maybe Types**
+  - <a href="doc/maybe_types.md#api_nan_maybe_local"><b><code>Nan::MaybeLocal</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_maybe"><b><code>Nan::Maybe</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_nothing"><b><code>Nan::Nothing</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_just"><b><code>Nan::Just</code></b></a>
+* **Maybe Helpers**
+  - <a href="doc/maybe_types.md#api_nan_call"><b><code>Nan::Call()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_to_detail_string"><b><code>Nan::ToDetailString()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_to_array_index"><b><code>Nan::ToArrayIndex()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_equals"><b><code>Nan::Equals()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_new_instance"><b><code>Nan::NewInstance()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_function"><b><code>Nan::GetFunction()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_set"><b><code>Nan::Set()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_define_own_property"><b><code>Nan::DefineOwnProperty()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_force_set"><del><b><code>Nan::ForceSet()</code></b></del></a>
+  - <a href="doc/maybe_types.md#api_nan_get"><b><code>Nan::Get()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_property_attribute"><b><code>Nan::GetPropertyAttributes()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_has"><b><code>Nan::Has()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_delete"><b><code>Nan::Delete()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_property_names"><b><code>Nan::GetPropertyNames()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_own_property_names"><b><code>Nan::GetOwnPropertyNames()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_set_prototype"><b><code>Nan::SetPrototype()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_object_proto_to_string"><b><code>Nan::ObjectProtoToString()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_has_own_property"><b><code>Nan::HasOwnProperty()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_has_real_named_property"><b><code>Nan::HasRealNamedProperty()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_has_real_indexed_property"><b><code>Nan::HasRealIndexedProperty()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_has_real_named_callback_property"><b><code>Nan::HasRealNamedCallbackProperty()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_real_named_property_in_prototype_chain"><b><code>Nan::GetRealNamedPropertyInPrototypeChain()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_real_named_property"><b><code>Nan::GetRealNamedProperty()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_call_as_function"><b><code>Nan::CallAsFunction()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_call_as_constructor"><b><code>Nan::CallAsConstructor()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_source_line"><b><code>Nan::GetSourceLine()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_line_number"><b><code>Nan::GetLineNumber()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_start_column"><b><code>Nan::GetStartColumn()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_end_column"><b><code>Nan::GetEndColumn()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_clone_element_at"><b><code>Nan::CloneElementAt()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_has_private"><b><code>Nan::HasPrivate()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_get_private"><b><code>Nan::GetPrivate()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_set_private"><b><code>Nan::SetPrivate()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_delete_private"><b><code>Nan::DeletePrivate()</code></b></a>
+  - <a href="doc/maybe_types.md#api_nan_make_maybe"><b><code>Nan::MakeMaybe()</code></b></a>
+
+### Script
+
+NAN provides a `v8::Script` helpers as the API has changed over the supported versions of V8.
+
+ - <a href="doc/script.md#api_nan_compile_script"><b><code>Nan::CompileScript()</code></b></a>
+ - <a href="doc/script.md#api_nan_run_script"><b><code>Nan::RunScript()</code></b></a>
+
+
+### JSON
+
+The _JSON_ object provides the c++ versions of the methods offered by the `JSON` object in javascript. V8 exposes these methods via the `v8::JSON` object.
+
+ - <a href="doc/json.md#api_nan_json_parse"><b><code>Nan::JSON.Parse</code></b></a>
+ - <a href="doc/json.md#api_nan_json_stringify"><b><code>Nan::JSON.Stringify</code></b></a>
+
+Refer to the V8 JSON object in the [V8 documentation](https://v8docs.nodesource.com/node-7.4/da/d6f/classv8_1_1_j_s_o_n.html) for more information about these methods and their arguments.
+
+### Errors
+
+NAN includes helpers for creating, throwing and catching Errors as much of this functionality varies across the supported versions of V8 and must be abstracted.
+
+Note that an Error object is simply a specialized form of `v8::Value`.
+
+Also consult the V8 Embedders Guide section on [Exceptions](https://developers.google.com/v8/embed#exceptions) for more information.
+
+ - <a href="doc/errors.md#api_nan_error"><b><code>Nan::Error()</code></b></a>
+ - <a href="doc/errors.md#api_nan_range_error"><b><code>Nan::RangeError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_reference_error"><b><code>Nan::ReferenceError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_syntax_error"><b><code>Nan::SyntaxError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_type_error"><b><code>Nan::TypeError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_throw_error"><b><code>Nan::ThrowError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_throw_range_error"><b><code>Nan::ThrowRangeError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_throw_reference_error"><b><code>Nan::ThrowReferenceError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_throw_syntax_error"><b><code>Nan::ThrowSyntaxError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_throw_type_error"><b><code>Nan::ThrowTypeError()</code></b></a>
+ - <a href="doc/errors.md#api_nan_fatal_exception"><b><code>Nan::FatalException()</code></b></a>
+ - <a href="doc/errors.md#api_nan_errno_exception"><b><code>Nan::ErrnoException()</code></b></a>
+ - <a href="doc/errors.md#api_nan_try_catch"><b><code>Nan::TryCatch</code></b></a>
+
+
+### Buffers
+
+NAN's `node::Buffer` helpers exist as the API has changed across supported Node versions. Use these methods to ensure compatibility.
+
+ - <a href="doc/buffers.md#api_nan_new_buffer"><b><code>Nan::NewBuffer()</code></b></a>
+ - <a href="doc/buffers.md#api_nan_copy_buffer"><b><code>Nan::CopyBuffer()</code></b></a>
+ - <a href="doc/buffers.md#api_nan_free_callback"><b><code>Nan::FreeCallback()</code></b></a>
+
+### Nan::Callback
+
+`Nan::Callback` makes it easier to use `v8::Function` handles as callbacks. A class that wraps a `v8::Function` handle, protecting it from garbage collection and making it particularly useful for storage and use across asynchronous execution.
+
+ - <a href="doc/callback.md#api_nan_callback"><b><code>Nan::Callback</code></b></a>
+
+### Asynchronous work helpers
+
+`Nan::AsyncWorker`, `Nan::AsyncProgressWorker` and `Nan::AsyncProgressQueueWorker` are helper classes that make working with asynchronous code easier.
+
+ - <a href="doc/asyncworker.md#api_nan_async_worker"><b><code>Nan::AsyncWorker</code></b></a>
+ - <a href="doc/asyncworker.md#api_nan_async_progress_worker"><b><code>Nan::AsyncProgressWorkerBase &amp; Nan::AsyncProgressWorker</code></b></a>
+ - <a href="doc/asyncworker.md#api_nan_async_progress_queue_worker"><b><code>Nan::AsyncProgressQueueWorker</code></b></a>
+ - <a href="doc/asyncworker.md#api_nan_async_queue_worker"><b><code>Nan::AsyncQueueWorker</code></b></a>
+
+### Strings & Bytes
+
+Miscellaneous string & byte encoding and decoding functionality provided for compatibility across supported versions of V8 and Node. Implemented by NAN to ensure that all encoding types are supported, even for older versions of Node where they are missing.
+
+ - <a href="doc/string_bytes.md#api_nan_encoding"><b><code>Nan::Encoding</code></b></a>
+ - <a href="doc/string_bytes.md#api_nan_encode"><b><code>Nan::Encode()</code></b></a>
+ - <a href="doc/string_bytes.md#api_nan_decode_bytes"><b><code>Nan::DecodeBytes()</code></b></a>
+ - <a href="doc/string_bytes.md#api_nan_decode_write"><b><code>Nan::DecodeWrite()</code></b></a>
+
+
+### Object Wrappers
+
+The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects.
+
+ - <a href="doc/object_wrappers.md#api_nan_object_wrap"><b><code>Nan::ObjectWrap</code></b></a>
+
+
+### V8 internals
+
+The hooks to access V8 internals—including GC and statistics—are different across the supported versions of V8, therefore NAN provides its own hooks that call the appropriate V8 methods.
+
+ - <a href="doc/v8_internals.md#api_nan_gc_callback"><b><code>NAN_GC_CALLBACK()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_add_gc_epilogue_callback"><b><code>Nan::AddGCEpilogueCallback()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_remove_gc_epilogue_callback"><b><code>Nan::RemoveGCEpilogueCallback()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_add_gc_prologue_callback"><b><code>Nan::AddGCPrologueCallback()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_remove_gc_prologue_callback"><b><code>Nan::RemoveGCPrologueCallback()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_get_heap_statistics"><b><code>Nan::GetHeapStatistics()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_set_counter_function"><b><code>Nan::SetCounterFunction()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_set_create_histogram_function"><b><code>Nan::SetCreateHistogramFunction()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_set_add_histogram_sample_function"><b><code>Nan::SetAddHistogramSampleFunction()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_idle_notification"><b><code>Nan::IdleNotification()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_low_memory_notification"><b><code>Nan::LowMemoryNotification()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_context_disposed_notification"><b><code>Nan::ContextDisposedNotification()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_get_internal_field_pointer"><b><code>Nan::GetInternalFieldPointer()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_set_internal_field_pointer"><b><code>Nan::SetInternalFieldPointer()</code></b></a>
+ - <a href="doc/v8_internals.md#api_nan_adjust_external_memory"><b><code>Nan::AdjustExternalMemory()</code></b></a>
+
+
+### Miscellaneous V8 Helpers
+
+ - <a href="doc/v8_misc.md#api_nan_utf8_string"><b><code>Nan::Utf8String</code></b></a>
+ - <a href="doc/v8_misc.md#api_nan_get_current_context"><b><code>Nan::GetCurrentContext()</code></b></a>
+ - <a href="doc/v8_misc.md#api_nan_set_isolate_data"><b><code>Nan::SetIsolateData()</code></b></a>
+ - <a href="doc/v8_misc.md#api_nan_get_isolate_data"><b><code>Nan::GetIsolateData()</code></b></a>
+ - <a href="doc/v8_misc.md#api_nan_typedarray_contents"><b><code>Nan::TypedArrayContents</code></b></a>
+
+
+### Miscellaneous Node Helpers
+
+ - <a href="doc/node_misc.md#api_nan_asyncresource"><b><code>Nan::AsyncResource</code></b></a>
+ - <a href="doc/node_misc.md#api_nan_make_callback"><b><code>Nan::MakeCallback()</code></b></a>
+ - <a href="doc/node_misc.md#api_nan_module_init"><b><code>NAN_MODULE_INIT()</code></b></a>
+ - <a href="doc/node_misc.md#api_nan_export"><b><code>Nan::Export()</code></b></a>
+
+<!-- END API -->
+
+
+<a name="tests"></a>
+
+### Tests
+
+To run the NAN tests do:
+
+``` sh
+npm install
+npm run-script rebuild-tests
+npm test
+```
+
+Or just:
+
+``` sh
+npm install
+make test
+```
+
+<a name="issues"></a>
+
+## Known issues
+
+### Compiling against Node.js 0.12 on OSX
+
+With new enough compilers available on OSX, the versions of V8 headers corresponding to Node.js 0.12
+do not compile anymore. The error looks something like:
+
+```
+❯   CXX(target) Release/obj.target/accessors/cpp/accessors.o
+In file included from ../cpp/accessors.cpp:9:
+In file included from ../../nan.h:51:
+In file included from /Users/ofrobots/.node-gyp/0.12.18/include/node/node.h:61:
+/Users/ofrobots/.node-gyp/0.12.18/include/node/v8.h:5800:54: error: 'CreateHandle' is a protected member of 'v8::HandleScope'
+  return Handle<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(
+                                        ~~~~~~~~~~~~~^~~~~~~~~~~~
+```
+
+This can be worked around by patching your local versions of v8.h corresponding to Node 0.12 to make
+`v8::Handle` a friend of `v8::HandleScope`. Since neither Node.js not V8 support this release line anymore
+this patch cannot be released by either project in an official release.
+
+For this reason, we do not test against Node.js 0.12 on OSX in this project's CI. If you need to support
+that configuration, you will need to either get an older compiler, or apply a source patch to the version
+of V8 headers as a workaround.
+
+<a name="governance"></a>
+
+## Governance & Contributing
+
+NAN is governed by the [Node.js Addon API Working Group](https://github.com/nodejs/CTC/blob/master/WORKING_GROUPS.md#addon-api)
+
+### Addon API Working Group (WG)
+
+The NAN project is jointly governed by a Working Group which is responsible for high-level guidance of the project.
+
+Members of the WG are also known as Collaborators, there is no distinction between the two, unlike other Node.js projects.
+
+The WG has final authority over this project including:
+
+* Technical direction
+* Project governance and process (including this policy)
+* Contribution policy
+* GitHub repository hosting
+* Maintaining the list of additional Collaborators
+
+For the current list of WG members, see the project [README.md](./README.md#collaborators).
+
+Individuals making significant and valuable contributions are made members of the WG and given commit-access to the project. These individuals are identified by the WG and their addition to the WG is discussed via GitHub and requires unanimous consensus amongst those WG members participating in the discussion with a quorum of 50% of WG members required for acceptance of the vote.
+
+_Note:_ If you make a significant contribution and are not considered for commit-access log an issue or contact a WG member directly.
+
+For the current list of WG members / Collaborators, see the project [README.md](./README.md#collaborators).
+
+### Consensus Seeking Process
+
+The WG follows a [Consensus Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making) decision making model.
+
+Modifications of the contents of the NAN repository are made on a collaborative basis. Anybody with a GitHub account may propose a modification via pull request and it will be considered by the WG. All pull requests must be reviewed and accepted by a WG member with sufficient expertise who is able to take full responsibility for the change. In the case of pull requests proposed by an existing WG member, an additional WG member is required for sign-off. Consensus should be sought if additional WG members participate and there is disagreement around a particular modification.
+
+If a change proposal cannot reach a consensus, a WG member can call for a vote amongst the members of the WG. Simple majority wins.
+
+<a id="developers-certificate-of-origin"></a>
+
+## Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+* (a) The contribution was created in whole or in part by me and I
+  have the right to submit it under the open source license
+  indicated in the file; or
+
+* (b) The contribution is based upon previous work that, to the best
+  of my knowledge, is covered under an appropriate open source
+  license and I have the right under that license to submit that
+  work with modifications, whether created in whole or in part
+  by me, under the same open source license (unless I am
+  permitted to submit under a different license), as indicated
+  in the file; or
+
+* (c) The contribution was provided directly to me by some other
+  person who certified (a), (b) or (c) and I have not modified
+  it.
+
+* (d) I understand and agree that this project and the contribution
+  are public and that a record of the contribution (including all
+  personal information I submit with it, including my sign-off) is
+  maintained indefinitely and may be redistributed consistent with
+  this project or the open source license(s) involved.
+
+<a name="collaborators"></a>
+
+### WG Members / Collaborators
+
+<table><tbody>
+<tr><th align="left">Rod Vagg</th><td><a href="https://github.com/rvagg">GitHub/rvagg</a></td><td><a href="http://twitter.com/rvagg">Twitter/@rvagg</a></td></tr>
+<tr><th align="left">Benjamin Byholm</th><td><a href="https://github.com/kkoopa/">GitHub/kkoopa</a></td><td>-</td></tr>
+<tr><th align="left">Trevor Norris</th><td><a href="https://github.com/trevnorris">GitHub/trevnorris</a></td><td><a href="http://twitter.com/trevnorris">Twitter/@trevnorris</a></td></tr>
+<tr><th align="left">Nathan Rajlich</th><td><a href="https://github.com/TooTallNate">GitHub/TooTallNate</a></td><td><a href="http://twitter.com/TooTallNate">Twitter/@TooTallNate</a></td></tr>
+<tr><th align="left">Brett Lawson</th><td><a href="https://github.com/brett19">GitHub/brett19</a></td><td><a href="http://twitter.com/brett19x">Twitter/@brett19x</a></td></tr>
+<tr><th align="left">Ben Noordhuis</th><td><a href="https://github.com/bnoordhuis">GitHub/bnoordhuis</a></td><td><a href="http://twitter.com/bnoordhuis">Twitter/@bnoordhuis</a></td></tr>
+<tr><th align="left">David Siegel</th><td><a href="https://github.com/agnat">GitHub/agnat</a></td><td><a href="http://twitter.com/agnat">Twitter/@agnat</a></td></tr>
+<tr><th align="left">Michael Ira Krufky</th><td><a href="https://github.com/mkrufky">GitHub/mkrufky</a></td><td><a href="http://twitter.com/mkrufky">Twitter/@mkrufky</a></td></tr>
+</tbody></table>
+
+## Licence &amp; copyright
+
+Copyright (c) 2018 NAN WG Members / Collaborators (listed above).
+
+Native Abstractions for Node.js is licensed under an MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
diff --git a/input_devices/mag/node_modules/nan/doc/asyncworker.md b/input_devices/mag/node_modules/nan/doc/asyncworker.md
new file mode 100644
index 00000000..239de801
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/asyncworker.md
@@ -0,0 +1,146 @@
+## Asynchronous work helpers
+
+`Nan::AsyncWorker`, `Nan::AsyncProgressWorker` and `Nan::AsyncProgressQueueWorker` are helper classes that make working with asynchronous code easier.
+
+ - <a href="#api_nan_async_worker"><b><code>Nan::AsyncWorker</code></b></a>
+ - <a href="#api_nan_async_progress_worker"><b><code>Nan::AsyncProgressWorkerBase &amp; Nan::AsyncProgressWorker</code></b></a>
+ - <a href="#api_nan_async_progress_queue_worker"><b><code>Nan::AsyncProgressQueueWorker</code></b></a>
+ - <a href="#api_nan_async_queue_worker"><b><code>Nan::AsyncQueueWorker</code></b></a>
+
+<a name="api_nan_async_worker"></a>
+### Nan::AsyncWorker
+
+`Nan::AsyncWorker` is an _abstract_ class that you can subclass to have much of the annoying asynchronous queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the asynchronous work is in progress.
+
+This class internally handles the details of creating an [`AsyncResource`][AsyncResource], and running the callback in the
+correct async context. To be able to identify the async resources created by this class in async-hooks, provide a
+`resource_name` to the constructor. It is recommended that the module name be used as a prefix to the `resource_name` to avoid
+collisions in the names. For more details see [`AsyncResource`][AsyncResource] documentation.  The `resource_name` needs to stay valid for the lifetime of the worker instance.
+
+Definition:
+
+```c++
+class AsyncWorker {
+ public:
+  explicit AsyncWorker(Callback *callback_, const char* resource_name = "nan:AsyncWorker");
+
+  virtual ~AsyncWorker();
+
+  virtual void WorkComplete();
+
+  void SaveToPersistent(const char *key, const v8::Local<v8::Value> &value);
+
+  void SaveToPersistent(const v8::Local<v8::String> &key,
+                        const v8::Local<v8::Value> &value);
+
+  void SaveToPersistent(uint32_t index,
+                        const v8::Local<v8::Value> &value);
+
+  v8::Local<v8::Value> GetFromPersistent(const char *key) const;
+
+  v8::Local<v8::Value> GetFromPersistent(const v8::Local<v8::String> &key) const;
+
+  v8::Local<v8::Value> GetFromPersistent(uint32_t index) const;
+
+  virtual void Execute() = 0;
+
+  uv_work_t request;
+
+  virtual void Destroy();
+
+ protected:
+  Persistent<v8::Object> persistentHandle;
+
+  Callback *callback;
+
+  virtual void HandleOKCallback();
+
+  virtual void HandleErrorCallback();
+
+  void SetErrorMessage(const char *msg);
+
+  const char* ErrorMessage();
+};
+```
+
+<a name="api_nan_async_progress_worker"></a>
+### Nan::AsyncProgressWorkerBase &amp; Nan::AsyncProgressWorker
+
+`Nan::AsyncProgressWorkerBase` is an _abstract_ class template that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript.
+
+Previously the definiton of `Nan::AsyncProgressWorker` only allowed sending `const char` data. Now extending `Nan::AsyncProgressWorker` will yield an instance of the implicit `Nan::AsyncProgressWorkerBase` template with type `<char>` for compatibility.
+
+`Nan::AsyncProgressWorkerBase` &amp; `Nan::AsyncProgressWorker` is intended for best-effort delivery of nonessential progress messages, e.g. a progress bar.  The last event sent before the main thread is woken will be delivered.
+
+Definition:
+
+```c++
+template<class T>
+class AsyncProgressWorkerBase<T> : public AsyncWorker {
+ public:
+  explicit AsyncProgressWorkerBase(Callback *callback_, const char* resource_name = ...);
+
+  virtual ~AsyncProgressWorkerBase();
+
+  void WorkProgress();
+
+  class ExecutionProgress {
+   public:
+    void Signal() const;
+    void Send(const T* data, size_t count) const;
+  };
+
+  virtual void Execute(const ExecutionProgress& progress) = 0;
+
+  virtual void HandleProgressCallback(const T *data, size_t count) = 0;
+
+  virtual void Destroy();
+};
+
+typedef AsyncProgressWorkerBase<T> AsyncProgressWorker;
+```
+
+<a name="api_nan_async_progress_queue_worker"></a>
+### Nan::AsyncProgressQueueWorker
+
+`Nan::AsyncProgressQueueWorker` is an _abstract_ class template that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript.
+
+`Nan::AsyncProgressQueueWorker` behaves exactly the same as `Nan::AsyncProgressWorker`, except all events are queued and delivered to the main thread.
+
+Definition:
+
+```c++
+template<class T>
+class AsyncProgressQueueWorker<T> : public AsyncWorker {
+ public:
+  explicit AsyncProgressQueueWorker(Callback *callback_, const char* resource_name = "nan:AsyncProgressQueueWorker");
+
+  virtual ~AsyncProgressQueueWorker();
+
+  void WorkProgress();
+
+  class ExecutionProgress {
+   public:
+    void Send(const T* data, size_t count) const;
+  };
+
+  virtual void Execute(const ExecutionProgress& progress) = 0;
+
+  virtual void HandleProgressCallback(const T *data, size_t count) = 0;
+
+  virtual void Destroy();
+};
+```
+
+<a name="api_nan_async_queue_worker"></a>
+### Nan::AsyncQueueWorker
+
+`Nan::AsyncQueueWorker` will run a `Nan::AsyncWorker` asynchronously via libuv. Both the `execute` and `after_work` steps are taken care of for you. Most of the logic for this is embedded in `Nan::AsyncWorker`.
+
+Definition:
+
+```c++
+void AsyncQueueWorker(AsyncWorker *);
+```
+
+[AsyncResource]: "node_misc.html#api_nan_asyncresource"
diff --git a/input_devices/mag/node_modules/nan/doc/buffers.md b/input_devices/mag/node_modules/nan/doc/buffers.md
new file mode 100644
index 00000000..8d8d25cf
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/buffers.md
@@ -0,0 +1,54 @@
+## Buffers
+
+NAN's `node::Buffer` helpers exist as the API has changed across supported Node versions. Use these methods to ensure compatibility.
+
+ - <a href="#api_nan_new_buffer"><b><code>Nan::NewBuffer()</code></b></a>
+ - <a href="#api_nan_copy_buffer"><b><code>Nan::CopyBuffer()</code></b></a>
+ - <a href="#api_nan_free_callback"><b><code>Nan::FreeCallback()</code></b></a>
+
+<a name="api_nan_new_buffer"></a>
+### Nan::NewBuffer()
+
+Allocate a new `node::Buffer` object with the specified size and optional data. Calls `node::Buffer::New()`.
+
+Note that when creating a `Buffer` using `Nan::NewBuffer()` and an existing `char*`, it is assumed that the ownership of the pointer is being transferred to the new `Buffer` for management.
+When a `node::Buffer` instance is garbage collected and a `FreeCallback` has not been specified, `data` will be disposed of via a call to `free()`.
+You _must not_ free the memory space manually once you have created a `Buffer` in this way.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Object> Nan::NewBuffer(uint32_t size)
+Nan::MaybeLocal<v8::Object> Nan::NewBuffer(char* data, uint32_t size)
+Nan::MaybeLocal<v8::Object> Nan::NewBuffer(char *data,
+                                           size_t length,
+                                           Nan::FreeCallback callback,
+                                           void *hint)
+```
+
+
+<a name="api_nan_copy_buffer"></a>
+### Nan::CopyBuffer()
+
+Similar to [`Nan::NewBuffer()`](#api_nan_new_buffer) except that an implicit memcpy will occur within Node. Calls `node::Buffer::Copy()`.
+
+Management of the `char*` is left to the user, you should manually free the memory space if necessary as the new `Buffer` will have its own copy.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Object> Nan::CopyBuffer(const char *data, uint32_t size)
+```
+
+
+<a name="api_nan_free_callback"></a>
+### Nan::FreeCallback()
+
+A free callback that can be provided to [`Nan::NewBuffer()`](#api_nan_new_buffer).
+The supplied callback will be invoked when the `Buffer` undergoes garbage collection.
+
+Signature:
+
+```c++
+typedef void (*FreeCallback)(char *data, void *hint);
+```
diff --git a/input_devices/mag/node_modules/nan/doc/callback.md b/input_devices/mag/node_modules/nan/doc/callback.md
new file mode 100644
index 00000000..f7af0bfd
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/callback.md
@@ -0,0 +1,76 @@
+## Nan::Callback
+
+`Nan::Callback` makes it easier to use `v8::Function` handles as callbacks. A class that wraps a `v8::Function` handle, protecting it from garbage collection and making it particularly useful for storage and use across asynchronous execution.
+
+ - <a href="#api_nan_callback"><b><code>Nan::Callback</code></b></a>
+
+<a name="api_nan_callback"></a>
+### Nan::Callback
+
+```c++
+class Callback {
+ public:
+  Callback();
+
+  explicit Callback(const v8::Local<v8::Function> &fn);
+
+  ~Callback();
+
+  bool operator==(const Callback &other) const;
+
+  bool operator!=(const Callback &other) const;
+
+  v8::Local<v8::Function> operator*() const;
+
+  MaybeLocal<v8::Value> operator()(AsyncResource* async_resource,
+                                   v8::Local<v8::Object> target,
+                                   int argc = 0,
+                                   v8::Local<v8::Value> argv[] = 0) const;
+
+  MaybeLocal<v8::Value> operator()(AsyncResource* async_resource,
+                                   int argc = 0,
+                                   v8::Local<v8::Value> argv[] = 0) const;
+
+  void SetFunction(const v8::Local<v8::Function> &fn);
+
+  v8::Local<v8::Function> GetFunction() const;
+
+  bool IsEmpty() const;
+
+  void Reset(const v8::Local<v8::Function> &fn);
+
+  void Reset();
+
+  MaybeLocal<v8::Value> Call(v8::Local<v8::Object> target,
+                            int argc,
+                            v8::Local<v8::Value> argv[],
+                            AsyncResource* async_resource) const;
+  MaybeLocal<v8::Value> Call(int argc,
+                             v8::Local<v8::Value> argv[],
+                             AsyncResource* async_resource) const;
+
+  // Deprecated versions. Use the versions that accept an async_resource instead
+  // as they run the callback in the correct async context as specified by the
+  // resource. If you want to call a synchronous JS function (i.e. on a
+  // non-empty JS stack), you can use Nan::Call instead.
+  v8::Local<v8::Value> operator()(v8::Local<v8::Object> target,
+                                  int argc = 0,
+                                  v8::Local<v8::Value> argv[] = 0) const;
+
+  v8::Local<v8::Value> operator()(int argc = 0,
+                                  v8::Local<v8::Value> argv[] = 0) const;
+  v8::Local<v8::Value> Call(v8::Local<v8::Object> target,
+                            int argc,
+                            v8::Local<v8::Value> argv[]) const;
+
+  v8::Local<v8::Value> Call(int argc, v8::Local<v8::Value> argv[]) const;
+};
+```
+
+Example usage:
+
+```c++
+v8::Local<v8::Function> function;
+Nan::Callback callback(function);
+callback.Call(0, 0);
+```
diff --git a/input_devices/mag/node_modules/nan/doc/converters.md b/input_devices/mag/node_modules/nan/doc/converters.md
new file mode 100644
index 00000000..d20861b5
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/converters.md
@@ -0,0 +1,41 @@
+## Converters
+
+NAN contains functions that convert `v8::Value`s to other `v8::Value` types and native types. Since type conversion is not guaranteed to succeed, they return `Nan::Maybe` types. These converters can be used in place of `value->ToX()` and `value->XValue()` (where `X` is one of the types, e.g. `Boolean`) in a way that provides a consistent interface across V8 versions. Newer versions of V8 use the new `v8::Maybe` and `v8::MaybeLocal` types for these conversions, older versions don't have this functionality so it is provided by NAN.
+
+ - <a href="#api_nan_to"><b><code>Nan::To()</code></b></a>
+
+<a name="api_nan_to"></a>
+### Nan::To()
+
+Converts a `v8::Local<v8::Value>` to a different subtype of `v8::Value` or to a native data type. Returns a `Nan::MaybeLocal<>` or a `Nan::Maybe<>` accordingly.
+
+See [maybe_types.md](./maybe_types.md) for more information on `Nan::Maybe` types.
+
+Signatures:
+
+```c++
+// V8 types
+Nan::MaybeLocal<v8::Boolean> Nan::To<v8::Boolean>(v8::Local<v8::Value> val);
+Nan::MaybeLocal<v8::Int32> Nan::To<v8::Int32>(v8::Local<v8::Value> val);
+Nan::MaybeLocal<v8::Integer> Nan::To<v8::Integer>(v8::Local<v8::Value> val);
+Nan::MaybeLocal<v8::Object> Nan::To<v8::Object>(v8::Local<v8::Value> val);
+Nan::MaybeLocal<v8::Number> Nan::To<v8::Number>(v8::Local<v8::Value> val);
+Nan::MaybeLocal<v8::String> Nan::To<v8::String>(v8::Local<v8::Value> val);
+Nan::MaybeLocal<v8::Uint32> Nan::To<v8::Uint32>(v8::Local<v8::Value> val);
+
+// Native types
+Nan::Maybe<bool> Nan::To<bool>(v8::Local<v8::Value> val);
+Nan::Maybe<double> Nan::To<double>(v8::Local<v8::Value> val);
+Nan::Maybe<int32_t> Nan::To<int32_t>(v8::Local<v8::Value> val);
+Nan::Maybe<int64_t> Nan::To<int64_t>(v8::Local<v8::Value> val);
+Nan::Maybe<uint32_t> Nan::To<uint32_t>(v8::Local<v8::Value> val);
+```
+
+### Example
+
+```c++
+v8::Local<v8::Value> val;
+Nan::MaybeLocal<v8::String> str = Nan::To<v8::String>(val);
+Nan::Maybe<double> d = Nan::To<double>(val);
+```
+
diff --git a/input_devices/mag/node_modules/nan/doc/errors.md b/input_devices/mag/node_modules/nan/doc/errors.md
new file mode 100644
index 00000000..b93b3535
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/errors.md
@@ -0,0 +1,226 @@
+## Errors
+
+NAN includes helpers for creating, throwing and catching Errors as much of this functionality varies across the supported versions of V8 and must be abstracted.
+
+Note that an Error object is simply a specialized form of `v8::Value`.
+
+Also consult the V8 Embedders Guide section on [Exceptions](https://developers.google.com/v8/embed#exceptions) for more information.
+
+ - <a href="#api_nan_error"><b><code>Nan::Error()</code></b></a>
+ - <a href="#api_nan_range_error"><b><code>Nan::RangeError()</code></b></a>
+ - <a href="#api_nan_reference_error"><b><code>Nan::ReferenceError()</code></b></a>
+ - <a href="#api_nan_syntax_error"><b><code>Nan::SyntaxError()</code></b></a>
+ - <a href="#api_nan_type_error"><b><code>Nan::TypeError()</code></b></a>
+ - <a href="#api_nan_throw_error"><b><code>Nan::ThrowError()</code></b></a>
+ - <a href="#api_nan_throw_range_error"><b><code>Nan::ThrowRangeError()</code></b></a>
+ - <a href="#api_nan_throw_reference_error"><b><code>Nan::ThrowReferenceError()</code></b></a>
+ - <a href="#api_nan_throw_syntax_error"><b><code>Nan::ThrowSyntaxError()</code></b></a>
+ - <a href="#api_nan_throw_type_error"><b><code>Nan::ThrowTypeError()</code></b></a>
+ - <a href="#api_nan_fatal_exception"><b><code>Nan::FatalException()</code></b></a>
+ - <a href="#api_nan_errno_exception"><b><code>Nan::ErrnoException()</code></b></a>
+ - <a href="#api_nan_try_catch"><b><code>Nan::TryCatch</code></b></a>
+
+
+<a name="api_nan_error"></a>
+### Nan::Error()
+
+Create a new Error object using the [v8::Exception](https://v8docs.nodesource.com/io.js-3.3/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8.
+
+Note that an Error object is simply a specialized form of `v8::Value`.
+
+Signature:
+
+```c++
+v8::Local<v8::Value> Nan::Error(const char *msg);
+v8::Local<v8::Value> Nan::Error(v8::Local<v8::String> msg);
+```
+
+
+<a name="api_nan_range_error"></a>
+### Nan::RangeError()
+
+Create a new RangeError object using the [v8::Exception](https://v8docs.nodesource.com/io.js-3.3/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8.
+
+Note that an RangeError object is simply a specialized form of `v8::Value`.
+
+Signature:
+
+```c++
+v8::Local<v8::Value> Nan::RangeError(const char *msg);
+v8::Local<v8::Value> Nan::RangeError(v8::Local<v8::String> msg);
+```
+
+
+<a name="api_nan_reference_error"></a>
+### Nan::ReferenceError()
+
+Create a new ReferenceError object using the [v8::Exception](https://v8docs.nodesource.com/io.js-3.3/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8.
+
+Note that an ReferenceError object is simply a specialized form of `v8::Value`.
+
+Signature:
+
+```c++
+v8::Local<v8::Value> Nan::ReferenceError(const char *msg);
+v8::Local<v8::Value> Nan::ReferenceError(v8::Local<v8::String> msg);
+```
+
+
+<a name="api_nan_syntax_error"></a>
+### Nan::SyntaxError()
+
+Create a new SyntaxError object using the [v8::Exception](https://v8docs.nodesource.com/io.js-3.3/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8.
+
+Note that an SyntaxError object is simply a specialized form of `v8::Value`.
+
+Signature:
+
+```c++
+v8::Local<v8::Value> Nan::SyntaxError(const char *msg);
+v8::Local<v8::Value> Nan::SyntaxError(v8::Local<v8::String> msg);
+```
+
+
+<a name="api_nan_type_error"></a>
+### Nan::TypeError()
+
+Create a new TypeError object using the [v8::Exception](https://v8docs.nodesource.com/io.js-3.3/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8.
+
+Note that an TypeError object is simply a specialized form of `v8::Value`.
+
+Signature:
+
+```c++
+v8::Local<v8::Value> Nan::TypeError(const char *msg);
+v8::Local<v8::Value> Nan::TypeError(v8::Local<v8::String> msg);
+```
+
+
+<a name="api_nan_throw_error"></a>
+### Nan::ThrowError()
+
+Throw an Error object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new Error object will be created.
+
+Signature:
+
+```c++
+void Nan::ThrowError(const char *msg);
+void Nan::ThrowError(v8::Local<v8::String> msg);
+void Nan::ThrowError(v8::Local<v8::Value> error);
+```
+
+
+<a name="api_nan_throw_range_error"></a>
+### Nan::ThrowRangeError()
+
+Throw an RangeError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new RangeError object will be created.
+
+Signature:
+
+```c++
+void Nan::ThrowRangeError(const char *msg);
+void Nan::ThrowRangeError(v8::Local<v8::String> msg);
+void Nan::ThrowRangeError(v8::Local<v8::Value> error);
+```
+
+
+<a name="api_nan_throw_reference_error"></a>
+### Nan::ThrowReferenceError()
+
+Throw an ReferenceError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new ReferenceError object will be created.
+
+Signature:
+
+```c++
+void Nan::ThrowReferenceError(const char *msg);
+void Nan::ThrowReferenceError(v8::Local<v8::String> msg);
+void Nan::ThrowReferenceError(v8::Local<v8::Value> error);
+```
+
+
+<a name="api_nan_throw_syntax_error"></a>
+### Nan::ThrowSyntaxError()
+
+Throw an SyntaxError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new SyntaxError object will be created.
+
+Signature:
+
+```c++
+void Nan::ThrowSyntaxError(const char *msg);
+void Nan::ThrowSyntaxError(v8::Local<v8::String> msg);
+void Nan::ThrowSyntaxError(v8::Local<v8::Value> error);
+```
+
+
+<a name="api_nan_throw_type_error"></a>
+### Nan::ThrowTypeError()
+
+Throw an TypeError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new TypeError object will be created.
+
+Signature:
+
+```c++
+void Nan::ThrowTypeError(const char *msg);
+void Nan::ThrowTypeError(v8::Local<v8::String> msg);
+void Nan::ThrowTypeError(v8::Local<v8::Value> error);
+```
+
+<a name="api_nan_fatal_exception"></a>
+### Nan::FatalException()
+
+Replaces `node::FatalException()` which has a different API across supported versions of Node. For use with [`Nan::TryCatch`](#api_nan_try_catch).
+
+Signature:
+
+```c++
+void Nan::FatalException(const Nan::TryCatch& try_catch);
+```
+
+<a name="api_nan_errno_exception"></a>
+### Nan::ErrnoException()
+
+Replaces `node::ErrnoException()` which has a different API across supported versions of Node. 
+
+Signature:
+
+```c++
+v8::Local<v8::Value> Nan::ErrnoException(int errorno,
+                                         const char* syscall = NULL,
+                                         const char* message = NULL,
+                                         const char* path = NULL);
+```
+
+
+<a name="api_nan_try_catch"></a>
+### Nan::TryCatch
+
+A simple wrapper around [`v8::TryCatch`](https://v8docs.nodesource.com/io.js-3.3/d4/dc6/classv8_1_1_try_catch.html) compatible with all supported versions of V8. Can be used as a direct replacement in most cases. See also [`Nan::FatalException()`](#api_nan_fatal_exception) for an internal use compatible with `node::FatalException`.
+
+Signature:
+
+```c++
+class Nan::TryCatch {
+ public:
+  Nan::TryCatch();
+
+  bool HasCaught() const;
+
+  bool CanContinue() const;
+
+  v8::Local<v8::Value> ReThrow();
+
+  v8::Local<v8::Value> Exception() const;
+
+  // Nan::MaybeLocal for older versions of V8
+  v8::MaybeLocal<v8::Value> StackTrace() const;
+
+  v8::Local<v8::Message> Message() const;
+
+  void Reset();
+
+  void SetVerbose(bool value);
+
+  void SetCaptureMessage(bool value);
+};
+```
+
diff --git a/input_devices/mag/node_modules/nan/doc/json.md b/input_devices/mag/node_modules/nan/doc/json.md
new file mode 100644
index 00000000..c916c4d1
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/json.md
@@ -0,0 +1,62 @@
+## JSON
+
+The _JSON_ object provides the c++ versions of the methods offered by the `JSON` object in javascript. V8 exposes these methods via the `v8::JSON` object.
+
+ - <a href="#api_nan_json_parse"><b><code>Nan::JSON.Parse</code></b></a>
+ - <a href="#api_nan_json_stringify"><b><code>Nan::JSON.Stringify</code></b></a>
+
+Refer to the V8 JSON object in the [V8 documentation](https://v8docs.nodesource.com/node-7.4/da/d6f/classv8_1_1_j_s_o_n.html) for more information about these methods and their arguments.
+
+<a name="api_nan_json_parse"></a>
+
+### Nan::JSON.Parse
+
+A simple wrapper around [`v8::JSON::Parse`](https://v8docs.nodesource.com/node-7.4/da/d6f/classv8_1_1_j_s_o_n.html#a936310d2540fb630ed37d3ee3ffe4504).
+
+Definition:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::JSON::Parse(v8::Local<v8::String> json_string);
+```
+
+Use `JSON.Parse(json_string)` to parse a string into a `v8::Value`.
+
+Example:
+
+```c++
+v8::Local<v8::String> json_string = Nan::New("{ \"JSON\": \"object\" }").ToLocalChecked();
+
+Nan::JSON NanJSON;
+Nan::MaybeLocal<v8::Value> result = NanJSON.Parse(json_string);
+if (!result.IsEmpty()) {
+  v8::Local<v8::Value> val = result.ToLocalChecked();
+}
+```
+
+<a name="api_nan_json_stringify"></a>
+
+### Nan::JSON.Stringify
+
+A simple wrapper around [`v8::JSON::Stringify`](https://v8docs.nodesource.com/node-7.4/da/d6f/classv8_1_1_j_s_o_n.html#a44b255c3531489ce43f6110209138860).
+
+Definition:
+
+```c++
+Nan::MaybeLocal<v8::String> Nan::JSON::Stringify(v8::Local<v8::Object> json_object, v8::Local<v8::String> gap = v8::Local<v8::String>());
+```
+
+Use `JSON.Stringify(value)` to stringify a `v8::Object`.
+
+Example:
+
+```c++
+// using `v8::Local<v8::Value> val` from the `JSON::Parse` example
+v8::Local<v8::Object> obj = Nan::To<v8::Object>(val).ToLocalChecked();
+
+Nan::JSON NanJSON;
+Nan::MaybeLocal<v8::String> result = NanJSON.Stringify(obj);
+if (!result.IsEmpty()) {
+  v8::Local<v8::String> stringified = result.ToLocalChecked();
+}
+```
+
diff --git a/input_devices/mag/node_modules/nan/doc/maybe_types.md b/input_devices/mag/node_modules/nan/doc/maybe_types.md
new file mode 100644
index 00000000..f11df56d
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/maybe_types.md
@@ -0,0 +1,583 @@
+## Maybe Types
+
+The `Nan::MaybeLocal` and `Nan::Maybe` types are monads that encapsulate `v8::Local` handles that _may be empty_.
+
+* **Maybe Types**
+  - <a href="#api_nan_maybe_local"><b><code>Nan::MaybeLocal</code></b></a>
+  - <a href="#api_nan_maybe"><b><code>Nan::Maybe</code></b></a>
+  - <a href="#api_nan_nothing"><b><code>Nan::Nothing</code></b></a>
+  - <a href="#api_nan_just"><b><code>Nan::Just</code></b></a>
+* **Maybe Helpers**
+  - <a href="#api_nan_call"><b><code>Nan::Call()</code></b></a>
+  - <a href="#api_nan_to_detail_string"><b><code>Nan::ToDetailString()</code></b></a>
+  - <a href="#api_nan_to_array_index"><b><code>Nan::ToArrayIndex()</code></b></a>
+  - <a href="#api_nan_equals"><b><code>Nan::Equals()</code></b></a>
+  - <a href="#api_nan_new_instance"><b><code>Nan::NewInstance()</code></b></a>
+  - <a href="#api_nan_get_function"><b><code>Nan::GetFunction()</code></b></a>
+  - <a href="#api_nan_set"><b><code>Nan::Set()</code></b></a>
+  - <a href="#api_nan_define_own_property"><b><code>Nan::DefineOwnProperty()</code></b></a>
+  - <a href="#api_nan_force_set"><del><b><code>Nan::ForceSet()</code></b></del></a>
+  - <a href="#api_nan_get"><b><code>Nan::Get()</code></b></a>
+  - <a href="#api_nan_get_property_attribute"><b><code>Nan::GetPropertyAttributes()</code></b></a>
+  - <a href="#api_nan_has"><b><code>Nan::Has()</code></b></a>
+  - <a href="#api_nan_delete"><b><code>Nan::Delete()</code></b></a>
+  - <a href="#api_nan_get_property_names"><b><code>Nan::GetPropertyNames()</code></b></a>
+  - <a href="#api_nan_get_own_property_names"><b><code>Nan::GetOwnPropertyNames()</code></b></a>
+  - <a href="#api_nan_set_prototype"><b><code>Nan::SetPrototype()</code></b></a>
+  - <a href="#api_nan_object_proto_to_string"><b><code>Nan::ObjectProtoToString()</code></b></a>
+  - <a href="#api_nan_has_own_property"><b><code>Nan::HasOwnProperty()</code></b></a>
+  - <a href="#api_nan_has_real_named_property"><b><code>Nan::HasRealNamedProperty()</code></b></a>
+  - <a href="#api_nan_has_real_indexed_property"><b><code>Nan::HasRealIndexedProperty()</code></b></a>
+  - <a href="#api_nan_has_real_named_callback_property"><b><code>Nan::HasRealNamedCallbackProperty()</code></b></a>
+  - <a href="#api_nan_get_real_named_property_in_prototype_chain"><b><code>Nan::GetRealNamedPropertyInPrototypeChain()</code></b></a>
+  - <a href="#api_nan_get_real_named_property"><b><code>Nan::GetRealNamedProperty()</code></b></a>
+  - <a href="#api_nan_call_as_function"><b><code>Nan::CallAsFunction()</code></b></a>
+  - <a href="#api_nan_call_as_constructor"><b><code>Nan::CallAsConstructor()</code></b></a>
+  - <a href="#api_nan_get_source_line"><b><code>Nan::GetSourceLine()</code></b></a>
+  - <a href="#api_nan_get_line_number"><b><code>Nan::GetLineNumber()</code></b></a>
+  - <a href="#api_nan_get_start_column"><b><code>Nan::GetStartColumn()</code></b></a>
+  - <a href="#api_nan_get_end_column"><b><code>Nan::GetEndColumn()</code></b></a>
+  - <a href="#api_nan_clone_element_at"><b><code>Nan::CloneElementAt()</code></b></a>
+  - <a href="#api_nan_has_private"><b><code>Nan::HasPrivate()</code></b></a>
+  - <a href="#api_nan_get_private"><b><code>Nan::GetPrivate()</code></b></a>
+  - <a href="#api_nan_set_private"><b><code>Nan::SetPrivate()</code></b></a>
+  - <a href="#api_nan_delete_private"><b><code>Nan::DeletePrivate()</code></b></a>
+  - <a href="#api_nan_make_maybe"><b><code>Nan::MakeMaybe()</code></b></a>
+
+<a name="api_nan_maybe_local"></a>
+### Nan::MaybeLocal
+
+A `Nan::MaybeLocal<T>` is a wrapper around [`v8::Local<T>`](https://v8docs.nodesource.com/io.js-3.3/de/deb/classv8_1_1_local.html) that enforces a check that determines whether the `v8::Local<T>` is empty before it can be used.
+
+If an API method returns a `Nan::MaybeLocal`, the API method can potentially fail either because an exception is thrown, or because an exception is pending, e.g. because a previous API call threw an exception that hasn't been caught yet, or because a `v8::TerminateExecution` exception was thrown. In that case, an empty `Nan::MaybeLocal` is returned.
+
+Definition:
+
+```c++
+template<typename T> class Nan::MaybeLocal {
+ public:
+  MaybeLocal();
+
+  template<typename S> MaybeLocal(v8::Local<S> that);
+
+  bool IsEmpty() const;
+
+  template<typename S> bool ToLocal(v8::Local<S> *out);
+
+  // Will crash if the MaybeLocal<> is empty.
+  v8::Local<T> ToLocalChecked();
+
+  template<typename S> v8::Local<S> FromMaybe(v8::Local<S> default_value) const;
+};
+```
+
+See the documentation for [`v8::MaybeLocal`](https://v8docs.nodesource.com/io.js-3.3/d8/d7d/classv8_1_1_maybe_local.html) for further details.
+
+<a name="api_nan_maybe"></a>
+### Nan::Maybe
+
+A simple `Nan::Maybe` type, representing an object which may or may not have a value, see https://hackage.haskell.org/package/base/docs/Data-Maybe.html.
+
+If an API method returns a `Nan::Maybe<>`, the API method can potentially fail either because an exception is thrown, or because an exception is pending, e.g. because a previous API call threw an exception that hasn't been caught yet, or because a `v8::TerminateExecution` exception was thrown. In that case, a "Nothing" value is returned.
+
+Definition:
+
+```c++
+template<typename T> class Nan::Maybe {
+ public:
+  bool IsNothing() const;
+  bool IsJust() const;
+
+  // Will crash if the Maybe<> is nothing.
+  T FromJust();
+
+  T FromMaybe(const T& default_value);
+
+  bool operator==(const Maybe &other);
+
+  bool operator!=(const Maybe &other);
+};
+```
+
+See the documentation for [`v8::Maybe`](https://v8docs.nodesource.com/io.js-3.3/d9/d4b/classv8_1_1_maybe.html) for further details.
+
+<a name="api_nan_nothing"></a>
+### Nan::Nothing
+
+Construct an empty `Nan::Maybe` type representing _nothing_.
+
+```c++
+template<typename T> Nan::Maybe<T> Nan::Nothing();
+```
+
+<a name="api_nan_just"></a>
+### Nan::Just
+
+Construct a `Nan::Maybe` type representing _just_ a value.
+
+```c++
+template<typename T> Nan::Maybe<T> Nan::Just(const T &t);
+```
+
+<a name="api_nan_call"></a>
+### Nan::Call()
+
+A helper method for calling a synchronous [`v8::Function#Call()`](https://v8docs.nodesource.com/io.js-3.3/d5/d54/classv8_1_1_function.html#a468a89f737af0612db10132799c827c0) in a way compatible across supported versions of V8.
+
+For asynchronous callbacks, use Nan::Callback::Call along with an AsyncResource.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::Call(v8::Local<v8::Function> fun, v8::Local<v8::Object> recv, int argc, v8::Local<v8::Value> argv[]);
+Nan::MaybeLocal<v8::Value> Nan::Call(const Nan::Callback& callback, v8::Local<v8::Object> recv,
+ int argc, v8::Local<v8::Value> argv[]);
+Nan::MaybeLocal<v8::Value> Nan::Call(const Nan::Callback& callback, int argc, v8::Local<v8::Value> argv[]);
+```
+
+
+<a name="api_nan_to_detail_string"></a>
+### Nan::ToDetailString()
+
+A helper method for calling [`v8::Value#ToDetailString()`](https://v8docs.nodesource.com/io.js-3.3/dc/d0a/classv8_1_1_value.html#a2f9770296dc2c8d274bc8cc0dca243e5) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::String> Nan::ToDetailString(v8::Local<v8::Value> val);
+```
+
+
+<a name="api_nan_to_array_index"></a>
+### Nan::ToArrayIndex()
+
+A helper method for calling [`v8::Value#ToArrayIndex()`](https://v8docs.nodesource.com/io.js-3.3/dc/d0a/classv8_1_1_value.html#acc5bbef3c805ec458470c0fcd6f13493) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Uint32> Nan::ToArrayIndex(v8::Local<v8::Value> val);
+```
+
+
+<a name="api_nan_equals"></a>
+### Nan::Equals()
+
+A helper method for calling [`v8::Value#Equals()`](https://v8docs.nodesource.com/io.js-3.3/dc/d0a/classv8_1_1_value.html#a0d9616ab2de899d4e3047c30a10c9285) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::Equals(v8::Local<v8::Value> a, v8::Local<v8::Value>(b));
+```
+
+
+<a name="api_nan_new_instance"></a>
+### Nan::NewInstance()
+
+A helper method for calling [`v8::Function#NewInstance()`](https://v8docs.nodesource.com/io.js-3.3/d5/d54/classv8_1_1_function.html#a691b13f7a553069732cbacf5ac8c62ec) and [`v8::ObjectTemplate#NewInstance()`](https://v8docs.nodesource.com/io.js-3.3/db/d5f/classv8_1_1_object_template.html#ad605a7543cfbc5dab54cdb0883d14ae4) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Object> Nan::NewInstance(v8::Local<v8::Function> h);
+Nan::MaybeLocal<v8::Object> Nan::NewInstance(v8::Local<v8::Function> h, int argc, v8::Local<v8::Value> argv[]);
+Nan::MaybeLocal<v8::Object> Nan::NewInstance(v8::Local<v8::ObjectTemplate> h);
+```
+
+
+<a name="api_nan_get_function"></a>
+### Nan::GetFunction()
+
+A helper method for calling [`v8::FunctionTemplate#GetFunction()`](https://v8docs.nodesource.com/io.js-3.3/d8/d83/classv8_1_1_function_template.html#a56d904662a86eca78da37d9bb0ed3705) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Function> Nan::GetFunction(v8::Local<v8::FunctionTemplate> t);
+```
+
+
+<a name="api_nan_set"></a>
+### Nan::Set()
+
+A helper method for calling [`v8::Object#Set()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a67604ea3734f170c66026064ea808f20) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::Set(v8::Local<v8::Object> obj,
+                          v8::Local<v8::Value> key,
+                          v8::Local<v8::Value> value)
+Nan::Maybe<bool> Nan::Set(v8::Local<v8::Object> obj,
+                          uint32_t index,
+                          v8::Local<v8::Value> value);
+```
+
+
+<a name="api_nan_define_own_property"></a>
+### Nan::DefineOwnProperty()
+
+A helper method for calling [`v8::Object#DefineOwnProperty()`](https://v8docs.nodesource.com/node-4.8/db/d85/classv8_1_1_object.html#a6f76b2ed605cb8f9185b92de0033a820) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::DefineOwnProperty(v8::Local<v8::Object> obj,
+                                        v8::Local<v8::String> key,
+                                        v8::Local<v8::Value> value,
+                                        v8::PropertyAttribute attribs = v8::None);
+```
+
+
+<a name="api_nan_force_set"></a>
+### <del>Nan::ForceSet()</del>
+
+Deprecated, use <a href="#api_nan_define_own_property"><code>Nan::DefineOwnProperty()</code></a>.
+
+<del>A helper method for calling [`v8::Object#ForceSet()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a796b7b682896fb64bf1872747734e836) in a way compatible across supported versions of V8.</del>
+
+Signature:
+
+```c++
+NAN_DEPRECATED Nan::Maybe<bool> Nan::ForceSet(v8::Local<v8::Object> obj,
+                                              v8::Local<v8::Value> key,
+                                              v8::Local<v8::Value> value,
+                                              v8::PropertyAttribute attribs = v8::None);
+```
+
+
+<a name="api_nan_get"></a>
+### Nan::Get()
+
+A helper method for calling [`v8::Object#Get()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a2565f03e736694f6b1e1cf22a0b4eac2) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::Get(v8::Local<v8::Object> obj,
+                                    v8::Local<v8::Value> key);
+Nan::MaybeLocal<v8::Value> Nan::Get(v8::Local<v8::Object> obj, uint32_t index);
+```
+
+
+<a name="api_nan_get_property_attribute"></a>
+### Nan::GetPropertyAttributes()
+
+A helper method for calling [`v8::Object#GetPropertyAttributes()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a9b898894da3d1db2714fd9325a54fe57) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<v8::PropertyAttribute> Nan::GetPropertyAttributes(
+    v8::Local<v8::Object> obj,
+    v8::Local<v8::Value> key);
+```
+
+
+<a name="api_nan_has"></a>
+### Nan::Has()
+
+A helper method for calling [`v8::Object#Has()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#ab3c3d89ea7c2f9afd08965bd7299a41d) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::Has(v8::Local<v8::Object> obj, v8::Local<v8::String> key);
+Nan::Maybe<bool> Nan::Has(v8::Local<v8::Object> obj, uint32_t index);
+```
+
+
+<a name="api_nan_delete"></a>
+### Nan::Delete()
+
+A helper method for calling [`v8::Object#Delete()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a2fa0f5a592582434ed1ceceff7d891ef) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::Delete(v8::Local<v8::Object> obj,
+                             v8::Local<v8::String> key);
+Nan::Maybe<bool> Nan::Delete(v8::Local<v8::Object> obj, uint32_t index);
+```
+
+
+<a name="api_nan_get_property_names"></a>
+### Nan::GetPropertyNames()
+
+A helper method for calling [`v8::Object#GetPropertyNames()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#aced885270cfd2c956367b5eedc7fbfe8) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Array> Nan::GetPropertyNames(v8::Local<v8::Object> obj);
+```
+
+
+<a name="api_nan_get_own_property_names"></a>
+### Nan::GetOwnPropertyNames()
+
+A helper method for calling [`v8::Object#GetOwnPropertyNames()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a79a6e4d66049b9aa648ed4dfdb23e6eb) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Array> Nan::GetOwnPropertyNames(v8::Local<v8::Object> obj);
+```
+
+
+<a name="api_nan_set_prototype"></a>
+### Nan::SetPrototype()
+
+A helper method for calling [`v8::Object#SetPrototype()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a442706b22fceda6e6d1f632122a9a9f4) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::SetPrototype(v8::Local<v8::Object> obj,
+                                   v8::Local<v8::Value> prototype);
+```
+
+
+<a name="api_nan_object_proto_to_string"></a>
+### Nan::ObjectProtoToString()
+
+A helper method for calling [`v8::Object#ObjectProtoToString()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#ab7a92b4dcf822bef72f6c0ac6fea1f0b) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::String> Nan::ObjectProtoToString(v8::Local<v8::Object> obj);
+```
+
+
+<a name="api_nan_has_own_property"></a>
+### Nan::HasOwnProperty()
+
+A helper method for calling [`v8::Object#HasOwnProperty()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#ab7b7245442ca6de1e1c145ea3fd653ff) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::HasOwnProperty(v8::Local<v8::Object> obj,
+                                     v8::Local<v8::String> key);
+```
+
+
+<a name="api_nan_has_real_named_property"></a>
+### Nan::HasRealNamedProperty()
+
+A helper method for calling [`v8::Object#HasRealNamedProperty()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#ad8b80a59c9eb3c1e6c3cd6c84571f767) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::HasRealNamedProperty(v8::Local<v8::Object> obj,
+                                           v8::Local<v8::String> key);
+```
+
+
+<a name="api_nan_has_real_indexed_property"></a>
+### Nan::HasRealIndexedProperty()
+
+A helper method for calling [`v8::Object#HasRealIndexedProperty()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#af94fc1135a5e74a2193fb72c3a1b9855) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::HasRealIndexedProperty(v8::Local<v8::Object> obj,
+                                             uint32_t index);
+```
+
+
+<a name="api_nan_has_real_named_callback_property"></a>
+### Nan::HasRealNamedCallbackProperty()
+
+A helper method for calling [`v8::Object#HasRealNamedCallbackProperty()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#af743b7ea132b89f84d34d164d0668811) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::HasRealNamedCallbackProperty(
+    v8::Local<v8::Object> obj,
+    v8::Local<v8::String> key);
+```
+
+
+<a name="api_nan_get_real_named_property_in_prototype_chain"></a>
+### Nan::GetRealNamedPropertyInPrototypeChain()
+
+A helper method for calling [`v8::Object#GetRealNamedPropertyInPrototypeChain()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a8700b1862e6b4783716964ba4d5e6172) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::GetRealNamedPropertyInPrototypeChain(
+    v8::Local<v8::Object> obj,
+    v8::Local<v8::String> key);
+```
+
+
+<a name="api_nan_get_real_named_property"></a>
+### Nan::GetRealNamedProperty()
+
+A helper method for calling [`v8::Object#GetRealNamedProperty()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a84471a824576a5994fdd0ffcbf99ccc0) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::GetRealNamedProperty(v8::Local<v8::Object> obj,
+                                                     v8::Local<v8::String> key);
+```
+
+
+<a name="api_nan_call_as_function"></a>
+### Nan::CallAsFunction()
+
+A helper method for calling [`v8::Object#CallAsFunction()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a9ef18be634e79b4f0cdffa1667a29f58) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::CallAsFunction(v8::Local<v8::Object> obj,
+                                               v8::Local<v8::Object> recv,
+                                               int argc,
+                                               v8::Local<v8::Value> argv[]);
+```
+
+
+<a name="api_nan_call_as_constructor"></a>
+### Nan::CallAsConstructor()
+
+A helper method for calling [`v8::Object#CallAsConstructor()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#a50d571de50d0b0dfb28795619d07a01b) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::CallAsConstructor(v8::Local<v8::Object> obj,
+                                                  int argc,
+                                                  v8::Local<v8::Value> argv[]);
+```
+
+
+<a name="api_nan_get_source_line"></a>
+### Nan::GetSourceLine()
+
+A helper method for calling [`v8::Message#GetSourceLine()`](https://v8docs.nodesource.com/io.js-3.3/d9/d28/classv8_1_1_message.html#a849f7a6c41549d83d8159825efccd23a) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::String> Nan::GetSourceLine(v8::Local<v8::Message> msg);
+```
+
+
+<a name="api_nan_get_line_number"></a>
+### Nan::GetLineNumber()
+
+A helper method for calling [`v8::Message#GetLineNumber()`](https://v8docs.nodesource.com/io.js-3.3/d9/d28/classv8_1_1_message.html#adbe46c10a88a6565f2732a2d2adf99b9) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<int> Nan::GetLineNumber(v8::Local<v8::Message> msg);
+```
+
+
+<a name="api_nan_get_start_column"></a>
+### Nan::GetStartColumn()
+
+A helper method for calling [`v8::Message#GetStartColumn()`](https://v8docs.nodesource.com/io.js-3.3/d9/d28/classv8_1_1_message.html#a60ede616ba3822d712e44c7a74487ba6) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<int> Nan::GetStartColumn(v8::Local<v8::Message> msg);
+```
+
+
+<a name="api_nan_get_end_column"></a>
+### Nan::GetEndColumn()
+
+A helper method for calling [`v8::Message#GetEndColumn()`](https://v8docs.nodesource.com/io.js-3.3/d9/d28/classv8_1_1_message.html#aaa004cf19e529da980bc19fcb76d93be) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<int> Nan::GetEndColumn(v8::Local<v8::Message> msg);
+```
+
+
+<a name="api_nan_clone_element_at"></a>
+### Nan::CloneElementAt()
+
+A helper method for calling [`v8::Array#CloneElementAt()`](https://v8docs.nodesource.com/io.js-3.3/d3/d32/classv8_1_1_array.html#a1d3a878d4c1c7cae974dd50a1639245e) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Object> Nan::CloneElementAt(v8::Local<v8::Array> array, uint32_t index);
+```
+
+<a name="api_nan_has_private"></a>
+### Nan::HasPrivate()
+
+A helper method for calling [`v8::Object#HasPrivate()`](https://v8docs.nodesource.com/node-7.2/db/d85/classv8_1_1_object.html#af68a0b98066cfdeb8f943e98a40ba08d) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::HasPrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key);
+```
+
+<a name="api_nan_get_private"></a>
+### Nan::GetPrivate()
+
+A helper method for calling [`v8::Object#GetPrivate()`](https://v8docs.nodesource.com/node-7.2/db/d85/classv8_1_1_object.html#a169f2da506acbec34deadd9149a1925a) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::GetPrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key);
+```
+
+<a name="api_nan_set_private"></a>
+### Nan::SetPrivate()
+
+A helper method for calling [`v8::Object#SetPrivate()`](https://v8docs.nodesource.com/node-7.2/db/d85/classv8_1_1_object.html#ace1769b0f3b86bfe9fda1010916360ee) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::SetPrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key, v8::Local<v8::Value> value);
+```
+
+<a name="api_nan_delete_private"></a>
+### Nan::DeletePrivate()
+
+A helper method for calling [`v8::Object#DeletePrivate()`](https://v8docs.nodesource.com/node-7.2/db/d85/classv8_1_1_object.html#a138bb32a304f3982be02ad499693b8fd) in a way compatible across supported versions of V8.
+
+Signature:
+
+```c++
+Nan::Maybe<bool> Nan::DeletePrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key);
+```
+
+<a name="api_nan_make_maybe"></a>
+### Nan::MakeMaybe()
+
+Wraps a `v8::Local<>` in a `Nan::MaybeLocal<>`. When called with a `Nan::MaybeLocal<>` it just returns its argument. This is useful in generic template code that builds on NAN.
+
+Synopsis:
+
+```c++
+  MaybeLocal<v8::Number> someNumber = MakeMaybe(New<v8::Number>(3.141592654));
+  MaybeLocal<v8::String> someString = MakeMaybe(New<v8::String>("probably"));
+```
+
+Signature:
+
+```c++
+template <typename T, template <typename> class MaybeMaybe>
+Nan::MaybeLocal<T> Nan::MakeMaybe(MaybeMaybe<T> v);
+```
diff --git a/input_devices/mag/node_modules/nan/doc/methods.md b/input_devices/mag/node_modules/nan/doc/methods.md
new file mode 100644
index 00000000..4cdfa997
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/methods.md
@@ -0,0 +1,661 @@
+## JavaScript-accessible methods
+
+A _template_ is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated from JavaScript. See the V8 Embedders Guide section on [Templates](https://github.com/v8/v8/wiki/Embedder%27s-Guide#templates) for further information.
+
+In order to expose functionality to JavaScript via a template, you must provide it to V8 in a form that it understands. Across the versions of V8 supported by NAN, JavaScript-accessible method signatures vary widely, NAN fully abstracts method declaration and provides you with an interface that is similar to the most recent V8 API but is backward-compatible with older versions that still use the now-deceased `v8::Argument` type.
+
+* **Method argument types**
+ - <a href="#api_nan_function_callback_info"><b><code>Nan::FunctionCallbackInfo</code></b></a>
+ - <a href="#api_nan_property_callback_info"><b><code>Nan::PropertyCallbackInfo</code></b></a>
+ - <a href="#api_nan_return_value"><b><code>Nan::ReturnValue</code></b></a>
+* **Method declarations**
+ - <a href="#api_nan_method"><b>Method declaration</b></a>
+ - <a href="#api_nan_getter"><b>Getter declaration</b></a>
+ - <a href="#api_nan_setter"><b>Setter declaration</b></a>
+ - <a href="#api_nan_property_getter"><b>Property getter declaration</b></a>
+ - <a href="#api_nan_property_setter"><b>Property setter declaration</b></a>
+ - <a href="#api_nan_property_enumerator"><b>Property enumerator declaration</b></a>
+ - <a href="#api_nan_property_deleter"><b>Property deleter declaration</b></a>
+ - <a href="#api_nan_property_query"><b>Property query declaration</b></a>
+ - <a href="#api_nan_index_getter"><b>Index getter declaration</b></a>
+ - <a href="#api_nan_index_setter"><b>Index setter declaration</b></a>
+ - <a href="#api_nan_index_enumerator"><b>Index enumerator declaration</b></a>
+ - <a href="#api_nan_index_deleter"><b>Index deleter declaration</b></a>
+ - <a href="#api_nan_index_query"><b>Index query declaration</b></a>
+* Method and template helpers
+ - <a href="#api_nan_set_method"><b><code>Nan::SetMethod()</code></b></a>
+ - <a href="#api_nan_set_prototype_method"><b><code>Nan::SetPrototypeMethod()</code></b></a>
+ - <a href="#api_nan_set_accessor"><b><code>Nan::SetAccessor()</code></b></a>
+ - <a href="#api_nan_set_named_property_handler"><b><code>Nan::SetNamedPropertyHandler()</code></b></a>
+ - <a href="#api_nan_set_indexed_property_handler"><b><code>Nan::SetIndexedPropertyHandler()</code></b></a>
+ - <a href="#api_nan_set_template"><b><code>Nan::SetTemplate()</code></b></a>
+ - <a href="#api_nan_set_prototype_template"><b><code>Nan::SetPrototypeTemplate()</code></b></a>
+ - <a href="#api_nan_set_instance_template"><b><code>Nan::SetInstanceTemplate()</code></b></a>
+ - <a href="#api_nan_set_call_handler"><b><code>Nan::SetCallHandler()</code></b></a>
+ - <a href="#api_nan_set_call_as_function_handler"><b><code>Nan::SetCallAsFunctionHandler()</code></b></a>
+
+<a name="api_nan_function_callback_info"></a>
+### Nan::FunctionCallbackInfo
+
+`Nan::FunctionCallbackInfo` should be used in place of [`v8::FunctionCallbackInfo`](https://v8docs.nodesource.com/node-8.0/dd/d0d/classv8_1_1_function_callback_info.html), even with older versions of Node where `v8::FunctionCallbackInfo` does not exist.
+
+Definition:
+
+```c++
+template<typename T> class FunctionCallbackInfo {
+ public:
+  ReturnValue<T> GetReturnValue() const;
+  v8::Local<v8::Function> Callee(); // NOTE: Not available in NodeJS >= 10.0.0
+  v8::Local<v8::Value> Data();
+  v8::Local<v8::Object> Holder();
+  bool IsConstructCall();
+  int Length() const;
+  v8::Local<v8::Value> operator[](int i) const;
+  v8::Local<v8::Object> This() const;
+  v8::Isolate *GetIsolate() const;
+};
+```
+
+See the [`v8::FunctionCallbackInfo`](https://v8docs.nodesource.com/node-8.0/dd/d0d/classv8_1_1_function_callback_info.html) documentation for usage details on these. See [`Nan::ReturnValue`](#api_nan_return_value) for further information on how to set a return value from methods.
+
+**Note:** `FunctionCallbackInfo::Callee` is removed in Node.js after `10.0.0` because it is was deprecated in V8. Consider using `info.Data()` to pass any information you need.
+
+<a name="api_nan_property_callback_info"></a>
+### Nan::PropertyCallbackInfo
+
+`Nan::PropertyCallbackInfo` should be used in place of [`v8::PropertyCallbackInfo`](https://v8docs.nodesource.com/node-8.0/d7/dc5/classv8_1_1_property_callback_info.html), even with older versions of Node where `v8::PropertyCallbackInfo` does not exist.
+
+Definition:
+
+```c++
+template<typename T> class PropertyCallbackInfo : public PropertyCallbackInfoBase<T> {
+ public:
+  ReturnValue<T> GetReturnValue() const;
+  v8::Isolate* GetIsolate() const;
+  v8::Local<v8::Value> Data() const;
+  v8::Local<v8::Object> This() const;
+  v8::Local<v8::Object> Holder() const;
+};
+```
+
+See the [`v8::PropertyCallbackInfo`](https://v8docs.nodesource.com/node-8.0/d7/dc5/classv8_1_1_property_callback_info.html) documentation for usage details on these. See [`Nan::ReturnValue`](#api_nan_return_value) for further information on how to set a return value from property accessor methods.
+
+<a name="api_nan_return_value"></a>
+### Nan::ReturnValue
+
+`Nan::ReturnValue` is used in place of [`v8::ReturnValue`](https://v8docs.nodesource.com/node-8.0/da/da7/classv8_1_1_return_value.html) on both [`Nan::FunctionCallbackInfo`](#api_nan_function_callback_info) and [`Nan::PropertyCallbackInfo`](#api_nan_property_callback_info) as the return type of `GetReturnValue()`.
+
+Example usage:
+
+```c++
+void EmptyArray(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(Nan::New<v8::Array>());
+}
+```
+
+Definition:
+
+```c++
+template<typename T> class ReturnValue {
+ public:
+  // Handle setters
+  template <typename S> void Set(const v8::Local<S> &handle);
+  template <typename S> void Set(const Nan::Global<S> &handle);
+
+  // Fast primitive setters
+  void Set(bool value);
+  void Set(double i);
+  void Set(int32_t i);
+  void Set(uint32_t i);
+
+  // Fast JS primitive setters
+  void SetNull();
+  void SetUndefined();
+  void SetEmptyString();
+
+  // Convenience getter for isolate
+  v8::Isolate *GetIsolate() const;
+};
+```
+
+See the documentation on [`v8::ReturnValue`](https://v8docs.nodesource.com/node-8.0/da/da7/classv8_1_1_return_value.html) for further information on this.
+
+<a name="api_nan_method"></a>
+### Method declaration
+
+JavaScript-accessible methods should be declared with the following signature to form a `Nan::FunctionCallback`:
+
+```c++
+typedef void(*FunctionCallback)(const FunctionCallbackInfo<v8::Value>&);
+```
+
+Example:
+
+```c++
+void MethodName(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+  ...
+}
+```
+
+You do not need to declare a new `HandleScope` within a method as one is implicitly created for you.
+
+**Example usage**
+
+```c++
+// .h:
+class Foo : public Nan::ObjectWrap {
+  ...
+
+  static void Bar(const Nan::FunctionCallbackInfo<v8::Value>& info);
+  static void Baz(const Nan::FunctionCallbackInfo<v8::Value>& info);
+}
+
+
+// .cc:
+void Foo::Bar(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+  ...
+}
+
+void Foo::Baz(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+  ...
+}
+```
+
+A helper macro `NAN_METHOD(methodname)` exists, compatible with NAN v1 method declarations.
+
+**Example usage with `NAN_METHOD(methodname)`**
+
+```c++
+// .h:
+class Foo : public Nan::ObjectWrap {
+  ...
+
+  static NAN_METHOD(Bar);
+  static NAN_METHOD(Baz);
+}
+
+
+// .cc:
+NAN_METHOD(Foo::Bar) {
+  ...
+}
+
+NAN_METHOD(Foo::Baz) {
+  ...
+}
+```
+
+Use [`Nan::SetPrototypeMethod`](#api_nan_set_prototype_method) to attach a method to a JavaScript function prototype or [`Nan::SetMethod`](#api_nan_set_method) to attach a method directly on a JavaScript object.
+
+<a name="api_nan_getter"></a>
+### Getter declaration
+
+JavaScript-accessible getters should be declared with the following signature to form a `Nan::GetterCallback`:
+
+```c++
+typedef void(*GetterCallback)(v8::Local<v8::String>,
+                              const PropertyCallbackInfo<v8::Value>&);
+```
+
+Example:
+
+```c++
+void GetterName(v8::Local<v8::String> property,
+                const Nan::PropertyCallbackInfo<v8::Value>& info) {
+  ...
+}
+```
+
+You do not need to declare a new `HandleScope` within a getter as one is implicitly created for you.
+
+A helper macro `NAN_GETTER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on [Accessors](https://developers.google.com/v8/embed#accesssors).
+
+<a name="api_nan_setter"></a>
+### Setter declaration
+
+JavaScript-accessible setters should be declared with the following signature to form a <b><code>Nan::SetterCallback</code></b>:
+
+```c++
+typedef void(*SetterCallback)(v8::Local<v8::String>,
+                              v8::Local<v8::Value>,
+                              const PropertyCallbackInfo<void>&);
+```
+
+Example:
+
+```c++
+void SetterName(v8::Local<v8::String> property,
+                v8::Local<v8::Value> value,
+                const Nan::PropertyCallbackInfo<void>& info) {
+  ...
+}
+```
+
+You do not need to declare a new `HandleScope` within a setter as one is implicitly created for you.
+
+A helper macro `NAN_SETTER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on [Accessors](https://developers.google.com/v8/embed#accesssors).
+
+<a name="api_nan_property_getter"></a>
+### Property getter declaration
+
+JavaScript-accessible property getters should be declared with the following signature to form a <b><code>Nan::PropertyGetterCallback</code></b>:
+
+```c++
+typedef void(*PropertyGetterCallback)(v8::Local<v8::String>,
+                                      const PropertyCallbackInfo<v8::Value>&);
+```
+
+Example:
+
+```c++
+void PropertyGetterName(v8::Local<v8::String> property,
+                        const Nan::PropertyCallbackInfo<v8::Value>& info) {
+  ...
+}
+```
+
+You do not need to declare a new `HandleScope` within a property getter as one is implicitly created for you.
+
+A helper macro `NAN_PROPERTY_GETTER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_property_setter"></a>
+### Property setter declaration
+
+JavaScript-accessible property setters should be declared with the following signature to form a <b><code>Nan::PropertySetterCallback</code></b>:
+
+```c++
+typedef void(*PropertySetterCallback)(v8::Local<v8::String>,
+                                      v8::Local<v8::Value>,
+                                      const PropertyCallbackInfo<v8::Value>&);
+```
+
+Example:
+
+```c++
+void PropertySetterName(v8::Local<v8::String> property,
+                        v8::Local<v8::Value> value,
+                        const Nan::PropertyCallbackInfo<v8::Value>& info);
+```
+
+You do not need to declare a new `HandleScope` within a property setter as one is implicitly created for you.
+
+A helper macro `NAN_PROPERTY_SETTER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_property_enumerator"></a>
+### Property enumerator declaration
+
+JavaScript-accessible property enumerators should be declared with the following signature to form a <b><code>Nan::PropertyEnumeratorCallback</code></b>:
+
+```c++
+typedef void(*PropertyEnumeratorCallback)(const PropertyCallbackInfo<v8::Array>&);
+```
+
+Example:
+
+```c++
+void PropertyEnumeratorName(const Nan::PropertyCallbackInfo<v8::Array>& info);
+```
+
+You do not need to declare a new `HandleScope` within a property enumerator as one is implicitly created for you.
+
+A helper macro `NAN_PROPERTY_ENUMERATOR(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_property_deleter"></a>
+### Property deleter declaration
+
+JavaScript-accessible property deleters should be declared with the following signature to form a <b><code>Nan::PropertyDeleterCallback</code></b>:
+
+```c++
+typedef void(*PropertyDeleterCallback)(v8::Local<v8::String>,
+                                       const PropertyCallbackInfo<v8::Boolean>&);
+```
+
+Example:
+
+```c++
+void PropertyDeleterName(v8::Local<v8::String> property,
+                         const Nan::PropertyCallbackInfo<v8::Boolean>& info);
+```
+
+You do not need to declare a new `HandleScope` within a property deleter as one is implicitly created for you.
+
+A helper macro `NAN_PROPERTY_DELETER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_property_query"></a>
+### Property query declaration
+
+JavaScript-accessible property query methods should be declared with the following signature to form a <b><code>Nan::PropertyQueryCallback</code></b>:
+
+```c++
+typedef void(*PropertyQueryCallback)(v8::Local<v8::String>,
+                                     const PropertyCallbackInfo<v8::Integer>&);
+```
+
+Example:
+
+```c++
+void PropertyQueryName(v8::Local<v8::String> property,
+                       const Nan::PropertyCallbackInfo<v8::Integer>& info);
+```
+
+You do not need to declare a new `HandleScope` within a property query method as one is implicitly created for you.
+
+A helper macro `NAN_PROPERTY_QUERY(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_index_getter"></a>
+### Index getter declaration
+
+JavaScript-accessible index getter methods should be declared with the following signature to form a <b><code>Nan::IndexGetterCallback</code></b>:
+
+```c++
+typedef void(*IndexGetterCallback)(uint32_t,
+                                   const PropertyCallbackInfo<v8::Value>&);
+```
+
+Example:
+
+```c++
+void IndexGetterName(uint32_t index, const PropertyCallbackInfo<v8::Value>& info);
+```
+
+You do not need to declare a new `HandleScope` within a index getter as one is implicitly created for you.
+
+A helper macro `NAN_INDEX_GETTER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_index_setter"></a>
+### Index setter declaration
+
+JavaScript-accessible index setter methods should be declared with the following signature to form a <b><code>Nan::IndexSetterCallback</code></b>:
+
+```c++
+typedef void(*IndexSetterCallback)(uint32_t,
+                                   v8::Local<v8::Value>,
+                                   const PropertyCallbackInfo<v8::Value>&);
+```
+
+Example:
+
+```c++
+void IndexSetterName(uint32_t index,
+                     v8::Local<v8::Value> value,
+                     const PropertyCallbackInfo<v8::Value>& info);
+```
+
+You do not need to declare a new `HandleScope` within a index setter as one is implicitly created for you.
+
+A helper macro `NAN_INDEX_SETTER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_index_enumerator"></a>
+### Index enumerator declaration
+
+JavaScript-accessible index enumerator methods should be declared with the following signature to form a <b><code>Nan::IndexEnumeratorCallback</code></b>:
+
+```c++
+typedef void(*IndexEnumeratorCallback)(const PropertyCallbackInfo<v8::Array>&);
+```
+
+Example:
+
+```c++
+void IndexEnumeratorName(const PropertyCallbackInfo<v8::Array>& info);
+```
+
+You do not need to declare a new `HandleScope` within a index enumerator as one is implicitly created for you.
+
+A helper macro `NAN_INDEX_ENUMERATOR(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_index_deleter"></a>
+### Index deleter declaration
+
+JavaScript-accessible index deleter methods should be declared with the following signature to form a <b><code>Nan::IndexDeleterCallback</code></b>:
+
+```c++
+typedef void(*IndexDeleterCallback)(uint32_t,
+                                    const PropertyCallbackInfo<v8::Boolean>&);
+```
+
+Example:
+
+```c++
+void IndexDeleterName(uint32_t index, const PropertyCallbackInfo<v8::Boolean>& info);
+```
+
+You do not need to declare a new `HandleScope` within a index deleter as one is implicitly created for you.
+
+A helper macro `NAN_INDEX_DELETER(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_index_query"></a>
+### Index query declaration
+
+JavaScript-accessible index query methods should be declared with the following signature to form a <b><code>Nan::IndexQueryCallback</code></b>:
+
+```c++
+typedef void(*IndexQueryCallback)(uint32_t,
+                                  const PropertyCallbackInfo<v8::Integer>&);
+```
+
+Example:
+
+```c++
+void IndexQueryName(uint32_t index, const PropertyCallbackInfo<v8::Integer>& info);
+```
+
+You do not need to declare a new `HandleScope` within a index query method as one is implicitly created for you.
+
+A helper macro `NAN_INDEX_QUERY(methodname)` exists, compatible with NAN v1 method declarations.
+
+Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors).
+
+<a name="api_nan_set_method"></a>
+### Nan::SetMethod()
+
+Sets a method with a given name directly on a JavaScript object where the method has the `Nan::FunctionCallback` signature (see <a href="#api_nan_method">Method declaration</a>).
+
+Signature:
+
+```c++
+void Nan::SetMethod(v8::Local<v8::Object> recv,
+                    const char *name,
+                    Nan::FunctionCallback callback)
+void Nan::SetMethod(v8::Local<v8::Template> templ,
+                    const char *name,
+                    Nan::FunctionCallback callback)
+```
+
+<a name="api_nan_set_prototype_method"></a>
+### Nan::SetPrototypeMethod()
+
+Sets a method with a given name on a `FunctionTemplate`'s prototype where the method has the `Nan::FunctionCallback` signature (see <a href="#api_nan_method">Method declaration</a>).
+
+Signature:
+
+```c++
+void Nan::SetPrototypeMethod(v8::Local<v8::FunctionTemplate> recv,
+                             const char* name,
+                             Nan::FunctionCallback callback)
+```
+
+<a name="api_nan_set_accessor"></a>
+### Nan::SetAccessor()
+
+Sets getters and setters for a property with a given name on an `ObjectTemplate` or a plain `Object`. Accepts getters with the `Nan::GetterCallback` signature (see <a href="#api_nan_getter">Getter declaration</a>) and setters with the `Nan::SetterCallback` signature (see <a href="#api_nan_setter">Setter declaration</a>).
+
+Signature:
+
+```c++
+void SetAccessor(v8::Local<v8::ObjectTemplate> tpl,
+                 v8::Local<v8::String> name,
+                 Nan::GetterCallback getter,
+                 Nan::SetterCallback setter = 0,
+                 v8::Local<v8::Value> data = v8::Local<v8::Value>(),
+                 v8::AccessControl settings = v8::DEFAULT,
+                 v8::PropertyAttribute attribute = v8::None,
+                 imp::Sig signature = imp::Sig());
+bool SetAccessor(v8::Local<v8::Object> obj,
+                 v8::Local<v8::String> name,
+                 Nan::GetterCallback getter,
+                 Nan::SetterCallback setter = 0,
+                 v8::Local<v8::Value> data = v8::Local<v8::Value>(),
+                 v8::AccessControl settings = v8::DEFAULT,
+                 v8::PropertyAttribute attribute = v8::None)
+```
+
+See the V8 [`ObjectTemplate#SetAccessor()`](https://v8docs.nodesource.com/node-8.0/db/d5f/classv8_1_1_object_template.html#aca0ed196f8a9adb1f68b1aadb6c9cd77) and [`Object#SetAccessor()`](https://v8docs.nodesource.com/node-8.0/db/d85/classv8_1_1_object.html#a3f9dee085f5ec346465f1dc924325043) for further information about how to use `Nan::SetAccessor()`.
+
+<a name="api_nan_set_named_property_handler"></a>
+### Nan::SetNamedPropertyHandler()
+
+Sets named property getters, setters, query, deleter and enumerator methods on an `ObjectTemplate`. Accepts:
+
+* Property getters with the `Nan::PropertyGetterCallback` signature (see <a href="#api_nan_property_getter">Property getter declaration</a>)
+* Property setters with the `Nan::PropertySetterCallback` signature (see <a href="#api_nan_property_setter">Property setter declaration</a>)
+* Property query methods with the `Nan::PropertyQueryCallback` signature (see <a href="#api_nan_property_query">Property query declaration</a>)
+* Property deleters with the `Nan::PropertyDeleterCallback` signature (see <a href="#api_nan_property_deleter">Property deleter declaration</a>)
+* Property enumerators with the `Nan::PropertyEnumeratorCallback` signature (see <a href="#api_nan_property_enumerator">Property enumerator declaration</a>)
+
+Signature:
+
+```c++
+void SetNamedPropertyHandler(v8::Local<v8::ObjectTemplate> tpl,
+                             Nan::PropertyGetterCallback getter,
+                             Nan::PropertySetterCallback setter = 0,
+                             Nan::PropertyQueryCallback query = 0,
+                             Nan::PropertyDeleterCallback deleter = 0,
+                             Nan::PropertyEnumeratorCallback enumerator = 0,
+                             v8::Local<v8::Value> data = v8::Local<v8::Value>())
+```
+
+See the V8 [`ObjectTemplate#SetNamedPropertyHandler()`](https://v8docs.nodesource.com/io.js-3.3/db/d5f/classv8_1_1_object_template.html#a34d1cc45b642cd131706663801aadd76) for further information about how to use `Nan::SetNamedPropertyHandler()`.
+
+<a name="api_nan_set_indexed_property_handler"></a>
+### Nan::SetIndexedPropertyHandler()
+
+Sets indexed property getters, setters, query, deleter and enumerator methods on an `ObjectTemplate`. Accepts:
+
+* Indexed property getters with the `Nan::IndexGetterCallback` signature (see <a href="#api_nan_index_getter">Index getter declaration</a>)
+* Indexed property setters with the `Nan::IndexSetterCallback` signature (see <a href="#api_nan_index_setter">Index setter declaration</a>)
+* Indexed property query methods with the `Nan::IndexQueryCallback` signature (see <a href="#api_nan_index_query">Index query declaration</a>)
+* Indexed property deleters with the `Nan::IndexDeleterCallback` signature (see <a href="#api_nan_index_deleter">Index deleter declaration</a>)
+* Indexed property enumerators with the `Nan::IndexEnumeratorCallback` signature (see <a href="#api_nan_index_enumerator">Index enumerator declaration</a>)
+
+Signature:
+
+```c++
+void SetIndexedPropertyHandler(v8::Local<v8::ObjectTemplate> tpl,
+                               Nan::IndexGetterCallback getter,
+                               Nan::IndexSetterCallback setter = 0,
+                               Nan::IndexQueryCallback query = 0,
+                               Nan::IndexDeleterCallback deleter = 0,
+                               Nan::IndexEnumeratorCallback enumerator = 0,
+                               v8::Local<v8::Value> data = v8::Local<v8::Value>())
+```
+
+See the V8 [`ObjectTemplate#SetIndexedPropertyHandler()`](https://v8docs.nodesource.com/node-8.0/db/d5f/classv8_1_1_object_template.html#ac89f06d634add0e890452033f7d17ff1) for further information about how to use `Nan::SetIndexedPropertyHandler()`.
+
+<a name="api_nan_set_template"></a>
+### Nan::SetTemplate()
+
+Adds properties on an `Object`'s or `Function`'s template.
+
+Signature:
+
+```c++
+void Nan::SetTemplate(v8::Local<v8::Template> templ,
+                      const char *name,
+                      v8::Local<v8::Data> value);
+void Nan::SetTemplate(v8::Local<v8::Template> templ,
+                      v8::Local<v8::String> name,
+                      v8::Local<v8::Data> value,
+                      v8::PropertyAttribute attributes)
+```
+
+Calls the `Template`'s [`Set()`](https://v8docs.nodesource.com/node-8.0/db/df7/classv8_1_1_template.html#ae3fbaff137557aa6a0233bc7e52214ac).
+
+<a name="api_nan_set_prototype_template"></a>
+### Nan::SetPrototypeTemplate()
+
+Adds properties on an `Object`'s or `Function`'s prototype template.
+
+Signature:
+
+```c++
+void Nan::SetPrototypeTemplate(v8::Local<v8::FunctionTemplate> templ,
+                               const char *name,
+                               v8::Local<v8::Data> value);
+void Nan::SetPrototypeTemplate(v8::Local<v8::FunctionTemplate> templ,
+                               v8::Local<v8::String> name,
+                               v8::Local<v8::Data> value,
+                               v8::PropertyAttribute attributes)
+```
+
+Calls the `FunctionTemplate`'s _PrototypeTemplate's_ [`Set()`](https://v8docs.nodesource.com/io.js-3.3/db/df7/classv8_1_1_template.html#a2db6a56597bf23c59659c0659e564ddf).
+
+<a name="api_nan_set_instance_template"></a>
+### Nan::SetInstanceTemplate()
+
+Use to add instance properties on `FunctionTemplate`'s.
+
+Signature:
+
+```c++
+void Nan::SetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ,
+                              const char *name,
+                              v8::Local<v8::Data> value);
+void Nan::SetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ,
+                              v8::Local<v8::String> name,
+                              v8::Local<v8::Data> value,
+                              v8::PropertyAttribute attributes)
+```
+
+Calls the `FunctionTemplate`'s _InstanceTemplate's_ [`Set()`](https://v8docs.nodesource.com/io.js-3.3/db/df7/classv8_1_1_template.html#a2db6a56597bf23c59659c0659e564ddf).
+
+<a name="api_nan_set_call_handler"></a>
+### Nan::SetCallHandler()
+
+Set the call-handler callback for a `v8::FunctionTemplate`.
+This callback is called whenever the function created from this FunctionTemplate is called.
+
+Signature:
+
+```c++
+void Nan::SetCallHandler(v8::Local<v8::FunctionTemplate> templ, Nan::FunctionCallback callback, v8::Local<v8::Value> data = v8::Local<v8::Value>())
+```
+
+Calls the `FunctionTemplate`'s [`SetCallHandler()`](https://v8docs.nodesource.com/node-8.0/d8/d83/classv8_1_1_function_template.html#a2d3845db66392074c5a018a66efbfada).
+
+<a name="api_nan_set_call_as_function_handler"></a>
+### Nan::SetCallAsFunctionHandler()
+
+Sets the callback to be used when calling instances created from the `v8::ObjectTemplate` as a function.
+If no callback is set, instances behave like normal JavaScript objects that cannot be called as a function.
+
+Signature:
+
+```c++
+void Nan::SetCallAsFunctionHandler(v8::Local<v8::ObjectTemplate> templ, Nan::FunctionCallback callback, v8::Local<v8::Value> data = v8::Local<v8::Value>())
+```
+
+Calls the `ObjectTemplate`'s [`SetCallAsFunctionHandler()`](https://v8docs.nodesource.com/node-8.0/db/d5f/classv8_1_1_object_template.html#a5e9612fc80bf6db8f2da199b9b0bd04e).
+
diff --git a/input_devices/mag/node_modules/nan/doc/new.md b/input_devices/mag/node_modules/nan/doc/new.md
new file mode 100644
index 00000000..0804b62f
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/new.md
@@ -0,0 +1,147 @@
+## New
+
+NAN provides a `Nan::New()` helper for the creation of new JavaScript objects in a way that's compatible across the supported versions of V8.
+
+ - <a href="#api_nan_new"><b><code>Nan::New()</code></b></a>
+ - <a href="#api_nan_undefined"><b><code>Nan::Undefined()</code></b></a>
+ - <a href="#api_nan_null"><b><code>Nan::Null()</code></b></a>
+ - <a href="#api_nan_true"><b><code>Nan::True()</code></b></a>
+ - <a href="#api_nan_false"><b><code>Nan::False()</code></b></a>
+ - <a href="#api_nan_empty_string"><b><code>Nan::EmptyString()</code></b></a>
+
+
+<a name="api_nan_new"></a>
+### Nan::New()
+
+`Nan::New()` should be used to instantiate new JavaScript objects.
+
+Refer to the specific V8 type in the [V8 documentation](https://v8docs.nodesource.com/io.js-3.3/d1/d83/classv8_1_1_data.html) for information on the types of arguments required for instantiation.
+
+Signatures:
+
+Return types are mostly omitted from the signatures for simplicity. In most cases the type will be contained within a `v8::Local<T>`. The following types will be contained within a `Nan::MaybeLocal<T>`: `v8::String`, `v8::Date`, `v8::RegExp`, `v8::Script`, `v8::UnboundScript`.
+
+Empty objects:
+
+```c++
+Nan::New<T>();
+```
+
+Generic single and multiple-argument:
+
+```c++
+Nan::New<T>(A0 arg0);
+Nan::New<T>(A0 arg0, A1 arg1);
+Nan::New<T>(A0 arg0, A1 arg1, A2 arg2);
+Nan::New<T>(A0 arg0, A1 arg1, A2 arg2, A3 arg3);
+```
+
+For creating `v8::FunctionTemplate` and `v8::Function` objects:
+
+_The definition of `Nan::FunctionCallback` can be found in the [Method declaration](./methods.md#api_nan_method) documentation._
+
+```c++
+Nan::New<T>(Nan::FunctionCallback callback,
+            v8::Local<v8::Value> data = v8::Local<v8::Value>());
+Nan::New<T>(Nan::FunctionCallback callback,
+            v8::Local<v8::Value> data = v8::Local<v8::Value>(),
+            A2 a2 = A2());
+```
+
+Native number types:
+
+```c++
+v8::Local<v8::Boolean> Nan::New<T>(bool value);
+v8::Local<v8::Int32> Nan::New<T>(int32_t value);
+v8::Local<v8::Uint32> Nan::New<T>(uint32_t value);
+v8::Local<v8::Number> Nan::New<T>(double value);
+```
+
+String types:
+
+```c++
+Nan::MaybeLocal<v8::String> Nan::New<T>(std::string const& value);
+Nan::MaybeLocal<v8::String> Nan::New<T>(const char * value, int length);
+Nan::MaybeLocal<v8::String> Nan::New<T>(const char * value);
+Nan::MaybeLocal<v8::String> Nan::New<T>(const uint16_t * value);
+Nan::MaybeLocal<v8::String> Nan::New<T>(const uint16_t * value, int length);
+```
+
+Specialized types:
+
+```c++
+v8::Local<v8::String> Nan::New<T>(v8::String::ExternalStringResource * value);
+v8::Local<v8::String> Nan::New<T>(Nan::ExternalOneByteStringResource * value);
+v8::Local<v8::RegExp> Nan::New<T>(v8::Local<v8::String> pattern, v8::RegExp::Flags flags);
+```
+
+Note that `Nan::ExternalOneByteStringResource` maps to [`v8::String::ExternalOneByteStringResource`](https://v8docs.nodesource.com/io.js-3.3/d9/db3/classv8_1_1_string_1_1_external_one_byte_string_resource.html), and `v8::String::ExternalAsciiStringResource` in older versions of V8.
+
+
+<a name="api_nan_undefined"></a>
+### Nan::Undefined()
+
+A helper method to reference the `v8::Undefined` object in a way that is compatible across all supported versions of V8.
+
+Signature:
+
+```c++
+v8::Local<v8::Primitive> Nan::Undefined()
+```
+
+<a name="api_nan_null"></a>
+### Nan::Null()
+
+A helper method to reference the `v8::Null` object in a way that is compatible across all supported versions of V8.
+
+Signature:
+
+```c++
+v8::Local<v8::Primitive> Nan::Null()
+```
+
+<a name="api_nan_true"></a>
+### Nan::True()
+
+A helper method to reference the `v8::Boolean` object representing the `true` value in a way that is compatible across all supported versions of V8.
+
+Signature:
+
+```c++
+v8::Local<v8::Boolean> Nan::True()
+```
+
+<a name="api_nan_false"></a>
+### Nan::False()
+
+A helper method to reference the `v8::Boolean` object representing the `false` value in a way that is compatible across all supported versions of V8.
+
+Signature:
+
+```c++
+v8::Local<v8::Boolean> Nan::False()
+```
+
+<a name="api_nan_empty_string"></a>
+### Nan::EmptyString()
+
+Call [`v8::String::Empty`](https://v8docs.nodesource.com/io.js-3.3/d2/db3/classv8_1_1_string.html#a7c1bc8886115d7ee46f1d571dd6ebc6d) to reference the empty string in a way that is compatible across all supported versions of V8.
+
+Signature:
+
+```c++
+v8::Local<v8::String> Nan::EmptyString()
+```
+
+
+<a name="api_nan_new_one_byte_string"></a>
+### Nan::NewOneByteString()
+
+An implementation of [`v8::String::NewFromOneByte()`](https://v8docs.nodesource.com/io.js-3.3/d2/db3/classv8_1_1_string.html#a5264d50b96d2c896ce525a734dc10f09) provided for consistent availability and API across supported versions of V8. Allocates a new string from Latin-1 data.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::String> Nan::NewOneByteString(const uint8_t * value,
+                                                  int length = -1)
+```
diff --git a/input_devices/mag/node_modules/nan/doc/node_misc.md b/input_devices/mag/node_modules/nan/doc/node_misc.md
new file mode 100644
index 00000000..17578e34
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/node_misc.md
@@ -0,0 +1,123 @@
+## Miscellaneous Node Helpers
+
+ - <a href="#api_nan_asyncresource"><b><code>Nan::AsyncResource</code></b></a>
+ - <a href="#api_nan_make_callback"><b><code>Nan::MakeCallback()</code></b></a>
+ - <a href="#api_nan_module_init"><b><code>NAN_MODULE_INIT()</code></b></a>
+ - <a href="#api_nan_export"><b><code>Nan::Export()</code></b></a>
+
+<a name="api_nan_asyncresource"></a>
+### Nan::AsyncResource
+
+This class is analogous to the `AsyncResource` JavaScript class exposed by Node's [async_hooks][] API.
+
+When calling back into JavaScript asynchronously, special care must be taken to ensure that the runtime can properly track
+async hops. `Nan::AsyncResource` is a class that provides an RAII wrapper around `node::EmitAsyncInit`, `node::EmitAsyncDestroy`,
+and `node::MakeCallback`. Using this mechanism to call back into JavaScript, as opposed to `Nan::MakeCallback` or
+`v8::Function::Call` ensures that the callback is executed in the correct async context. This ensures that async mechanisms
+such as domains and [async_hooks][] function correctly.
+
+Definition:
+
+```c++
+class AsyncResource {
+ public:
+  AsyncResource(v8::Local<v8::String> name,
+                v8::Local<v8::Object> resource = New<v8::Object>());
+  AsyncResource(const char* name,
+                v8::Local<v8::Object> resource = New<v8::Object>());
+  ~AsyncResource();
+
+  v8::MaybeLocal<v8::Value> runInAsyncScope(v8::Local<v8::Object> target,
+                                            v8::Local<v8::Function> func,
+                                            int argc,
+                                            v8::Local<v8::Value>* argv);
+  v8::MaybeLocal<v8::Value> runInAsyncScope(v8::Local<v8::Object> target,
+                                            v8::Local<v8::String> symbol,
+                                            int argc,
+                                            v8::Local<v8::Value>* argv);
+  v8::MaybeLocal<v8::Value> runInAsyncScope(v8::Local<v8::Object> target,
+                                            const char* method,
+                                            int argc,
+                                            v8::Local<v8::Value>* argv);
+};
+```
+
+* `name`: Identifier for the kind of resource that is being provided for diagnostics information exposed by the [async_hooks][]
+  API. This will be passed to the possible `init` hook as the `type`. To avoid name collisions with other modules we recommend
+  that the name include the name of the owning module as a prefix. For example `mysql` module could use something like
+  `mysql:batch-db-query-resource`.
+* `resource`: An optional object associated with the async work that will be passed to the possible [async_hooks][]
+  `init` hook. If this parameter is omitted, or an empty handle is provided, this object will be created automatically.
+* When calling JS on behalf of this resource, one can use `runInAsyncScope`. This will ensure that the callback runs in the
+  correct async execution context.
+* `AsyncDestroy` is automatically called when an AsyncResource object is destroyed.
+
+For more details, see the Node [async_hooks][] documentation. You might also want to take a look at the documentation for the
+[N-API counterpart][napi]. For example usage, see the `asyncresource.cpp` example in the `test/cpp` directory.
+
+<a name="api_nan_make_callback"></a>
+### Nan::MakeCallback()
+
+Deprecated wrappers around the legacy `node::MakeCallback()` APIs. Node.js 10+
+has deprecated these legacy APIs as they do not provide a mechanism to preserve
+async context.
+
+We recommend that you use the `AsyncResource` class and `AsyncResource::runInAsyncScope` instead of using `Nan::MakeCallback` or
+`v8::Function#Call()` directly. `AsyncResource` properly takes care of running the callback in the correct async execution
+context – something that is essential for functionality like domains, async_hooks and async debugging.
+
+Signatures:
+
+```c++
+NAN_DEPRECATED
+v8::Local<v8::Value> Nan::MakeCallback(v8::Local<v8::Object> target,
+                                       v8::Local<v8::Function> func,
+                                       int argc,
+                                       v8::Local<v8::Value>* argv);
+NAN_DEPRECATED
+v8::Local<v8::Value> Nan::MakeCallback(v8::Local<v8::Object> target,
+                                       v8::Local<v8::String> symbol,
+                                       int argc,
+                                       v8::Local<v8::Value>* argv);
+NAN_DEPRECATED
+v8::Local<v8::Value> Nan::MakeCallback(v8::Local<v8::Object> target,
+                                       const char* method,
+                                       int argc,
+                                       v8::Local<v8::Value>* argv);
+```
+
+
+<a name="api_nan_module_init"></a>
+### NAN_MODULE_INIT()
+
+Used to define the entry point function to a Node add-on. Creates a function with a given `name` that receives a `target` object representing the equivalent of the JavaScript `exports` object.
+
+See example below.
+
+<a name="api_nan_export"></a>
+### Nan::Export()
+
+A simple helper to register a `v8::FunctionTemplate` from a JavaScript-accessible method (see [Methods](./methods.md)) as a property on an object. Can be used in a way similar to assigning properties to `module.exports` in JavaScript.
+
+Signature:
+
+```c++
+void Export(v8::Local<v8::Object> target, const char *name, Nan::FunctionCallback f)
+```
+
+Also available as the shortcut `NAN_EXPORT` macro.
+
+Example:
+
+```c++
+NAN_METHOD(Foo) {
+  ...
+}
+
+NAN_MODULE_INIT(Init) {
+  NAN_EXPORT(target, Foo);
+}
+```
+
+[async_hooks]: https://nodejs.org/dist/latest-v9.x/docs/api/async_hooks.html
+[napi]: https://nodejs.org/dist/latest-v9.x/docs/api/n-api.html#n_api_custom_asynchronous_operations
diff --git a/input_devices/mag/node_modules/nan/doc/object_wrappers.md b/input_devices/mag/node_modules/nan/doc/object_wrappers.md
new file mode 100644
index 00000000..08dd6b55
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/object_wrappers.md
@@ -0,0 +1,263 @@
+## Object Wrappers
+
+The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects.
+
+ - <a href="#api_nan_object_wrap"><b><code>Nan::ObjectWrap</code></b></a>
+
+
+<a name="api_nan_object_wrap"></a>
+### Nan::ObjectWrap()
+
+A reimplementation of `node::ObjectWrap` that adds some API not present in older versions of Node. Should be preferred over `node::ObjectWrap` in all cases for consistency.
+
+Definition:
+
+```c++
+class ObjectWrap {
+ public:
+  ObjectWrap();
+
+  virtual ~ObjectWrap();
+
+  template <class T>
+  static inline T* Unwrap(v8::Local<v8::Object> handle);
+
+  inline v8::Local<v8::Object> handle();
+
+  inline Nan::Persistent<v8::Object>& persistent();
+
+ protected:
+  inline void Wrap(v8::Local<v8::Object> handle);
+
+  inline void MakeWeak();
+
+  /* Ref() marks the object as being attached to an event loop.
+   * Refed objects will not be garbage collected, even if
+   * all references are lost.
+   */
+  virtual void Ref();
+
+  /* Unref() marks an object as detached from the event loop.  This is its
+   * default state.  When an object with a "weak" reference changes from
+   * attached to detached state it will be freed. Be careful not to access
+   * the object after making this call as it might be gone!
+   * (A "weak reference" means an object that only has a
+   * persistant handle.)
+   *
+   * DO NOT CALL THIS FROM DESTRUCTOR
+   */
+  virtual void Unref();
+
+  int refs_;  // ro
+};
+```
+
+See the Node documentation on [Wrapping C++ Objects](https://nodejs.org/api/addons.html#addons_wrapping_c_objects) for more details.
+
+### This vs. Holder
+
+When calling `Unwrap`, it is important that the argument is indeed some JavaScript object which got wrapped by a `Wrap` call for this class or any derived class.
+The `Signature` installed by [`Nan::SetPrototypeMethod()`](methods.md#api_nan_set_prototype_method) does ensure that `info.Holder()` is just such an instance.
+In Node 0.12 and later, `info.This()` will also be of such a type, since otherwise the invocation will get rejected.
+However, in Node 0.10 and before it was possible to invoke a method on a JavaScript object which just had the extension type in its prototype chain.
+In such a situation, calling `Unwrap` on `info.This()` will likely lead to a failed assertion causing a crash, but could lead to even more serious corruption.
+
+On the other hand, calling `Unwrap` in an [accessor](methods.md#api_nan_set_accessor) should not use `Holder()` if the accessor is defined on the prototype.
+So either define your accessors on the instance template,
+or use `This()` after verifying that it is indeed a valid object.
+
+### Examples
+
+#### Basic
+
+```c++
+class MyObject : public Nan::ObjectWrap {
+ public:
+  static NAN_MODULE_INIT(Init) {
+    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
+    tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
+    tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+    Nan::SetPrototypeMethod(tpl, "getHandle", GetHandle);
+    Nan::SetPrototypeMethod(tpl, "getValue", GetValue);
+
+    constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
+    Nan::Set(target, Nan::New("MyObject").ToLocalChecked(),
+      Nan::GetFunction(tpl).ToLocalChecked());
+  }
+
+ private:
+  explicit MyObject(double value = 0) : value_(value) {}
+  ~MyObject() {}
+
+  static NAN_METHOD(New) {
+    if (info.IsConstructCall()) {
+      double value = info[0]->IsUndefined() ? 0 : Nan::To<double>(info[0]).FromJust();
+      MyObject *obj = new MyObject(value);
+      obj->Wrap(info.This());
+      info.GetReturnValue().Set(info.This());
+    } else {
+      const int argc = 1;
+      v8::Local<v8::Value> argv[argc] = {info[0]};
+      v8::Local<v8::Function> cons = Nan::New(constructor());
+      info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
+    }
+  }
+
+  static NAN_METHOD(GetHandle) {
+    MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.Holder());
+    info.GetReturnValue().Set(obj->handle());
+  }
+
+  static NAN_METHOD(GetValue) {
+    MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.Holder());
+    info.GetReturnValue().Set(obj->value_);
+  }
+
+  static inline Nan::Persistent<v8::Function> & constructor() {
+    static Nan::Persistent<v8::Function> my_constructor;
+    return my_constructor;
+  }
+
+  double value_;
+};
+
+NODE_MODULE(objectwrapper, MyObject::Init)
+```
+
+To use in Javascript:
+
+```Javascript
+var objectwrapper = require('bindings')('objectwrapper');
+
+var obj = new objectwrapper.MyObject(5);
+console.log('Should be 5: ' + obj.getValue());
+```
+
+#### Factory of wrapped objects
+
+```c++
+class MyFactoryObject : public Nan::ObjectWrap {
+ public:
+  static NAN_MODULE_INIT(Init) {
+    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
+    tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+    Nan::SetPrototypeMethod(tpl, "getValue", GetValue);
+
+    constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
+  }
+
+  static NAN_METHOD(NewInstance) {
+    v8::Local<v8::Function> cons = Nan::New(constructor());
+    double value = info[0]->IsNumber() ? Nan::To<double>(info[0]).FromJust() : 0;
+    const int argc = 1;
+    v8::Local<v8::Value> argv[1] = {Nan::New(value)};
+    info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
+  }
+
+  // Needed for the next example:
+  inline double value() const {
+    return value_;
+  }
+
+ private:
+  explicit MyFactoryObject(double value = 0) : value_(value) {}
+  ~MyFactoryObject() {}
+
+  static NAN_METHOD(New) {
+    if (info.IsConstructCall()) {
+      double value = info[0]->IsNumber() ? Nan::To<double>(info[0]).FromJust() : 0;
+      MyFactoryObject * obj = new MyFactoryObject(value);
+      obj->Wrap(info.This());
+      info.GetReturnValue().Set(info.This());
+    } else {
+      const int argc = 1;
+      v8::Local<v8::Value> argv[argc] = {info[0]};
+      v8::Local<v8::Function> cons = Nan::New(constructor());
+      info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
+    }
+  }
+
+  static NAN_METHOD(GetValue) {
+    MyFactoryObject* obj = ObjectWrap::Unwrap<MyFactoryObject>(info.Holder());
+    info.GetReturnValue().Set(obj->value_);
+  }
+
+  static inline Nan::Persistent<v8::Function> & constructor() {
+    static Nan::Persistent<v8::Function> my_constructor;
+    return my_constructor;
+  }
+
+  double value_;
+};
+
+NAN_MODULE_INIT(Init) {
+  MyFactoryObject::Init(target);
+  Nan::Set(target,
+    Nan::New<v8::String>("newFactoryObjectInstance").ToLocalChecked(),
+    Nan::GetFunction(
+      Nan::New<v8::FunctionTemplate>(MyFactoryObject::NewInstance)).ToLocalChecked()
+  );
+}
+
+NODE_MODULE(wrappedobjectfactory, Init)
+```
+
+To use in Javascript:
+
+```Javascript
+var wrappedobjectfactory = require('bindings')('wrappedobjectfactory');
+
+var obj = wrappedobjectfactory.newFactoryObjectInstance(10);
+console.log('Should be 10: ' + obj.getValue());
+```
+
+#### Passing wrapped objects around
+
+Use the `MyFactoryObject` class above along with the following:
+
+```c++
+static NAN_METHOD(Sum) {
+  Nan::MaybeLocal<v8::Object> maybe1 = Nan::To<v8::Object>(info[0]);
+  Nan::MaybeLocal<v8::Object> maybe2 = Nan::To<v8::Object>(info[1]);
+
+  // Quick check:
+  if (maybe1.IsEmpty() || maybe2.IsEmpty()) {
+    // return value is undefined by default
+    return;
+  }
+
+  MyFactoryObject* obj1 =
+    Nan::ObjectWrap::Unwrap<MyFactoryObject>(maybe1.ToLocalChecked());
+  MyFactoryObject* obj2 =
+    Nan::ObjectWrap::Unwrap<MyFactoryObject>(maybe2.ToLocalChecked());
+
+  info.GetReturnValue().Set(Nan::New<v8::Number>(obj1->value() + obj2->value()));
+}
+
+NAN_MODULE_INIT(Init) {
+  MyFactoryObject::Init(target);
+  Nan::Set(target,
+    Nan::New<v8::String>("newFactoryObjectInstance").ToLocalChecked(),
+    Nan::GetFunction(
+      Nan::New<v8::FunctionTemplate>(MyFactoryObject::NewInstance)).ToLocalChecked()
+  );
+  Nan::Set(target,
+    Nan::New<v8::String>("sum").ToLocalChecked(),
+    Nan::GetFunction(Nan::New<v8::FunctionTemplate>(Sum)).ToLocalChecked()
+  );
+}
+
+NODE_MODULE(myaddon, Init)
+```
+
+To use in Javascript:
+
+```Javascript
+var myaddon = require('bindings')('myaddon');
+
+var obj1 = myaddon.newFactoryObjectInstance(5);
+var obj2 = myaddon.newFactoryObjectInstance(10);
+console.log('sum of object values: ' + myaddon.sum(obj1, obj2));
+```
diff --git a/input_devices/mag/node_modules/nan/doc/persistent.md b/input_devices/mag/node_modules/nan/doc/persistent.md
new file mode 100644
index 00000000..af71c4f4
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/persistent.md
@@ -0,0 +1,296 @@
+## Persistent references
+
+An object reference that is independent of any `HandleScope` is a _persistent_ reference. Where a `Local` handle only lives as long as the `HandleScope` in which it was allocated, a `Persistent` handle remains valid until it is explicitly disposed.
+
+Due to the evolution of the V8 API, it is necessary for NAN to provide a wrapper implementation of the `Persistent` classes to supply compatibility across the V8 versions supported.
+
+ - <a href="#api_nan_persistent_base"><b><code>Nan::PersistentBase & v8::PersistentBase</code></b></a>
+ - <a href="#api_nan_non_copyable_persistent_traits"><b><code>Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits</code></b></a>
+ - <a href="#api_nan_copyable_persistent_traits"><b><code>Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits</code></b></a>
+ - <a href="#api_nan_persistent"><b><code>Nan::Persistent</code></b></a>
+ - <a href="#api_nan_global"><b><code>Nan::Global</code></b></a>
+ - <a href="#api_nan_weak_callback_info"><b><code>Nan::WeakCallbackInfo</code></b></a>
+ - <a href="#api_nan_weak_callback_type"><b><code>Nan::WeakCallbackType</code></b></a>
+
+Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://developers.google.com/v8/embed#handles).
+
+<a name="api_nan_persistent_base"></a>
+### Nan::PersistentBase & v8::PersistentBase
+
+A persistent handle contains a reference to a storage cell in V8 which holds an object value and which is updated by the garbage collector whenever the object is moved. A new storage cell can be created using the constructor or `Nan::PersistentBase::Reset()`. Existing handles can be disposed using an argument-less `Nan::PersistentBase::Reset()`.
+
+Definition:
+
+_(note: this is implemented as `Nan::PersistentBase` for older versions of V8 and the native `v8::PersistentBase` is used for newer versions of V8)_
+
+```c++
+template<typename T> class PersistentBase {
+ public:
+  /**
+   * If non-empty, destroy the underlying storage cell
+   */
+  void Reset();
+
+  /**
+   * If non-empty, destroy the underlying storage cell and create a new one with
+   * the contents of another if it is also non-empty
+   */
+  template<typename S> void Reset(const v8::Local<S> &other);
+
+  /**
+   * If non-empty, destroy the underlying storage cell and create a new one with
+   * the contents of another if it is also non-empty
+   */
+  template<typename S> void Reset(const PersistentBase<S> &other);
+
+  /** Returns true if the handle is empty. */
+  bool IsEmpty() const;
+
+  /**
+   * If non-empty, destroy the underlying storage cell
+   * IsEmpty() will return true after this call.
+   */
+  void Empty();
+
+  template<typename S> bool operator==(const PersistentBase<S> &that);
+
+  template<typename S> bool operator==(const v8::Local<S> &that);
+
+  template<typename S> bool operator!=(const PersistentBase<S> &that);
+
+  template<typename S> bool operator!=(const v8::Local<S> &that);
+
+   /**
+   *  Install a finalization callback on this object.
+   *  NOTE: There is no guarantee as to *when* or even *if* the callback is
+   *  invoked. The invocation is performed solely on a best effort basis.
+   *  As always, GC-based finalization should *not* be relied upon for any
+   *  critical form of resource management! At the moment you can either
+   *  specify a parameter for the callback or the location of two internal
+   *  fields in the dying object.
+   */
+  template<typename P>
+  void SetWeak(P *parameter,
+               typename WeakCallbackInfo<P>::Callback callback,
+               WeakCallbackType type);
+
+  void ClearWeak();
+
+  /**
+   * Marks the reference to this object independent. Garbage collector is free
+   * to ignore any object groups containing this object. Weak callback for an
+   * independent handle should not assume that it will be preceded by a global
+   * GC prologue callback or followed by a global GC epilogue callback.
+   */
+  void MarkIndependent() const;
+
+  bool IsIndependent() const;
+
+  /** Checks if the handle holds the only reference to an object. */
+  bool IsNearDeath() const;
+
+  /** Returns true if the handle's reference is weak.  */
+  bool IsWeak() const
+};
+```
+
+See the V8 documentation for [`PersistentBase`](https://v8docs.nodesource.com/io.js-3.3/d4/dca/classv8_1_1_persistent_base.html) for further information.
+
+**Tip:** To get a `v8::Local` reference to the original object back from a `PersistentBase` or `Persistent` object:
+
+```c++
+v8::Local<v8::Object> object = Nan::New(persistent);
+```
+
+<a name="api_nan_non_copyable_persistent_traits"></a>
+### Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits
+
+Default traits for `Nan::Persistent`. This class does not allow use of the a copy constructor or assignment operator. At present `kResetInDestructor` is not set, but that will change in a future version.
+
+Definition:
+
+_(note: this is implemented as `Nan::NonCopyablePersistentTraits` for older versions of V8 and the native `v8::NonCopyablePersistentTraits` is used for newer versions of V8)_
+
+```c++
+template<typename T> class NonCopyablePersistentTraits {
+ public:
+  typedef Persistent<T, NonCopyablePersistentTraits<T> > NonCopyablePersistent;
+
+  static const bool kResetInDestructor = false;
+
+  template<typename S, typename M>
+  static void Copy(const Persistent<S, M> &source,
+                   NonCopyablePersistent *dest);
+
+  template<typename O> static void Uncompilable();
+};
+```
+
+See the V8 documentation for [`NonCopyablePersistentTraits`](https://v8docs.nodesource.com/io.js-3.3/de/d73/classv8_1_1_non_copyable_persistent_traits.html) for further information.
+
+<a name="api_nan_copyable_persistent_traits"></a>
+### Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits
+
+A helper class of traits to allow copying and assignment of `Persistent`. This will clone the contents of storage cell, but not any of the flags, etc..
+
+Definition:
+
+_(note: this is implemented as `Nan::CopyablePersistentTraits` for older versions of V8 and the native `v8::NonCopyablePersistentTraits` is used for newer versions of V8)_
+
+```c++
+template<typename T>
+class CopyablePersistentTraits {
+ public:
+  typedef Persistent<T, CopyablePersistentTraits<T> > CopyablePersistent;
+
+  static const bool kResetInDestructor = true;
+
+  template<typename S, typename M>
+  static void Copy(const Persistent<S, M> &source,
+                   CopyablePersistent *dest);
+};
+```
+
+See the V8 documentation for [`CopyablePersistentTraits`](https://v8docs.nodesource.com/io.js-3.3/da/d5c/structv8_1_1_copyable_persistent_traits.html) for further information.
+
+<a name="api_nan_persistent"></a>
+### Nan::Persistent
+
+A type of `PersistentBase` which allows copy and assignment. Copy, assignment and destructor behavior is controlled by the traits class `M`.
+
+Definition:
+
+```c++
+template<typename T, typename M = NonCopyablePersistentTraits<T> >
+class Persistent;
+
+template<typename T, typename M> class Persistent : public PersistentBase<T> {
+ public:
+ /**
+  * A Persistent with no storage cell.
+  */
+  Persistent();
+
+  /**
+   * Construct a Persistent from a v8::Local. When the v8::Local is non-empty, a
+   * new storage cell is created pointing to the same object, and no flags are
+   * set.
+   */
+  template<typename S> Persistent(v8::Local<S> that);
+
+  /**
+   * Construct a Persistent from a Persistent. When the Persistent is non-empty,
+   * a new storage cell is created pointing to the same object, and no flags are
+   * set.
+   */
+  Persistent(const Persistent &that);
+
+  /**
+   * The copy constructors and assignment operator create a Persistent exactly
+   * as the Persistent constructor, but the Copy function from the traits class
+   * is called, allowing the setting of flags based on the copied Persistent.
+   */
+  Persistent &operator=(const Persistent &that);
+
+  template <typename S, typename M2>
+  Persistent &operator=(const Persistent<S, M2> &that);
+
+  /**
+   * The destructor will dispose the Persistent based on the kResetInDestructor
+   * flags in the traits class.  Since not calling dispose can result in a
+   * memory leak, it is recommended to always set this flag.
+   */
+  ~Persistent();
+};
+```
+
+See the V8 documentation for [`Persistent`](https://v8docs.nodesource.com/io.js-3.3/d2/d78/classv8_1_1_persistent.html) for further information.
+
+<a name="api_nan_global"></a>
+### Nan::Global
+
+A type of `PersistentBase` which has move semantics.
+
+```c++
+template<typename T> class Global : public PersistentBase<T> {
+ public:
+  /**
+   * A Global with no storage cell.
+   */
+  Global();
+
+  /**
+   * Construct a Global from a v8::Local. When the v8::Local is non-empty, a new
+   * storage cell is created pointing to the same object, and no flags are set.
+   */
+  template<typename S> Global(v8::Local<S> that);
+  /**
+   * Construct a Global from a PersistentBase. When the Persistent is non-empty,
+   * a new storage cell is created pointing to the same object, and no flags are
+   * set.
+   */
+  template<typename S> Global(const PersistentBase<S> &that);
+
+  /**
+   * Pass allows returning globals from functions, etc.
+   */
+  Global Pass();
+};
+```
+
+See the V8 documentation for [`Global`](https://v8docs.nodesource.com/io.js-3.3/d5/d40/classv8_1_1_global.html) for further information.
+
+<a name="api_nan_weak_callback_info"></a>
+### Nan::WeakCallbackInfo
+
+`Nan::WeakCallbackInfo` is used as an argument when setting a persistent reference as weak. You may need to free any external resources attached to the object. It is a mirror of `v8:WeakCallbackInfo` as found in newer versions of V8.
+
+Definition:
+
+```c++
+template<typename T> class WeakCallbackInfo {
+ public:
+  typedef void (*Callback)(const WeakCallbackInfo<T>& data);
+
+  v8::Isolate *GetIsolate() const;
+
+  /**
+   * Get the parameter that was associated with the weak handle.
+   */
+  T *GetParameter() const;
+
+  /**
+   * Get pointer from internal field, index can be 0 or 1.
+   */
+  void *GetInternalField(int index) const;
+};
+```
+
+Example usage:
+
+```c++
+void weakCallback(const WeakCallbackInfo<int> &data) {
+  int *parameter = data.GetParameter();
+  delete parameter;
+}
+
+Persistent<v8::Object> obj;
+int *data = new int(0);
+obj.SetWeak(data, callback, WeakCallbackType::kParameter);
+```
+
+See the V8 documentation for [`WeakCallbackInfo`](https://v8docs.nodesource.com/io.js-3.3/d8/d06/classv8_1_1_weak_callback_info.html) for further information.
+
+<a name="api_nan_weak_callback_type"></a>
+### Nan::WeakCallbackType
+
+Represents the type of a weak callback.
+A weak callback of type `kParameter` makes the supplied parameter to `Nan::PersistentBase::SetWeak` available through `WeakCallbackInfo::GetParameter`.
+A weak callback of type `kInternalFields` uses up to two internal fields at indices 0 and 1 on the `Nan::PersistentBase<v8::Object>` being made weak.
+Note that only `v8::Object`s and derivatives can have internal fields.
+
+Definition:
+
+```c++
+enum class WeakCallbackType { kParameter, kInternalFields };
+```
diff --git a/input_devices/mag/node_modules/nan/doc/scopes.md b/input_devices/mag/node_modules/nan/doc/scopes.md
new file mode 100644
index 00000000..1dfb417c
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/scopes.md
@@ -0,0 +1,73 @@
+## Scopes
+
+A _local handle_ is a pointer to an object. All V8 objects are accessed using handles, they are necessary because of the way the V8 garbage collector works.
+
+A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope.
+
+The creation of `HandleScope` objects is different across the supported versions of V8. Therefore, NAN provides its own implementations that can be used safely across these.
+
+ - <a href="#api_nan_handle_scope"><b><code>Nan::HandleScope</code></b></a>
+ - <a href="#api_nan_escapable_handle_scope"><b><code>Nan::EscapableHandleScope</code></b></a>
+
+Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://github.com/v8/v8/wiki/Embedder%27s%20Guide#handles-and-garbage-collection).
+
+<a name="api_nan_handle_scope"></a>
+### Nan::HandleScope
+
+A simple wrapper around [`v8::HandleScope`](https://v8docs.nodesource.com/io.js-3.3/d3/d95/classv8_1_1_handle_scope.html).
+
+Definition:
+
+```c++
+class Nan::HandleScope {
+ public:
+  Nan::HandleScope();
+  static int NumberOfHandles();
+};
+```
+
+Allocate a new `Nan::HandleScope` whenever you are creating new V8 JavaScript objects. Note that an implicit `HandleScope` is created for you on JavaScript-accessible methods so you do not need to insert one yourself.
+
+Example:
+
+```c++
+// new object is created, it needs a new scope:
+void Pointless() {
+  Nan::HandleScope scope;
+  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
+}
+
+// JavaScript-accessible method already has a HandleScope
+NAN_METHOD(Pointless2) {
+  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
+}
+```
+
+<a name="api_nan_escapable_handle_scope"></a>
+### Nan::EscapableHandleScope
+
+Similar to [`Nan::HandleScope`](#api_nan_handle_scope) but should be used in cases where a function needs to return a V8 JavaScript type that has been created within it.
+
+Definition:
+
+```c++
+class Nan::EscapableHandleScope {
+ public:
+  Nan::EscapableHandleScope();
+  static int NumberOfHandles();
+  template<typename T> v8::Local<T> Escape(v8::Local<T> value);
+}
+```
+
+Use `Escape(value)` to return the object.
+
+Example:
+
+```c++
+v8::Local<v8::Object> EmptyObj() {
+  Nan::EscapableHandleScope scope;
+  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
+  return scope.Escape(obj);
+}
+```
+
diff --git a/input_devices/mag/node_modules/nan/doc/script.md b/input_devices/mag/node_modules/nan/doc/script.md
new file mode 100644
index 00000000..e518505e
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/script.md
@@ -0,0 +1,38 @@
+## Script
+
+NAN provides a `v8::Script` helpers as the API has changed over the supported versions of V8.
+
+ - <a href="#api_nan_compile_script"><b><code>Nan::CompileScript()</code></b></a>
+ - <a href="#api_nan_run_script"><b><code>Nan::RunScript()</code></b></a>
+
+
+<a name="api_nan_compile_script"></a>
+### Nan::CompileScript()
+
+A wrapper around [`v8::Script::Compile()`](https://v8docs.nodesource.com/io.js-3.3/da/da5/classv8_1_1_script_compiler.html#a93f5072a0db55d881b969e9fc98e564b).
+
+Note that `Nan::BoundScript` is an alias for `v8::Script`.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<Nan::BoundScript> Nan::CompileScript(
+    v8::Local<v8::String> s,
+    const v8::ScriptOrigin& origin);
+Nan::MaybeLocal<Nan::BoundScript> Nan::CompileScript(v8::Local<v8::String> s);
+```
+
+
+<a name="api_nan_run_script"></a>
+### Nan::RunScript()
+
+Calls `script->Run()` or `script->BindToCurrentContext()->Run(Nan::GetCurrentContext())`.
+
+Note that `Nan::BoundScript` is an alias for `v8::Script` and `Nan::UnboundScript` is an alias for `v8::UnboundScript` where available and `v8::Script` on older versions of V8.
+
+Signature:
+
+```c++
+Nan::MaybeLocal<v8::Value> Nan::RunScript(v8::Local<Nan::UnboundScript> script)
+Nan::MaybeLocal<v8::Value> Nan::RunScript(v8::Local<Nan::BoundScript> script) 
+```
diff --git a/input_devices/mag/node_modules/nan/doc/string_bytes.md b/input_devices/mag/node_modules/nan/doc/string_bytes.md
new file mode 100644
index 00000000..7c1bd325
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/string_bytes.md
@@ -0,0 +1,62 @@
+## Strings & Bytes
+
+Miscellaneous string & byte encoding and decoding functionality provided for compatibility across supported versions of V8 and Node. Implemented by NAN to ensure that all encoding types are supported, even for older versions of Node where they are missing.
+
+ - <a href="#api_nan_encoding"><b><code>Nan::Encoding</code></b></a>
+ - <a href="#api_nan_encode"><b><code>Nan::Encode()</code></b></a>
+ - <a href="#api_nan_decode_bytes"><b><code>Nan::DecodeBytes()</code></b></a>
+ - <a href="#api_nan_decode_write"><b><code>Nan::DecodeWrite()</code></b></a>
+
+
+<a name="api_nan_encoding"></a>
+### Nan::Encoding
+
+An enum representing the supported encoding types. A copy of `node::encoding` that is consistent across versions of Node.
+
+Definition:
+
+```c++
+enum Nan::Encoding { ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER }
+```
+
+
+<a name="api_nan_encode"></a>
+### Nan::Encode()
+
+A wrapper around `node::Encode()` that provides a consistent implementation across supported versions of Node.
+
+Signature:
+
+```c++
+v8::Local<v8::Value> Nan::Encode(const void *buf,
+                                 size_t len,
+                                 enum Nan::Encoding encoding = BINARY);
+```
+
+
+<a name="api_nan_decode_bytes"></a>
+### Nan::DecodeBytes()
+
+A wrapper around `node::DecodeBytes()` that provides a consistent implementation across supported versions of Node.
+
+Signature:
+
+```c++
+ssize_t Nan::DecodeBytes(v8::Local<v8::Value> val,
+                         enum Nan::Encoding encoding = BINARY);
+```
+
+
+<a name="api_nan_decode_write"></a>
+### Nan::DecodeWrite()
+
+A wrapper around `node::DecodeWrite()` that provides a consistent implementation across supported versions of Node.
+
+Signature:
+
+```c++
+ssize_t Nan::DecodeWrite(char *buf,
+                         size_t len,
+                         v8::Local<v8::Value> val,
+                         enum Nan::Encoding encoding = BINARY);
+```
diff --git a/input_devices/mag/node_modules/nan/doc/v8_internals.md b/input_devices/mag/node_modules/nan/doc/v8_internals.md
new file mode 100644
index 00000000..430c4353
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/v8_internals.md
@@ -0,0 +1,199 @@
+## V8 internals
+
+The hooks to access V8 internals—including GC and statistics—are different across the supported versions of V8, therefore NAN provides its own hooks that call the appropriate V8 methods.
+
+ - <a href="#api_nan_gc_callback"><b><code>NAN_GC_CALLBACK()</code></b></a>
+ - <a href="#api_nan_add_gc_epilogue_callback"><b><code>Nan::AddGCEpilogueCallback()</code></b></a>
+ - <a href="#api_nan_remove_gc_epilogue_callback"><b><code>Nan::RemoveGCEpilogueCallback()</code></b></a>
+ - <a href="#api_nan_add_gc_prologue_callback"><b><code>Nan::AddGCPrologueCallback()</code></b></a>
+ - <a href="#api_nan_remove_gc_prologue_callback"><b><code>Nan::RemoveGCPrologueCallback()</code></b></a>
+ - <a href="#api_nan_get_heap_statistics"><b><code>Nan::GetHeapStatistics()</code></b></a>
+ - <a href="#api_nan_set_counter_function"><b><code>Nan::SetCounterFunction()</code></b></a>
+ - <a href="#api_nan_set_create_histogram_function"><b><code>Nan::SetCreateHistogramFunction()</code></b></a>
+ - <a href="#api_nan_set_add_histogram_sample_function"><b><code>Nan::SetAddHistogramSampleFunction()</code></b></a>
+ - <a href="#api_nan_idle_notification"><b><code>Nan::IdleNotification()</code></b></a>
+ - <a href="#api_nan_low_memory_notification"><b><code>Nan::LowMemoryNotification()</code></b></a>
+ - <a href="#api_nan_context_disposed_notification"><b><code>Nan::ContextDisposedNotification()</code></b></a>
+ - <a href="#api_nan_get_internal_field_pointer"><b><code>Nan::GetInternalFieldPointer()</code></b></a>
+ - <a href="#api_nan_set_internal_field_pointer"><b><code>Nan::SetInternalFieldPointer()</code></b></a>
+ - <a href="#api_nan_adjust_external_memory"><b><code>Nan::AdjustExternalMemory()</code></b></a>
+
+
+<a name="api_nan_gc_callback"></a>
+### NAN_GC_CALLBACK(callbackname)
+
+Use `NAN_GC_CALLBACK` to declare your callbacks for `Nan::AddGCPrologueCallback()` and `Nan::AddGCEpilogueCallback()`. Your new method receives the arguments `v8::GCType type` and `v8::GCCallbackFlags flags`.
+
+```c++
+static Nan::Persistent<Function> callback;
+
+NAN_GC_CALLBACK(gcPrologueCallback) {
+  v8::Local<Value> argv[] = { Nan::New("prologue").ToLocalChecked() };
+  Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(callback), 1, argv);
+}
+
+NAN_METHOD(Hook) {
+  callback.Reset(To<Function>(args[0]).ToLocalChecked());
+  Nan::AddGCPrologueCallback(gcPrologueCallback);
+  info.GetReturnValue().Set(info.Holder());
+}
+```
+
+<a name="api_nan_add_gc_epilogue_callback"></a>
+### Nan::AddGCEpilogueCallback()
+
+Signature:
+
+```c++
+void Nan::AddGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback, v8::GCType gc_type_filter = v8::kGCTypeAll)
+```
+
+Calls V8's [`AddGCEpilogueCallback()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a90d1860babc76059c62514b422f56960).
+
+<a name="api_nan_remove_gc_epilogue_callback"></a>
+### Nan::RemoveGCEpilogueCallback()
+
+Signature:
+
+```c++
+void Nan::RemoveGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback)
+```
+
+Calls V8's [`RemoveGCEpilogueCallback()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a05c60859fd4b8e96bfcd451281ed6c7c).
+
+<a name="api_nan_add_gc_prologue_callback"></a>
+### Nan::AddGCPrologueCallback()
+
+Signature:
+
+```c++
+void Nan::AddGCPrologueCallback(v8::Isolate::GCPrologueCallback, v8::GCType gc_type_filter callback)
+```
+
+Calls V8's [`AddGCPrologueCallback()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#ab4b87b8f9f8e5bf95eba4009357e001f).
+
+<a name="api_nan_remove_gc_prologue_callback"></a>
+### Nan::RemoveGCPrologueCallback()
+
+Signature:
+
+```c++
+void Nan::RemoveGCPrologueCallback(v8::Isolate::GCPrologueCallback callback)
+```
+
+Calls V8's [`RemoveGCEpilogueCallback()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a9f6c51932811593f81ff30b949124186).
+
+<a name="api_nan_get_heap_statistics"></a>
+### Nan::GetHeapStatistics()
+
+Signature:
+
+```c++
+void Nan::GetHeapStatistics(v8::HeapStatistics *heap_statistics)
+```
+
+Calls V8's [`GetHeapStatistics()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a5593ac74687b713095c38987e5950b34).
+
+<a name="api_nan_set_counter_function"></a>
+### Nan::SetCounterFunction()
+
+Signature:
+
+```c++
+void Nan::SetCounterFunction(v8::CounterLookupCallback cb)
+```
+
+Calls V8's [`SetCounterFunction()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a045d7754e62fa0ec72ae6c259b29af94).
+
+<a name="api_nan_set_create_histogram_function"></a>
+### Nan::SetCreateHistogramFunction()
+
+Signature:
+
+```c++
+void Nan::SetCreateHistogramFunction(v8::CreateHistogramCallback cb) 
+```
+
+Calls V8's [`SetCreateHistogramFunction()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a542d67e85089cb3f92aadf032f99e732).
+
+<a name="api_nan_set_add_histogram_sample_function"></a>
+### Nan::SetAddHistogramSampleFunction()
+
+Signature:
+
+```c++
+void Nan::SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) 
+```
+
+Calls V8's [`SetAddHistogramSampleFunction()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#aeb420b690bc2c216882d6fdd00ddd3ea).
+
+<a name="api_nan_idle_notification"></a>
+### Nan::IdleNotification()
+
+Signature:
+
+```c++
+void Nan::IdleNotification(v8::HeapStatistics *heap_statistics)
+```
+
+Calls V8's [`IdleNotification()` or `IdleNotificationDeadline()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#ad6a2a02657f5425ad460060652a5a118) depending on V8 version.
+
+<a name="api_nan_low_memory_notification"></a>
+### Nan::LowMemoryNotification()
+
+Signature:
+
+```c++
+void Nan::LowMemoryNotification() 
+```
+
+Calls V8's [`LowMemoryNotification()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a24647f61d6b41f69668094bdcd6ea91f).
+
+<a name="api_nan_context_disposed_notification"></a>
+### Nan::ContextDisposedNotification()
+
+Signature:
+
+```c++
+void Nan::ContextDisposedNotification()
+```
+
+Calls V8's [`ContextDisposedNotification()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#ad7f5dc559866343fe6cd8db1f134d48b).
+
+<a name="api_nan_get_internal_field_pointer"></a>
+### Nan::GetInternalFieldPointer()
+
+Gets a pointer to the internal field with at `index` from a V8 `Object` handle.
+
+Signature:
+
+```c++
+void* Nan::GetInternalFieldPointer(v8::Local<v8::Object> object, int index) 
+```
+
+Calls the Object's [`GetAlignedPointerFromInternalField()` or `GetPointerFromInternalField()`](https://v8docs.nodesource.com/io.js-3.3/db/d85/classv8_1_1_object.html#ab3c57184263cf29963ef0017bec82281) depending on the version of V8.
+
+<a name="api_nan_set_internal_field_pointer"></a>
+### Nan::SetInternalFieldPointer()
+
+Sets the value of the internal field at `index` on a V8 `Object` handle.
+
+Signature:
+
+```c++
+void Nan::SetInternalFieldPointer(v8::Local<v8::Object> object, int index, void* value)
+```
+
+Calls the Object's [`SetAlignedPointerInInternalField()` or `SetPointerInInternalField()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#ad7f5dc559866343fe6cd8db1f134d48b) depending on the version of V8.
+
+<a name="api_nan_adjust_external_memory"></a>
+### Nan::AdjustExternalMemory()
+
+Signature:
+
+```c++
+int Nan::AdjustExternalMemory(int bytesChange)
+```
+
+Calls V8's [`AdjustAmountOfExternalAllocatedMemory()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#ae1a59cac60409d3922582c4af675473e).
+
diff --git a/input_devices/mag/node_modules/nan/doc/v8_misc.md b/input_devices/mag/node_modules/nan/doc/v8_misc.md
new file mode 100644
index 00000000..8aa6653f
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/doc/v8_misc.md
@@ -0,0 +1,85 @@
+## Miscellaneous V8 Helpers
+
+ - <a href="#api_nan_utf8_string"><b><code>Nan::Utf8String</code></b></a>
+ - <a href="#api_nan_get_current_context"><b><code>Nan::GetCurrentContext()</code></b></a>
+ - <a href="#api_nan_set_isolate_data"><b><code>Nan::SetIsolateData()</code></b></a>
+ - <a href="#api_nan_get_isolate_data"><b><code>Nan::GetIsolateData()</code></b></a>
+ - <a href="#api_nan_typedarray_contents"><b><code>Nan::TypedArrayContents</code></b></a>
+
+
+<a name="api_nan_utf8_string"></a>
+### Nan::Utf8String
+
+Converts an object to a UTF-8-encoded character array. If conversion to a string fails (e.g. due to an exception in the toString() method of the object) then the length() method returns 0 and the * operator returns NULL. The underlying memory used for this object is managed by the object.
+
+An implementation of [`v8::String::Utf8Value`](https://v8docs.nodesource.com/io.js-3.3/d4/d1b/classv8_1_1_string_1_1_utf8_value.html) that is consistent across all supported versions of V8.
+
+Definition:
+
+```c++
+class Nan::Utf8String {
+ public:
+  Nan::Utf8String(v8::Local<v8::Value> from);
+
+  int length() const;
+
+  char* operator*();
+  const char* operator*() const;
+};
+```
+
+<a name="api_nan_get_current_context"></a>
+### Nan::GetCurrentContext()
+
+A call to [`v8::Isolate::GetCurrent()->GetCurrentContext()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a81c7a1ed7001ae2a65e89107f75fd053) that works across all supported versions of V8.
+
+Signature:
+
+```c++
+v8::Local<v8::Context> Nan::GetCurrentContext()
+```
+
+<a name="api_nan_set_isolate_data"></a>
+### Nan::SetIsolateData()
+
+A helper to provide a consistent API to [`v8::Isolate#SetData()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#a7acadfe7965997e9c386a05f098fbe36).
+
+Signature:
+
+```c++
+void Nan::SetIsolateData(v8::Isolate *isolate, T *data)
+```
+
+
+<a name="api_nan_get_isolate_data"></a>
+### Nan::GetIsolateData()
+
+A helper to provide a consistent API to [`v8::Isolate#GetData()`](https://v8docs.nodesource.com/io.js-3.3/d5/dda/classv8_1_1_isolate.html#aabd223436bc1100a787dadaa024c6257).
+
+Signature:
+
+```c++
+T *Nan::GetIsolateData(v8::Isolate *isolate)
+```
+
+<a name="api_nan_typedarray_contents"></a>
+### Nan::TypedArrayContents<T>
+
+A helper class for accessing the contents of an ArrayBufferView (aka a typedarray) from C++.  If the input array is not a valid typedarray, then the data pointer of TypedArrayContents will default to `NULL` and the length will be 0.  If the data pointer is not compatible with the alignment requirements of type, an assertion error will fail.
+
+Note that you must store a reference to the `array` object while you are accessing its contents.
+
+Definition:
+
+```c++
+template<typename T>
+class Nan::TypedArrayContents {
+ public:
+  TypedArrayContents(v8::Local<Value> array);
+
+  size_t length() const;
+
+  T* const operator*();
+  const T* const operator*() const;
+};
+```
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/include_dirs.js b/input_devices/mag/node_modules/nan/include_dirs.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/nan/include_dirs.js
rename to input_devices/mag/node_modules/nan/include_dirs.js
diff --git a/input_devices/mag/node_modules/nan/nan-2.11.1.tgz b/input_devices/mag/node_modules/nan/nan-2.11.1.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..978f4b2f261b49400aba6046d45f328b48a26e8a
GIT binary patch
literal 74561
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

literal 0
HcmV?d00001

diff --git a/input_devices/mag/node_modules/nan/nan.h b/input_devices/mag/node_modules/nan/nan.h
new file mode 100644
index 00000000..142baa82
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan.h
@@ -0,0 +1,2802 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors:
+ *   - Rod Vagg <https://github.com/rvagg>
+ *   - Benjamin Byholm <https://github.com/kkoopa>
+ *   - Trevor Norris <https://github.com/trevnorris>
+ *   - Nathan Rajlich <https://github.com/TooTallNate>
+ *   - Brett Lawson <https://github.com/brett19>
+ *   - Ben Noordhuis <https://github.com/bnoordhuis>
+ *   - David Siegel <https://github.com/agnat>
+ *   - Michael Ira Krufky <https://github.com/mkrufky>
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ *
+ * Version 2.11.1: current Node 10.11.0, Node 12: 0.12.18, Node 10: 0.10.48, iojs: 3.3.1
+ *
+ * See https://github.com/nodejs/nan for the latest update to this file
+ **********************************************************************************/
+
+#ifndef NAN_H_
+#define NAN_H_
+
+#include <node_version.h>
+
+#define NODE_0_10_MODULE_VERSION 11
+#define NODE_0_12_MODULE_VERSION 14
+#define ATOM_0_21_MODULE_VERSION 41
+#define IOJS_1_0_MODULE_VERSION  42
+#define IOJS_1_1_MODULE_VERSION  43
+#define IOJS_2_0_MODULE_VERSION  44
+#define IOJS_3_0_MODULE_VERSION  45
+#define NODE_4_0_MODULE_VERSION  46
+#define NODE_5_0_MODULE_VERSION  47
+#define NODE_6_0_MODULE_VERSION  48
+#define NODE_7_0_MODULE_VERSION  51
+#define NODE_8_0_MODULE_VERSION  57
+#define NODE_9_0_MODULE_VERSION  59
+#define NODE_10_0_MODULE_VERSION 64
+
+#ifdef _MSC_VER
+# define NAN_HAS_CPLUSPLUS_11 (_MSC_VER >= 1800)
+#else
+# define NAN_HAS_CPLUSPLUS_11 (__cplusplus >= 201103L)
+#endif
+
+#if NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION && !NAN_HAS_CPLUSPLUS_11
+# error This version of node/NAN/v8 requires a C++11 compiler
+#endif
+
+#include <uv.h>
+#include <node.h>
+#include <node_buffer.h>
+#include <node_object_wrap.h>
+#include <algorithm>
+#include <cstring>
+#include <climits>
+#include <cstdlib>
+#include <utility>
+#if defined(_MSC_VER)
+# pragma warning( push )
+# pragma warning( disable : 4530 )
+# include <queue>
+# include <string>
+# include <vector>
+# pragma warning( pop )
+#else
+# include <queue>
+# include <string>
+# include <vector>
+#endif
+
+// uv helpers
+#ifdef UV_VERSION_MAJOR
+# ifndef UV_VERSION_PATCH
+#  define UV_VERSION_PATCH 0
+# endif
+# define NAUV_UVVERSION ((UV_VERSION_MAJOR << 16) | \
+                         (UV_VERSION_MINOR <<  8) | \
+                         (UV_VERSION_PATCH))
+#else
+# define NAUV_UVVERSION 0x000b00
+#endif
+
+#if NAUV_UVVERSION < 0x000b0b
+# ifdef WIN32
+#  include <windows.h>
+# else
+#  include <pthread.h>
+# endif
+#endif
+
+namespace Nan {
+
+#define NAN_CONCAT(a, b) NAN_CONCAT_HELPER(a, b)
+#define NAN_CONCAT_HELPER(a, b) a##b
+
+#define NAN_INLINE inline  // TODO(bnoordhuis) Remove in v3.0.0.
+
+#if defined(__GNUC__) && \
+    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
+# define NAN_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER) && \
+    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
+# define NAN_DEPRECATED __declspec(deprecated)
+#else
+# define NAN_DEPRECATED
+#endif
+
+#if NAN_HAS_CPLUSPLUS_11
+# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&) = delete;
+# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&) = delete;
+# define NAN_DISALLOW_MOVE(CLASS)                                              \
+    CLASS(CLASS&&) = delete;  /* NOLINT(build/c++11) */                        \
+    void operator=(CLASS&&) = delete;
+#else
+# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&);
+# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&);
+# define NAN_DISALLOW_MOVE(CLASS)
+#endif
+
+#define NAN_DISALLOW_ASSIGN_COPY(CLASS)                                        \
+    NAN_DISALLOW_ASSIGN(CLASS)                                                 \
+    NAN_DISALLOW_COPY(CLASS)
+
+#define NAN_DISALLOW_ASSIGN_MOVE(CLASS)                                        \
+    NAN_DISALLOW_ASSIGN(CLASS)                                                 \
+    NAN_DISALLOW_MOVE(CLASS)
+
+#define NAN_DISALLOW_COPY_MOVE(CLASS)                                          \
+    NAN_DISALLOW_COPY(CLASS)                                                   \
+    NAN_DISALLOW_MOVE(CLASS)
+
+#define NAN_DISALLOW_ASSIGN_COPY_MOVE(CLASS)                                   \
+    NAN_DISALLOW_ASSIGN(CLASS)                                                 \
+    NAN_DISALLOW_COPY(CLASS)                                                   \
+    NAN_DISALLOW_MOVE(CLASS)
+
+#define TYPE_CHECK(T, S)                                                       \
+    while (false) {                                                            \
+      *(static_cast<T *volatile *>(0)) = static_cast<S*>(0);                   \
+    }
+
+//=== RegistrationFunction =====================================================
+
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+  typedef v8::Handle<v8::Object> ADDON_REGISTER_FUNCTION_ARGS_TYPE;
+#else
+  typedef v8::Local<v8::Object> ADDON_REGISTER_FUNCTION_ARGS_TYPE;
+#endif
+
+#define NAN_MODULE_INIT(name)                                                  \
+    void name(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target)
+
+#if NODE_MAJOR_VERSION >= 10 || \
+    NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3
+#define NAN_MODULE_WORKER_ENABLED(module_name, registration)                   \
+    extern "C" NODE_MODULE_EXPORT void                                         \
+      NAN_CONCAT(node_register_module_v, NODE_MODULE_VERSION)(                 \
+        v8::Local<v8::Object> exports, v8::Local<v8::Value> module,            \
+        v8::Local<v8::Context> context)                                        \
+    {                                                                          \
+        registration(exports);                                                 \
+    }
+#else
+#define NAN_MODULE_WORKER_ENABLED(module_name, registration)                   \
+    NODE_MODULE(module_name, registration)
+#endif
+
+//=== CallbackInfo =============================================================
+
+#include "nan_callbacks.h"  // NOLINT(build/include)
+
+//==============================================================================
+
+#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION)
+typedef v8::Script             UnboundScript;
+typedef v8::Script             BoundScript;
+#else
+typedef v8::UnboundScript      UnboundScript;
+typedef v8::Script             BoundScript;
+#endif
+
+#if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION)
+typedef v8::String::ExternalAsciiStringResource
+    ExternalOneByteStringResource;
+#else
+typedef v8::String::ExternalOneByteStringResource
+    ExternalOneByteStringResource;
+#endif
+
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+template<typename T>
+class NonCopyablePersistentTraits :
+    public v8::NonCopyablePersistentTraits<T> {};
+template<typename T>
+class CopyablePersistentTraits :
+    public v8::CopyablePersistentTraits<T> {};
+
+template<typename T>
+class PersistentBase :
+    public v8::PersistentBase<T> {};
+
+template<typename T, typename M = v8::NonCopyablePersistentTraits<T> >
+class Persistent;
+#else
+template<typename T> class NonCopyablePersistentTraits;
+template<typename T> class PersistentBase;
+template<typename T, typename P> class WeakCallbackData;
+template<typename T, typename M = NonCopyablePersistentTraits<T> >
+class Persistent;
+#endif  // NODE_MODULE_VERSION
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+# include "nan_maybe_43_inl.h"  // NOLINT(build/include)
+#else
+# include "nan_maybe_pre_43_inl.h"  // NOLINT(build/include)
+#endif
+
+#include "nan_converters.h"  // NOLINT(build/include)
+#include "nan_new.h"  // NOLINT(build/include)
+
+#if NAUV_UVVERSION < 0x000b17
+#define NAUV_WORK_CB(func) \
+    void func(uv_async_t *async, int)
+#else
+#define NAUV_WORK_CB(func) \
+    void func(uv_async_t *async)
+#endif
+
+#if NAUV_UVVERSION >= 0x000b0b
+
+typedef uv_key_t nauv_key_t;
+
+inline int nauv_key_create(nauv_key_t *key) {
+  return uv_key_create(key);
+}
+
+inline void nauv_key_delete(nauv_key_t *key) {
+  uv_key_delete(key);
+}
+
+inline void* nauv_key_get(nauv_key_t *key) {
+  return uv_key_get(key);
+}
+
+inline void nauv_key_set(nauv_key_t *key, void *value) {
+  uv_key_set(key, value);
+}
+
+#else
+
+/* Implement thread local storage for older versions of libuv.
+ * This is essentially a backport of libuv commit 5d2434bf
+ * written by Ben Noordhuis, adjusted for names and inline.
+ */
+
+#ifndef WIN32
+
+typedef pthread_key_t nauv_key_t;
+
+inline int nauv_key_create(nauv_key_t* key) {
+  return -pthread_key_create(key, NULL);
+}
+
+inline void nauv_key_delete(nauv_key_t* key) {
+  if (pthread_key_delete(*key))
+    abort();
+}
+
+inline void* nauv_key_get(nauv_key_t* key) {
+  return pthread_getspecific(*key);
+}
+
+inline void nauv_key_set(nauv_key_t* key, void* value) {
+  if (pthread_setspecific(*key, value))
+    abort();
+}
+
+#else
+
+typedef struct {
+  DWORD tls_index;
+} nauv_key_t;
+
+inline int nauv_key_create(nauv_key_t* key) {
+  key->tls_index = TlsAlloc();
+  if (key->tls_index == TLS_OUT_OF_INDEXES)
+    return UV_ENOMEM;
+  return 0;
+}
+
+inline void nauv_key_delete(nauv_key_t* key) {
+  if (TlsFree(key->tls_index) == FALSE)
+    abort();
+  key->tls_index = TLS_OUT_OF_INDEXES;
+}
+
+inline void* nauv_key_get(nauv_key_t* key) {
+  void* value = TlsGetValue(key->tls_index);
+  if (value == NULL)
+    if (GetLastError() != ERROR_SUCCESS)
+      abort();
+  return value;
+}
+
+inline void nauv_key_set(nauv_key_t* key, void* value) {
+  if (TlsSetValue(key->tls_index, value) == FALSE)
+    abort();
+}
+
+#endif
+#endif
+
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+template<typename T>
+v8::Local<T> New(v8::Handle<T>);
+#endif
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+  typedef v8::WeakCallbackType WeakCallbackType;
+#else
+struct WeakCallbackType {
+  enum E {kParameter, kInternalFields};
+  E type;
+  WeakCallbackType(E other) : type(other) {}  // NOLINT(runtime/explicit)
+  inline bool operator==(E other) { return other == this->type; }
+  inline bool operator!=(E other) { return !operator==(other); }
+};
+#endif
+
+template<typename P> class WeakCallbackInfo;
+
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+# include "nan_persistent_12_inl.h"  // NOLINT(build/include)
+#else
+# include "nan_persistent_pre_12_inl.h"  // NOLINT(build/include)
+#endif
+
+namespace imp {
+  static const size_t kMaxLength = 0x3fffffff;
+  // v8::String::REPLACE_INVALID_UTF8 was introduced
+  // in node.js v0.10.29 and v0.8.27.
+#if NODE_MAJOR_VERSION > 0 || \
+    NODE_MINOR_VERSION > 10 || \
+    NODE_MINOR_VERSION == 10 && NODE_PATCH_VERSION >= 29 || \
+    NODE_MINOR_VERSION == 8 && NODE_PATCH_VERSION >= 27
+  static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8;
+#else
+  static const unsigned kReplaceInvalidUtf8 = 0;
+#endif
+}  // end of namespace imp
+
+//=== HandleScope ==============================================================
+
+class HandleScope {
+  v8::HandleScope scope;
+
+ public:
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+  inline HandleScope() : scope(v8::Isolate::GetCurrent()) {}
+  inline static int NumberOfHandles() {
+    return v8::HandleScope::NumberOfHandles(v8::Isolate::GetCurrent());
+  }
+#else
+  inline HandleScope() : scope() {}
+  inline static int NumberOfHandles() {
+    return v8::HandleScope::NumberOfHandles();
+  }
+#endif
+
+ private:
+  // Make it hard to create heap-allocated or illegal handle scopes by
+  // disallowing certain operations.
+  HandleScope(const HandleScope &);
+  void operator=(const HandleScope &);
+  void *operator new(size_t size);
+  void operator delete(void *, size_t) {
+    abort();
+  }
+};
+
+class EscapableHandleScope {
+ public:
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+  inline EscapableHandleScope() : scope(v8::Isolate::GetCurrent()) {}
+
+  inline static int NumberOfHandles() {
+    return v8::EscapableHandleScope::NumberOfHandles(v8::Isolate::GetCurrent());
+  }
+
+  template<typename T>
+  inline v8::Local<T> Escape(v8::Local<T> value) {
+    return scope.Escape(value);
+  }
+
+ private:
+  v8::EscapableHandleScope scope;
+#else
+  inline EscapableHandleScope() : scope() {}
+
+  inline static int NumberOfHandles() {
+    return v8::HandleScope::NumberOfHandles();
+  }
+
+  template<typename T>
+  inline v8::Local<T> Escape(v8::Local<T> value) {
+    return scope.Close(value);
+  }
+
+ private:
+  v8::HandleScope scope;
+#endif
+
+ private:
+  // Make it hard to create heap-allocated or illegal handle scopes by
+  // disallowing certain operations.
+  EscapableHandleScope(const EscapableHandleScope &);
+  void operator=(const EscapableHandleScope &);
+  void *operator new(size_t size);
+  void operator delete(void *, size_t) {
+    abort();
+  }
+};
+
+//=== TryCatch =================================================================
+
+class TryCatch {
+  v8::TryCatch try_catch_;
+  friend void FatalException(const TryCatch&);
+
+ public:
+#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+  TryCatch() : try_catch_(v8::Isolate::GetCurrent()) {}
+#endif
+
+  inline bool HasCaught() const { return try_catch_.HasCaught(); }
+
+  inline bool CanContinue() const { return try_catch_.CanContinue(); }
+
+  inline v8::Local<v8::Value> ReThrow() {
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    return New(try_catch_.ReThrow());
+#else
+    return try_catch_.ReThrow();
+#endif
+  }
+
+  inline v8::Local<v8::Value> Exception() const {
+    return try_catch_.Exception();
+  }
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+  inline v8::MaybeLocal<v8::Value> StackTrace() const {
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+    return scope.Escape(try_catch_.StackTrace(isolate->GetCurrentContext())
+                            .FromMaybe(v8::Local<v8::Value>()));
+  }
+#else
+  inline MaybeLocal<v8::Value> StackTrace() const {
+    return try_catch_.StackTrace();
+  }
+#endif
+
+  inline v8::Local<v8::Message> Message() const {
+    return try_catch_.Message();
+  }
+
+  inline void Reset() { try_catch_.Reset(); }
+
+  inline void SetVerbose(bool value) { try_catch_.SetVerbose(value); }
+
+  inline void SetCaptureMessage(bool value) {
+    try_catch_.SetCaptureMessage(value);
+  }
+};
+
+v8::Local<v8::Value> MakeCallback(v8::Local<v8::Object> target,
+                                  v8::Local<v8::Function> func,
+                                  int argc,
+                                  v8::Local<v8::Value>* argv);
+v8::Local<v8::Value> MakeCallback(v8::Local<v8::Object> target,
+                                  v8::Local<v8::String> symbol,
+                                  int argc,
+                                  v8::Local<v8::Value>* argv);
+v8::Local<v8::Value> MakeCallback(v8::Local<v8::Object> target,
+                                  const char* method,
+                                  int argc,
+                                  v8::Local<v8::Value>* argv);
+
+// === AsyncResource ===========================================================
+
+class AsyncResource {
+ public:
+  AsyncResource(
+      v8::Local<v8::String> name
+    , v8::Local<v8::Object> resource = New<v8::Object>()) {
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    v8::Isolate* isolate = v8::Isolate::GetCurrent();
+
+    if (resource.IsEmpty()) {
+      resource = New<v8::Object>();
+    }
+
+    context = node::EmitAsyncInit(isolate, resource, name);
+#endif
+  }
+
+  AsyncResource(
+      const char* name
+    , v8::Local<v8::Object> resource = New<v8::Object>()) {
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    v8::Isolate* isolate = v8::Isolate::GetCurrent();
+
+    if (resource.IsEmpty()) {
+      resource = New<v8::Object>();
+    }
+
+    v8::Local<v8::String> name_string =
+        New<v8::String>(name).ToLocalChecked();
+    context = node::EmitAsyncInit(isolate, resource, name_string);
+#endif
+  }
+
+  ~AsyncResource() {
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    v8::Isolate* isolate = v8::Isolate::GetCurrent();
+    node::EmitAsyncDestroy(isolate, context);
+#endif
+  }
+
+  inline MaybeLocal<v8::Value> runInAsyncScope(
+      v8::Local<v8::Object> target
+    , v8::Local<v8::Function> func
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION
+    return MakeCallback(target, func, argc, argv);
+#else
+    return node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, func, argc, argv, context);
+#endif
+  }
+
+  inline MaybeLocal<v8::Value> runInAsyncScope(
+      v8::Local<v8::Object> target
+    , v8::Local<v8::String> symbol
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION
+    return MakeCallback(target, symbol, argc, argv);
+#else
+    return node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, symbol, argc, argv, context);
+#endif
+  }
+
+  inline MaybeLocal<v8::Value> runInAsyncScope(
+      v8::Local<v8::Object> target
+    , const char* method
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION
+    return MakeCallback(target, method, argc, argv);
+#else
+    return node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, method, argc, argv, context);
+#endif
+  }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncResource)
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+  node::async_context context;
+#endif
+};
+
+inline uv_loop_t* GetCurrentEventLoop() {
+#if NODE_MAJOR_VERSION >= 10 || \
+  NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3 || \
+  NODE_MAJOR_VERSION == 8 && NODE_MINOR_VERSION >= 10
+    return node::GetCurrentEventLoop(v8::Isolate::GetCurrent());
+#else
+    return uv_default_loop();
+#endif
+}
+
+//============ =================================================================
+
+/* node 0.12  */
+#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
+  inline
+  void SetCounterFunction(v8::CounterLookupCallback cb) {
+    v8::Isolate::GetCurrent()->SetCounterFunction(cb);
+  }
+
+  inline
+  void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
+    v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
+  }
+
+  inline
+  void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
+    v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb);
+  }
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+  inline bool IdleNotification(int idle_time_in_ms) {
+    return v8::Isolate::GetCurrent()->IdleNotificationDeadline(
+        idle_time_in_ms * 0.001);
+  }
+# else
+  inline bool IdleNotification(int idle_time_in_ms) {
+    return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
+  }
+#endif
+
+  inline void LowMemoryNotification() {
+    v8::Isolate::GetCurrent()->LowMemoryNotification();
+  }
+
+  inline void ContextDisposedNotification() {
+    v8::Isolate::GetCurrent()->ContextDisposedNotification();
+  }
+#else
+  inline
+  void SetCounterFunction(v8::CounterLookupCallback cb) {
+    v8::V8::SetCounterFunction(cb);
+  }
+
+  inline
+  void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
+    v8::V8::SetCreateHistogramFunction(cb);
+  }
+
+  inline
+  void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
+    v8::V8::SetAddHistogramSampleFunction(cb);
+  }
+
+  inline bool IdleNotification(int idle_time_in_ms) {
+    return v8::V8::IdleNotification(idle_time_in_ms);
+  }
+
+  inline void LowMemoryNotification() {
+    v8::V8::LowMemoryNotification();
+  }
+
+  inline void ContextDisposedNotification() {
+    v8::V8::ContextDisposedNotification();
+  }
+#endif
+
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)  // Node 0.12
+  inline v8::Local<v8::Primitive> Undefined() {
+# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::Undefined(v8::Isolate::GetCurrent())));
+# else
+    return v8::Undefined(v8::Isolate::GetCurrent());
+# endif
+  }
+
+  inline v8::Local<v8::Primitive> Null() {
+# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::Null(v8::Isolate::GetCurrent())));
+# else
+    return v8::Null(v8::Isolate::GetCurrent());
+# endif
+  }
+
+  inline v8::Local<v8::Boolean> True() {
+# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::True(v8::Isolate::GetCurrent())));
+# else
+    return v8::True(v8::Isolate::GetCurrent());
+# endif
+  }
+
+  inline v8::Local<v8::Boolean> False() {
+# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::False(v8::Isolate::GetCurrent())));
+# else
+    return v8::False(v8::Isolate::GetCurrent());
+# endif
+  }
+
+  inline v8::Local<v8::String> EmptyString() {
+    return v8::String::Empty(v8::Isolate::GetCurrent());
+  }
+
+  inline int AdjustExternalMemory(int bc) {
+    return static_cast<int>(
+        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc));
+  }
+
+  inline void SetTemplate(
+      v8::Local<v8::Template> templ
+    , const char *name
+    , v8::Local<v8::Data> value) {
+    templ->Set(v8::Isolate::GetCurrent(), name, value);
+  }
+
+  inline void SetTemplate(
+      v8::Local<v8::Template> templ
+    , v8::Local<v8::String> name
+    , v8::Local<v8::Data> value
+    , v8::PropertyAttribute attributes) {
+    templ->Set(name, value, attributes);
+  }
+
+  inline v8::Local<v8::Context> GetCurrentContext() {
+    return v8::Isolate::GetCurrent()->GetCurrentContext();
+  }
+
+  inline void* GetInternalFieldPointer(
+      v8::Local<v8::Object> object
+    , int index) {
+    return object->GetAlignedPointerFromInternalField(index);
+  }
+
+  inline void SetInternalFieldPointer(
+      v8::Local<v8::Object> object
+    , int index
+    , void* value) {
+    object->SetAlignedPointerInInternalField(index, value);
+  }
+
+# define NAN_GC_CALLBACK(name)                                                 \
+    void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags)
+
+#if NODE_MODULE_VERSION <= NODE_4_0_MODULE_VERSION
+  typedef v8::Isolate::GCEpilogueCallback GCEpilogueCallback;
+  typedef v8::Isolate::GCPrologueCallback GCPrologueCallback;
+#else
+  typedef v8::Isolate::GCCallback GCEpilogueCallback;
+  typedef v8::Isolate::GCCallback GCPrologueCallback;
+#endif
+
+  inline void AddGCEpilogueCallback(
+      GCEpilogueCallback callback
+    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
+    v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter);
+  }
+
+  inline void RemoveGCEpilogueCallback(
+      GCEpilogueCallback callback) {
+    v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback);
+  }
+
+  inline void AddGCPrologueCallback(
+      GCPrologueCallback callback
+    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
+    v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter);
+  }
+
+  inline void RemoveGCPrologueCallback(
+      GCPrologueCallback callback) {
+    v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback);
+  }
+
+  inline void GetHeapStatistics(
+      v8::HeapStatistics *heap_statistics) {
+    v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics);
+  }
+
+# define X(NAME)                                                               \
+    inline v8::Local<v8::Value> NAME(const char *msg) {                        \
+      EscapableHandleScope scope;                                              \
+      return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked()));     \
+    }                                                                          \
+                                                                               \
+    inline                                                                     \
+    v8::Local<v8::Value> NAME(v8::Local<v8::String> msg) {                     \
+      return v8::Exception::NAME(msg);                                         \
+    }                                                                          \
+                                                                               \
+    inline void Throw ## NAME(const char *msg) {                               \
+      HandleScope scope;                                                       \
+      v8::Isolate::GetCurrent()->ThrowException(                               \
+          v8::Exception::NAME(New(msg).ToLocalChecked()));                     \
+    }                                                                          \
+                                                                               \
+    inline void Throw ## NAME(v8::Local<v8::String> msg) {                     \
+      HandleScope scope;                                                       \
+      v8::Isolate::GetCurrent()->ThrowException(                               \
+          v8::Exception::NAME(msg));                                           \
+    }
+
+  X(Error)
+  X(RangeError)
+  X(ReferenceError)
+  X(SyntaxError)
+  X(TypeError)
+
+# undef X
+
+  inline void ThrowError(v8::Local<v8::Value> error) {
+    v8::Isolate::GetCurrent()->ThrowException(error);
+  }
+
+  inline MaybeLocal<v8::Object> NewBuffer(
+      char *data
+    , size_t length
+#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
+    , node::Buffer::FreeCallback callback
+#else
+    , node::smalloc::FreeCallback callback
+#endif
+    , void *hint
+  ) {
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    assert(length <= imp::kMaxLength && "too large buffer");
+#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
+    return node::Buffer::New(
+        v8::Isolate::GetCurrent(), data, length, callback, hint);
+#else
+    return node::Buffer::New(v8::Isolate::GetCurrent(), data, length, callback,
+                             hint);
+#endif
+  }
+
+  inline MaybeLocal<v8::Object> CopyBuffer(
+      const char *data
+    , uint32_t size
+  ) {
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    assert(size <= imp::kMaxLength && "too large buffer");
+#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
+    return node::Buffer::Copy(
+        v8::Isolate::GetCurrent(), data, size);
+#else
+    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
+#endif
+  }
+
+  inline MaybeLocal<v8::Object> NewBuffer(uint32_t size) {
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    assert(size <= imp::kMaxLength && "too large buffer");
+#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
+    return node::Buffer::New(
+        v8::Isolate::GetCurrent(), size);
+#else
+    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
+#endif
+  }
+
+  inline MaybeLocal<v8::Object> NewBuffer(
+      char* data
+    , uint32_t size
+  ) {
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    assert(size <= imp::kMaxLength && "too large buffer");
+#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION
+    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
+#else
+    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
+#endif
+  }
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+  inline MaybeLocal<v8::String>
+  NewOneByteString(const uint8_t * value, int length = -1) {
+    return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
+          v8::NewStringType::kNormal, length);
+  }
+
+  inline MaybeLocal<BoundScript> CompileScript(
+      v8::Local<v8::String> s
+    , const v8::ScriptOrigin& origin
+  ) {
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+    v8::ScriptCompiler::Source source(s, origin);
+    return scope.Escape(
+        v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source)
+            .FromMaybe(v8::Local<BoundScript>()));
+  }
+
+  inline MaybeLocal<BoundScript> CompileScript(
+      v8::Local<v8::String> s
+  ) {
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+    v8::ScriptCompiler::Source source(s);
+    return scope.Escape(
+        v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source)
+            .FromMaybe(v8::Local<BoundScript>()));
+  }
+
+  inline MaybeLocal<v8::Value> RunScript(
+      v8::Local<UnboundScript> script
+  ) {
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+    return scope.Escape(script->BindToCurrentContext()
+                            ->Run(isolate->GetCurrentContext())
+                            .FromMaybe(v8::Local<v8::Value>()));
+  }
+
+  inline MaybeLocal<v8::Value> RunScript(
+      v8::Local<BoundScript> script
+  ) {
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+    return scope.Escape(script->Run(isolate->GetCurrentContext())
+                            .FromMaybe(v8::Local<v8::Value>()));
+  }
+#else
+  inline MaybeLocal<v8::String>
+  NewOneByteString(const uint8_t * value, int length = -1) {
+    return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
+                                      v8::String::kNormalString, length);
+  }
+
+  inline MaybeLocal<BoundScript> CompileScript(
+      v8::Local<v8::String> s
+    , const v8::ScriptOrigin& origin
+  ) {
+    v8::ScriptCompiler::Source source(s, origin);
+    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
+  }
+
+  inline MaybeLocal<BoundScript> CompileScript(
+      v8::Local<v8::String> s
+  ) {
+    v8::ScriptCompiler::Source source(s);
+    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
+  }
+
+  inline MaybeLocal<v8::Value> RunScript(
+      v8::Local<UnboundScript> script
+  ) {
+    EscapableHandleScope scope;
+    return scope.Escape(script->BindToCurrentContext()->Run());
+  }
+
+  inline MaybeLocal<v8::Value> RunScript(
+      v8::Local<BoundScript> script
+  ) {
+    return script->Run();
+  }
+#endif
+
+  NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
+      v8::Local<v8::Object> target
+    , v8::Local<v8::Function> func
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    return scope.Escape(New(node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, func, argc, argv)));
+#else
+# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    AsyncResource res("nan:makeCallback");
+    return res.runInAsyncScope(target, func, argc, argv)
+        .FromMaybe(v8::Local<v8::Value>());
+# else
+    return node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, func, argc, argv);
+# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+#endif  // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+  }
+
+  NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
+      v8::Local<v8::Object> target
+    , v8::Local<v8::String> symbol
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    return scope.Escape(New(node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, symbol, argc, argv)));
+#else
+# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    AsyncResource res("nan:makeCallback");
+    return res.runInAsyncScope(target, symbol, argc, argv)
+        .FromMaybe(v8::Local<v8::Value>());
+# else
+    return node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, symbol, argc, argv);
+# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+#endif  // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+  }
+
+  NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
+      v8::Local<v8::Object> target
+    , const char* method
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    return scope.Escape(New(node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, method, argc, argv)));
+#else
+# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    AsyncResource res("nan:makeCallback");
+    return res.runInAsyncScope(target, method, argc, argv)
+        .FromMaybe(v8::Local<v8::Value>());
+# else
+    return node::MakeCallback(
+        v8::Isolate::GetCurrent(), target, method, argc, argv);
+# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+#endif  // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+  }
+
+  inline void FatalException(const TryCatch& try_catch) {
+    node::FatalException(v8::Isolate::GetCurrent(), try_catch.try_catch_);
+  }
+
+  inline v8::Local<v8::Value> ErrnoException(
+          int errorno
+       ,  const char* syscall = NULL
+       ,  const char* message = NULL
+       ,  const char* path = NULL) {
+    return node::ErrnoException(v8::Isolate::GetCurrent(), errorno, syscall,
+            message, path);
+  }
+
+  NAN_DEPRECATED inline v8::Local<v8::Value> NanErrnoException(
+          int errorno
+       ,  const char* syscall = NULL
+       ,  const char* message = NULL
+       ,  const char* path = NULL) {
+    return ErrnoException(errorno, syscall, message, path);
+  }
+
+  template<typename T>
+  inline void SetIsolateData(
+      v8::Isolate *isolate
+    , T *data
+  ) {
+      isolate->SetData(0, data);
+  }
+
+  template<typename T>
+  inline T *GetIsolateData(
+      v8::Isolate *isolate
+  ) {
+      return static_cast<T*>(isolate->GetData(0));
+  }
+
+class Utf8String {
+ public:
+  inline explicit Utf8String(v8::Local<v8::Value> from) :
+      length_(0), str_(str_st_) {
+    HandleScope scope;
+    if (!from.IsEmpty()) {
+#if V8_MAJOR_VERSION >= 7
+      v8::Local<v8::String> string = from->ToString(v8::Isolate::GetCurrent());
+#else
+      v8::Local<v8::String> string = from->ToString();
+#endif
+      if (!string.IsEmpty()) {
+        size_t len = 3 * string->Length() + 1;
+        assert(len <= INT_MAX);
+        if (len > sizeof (str_st_)) {
+          str_ = static_cast<char*>(malloc(len));
+          assert(str_ != 0);
+        }
+        const int flags =
+            v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8;
+#if V8_MAJOR_VERSION >= 7
+        length_ = string->WriteUtf8(v8::Isolate::GetCurrent(), str_, static_cast<int>(len), 0, flags);
+#else
+        length_ = string->WriteUtf8(str_, static_cast<int>(len), 0, flags);
+#endif
+        str_[length_] = '\0';
+      }
+    }
+  }
+
+  inline int length() const {
+    return length_;
+  }
+
+  inline char* operator*() { return str_; }
+  inline const char* operator*() const { return str_; }
+
+  inline ~Utf8String() {
+    if (str_ != str_st_) {
+      free(str_);
+    }
+  }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String)
+
+  int length_;
+  char *str_;
+  char str_st_[1024];
+};
+
+#else  // Node 0.8 and 0.10
+  inline v8::Local<v8::Primitive> Undefined() {
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::Undefined()));
+  }
+
+  inline v8::Local<v8::Primitive> Null() {
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::Null()));
+  }
+
+  inline v8::Local<v8::Boolean> True() {
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::True()));
+  }
+
+  inline v8::Local<v8::Boolean> False() {
+    EscapableHandleScope scope;
+    return scope.Escape(New(v8::False()));
+  }
+
+  inline v8::Local<v8::String> EmptyString() {
+    return v8::String::Empty();
+  }
+
+  inline int AdjustExternalMemory(int bc) {
+    return static_cast<int>(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc));
+  }
+
+  inline void SetTemplate(
+      v8::Local<v8::Template> templ
+    , const char *name
+    , v8::Local<v8::Data> value) {
+    templ->Set(name, value);
+  }
+
+  inline void SetTemplate(
+      v8::Local<v8::Template> templ
+    , v8::Local<v8::String> name
+    , v8::Local<v8::Data> value
+    , v8::PropertyAttribute attributes) {
+    templ->Set(name, value, attributes);
+  }
+
+  inline v8::Local<v8::Context> GetCurrentContext() {
+    return v8::Context::GetCurrent();
+  }
+
+  inline void* GetInternalFieldPointer(
+      v8::Local<v8::Object> object
+    , int index) {
+    return object->GetPointerFromInternalField(index);
+  }
+
+  inline void SetInternalFieldPointer(
+      v8::Local<v8::Object> object
+    , int index
+    , void* value) {
+    object->SetPointerInInternalField(index, value);
+  }
+
+# define NAN_GC_CALLBACK(name)                                                 \
+    void name(v8::GCType type, v8::GCCallbackFlags flags)
+
+  inline void AddGCEpilogueCallback(
+    v8::GCEpilogueCallback callback
+  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
+    v8::V8::AddGCEpilogueCallback(callback, gc_type_filter);
+  }
+  inline void RemoveGCEpilogueCallback(
+    v8::GCEpilogueCallback callback) {
+    v8::V8::RemoveGCEpilogueCallback(callback);
+  }
+  inline void AddGCPrologueCallback(
+    v8::GCPrologueCallback callback
+  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
+    v8::V8::AddGCPrologueCallback(callback, gc_type_filter);
+  }
+  inline void RemoveGCPrologueCallback(
+    v8::GCPrologueCallback callback) {
+    v8::V8::RemoveGCPrologueCallback(callback);
+  }
+  inline void GetHeapStatistics(
+    v8::HeapStatistics *heap_statistics) {
+    v8::V8::GetHeapStatistics(heap_statistics);
+  }
+
+# define X(NAME)                                                               \
+    inline v8::Local<v8::Value> NAME(const char *msg) {                        \
+      EscapableHandleScope scope;                                              \
+      return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked()));     \
+    }                                                                          \
+                                                                               \
+    inline                                                                     \
+    v8::Local<v8::Value> NAME(v8::Local<v8::String> msg) {                     \
+      return v8::Exception::NAME(msg);                                         \
+    }                                                                          \
+                                                                               \
+    inline void Throw ## NAME(const char *msg) {                               \
+      HandleScope scope;                                                       \
+      v8::ThrowException(v8::Exception::NAME(New(msg).ToLocalChecked()));      \
+    }                                                                          \
+                                                                               \
+    inline                                                                     \
+    void Throw ## NAME(v8::Local<v8::String> errmsg) {                         \
+      HandleScope scope;                                                       \
+      v8::ThrowException(v8::Exception::NAME(errmsg));                         \
+    }
+
+  X(Error)
+  X(RangeError)
+  X(ReferenceError)
+  X(SyntaxError)
+  X(TypeError)
+
+# undef X
+
+  inline void ThrowError(v8::Local<v8::Value> error) {
+    v8::ThrowException(error);
+  }
+
+  inline MaybeLocal<v8::Object> NewBuffer(
+      char *data
+    , size_t length
+    , node::Buffer::free_callback callback
+    , void *hint
+  ) {
+    EscapableHandleScope scope;
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    assert(length <= imp::kMaxLength && "too large buffer");
+    return scope.Escape(
+        New(node::Buffer::New(data, length, callback, hint)->handle_));
+  }
+
+  inline MaybeLocal<v8::Object> CopyBuffer(
+      const char *data
+    , uint32_t size
+  ) {
+    EscapableHandleScope scope;
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    assert(size <= imp::kMaxLength && "too large buffer");
+#if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
+    return scope.Escape(New(node::Buffer::New(data, size)->handle_));
+#else
+    return scope.Escape(
+        New(node::Buffer::New(const_cast<char *>(data), size)->handle_));
+#endif
+  }
+
+  inline MaybeLocal<v8::Object> NewBuffer(uint32_t size) {
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    EscapableHandleScope scope;
+    assert(size <= imp::kMaxLength && "too large buffer");
+    return scope.Escape(New(node::Buffer::New(size)->handle_));
+  }
+
+  inline void FreeData(char *data, void *hint) {
+    (void) hint;  // unused
+    delete[] data;
+  }
+
+  inline MaybeLocal<v8::Object> NewBuffer(
+      char* data
+    , uint32_t size
+  ) {
+    EscapableHandleScope scope;
+    // arbitrary buffer lengths requires
+    // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION
+    assert(size <= imp::kMaxLength && "too large buffer");
+    return scope.Escape(
+        New(node::Buffer::New(data, size, FreeData, NULL)->handle_));
+  }
+
+namespace imp {
+inline void
+widenString(std::vector<uint16_t> *ws, const uint8_t *s, int l) {
+  size_t len = static_cast<size_t>(l);
+  if (l < 0) {
+    len = strlen(reinterpret_cast<const char*>(s));
+  }
+  assert(len <= INT_MAX && "string too long");
+  ws->resize(len);
+  std::copy(s, s + len, ws->begin());  // NOLINT(build/include_what_you_use)
+}
+}  // end of namespace imp
+
+  inline MaybeLocal<v8::String>
+  NewOneByteString(const uint8_t * value, int length = -1) {
+    std::vector<uint16_t> wideString;  // NOLINT(build/include_what_you_use)
+    imp::widenString(&wideString, value, length);
+    return v8::String::New(wideString.data(),
+                           static_cast<int>(wideString.size()));
+  }
+
+  inline MaybeLocal<BoundScript> CompileScript(
+      v8::Local<v8::String> s
+    , const v8::ScriptOrigin& origin
+  ) {
+    return v8::Script::Compile(s, const_cast<v8::ScriptOrigin *>(&origin));
+  }
+
+  inline MaybeLocal<BoundScript> CompileScript(
+    v8::Local<v8::String> s
+  ) {
+    return v8::Script::Compile(s);
+  }
+
+  inline
+  MaybeLocal<v8::Value> RunScript(v8::Local<v8::Script> script) {
+    return script->Run();
+  }
+
+  inline v8::Local<v8::Value> MakeCallback(
+      v8::Local<v8::Object> target
+    , v8::Local<v8::Function> func
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+    v8::HandleScope scope;
+    return scope.Close(New(node::MakeCallback(target, func, argc, argv)));
+  }
+
+  inline v8::Local<v8::Value> MakeCallback(
+      v8::Local<v8::Object> target
+    , v8::Local<v8::String> symbol
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+    v8::HandleScope scope;
+    return scope.Close(New(node::MakeCallback(target, symbol, argc, argv)));
+  }
+
+  inline v8::Local<v8::Value> MakeCallback(
+      v8::Local<v8::Object> target
+    , const char* method
+    , int argc
+    , v8::Local<v8::Value>* argv) {
+    v8::HandleScope scope;
+    return scope.Close(New(node::MakeCallback(target, method, argc, argv)));
+  }
+
+  inline void FatalException(const TryCatch& try_catch) {
+    node::FatalException(const_cast<v8::TryCatch &>(try_catch.try_catch_));
+  }
+
+  inline v8::Local<v8::Value> ErrnoException(
+          int errorno
+       ,  const char* syscall = NULL
+       ,  const char* message = NULL
+       ,  const char* path = NULL) {
+    return node::ErrnoException(errorno, syscall, message, path);
+  }
+
+  NAN_DEPRECATED inline v8::Local<v8::Value> NanErrnoException(
+          int errorno
+       ,  const char* syscall = NULL
+       ,  const char* message = NULL
+       ,  const char* path = NULL) {
+    return ErrnoException(errorno, syscall, message, path);
+  }
+
+
+  template<typename T>
+  inline void SetIsolateData(
+      v8::Isolate *isolate
+    , T *data
+  ) {
+      isolate->SetData(data);
+  }
+
+  template<typename T>
+  inline T *GetIsolateData(
+      v8::Isolate *isolate
+  ) {
+      return static_cast<T*>(isolate->GetData());
+  }
+
+class Utf8String {
+ public:
+  inline explicit Utf8String(v8::Local<v8::Value> from) :
+      length_(0), str_(str_st_) {
+    v8::HandleScope scope;
+    if (!from.IsEmpty()) {
+      v8::Local<v8::String> string = from->ToString();
+      if (!string.IsEmpty()) {
+        size_t len = 3 * string->Length() + 1;
+        assert(len <= INT_MAX);
+        if (len > sizeof (str_st_)) {
+          str_ = static_cast<char*>(malloc(len));
+          assert(str_ != 0);
+        }
+        const int flags =
+            v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8;
+        length_ = string->WriteUtf8(str_, static_cast<int>(len), 0, flags);
+        str_[length_] = '\0';
+      }
+    }
+  }
+
+  inline int length() const {
+    return length_;
+  }
+
+  inline char* operator*() { return str_; }
+  inline const char* operator*() const { return str_; }
+
+  inline ~Utf8String() {
+    if (str_ != str_st_) {
+      free(str_);
+    }
+  }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String)
+
+  int length_;
+  char *str_;
+  char str_st_[1024];
+};
+
+#endif  // NODE_MODULE_VERSION
+
+typedef void (*FreeCallback)(char *data, void *hint);
+
+typedef const FunctionCallbackInfo<v8::Value>& NAN_METHOD_ARGS_TYPE;
+typedef void NAN_METHOD_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Value>& NAN_GETTER_ARGS_TYPE;
+typedef void NAN_GETTER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<void>& NAN_SETTER_ARGS_TYPE;
+typedef void NAN_SETTER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Value>&
+    NAN_PROPERTY_GETTER_ARGS_TYPE;
+typedef void NAN_PROPERTY_GETTER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Value>&
+    NAN_PROPERTY_SETTER_ARGS_TYPE;
+typedef void NAN_PROPERTY_SETTER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Array>&
+    NAN_PROPERTY_ENUMERATOR_ARGS_TYPE;
+typedef void NAN_PROPERTY_ENUMERATOR_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Boolean>&
+    NAN_PROPERTY_DELETER_ARGS_TYPE;
+typedef void NAN_PROPERTY_DELETER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Integer>&
+    NAN_PROPERTY_QUERY_ARGS_TYPE;
+typedef void NAN_PROPERTY_QUERY_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Value>& NAN_INDEX_GETTER_ARGS_TYPE;
+typedef void NAN_INDEX_GETTER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Value>& NAN_INDEX_SETTER_ARGS_TYPE;
+typedef void NAN_INDEX_SETTER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Array>&
+    NAN_INDEX_ENUMERATOR_ARGS_TYPE;
+typedef void NAN_INDEX_ENUMERATOR_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Boolean>&
+    NAN_INDEX_DELETER_ARGS_TYPE;
+typedef void NAN_INDEX_DELETER_RETURN_TYPE;
+
+typedef const PropertyCallbackInfo<v8::Integer>&
+    NAN_INDEX_QUERY_ARGS_TYPE;
+typedef void NAN_INDEX_QUERY_RETURN_TYPE;
+
+#define NAN_METHOD(name)                                                       \
+    Nan::NAN_METHOD_RETURN_TYPE name(Nan::NAN_METHOD_ARGS_TYPE info)
+#define NAN_GETTER(name)                                                       \
+    Nan::NAN_GETTER_RETURN_TYPE name(                                          \
+        v8::Local<v8::String> property                                         \
+      , Nan::NAN_GETTER_ARGS_TYPE info)
+#define NAN_SETTER(name)                                                       \
+    Nan::NAN_SETTER_RETURN_TYPE name(                                          \
+        v8::Local<v8::String> property                                         \
+      , v8::Local<v8::Value> value                                             \
+      , Nan::NAN_SETTER_ARGS_TYPE info)
+#define NAN_PROPERTY_GETTER(name)                                              \
+    Nan::NAN_PROPERTY_GETTER_RETURN_TYPE name(                                 \
+        v8::Local<v8::String> property                                         \
+      , Nan::NAN_PROPERTY_GETTER_ARGS_TYPE info)
+#define NAN_PROPERTY_SETTER(name)                                              \
+    Nan::NAN_PROPERTY_SETTER_RETURN_TYPE name(                                 \
+        v8::Local<v8::String> property                                         \
+      , v8::Local<v8::Value> value                                             \
+      , Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info)
+#define NAN_PROPERTY_ENUMERATOR(name)                                          \
+    Nan::NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(                             \
+        Nan::NAN_PROPERTY_ENUMERATOR_ARGS_TYPE info)
+#define NAN_PROPERTY_DELETER(name)                                             \
+    Nan::NAN_PROPERTY_DELETER_RETURN_TYPE name(                                \
+        v8::Local<v8::String> property                                         \
+      , Nan::NAN_PROPERTY_DELETER_ARGS_TYPE info)
+#define NAN_PROPERTY_QUERY(name)                                               \
+    Nan::NAN_PROPERTY_QUERY_RETURN_TYPE name(                                  \
+        v8::Local<v8::String> property                                         \
+      , Nan::NAN_PROPERTY_QUERY_ARGS_TYPE info)
+# define NAN_INDEX_GETTER(name)                                                \
+    Nan::NAN_INDEX_GETTER_RETURN_TYPE name(                                    \
+        uint32_t index                                                         \
+      , Nan::NAN_INDEX_GETTER_ARGS_TYPE info)
+#define NAN_INDEX_SETTER(name)                                                 \
+    Nan::NAN_INDEX_SETTER_RETURN_TYPE name(                                    \
+        uint32_t index                                                         \
+      , v8::Local<v8::Value> value                                             \
+      , Nan::NAN_INDEX_SETTER_ARGS_TYPE info)
+#define NAN_INDEX_ENUMERATOR(name)                                             \
+    Nan::NAN_INDEX_ENUMERATOR_RETURN_TYPE                                      \
+    name(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE info)
+#define NAN_INDEX_DELETER(name)                                                \
+    Nan::NAN_INDEX_DELETER_RETURN_TYPE name(                                   \
+        uint32_t index                                                         \
+      , Nan::NAN_INDEX_DELETER_ARGS_TYPE info)
+#define NAN_INDEX_QUERY(name)                                                  \
+    Nan::NAN_INDEX_QUERY_RETURN_TYPE name(                                     \
+        uint32_t index                                                         \
+      , Nan::NAN_INDEX_QUERY_ARGS_TYPE info)
+
+class Callback {
+ public:
+  Callback() {}
+
+  explicit Callback(const v8::Local<v8::Function> &fn) : handle_(fn) {}
+
+  ~Callback() {
+    handle_.Reset();
+  }
+
+  bool operator==(const Callback &other) const {
+    return handle_ == other.handle_;
+  }
+
+  bool operator!=(const Callback &other) const {
+    return !operator==(other);
+  }
+
+  inline
+  v8::Local<v8::Function> operator*() const { return GetFunction(); }
+
+  NAN_DEPRECATED inline v8::Local<v8::Value> operator()(
+      v8::Local<v8::Object> target
+    , int argc = 0
+    , v8::Local<v8::Value> argv[] = 0) const {
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    AsyncResource async("nan:Callback:operator()");
+    return Call_(isolate, target, argc, argv, &async)
+        .FromMaybe(v8::Local<v8::Value>());
+# else
+    return Call_(isolate, target, argc, argv);
+# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+#else
+    return Call_(target, argc, argv);
+#endif  //  NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+  }
+
+  NAN_DEPRECATED inline v8::Local<v8::Value> operator()(
+      int argc = 0
+    , v8::Local<v8::Value> argv[] = 0) const {
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    AsyncResource async("nan:Callback:operator()");
+    return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(),
+                              argc, argv, &async)
+                            .FromMaybe(v8::Local<v8::Value>()));
+# else
+    return scope.Escape(
+        Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv));
+# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+#else
+    v8::HandleScope scope;
+    return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv));
+#endif  //  NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+  }
+
+  inline MaybeLocal<v8::Value> operator()(
+      AsyncResource* resource
+    , int argc = 0
+    , v8::Local<v8::Value> argv[] = 0) const {
+    return this->Call(argc, argv, resource);
+  }
+
+  inline MaybeLocal<v8::Value> operator()(
+      AsyncResource* resource
+    , v8::Local<v8::Object> target
+    , int argc = 0
+    , v8::Local<v8::Value> argv[] = 0) const {
+    return this->Call(target, argc, argv, resource);
+  }
+
+  // TODO(kkoopa): remove
+  inline void SetFunction(const v8::Local<v8::Function> &fn) {
+    Reset(fn);
+  }
+
+  inline void Reset(const v8::Local<v8::Function> &fn) {
+    handle_.Reset(fn);
+  }
+
+  inline void Reset() {
+    handle_.Reset();
+  }
+
+  inline v8::Local<v8::Function> GetFunction() const {
+    return New(handle_);
+  }
+
+  inline bool IsEmpty() const {
+    return handle_.IsEmpty();
+  }
+
+  // Deprecated: For async callbacks Use the versions that accept an
+  // AsyncResource. If this callback does not correspond to an async resource,
+  // that is, it is a synchronous function call on a non-empty JS stack, you
+  // should Nan::Call instead.
+  NAN_DEPRECATED inline v8::Local<v8::Value>
+  Call(v8::Local<v8::Object> target
+     , int argc
+     , v8::Local<v8::Value> argv[]) const {
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    AsyncResource async("nan:Callback:Call");
+    return Call_(isolate, target, argc, argv, &async)
+        .FromMaybe(v8::Local<v8::Value>());
+# else
+    return Call_(isolate, target, argc, argv);
+# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+#else
+    return Call_(target, argc, argv);
+#endif
+  }
+
+  // Deprecated: For async callbacks Use the versions that accept an
+  // AsyncResource. If this callback does not correspond to an async resource,
+  // that is, it is a synchronous function call on a non-empty JS stack, you
+  // should Nan::Call instead.
+  NAN_DEPRECATED inline v8::Local<v8::Value>
+  Call(int argc, v8::Local<v8::Value> argv[]) const {
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    AsyncResource async("nan:Callback:Call");
+    return Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv,
+                 &async)
+        .FromMaybe(v8::Local<v8::Value>());
+# else
+    return scope.Escape(
+        Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv));
+# endif  // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+#else
+    v8::HandleScope scope;
+    return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv));
+#endif
+  }
+
+  inline MaybeLocal<v8::Value>
+  Call(v8::Local<v8::Object> target
+     , int argc
+     , v8::Local<v8::Value> argv[]
+     , AsyncResource* resource) const {
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    v8::Isolate* isolate = v8::Isolate::GetCurrent();
+    return Call_(isolate, target, argc, argv, resource);
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    return Call_(isolate, target, argc, argv);
+#else
+    return Call_(target, argc, argv);
+#endif
+  }
+
+  inline MaybeLocal<v8::Value>
+  Call(int argc, v8::Local<v8::Value> argv[], AsyncResource* resource) const {
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+    v8::Isolate* isolate = v8::Isolate::GetCurrent();
+    return Call(isolate->GetCurrentContext()->Global(), argc, argv, resource);
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+    v8::Isolate *isolate = v8::Isolate::GetCurrent();
+    v8::EscapableHandleScope scope(isolate);
+    return scope.Escape(
+        Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv));
+#else
+    v8::HandleScope scope;
+    return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv));
+#endif
+  }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(Callback)
+  Persistent<v8::Function> handle_;
+
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+  MaybeLocal<v8::Value> Call_(v8::Isolate *isolate
+                            , v8::Local<v8::Object> target
+                            , int argc
+                            , v8::Local<v8::Value> argv[]
+                            , AsyncResource* resource) const {
+    EscapableHandleScope scope;
+    v8::Local<v8::Function> func = New(handle_);
+    auto maybe = resource->runInAsyncScope(target, func, argc, argv);
+    v8::Local<v8::Value> local;
+    if (!maybe.ToLocal(&local)) return MaybeLocal<v8::Value>();
+    return scope.Escape(local);
+  }
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+  v8::Local<v8::Value> Call_(v8::Isolate *isolate
+                           , v8::Local<v8::Object> target
+                           , int argc
+                           , v8::Local<v8::Value> argv[]) const {
+    EscapableHandleScope scope;
+
+    v8::Local<v8::Function> callback = New(handle_);
+# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+    return scope.Escape(New(node::MakeCallback(
+        isolate
+      , target
+      , callback
+      , argc
+      , argv
+    )));
+# else
+    return scope.Escape(node::MakeCallback(
+        isolate
+      , target
+      , callback
+      , argc
+      , argv
+    ));
+# endif
+  }
+#else
+  v8::Local<v8::Value> Call_(v8::Local<v8::Object> target
+                           , int argc
+                           , v8::Local<v8::Value> argv[]) const {
+    EscapableHandleScope scope;
+
+    v8::Local<v8::Function> callback = New(handle_);
+    return scope.Escape(New(node::MakeCallback(
+        target
+      , callback
+      , argc
+      , argv
+    )));
+  }
+#endif
+};
+
+inline MaybeLocal<v8::Value> Call(
+    const Nan::Callback& callback
+  , v8::Local<v8::Object> recv
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+  return Call(*callback, recv, argc, argv);
+}
+
+inline MaybeLocal<v8::Value> Call(
+    const Nan::Callback& callback
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(
+      Call(*callback, isolate->GetCurrentContext()->Global(), argc, argv)
+          .FromMaybe(v8::Local<v8::Value>()));
+#else
+  EscapableHandleScope scope;
+  return scope.Escape(
+      Call(*callback, v8::Context::GetCurrent()->Global(), argc, argv)
+          .FromMaybe(v8::Local<v8::Value>()));
+#endif
+}
+
+inline MaybeLocal<v8::Value> Call(
+    v8::Local<v8::String> symbol
+  , v8::Local<v8::Object> recv
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+  EscapableHandleScope scope;
+  v8::Local<v8::Value> fn_v =
+      Get(recv, symbol).FromMaybe(v8::Local<v8::Value>());
+  if (fn_v.IsEmpty() || !fn_v->IsFunction()) return v8::Local<v8::Value>();
+  v8::Local<v8::Function> fn = fn_v.As<v8::Function>();
+  return scope.Escape(
+      Call(fn, recv, argc, argv).FromMaybe(v8::Local<v8::Value>()));
+}
+
+inline MaybeLocal<v8::Value> Call(
+    const char* method
+  , v8::Local<v8::Object> recv
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+  EscapableHandleScope scope;
+  v8::Local<v8::String> method_string =
+      New<v8::String>(method).ToLocalChecked();
+  return scope.Escape(
+      Call(method_string, recv, argc, argv).FromMaybe(v8::Local<v8::Value>()));
+}
+
+/* abstract */ class AsyncWorker {
+ public:
+  explicit AsyncWorker(Callback *callback_,
+                       const char* resource_name = "nan:AsyncWorker")
+      : callback(callback_), errmsg_(NULL) {
+    request.data = this;
+
+    HandleScope scope;
+    v8::Local<v8::Object> obj = New<v8::Object>();
+    persistentHandle.Reset(obj);
+    async_resource = new AsyncResource(resource_name, obj);
+  }
+
+  virtual ~AsyncWorker() {
+    HandleScope scope;
+
+    if (!persistentHandle.IsEmpty())
+      persistentHandle.Reset();
+    delete callback;
+    delete[] errmsg_;
+    delete async_resource;
+  }
+
+  virtual void WorkComplete() {
+    HandleScope scope;
+
+    if (errmsg_ == NULL)
+      HandleOKCallback();
+    else
+      HandleErrorCallback();
+    delete callback;
+    callback = NULL;
+  }
+
+  inline void SaveToPersistent(
+      const char *key, const v8::Local<v8::Value> &value) {
+    HandleScope scope;
+    New(persistentHandle)->Set(New(key).ToLocalChecked(), value);
+  }
+
+  inline void SaveToPersistent(
+      const v8::Local<v8::String> &key, const v8::Local<v8::Value> &value) {
+    HandleScope scope;
+    New(persistentHandle)->Set(key, value);
+  }
+
+  inline void SaveToPersistent(
+      uint32_t index, const v8::Local<v8::Value> &value) {
+    HandleScope scope;
+    New(persistentHandle)->Set(index, value);
+  }
+
+  inline v8::Local<v8::Value> GetFromPersistent(const char *key) const {
+    EscapableHandleScope scope;
+    return scope.Escape(
+        New(persistentHandle)->Get(New(key).ToLocalChecked()));
+  }
+
+  inline v8::Local<v8::Value>
+  GetFromPersistent(const v8::Local<v8::String> &key) const {
+    EscapableHandleScope scope;
+    return scope.Escape(New(persistentHandle)->Get(key));
+  }
+
+  inline v8::Local<v8::Value> GetFromPersistent(uint32_t index) const {
+    EscapableHandleScope scope;
+    return scope.Escape(New(persistentHandle)->Get(index));
+  }
+
+  virtual void Execute() = 0;
+
+  uv_work_t request;
+
+  virtual void Destroy() {
+      delete this;
+  }
+
+ protected:
+  Persistent<v8::Object> persistentHandle;
+  Callback *callback;
+  AsyncResource *async_resource;
+
+  virtual void HandleOKCallback() {
+    HandleScope scope;
+
+    callback->Call(0, NULL, async_resource);
+  }
+
+  virtual void HandleErrorCallback() {
+    HandleScope scope;
+
+    v8::Local<v8::Value> argv[] = {
+      v8::Exception::Error(New<v8::String>(ErrorMessage()).ToLocalChecked())
+    };
+    callback->Call(1, argv, async_resource);
+  }
+
+  void SetErrorMessage(const char *msg) {
+    delete[] errmsg_;
+
+    size_t size = strlen(msg) + 1;
+    errmsg_ = new char[size];
+    memcpy(errmsg_, msg, size);
+  }
+
+  const char* ErrorMessage() const {
+    return errmsg_;
+  }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncWorker)
+  char *errmsg_;
+};
+
+/* abstract */ class AsyncBareProgressWorkerBase : public AsyncWorker {
+ public:
+  explicit AsyncBareProgressWorkerBase(
+      Callback *callback_,
+      const char* resource_name = "nan:AsyncBareProgressWorkerBase")
+      : AsyncWorker(callback_, resource_name) {
+    uv_async_init(
+        GetCurrentEventLoop()
+      , &async
+      , AsyncProgress_
+    );
+    async.data = this;
+  }
+
+  virtual ~AsyncBareProgressWorkerBase() {
+  }
+
+  virtual void WorkProgress() = 0;
+
+  virtual void Destroy() {
+      uv_close(reinterpret_cast<uv_handle_t*>(&async), AsyncClose_);
+  }
+
+ private:
+  inline static NAUV_WORK_CB(AsyncProgress_) {
+    AsyncBareProgressWorkerBase *worker =
+            static_cast<AsyncBareProgressWorkerBase*>(async->data);
+    worker->WorkProgress();
+  }
+
+  inline static void AsyncClose_(uv_handle_t* handle) {
+    AsyncBareProgressWorkerBase *worker =
+            static_cast<AsyncBareProgressWorkerBase*>(handle->data);
+    delete worker;
+  }
+
+ protected:
+  uv_async_t async;
+};
+
+template<class T>
+/* abstract */
+class AsyncBareProgressWorker : public AsyncBareProgressWorkerBase {
+ public:
+  explicit AsyncBareProgressWorker(
+      Callback *callback_,
+      const char* resource_name = "nan:AsyncBareProgressWorker")
+      : AsyncBareProgressWorkerBase(callback_, resource_name) {
+    uv_mutex_init(&async_lock);
+  }
+
+  virtual ~AsyncBareProgressWorker() {
+    uv_mutex_destroy(&async_lock);
+  }
+
+  class ExecutionProgress {
+    friend class AsyncBareProgressWorker;
+   public:
+    void Signal() const {
+      uv_mutex_lock(&that_->async_lock);
+      uv_async_send(&that_->async);
+      uv_mutex_unlock(&that_->async_lock);
+    }
+
+    void Send(const T* data, size_t count) const {
+      that_->SendProgress_(data, count);
+    }
+
+   private:
+    explicit ExecutionProgress(AsyncBareProgressWorker *that) : that_(that) {}
+    NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress)
+    AsyncBareProgressWorker* const that_;
+  };
+
+  virtual void Execute(const ExecutionProgress& progress) = 0;
+  virtual void HandleProgressCallback(const T *data, size_t size) = 0;
+
+ protected:
+  uv_mutex_t async_lock;
+
+ private:
+  void Execute() /*final override*/ {
+    ExecutionProgress progress(this);
+    Execute(progress);
+  }
+
+  virtual void SendProgress_(const T *data, size_t count) = 0;
+};
+
+template<class T>
+/* abstract */
+class AsyncProgressWorkerBase : public AsyncBareProgressWorker<T> {
+ public:
+  explicit AsyncProgressWorkerBase(
+      Callback *callback_,
+      const char* resource_name = "nan:AsyncProgressWorkerBase")
+      : AsyncBareProgressWorker<T>(callback_, resource_name), asyncdata_(NULL),
+        asyncsize_(0) {
+  }
+
+  virtual ~AsyncProgressWorkerBase() {
+    delete[] asyncdata_;
+  }
+
+  void WorkProgress() {
+    uv_mutex_lock(&this->async_lock);
+    T *data = asyncdata_;
+    size_t size = asyncsize_;
+    asyncdata_ = NULL;
+    asyncsize_ = 0;
+    uv_mutex_unlock(&this->async_lock);
+
+    // Don't send progress events after we've already completed.
+    if (this->callback) {
+        this->HandleProgressCallback(data, size);
+    }
+    delete[] data;
+  }
+
+ private:
+  void SendProgress_(const T *data, size_t count) {
+    T *new_data = new T[count];
+    {
+      T *it = new_data;
+      std::copy(data, data + count, it);
+    }
+
+    uv_mutex_lock(&this->async_lock);
+    T *old_data = asyncdata_;
+    asyncdata_ = new_data;
+    asyncsize_ = count;
+    uv_async_send(&this->async);
+    uv_mutex_unlock(&this->async_lock);
+
+    delete[] old_data;
+  }
+
+  T *asyncdata_;
+  size_t asyncsize_;
+};
+
+// This ensures compatibility to the previous un-templated AsyncProgressWorker
+// class definition.
+typedef AsyncProgressWorkerBase<char> AsyncProgressWorker;
+
+template<class T>
+/* abstract */
+class AsyncBareProgressQueueWorker : public AsyncBareProgressWorkerBase {
+ public:
+  explicit AsyncBareProgressQueueWorker(
+      Callback *callback_,
+      const char* resource_name = "nan:AsyncBareProgressQueueWorker")
+      : AsyncBareProgressWorkerBase(callback_, resource_name) {
+  }
+
+  virtual ~AsyncBareProgressQueueWorker() {
+  }
+
+  class ExecutionProgress {
+    friend class AsyncBareProgressQueueWorker;
+   public:
+    void Send(const T* data, size_t count) const {
+      that_->SendProgress_(data, count);
+    }
+
+   private:
+    explicit ExecutionProgress(AsyncBareProgressQueueWorker *that)
+        : that_(that) {}
+    NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress)
+    AsyncBareProgressQueueWorker* const that_;
+  };
+
+  virtual void Execute(const ExecutionProgress& progress) = 0;
+  virtual void HandleProgressCallback(const T *data, size_t size) = 0;
+
+ private:
+  void Execute() /*final override*/ {
+    ExecutionProgress progress(this);
+    Execute(progress);
+  }
+
+  virtual void SendProgress_(const T *data, size_t count) = 0;
+};
+
+template<class T>
+/* abstract */
+class AsyncProgressQueueWorker : public AsyncBareProgressQueueWorker<T> {
+ public:
+  explicit AsyncProgressQueueWorker(
+      Callback *callback_,
+      const char* resource_name = "nan:AsyncProgressQueueWorker")
+      : AsyncBareProgressQueueWorker<T>(callback_) {
+    uv_mutex_init(&async_lock);
+  }
+
+  virtual ~AsyncProgressQueueWorker() {
+    uv_mutex_lock(&async_lock);
+
+    while (!asyncdata_.empty()) {
+      std::pair<T*, size_t> &datapair = asyncdata_.front();
+      T *data = datapair.first;
+
+      asyncdata_.pop();
+
+      delete[] data;
+    }
+
+    uv_mutex_unlock(&async_lock);
+    uv_mutex_destroy(&async_lock);
+  }
+
+  void WorkComplete() {
+    WorkProgress();
+    AsyncWorker::WorkComplete();
+  }
+
+  void WorkProgress() {
+    uv_mutex_lock(&async_lock);
+
+    while (!asyncdata_.empty()) {
+      std::pair<T*, size_t> &datapair = asyncdata_.front();
+
+      T *data = datapair.first;
+      size_t size = datapair.second;
+
+      asyncdata_.pop();
+      uv_mutex_unlock(&async_lock);
+
+      // Don't send progress events after we've already completed.
+      if (this->callback) {
+          this->HandleProgressCallback(data, size);
+      }
+
+      delete[] data;
+
+      uv_mutex_lock(&async_lock);
+    }
+
+    uv_mutex_unlock(&async_lock);
+  }
+
+ private:
+  void SendProgress_(const T *data, size_t count) {
+    T *new_data = new T[count];
+    {
+      T *it = new_data;
+      std::copy(data, data + count, it);
+    }
+
+    uv_mutex_lock(&async_lock);
+    asyncdata_.push(std::pair<T*, size_t>(new_data, count));
+    uv_mutex_unlock(&async_lock);
+
+    uv_async_send(&this->async);
+  }
+
+  uv_mutex_t async_lock;
+  std::queue<std::pair<T*, size_t> > asyncdata_;
+};
+
+inline void AsyncExecute (uv_work_t* req) {
+  AsyncWorker *worker = static_cast<AsyncWorker*>(req->data);
+  worker->Execute();
+}
+
+inline void AsyncExecuteComplete (uv_work_t* req) {
+  AsyncWorker* worker = static_cast<AsyncWorker*>(req->data);
+  worker->WorkComplete();
+  worker->Destroy();
+}
+
+inline void AsyncQueueWorker (AsyncWorker* worker) {
+  uv_queue_work(
+      GetCurrentEventLoop()
+    , &worker->request
+    , AsyncExecute
+    , reinterpret_cast<uv_after_work_cb>(AsyncExecuteComplete)
+  );
+}
+
+namespace imp {
+
+inline
+ExternalOneByteStringResource const*
+GetExternalResource(v8::Local<v8::String> str) {
+#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
+    return str->GetExternalAsciiStringResource();
+#else
+    return str->GetExternalOneByteStringResource();
+#endif
+}
+
+inline
+bool
+IsExternal(v8::Local<v8::String> str) {
+#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
+    return str->IsExternalAscii();
+#else
+    return str->IsExternalOneByte();
+#endif
+}
+
+}  // end of namespace imp
+
+enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
+
+#if NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION
+# include "nan_string_bytes.h"  // NOLINT(build/include)
+#endif
+
+inline v8::Local<v8::Value> Encode(
+    const void *buf, size_t len, enum Encoding encoding = BINARY) {
+#if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION)
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  node::encoding node_enc = static_cast<node::encoding>(encoding);
+
+  if (encoding == UCS2) {
+    return node::Encode(
+        isolate
+      , reinterpret_cast<const uint16_t *>(buf)
+      , len / 2);
+  } else {
+    return node::Encode(
+        isolate
+      , reinterpret_cast<const char *>(buf)
+      , len
+      , node_enc);
+  }
+#elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+  return node::Encode(
+      v8::Isolate::GetCurrent()
+    , buf, len
+    , static_cast<node::encoding>(encoding));
+#else
+# if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
+  return node::Encode(buf, len, static_cast<node::encoding>(encoding));
+# else
+  return imp::Encode(reinterpret_cast<const char*>(buf), len, encoding);
+# endif
+#endif
+}
+
+inline ssize_t DecodeBytes(
+    v8::Local<v8::Value> val, enum Encoding encoding = BINARY) {
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+  return node::DecodeBytes(
+      v8::Isolate::GetCurrent()
+    , val
+    , static_cast<node::encoding>(encoding));
+#else
+# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
+  if (encoding == BUFFER) {
+    return node::DecodeBytes(val, node::BINARY);
+  }
+# endif
+  return node::DecodeBytes(val, static_cast<node::encoding>(encoding));
+#endif
+}
+
+inline ssize_t DecodeWrite(
+    char *buf
+  , size_t len
+  , v8::Local<v8::Value> val
+  , enum Encoding encoding = BINARY) {
+#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
+  return node::DecodeWrite(
+      v8::Isolate::GetCurrent()
+    , buf
+    , len
+    , val
+    , static_cast<node::encoding>(encoding));
+#else
+# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
+  if (encoding == BUFFER) {
+    return node::DecodeWrite(buf, len, val, node::BINARY);
+  }
+# endif
+  return node::DecodeWrite(
+      buf
+    , len
+    , val
+    , static_cast<node::encoding>(encoding));
+#endif
+}
+
+inline void SetPrototypeTemplate(
+    v8::Local<v8::FunctionTemplate> templ
+  , const char *name
+  , v8::Local<v8::Data> value
+) {
+  HandleScope scope;
+  SetTemplate(templ->PrototypeTemplate(), name, value);
+}
+
+inline void SetPrototypeTemplate(
+    v8::Local<v8::FunctionTemplate> templ
+  , v8::Local<v8::String> name
+  , v8::Local<v8::Data> value
+  , v8::PropertyAttribute attributes
+) {
+  HandleScope scope;
+  SetTemplate(templ->PrototypeTemplate(), name, value, attributes);
+}
+
+inline void SetInstanceTemplate(
+    v8::Local<v8::FunctionTemplate> templ
+  , const char *name
+  , v8::Local<v8::Data> value
+) {
+  HandleScope scope;
+  SetTemplate(templ->InstanceTemplate(), name, value);
+}
+
+inline void SetInstanceTemplate(
+    v8::Local<v8::FunctionTemplate> templ
+  , v8::Local<v8::String> name
+  , v8::Local<v8::Data> value
+  , v8::PropertyAttribute attributes
+) {
+  HandleScope scope;
+  SetTemplate(templ->InstanceTemplate(), name, value, attributes);
+}
+
+namespace imp {
+
+// Note(@agnat): Helper to distinguish different receiver types. The first
+// version deals with receivers derived from v8::Template. The second version
+// handles everything else. The final argument only serves as discriminator and
+// is unused.
+template <typename T>
+inline
+void
+SetMethodAux(T recv,
+             v8::Local<v8::String> name,
+             v8::Local<v8::FunctionTemplate> tpl,
+             v8::Template *) {
+  recv->Set(name, tpl);
+}
+
+template <typename T>
+inline
+void
+SetMethodAux(T recv,
+             v8::Local<v8::String> name,
+             v8::Local<v8::FunctionTemplate> tpl,
+             ...) {
+  recv->Set(name, GetFunction(tpl).ToLocalChecked());
+}
+
+}  // end of namespace imp
+
+template <typename T, template <typename> class HandleType>
+inline void SetMethod(
+    HandleType<T> recv
+  , const char *name
+  , FunctionCallback callback) {
+  HandleScope scope;
+  v8::Local<v8::FunctionTemplate> t = New<v8::FunctionTemplate>(callback);
+  v8::Local<v8::String> fn_name = New(name).ToLocalChecked();
+  t->SetClassName(fn_name);
+  // Note(@agnat): Pass an empty T* as discriminator. See note on
+  // SetMethodAux(...) above
+  imp::SetMethodAux(recv, fn_name, t, static_cast<T*>(0));
+}
+
+inline void SetPrototypeMethod(
+    v8::Local<v8::FunctionTemplate> recv
+  , const char* name, FunctionCallback callback) {
+  HandleScope scope;
+  v8::Local<v8::FunctionTemplate> t = New<v8::FunctionTemplate>(
+      callback
+    , v8::Local<v8::Value>()
+    , New<v8::Signature>(recv));
+  v8::Local<v8::String> fn_name = New(name).ToLocalChecked();
+  recv->PrototypeTemplate()->Set(fn_name, t);
+  t->SetClassName(fn_name);
+}
+
+//=== Accessors and Such =======================================================
+
+inline void SetAccessor(
+    v8::Local<v8::ObjectTemplate> tpl
+  , v8::Local<v8::String> name
+  , GetterCallback getter
+  , SetterCallback setter = 0
+  , v8::Local<v8::Value> data = v8::Local<v8::Value>()
+  , v8::AccessControl settings = v8::DEFAULT
+  , v8::PropertyAttribute attribute = v8::None
+  , imp::Sig signature = imp::Sig()) {
+  HandleScope scope;
+
+  imp::NativeGetter getter_ =
+      imp::GetterCallbackWrapper;
+  imp::NativeSetter setter_ =
+      setter ? imp::SetterCallbackWrapper : 0;
+
+  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
+  otpl->SetInternalFieldCount(imp::kAccessorFieldCount);
+  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
+
+  obj->SetInternalField(
+      imp::kGetterIndex
+    , New<v8::External>(reinterpret_cast<void *>(getter)));
+
+  if (setter != 0) {
+    obj->SetInternalField(
+        imp::kSetterIndex
+      , New<v8::External>(reinterpret_cast<void *>(setter)));
+  }
+
+  if (!data.IsEmpty()) {
+    obj->SetInternalField(imp::kDataIndex, data);
+  }
+
+  tpl->SetAccessor(
+      name
+    , getter_
+    , setter_
+    , obj
+    , settings
+    , attribute
+    , signature);
+}
+
+inline bool SetAccessor(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> name
+  , GetterCallback getter
+  , SetterCallback setter = 0
+  , v8::Local<v8::Value> data = v8::Local<v8::Value>()
+  , v8::AccessControl settings = v8::DEFAULT
+  , v8::PropertyAttribute attribute = v8::None) {
+  HandleScope scope;
+
+  imp::NativeGetter getter_ =
+      imp::GetterCallbackWrapper;
+  imp::NativeSetter setter_ =
+      setter ? imp::SetterCallbackWrapper : 0;
+
+  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
+  otpl->SetInternalFieldCount(imp::kAccessorFieldCount);
+  v8::Local<v8::Object> dataobj = NewInstance(otpl).ToLocalChecked();
+
+  dataobj->SetInternalField(
+      imp::kGetterIndex
+    , New<v8::External>(reinterpret_cast<void *>(getter)));
+
+  if (!data.IsEmpty()) {
+    dataobj->SetInternalField(imp::kDataIndex, data);
+  }
+
+  if (setter) {
+    dataobj->SetInternalField(
+        imp::kSetterIndex
+      , New<v8::External>(reinterpret_cast<void *>(setter)));
+  }
+
+#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION)
+  return obj->SetAccessor(
+      GetCurrentContext()
+    , name
+    , getter_
+    , setter_
+    , dataobj
+    , settings
+    , attribute).FromMaybe(false);
+#else
+  return obj->SetAccessor(
+      name
+    , getter_
+    , setter_
+    , dataobj
+    , settings
+    , attribute);
+#endif
+}
+
+inline void SetNamedPropertyHandler(
+    v8::Local<v8::ObjectTemplate> tpl
+  , PropertyGetterCallback getter
+  , PropertySetterCallback setter = 0
+  , PropertyQueryCallback query = 0
+  , PropertyDeleterCallback deleter = 0
+  , PropertyEnumeratorCallback enumerator = 0
+  , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
+  HandleScope scope;
+
+  imp::NativePropertyGetter getter_ =
+      imp::PropertyGetterCallbackWrapper;
+  imp::NativePropertySetter setter_ =
+      setter ? imp::PropertySetterCallbackWrapper : 0;
+  imp::NativePropertyQuery query_ =
+      query ? imp::PropertyQueryCallbackWrapper : 0;
+  imp::NativePropertyDeleter *deleter_ =
+      deleter ? imp::PropertyDeleterCallbackWrapper : 0;
+  imp::NativePropertyEnumerator enumerator_ =
+      enumerator ? imp::PropertyEnumeratorCallbackWrapper : 0;
+
+  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
+  otpl->SetInternalFieldCount(imp::kPropertyFieldCount);
+  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
+  obj->SetInternalField(
+      imp::kPropertyGetterIndex
+    , New<v8::External>(reinterpret_cast<void *>(getter)));
+
+  if (setter) {
+    obj->SetInternalField(
+        imp::kPropertySetterIndex
+      , New<v8::External>(reinterpret_cast<void *>(setter)));
+  }
+
+  if (query) {
+    obj->SetInternalField(
+        imp::kPropertyQueryIndex
+      , New<v8::External>(reinterpret_cast<void *>(query)));
+  }
+
+  if (deleter) {
+    obj->SetInternalField(
+        imp::kPropertyDeleterIndex
+      , New<v8::External>(reinterpret_cast<void *>(deleter)));
+  }
+
+  if (enumerator) {
+    obj->SetInternalField(
+        imp::kPropertyEnumeratorIndex
+      , New<v8::External>(reinterpret_cast<void *>(enumerator)));
+  }
+
+  if (!data.IsEmpty()) {
+    obj->SetInternalField(imp::kDataIndex, data);
+  }
+
+#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+  tpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      getter_, setter_, query_, deleter_, enumerator_, obj));
+#else
+  tpl->SetNamedPropertyHandler(
+      getter_
+    , setter_
+    , query_
+    , deleter_
+    , enumerator_
+    , obj);
+#endif
+}
+
+inline void SetIndexedPropertyHandler(
+    v8::Local<v8::ObjectTemplate> tpl
+  , IndexGetterCallback getter
+  , IndexSetterCallback setter = 0
+  , IndexQueryCallback query = 0
+  , IndexDeleterCallback deleter = 0
+  , IndexEnumeratorCallback enumerator = 0
+  , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
+  HandleScope scope;
+
+  imp::NativeIndexGetter getter_ =
+      imp::IndexGetterCallbackWrapper;
+  imp::NativeIndexSetter setter_ =
+      setter ? imp::IndexSetterCallbackWrapper : 0;
+  imp::NativeIndexQuery query_ =
+      query ? imp::IndexQueryCallbackWrapper : 0;
+  imp::NativeIndexDeleter deleter_ =
+      deleter ? imp::IndexDeleterCallbackWrapper : 0;
+  imp::NativeIndexEnumerator enumerator_ =
+      enumerator ? imp::IndexEnumeratorCallbackWrapper : 0;
+
+  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
+  otpl->SetInternalFieldCount(imp::kIndexPropertyFieldCount);
+  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
+  obj->SetInternalField(
+      imp::kIndexPropertyGetterIndex
+    , New<v8::External>(reinterpret_cast<void *>(getter)));
+
+  if (setter) {
+    obj->SetInternalField(
+        imp::kIndexPropertySetterIndex
+      , New<v8::External>(reinterpret_cast<void *>(setter)));
+  }
+
+  if (query) {
+    obj->SetInternalField(
+        imp::kIndexPropertyQueryIndex
+      , New<v8::External>(reinterpret_cast<void *>(query)));
+  }
+
+  if (deleter) {
+    obj->SetInternalField(
+        imp::kIndexPropertyDeleterIndex
+      , New<v8::External>(reinterpret_cast<void *>(deleter)));
+  }
+
+  if (enumerator) {
+    obj->SetInternalField(
+        imp::kIndexPropertyEnumeratorIndex
+      , New<v8::External>(reinterpret_cast<void *>(enumerator)));
+  }
+
+  if (!data.IsEmpty()) {
+    obj->SetInternalField(imp::kDataIndex, data);
+  }
+
+#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+  tpl->SetHandler(v8::IndexedPropertyHandlerConfiguration(
+      getter_, setter_, query_, deleter_, enumerator_, obj));
+#else
+  tpl->SetIndexedPropertyHandler(
+      getter_
+    , setter_
+    , query_
+    , deleter_
+    , enumerator_
+    , obj);
+#endif
+}
+
+inline void SetCallHandler(
+    v8::Local<v8::FunctionTemplate> tpl
+  , FunctionCallback callback
+  , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
+  HandleScope scope;
+
+  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
+  otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
+  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
+
+  obj->SetInternalField(
+      imp::kFunctionIndex
+    , New<v8::External>(reinterpret_cast<void *>(callback)));
+
+  if (!data.IsEmpty()) {
+    obj->SetInternalField(imp::kDataIndex, data);
+  }
+
+  tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj);
+}
+
+
+inline void SetCallAsFunctionHandler(
+    v8::Local<v8::ObjectTemplate> tpl,
+    FunctionCallback callback,
+    v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
+  HandleScope scope;
+
+  v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
+  otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
+  v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
+
+  obj->SetInternalField(
+      imp::kFunctionIndex
+    , New<v8::External>(reinterpret_cast<void *>(callback)));
+
+  if (!data.IsEmpty()) {
+    obj->SetInternalField(imp::kDataIndex, data);
+  }
+
+  tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj);
+}
+
+//=== Weak Persistent Handling =================================================
+
+#include "nan_weak.h"  // NOLINT(build/include)
+
+//=== ObjectWrap ===============================================================
+
+#include "nan_object_wrap.h"  // NOLINT(build/include)
+
+//=== HiddenValue/Private ======================================================
+
+#include "nan_private.h"  // NOLINT(build/include)
+
+//=== Export ==================================================================
+
+inline
+void
+Export(ADDON_REGISTER_FUNCTION_ARGS_TYPE target, const char *name,
+    FunctionCallback f) {
+  HandleScope scope;
+
+  Set(target, New<v8::String>(name).ToLocalChecked(),
+      GetFunction(New<v8::FunctionTemplate>(f)).ToLocalChecked());
+}
+
+//=== Tap Reverse Binding =====================================================
+
+struct Tap {
+  explicit Tap(v8::Local<v8::Value> t) : t_() {
+    HandleScope scope;
+
+    t_.Reset(To<v8::Object>(t).ToLocalChecked());
+  }
+
+  ~Tap() { t_.Reset(); }  // not sure if neccessary
+
+  inline void plan(int i) {
+    HandleScope scope;
+    v8::Local<v8::Value> arg = New(i);
+    Call("plan", New(t_), 1, &arg);
+  }
+
+  inline void ok(bool isOk, const char *msg = NULL) {
+    HandleScope scope;
+    v8::Local<v8::Value> args[2];
+    args[0] = New(isOk);
+    if (msg) args[1] = New(msg).ToLocalChecked();
+    Call("ok", New(t_), msg ? 2 : 1, args);
+  }
+
+  inline void pass(const char * msg = NULL) {
+    HandleScope scope;
+    v8::Local<v8::Value> hmsg;
+    if (msg) hmsg = New(msg).ToLocalChecked();
+    Call("pass", New(t_), msg ? 1 : 0, &hmsg);
+  }
+
+  inline void end() {
+    HandleScope scope;
+    Call("end", New(t_), 0, NULL);
+  }
+
+ private:
+  Persistent<v8::Object> t_;
+};
+
+#define NAN_STRINGIZE2(x) #x
+#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x)
+#define NAN_TEST_EXPRESSION(expression) \
+  ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression
+
+#define NAN_EXPORT(target, function) Export(target, #function, function)
+
+#undef TYPE_CHECK
+
+//=== Generic Maybefication ===================================================
+
+namespace imp {
+
+template <typename T> struct Maybefier;
+
+template <typename T> struct Maybefier<v8::Local<T> > {
+  inline static MaybeLocal<T> convert(v8::Local<T> v) {
+    return v;
+  }
+};
+
+template <typename T> struct Maybefier<MaybeLocal<T> > {
+  inline static MaybeLocal<T> convert(MaybeLocal<T> v) {
+    return v;
+  }
+};
+
+}  // end of namespace imp
+
+template <typename T, template <typename> class MaybeMaybe>
+inline MaybeLocal<T>
+MakeMaybe(MaybeMaybe<T> v) {
+  return imp::Maybefier<MaybeMaybe<T> >::convert(v);
+}
+
+//=== TypedArrayContents =======================================================
+
+#include "nan_typedarray_contents.h"  // NOLINT(build/include)
+
+//=== JSON =====================================================================
+
+#include "nan_json.h"  // NOLINT(build/include)
+
+}  // end of namespace Nan
+
+#endif  // NAN_H_
diff --git a/input_devices/mag/node_modules/nan/nan_callbacks.h b/input_devices/mag/node_modules/nan/nan_callbacks.h
new file mode 100644
index 00000000..53ede846
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_callbacks.h
@@ -0,0 +1,88 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_CALLBACKS_H_
+#define NAN_CALLBACKS_H_
+
+template<typename T> class FunctionCallbackInfo;
+template<typename T> class PropertyCallbackInfo;
+template<typename T> class Global;
+
+typedef void(*FunctionCallback)(const FunctionCallbackInfo<v8::Value>&);
+typedef void(*GetterCallback)
+    (v8::Local<v8::String>, const PropertyCallbackInfo<v8::Value>&);
+typedef void(*SetterCallback)(
+    v8::Local<v8::String>,
+    v8::Local<v8::Value>,
+    const PropertyCallbackInfo<void>&);
+typedef void(*PropertyGetterCallback)(
+    v8::Local<v8::String>,
+    const PropertyCallbackInfo<v8::Value>&);
+typedef void(*PropertySetterCallback)(
+    v8::Local<v8::String>,
+    v8::Local<v8::Value>,
+    const PropertyCallbackInfo<v8::Value>&);
+typedef void(*PropertyEnumeratorCallback)
+    (const PropertyCallbackInfo<v8::Array>&);
+typedef void(*PropertyDeleterCallback)(
+    v8::Local<v8::String>,
+    const PropertyCallbackInfo<v8::Boolean>&);
+typedef void(*PropertyQueryCallback)(
+    v8::Local<v8::String>,
+    const PropertyCallbackInfo<v8::Integer>&);
+typedef void(*IndexGetterCallback)(
+    uint32_t,
+    const PropertyCallbackInfo<v8::Value>&);
+typedef void(*IndexSetterCallback)(
+    uint32_t,
+    v8::Local<v8::Value>,
+    const PropertyCallbackInfo<v8::Value>&);
+typedef void(*IndexEnumeratorCallback)
+    (const PropertyCallbackInfo<v8::Array>&);
+typedef void(*IndexDeleterCallback)(
+    uint32_t,
+    const PropertyCallbackInfo<v8::Boolean>&);
+typedef void(*IndexQueryCallback)(
+    uint32_t,
+    const PropertyCallbackInfo<v8::Integer>&);
+
+namespace imp {
+typedef v8::Local<v8::AccessorSignature> Sig;
+
+static const int kDataIndex =                    0;
+
+static const int kFunctionIndex =                1;
+static const int kFunctionFieldCount =           2;
+
+static const int kGetterIndex =                  1;
+static const int kSetterIndex =                  2;
+static const int kAccessorFieldCount =           3;
+
+static const int kPropertyGetterIndex =          1;
+static const int kPropertySetterIndex =          2;
+static const int kPropertyEnumeratorIndex =      3;
+static const int kPropertyDeleterIndex =         4;
+static const int kPropertyQueryIndex =           5;
+static const int kPropertyFieldCount =           6;
+
+static const int kIndexPropertyGetterIndex =     1;
+static const int kIndexPropertySetterIndex =     2;
+static const int kIndexPropertyEnumeratorIndex = 3;
+static const int kIndexPropertyDeleterIndex =    4;
+static const int kIndexPropertyQueryIndex =      5;
+static const int kIndexPropertyFieldCount =      6;
+
+}  // end of namespace imp
+
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+# include "nan_callbacks_12_inl.h"  // NOLINT(build/include)
+#else
+# include "nan_callbacks_pre_12_inl.h"  // NOLINT(build/include)
+#endif
+
+#endif  // NAN_CALLBACKS_H_
diff --git a/input_devices/mag/node_modules/nan/nan_callbacks_12_inl.h b/input_devices/mag/node_modules/nan/nan_callbacks_12_inl.h
new file mode 100644
index 00000000..c27b18d8
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_callbacks_12_inl.h
@@ -0,0 +1,514 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_CALLBACKS_12_INL_H_
+#define NAN_CALLBACKS_12_INL_H_
+
+template<typename T>
+class ReturnValue {
+  v8::ReturnValue<T> value_;
+
+ public:
+  template <class S>
+  explicit inline ReturnValue(const v8::ReturnValue<S> &value) :
+      value_(value) {}
+  template <class S>
+  explicit inline ReturnValue(const ReturnValue<S>& that)
+      : value_(that.value_) {
+    TYPE_CHECK(T, S);
+  }
+
+  // Handle setters
+  template <typename S> inline void Set(const v8::Local<S> &handle) {
+    TYPE_CHECK(T, S);
+    value_.Set(handle);
+  }
+
+  template <typename S> inline void Set(const Global<S> &handle) {
+    TYPE_CHECK(T, S);
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) &&                       \
+  (V8_MINOR_VERSION > 5 || (V8_MINOR_VERSION == 5 &&                           \
+  defined(V8_BUILD_NUMBER) && V8_BUILD_NUMBER >= 8))))
+    value_.Set(handle);
+#else
+    value_.Set(*reinterpret_cast<const v8::Persistent<S>*>(&handle));
+    const_cast<Global<S> &>(handle).Reset();
+#endif
+  }
+
+  // Fast primitive setters
+  inline void Set(bool value) {
+    TYPE_CHECK(T, v8::Boolean);
+    value_.Set(value);
+  }
+
+  inline void Set(double i) {
+    TYPE_CHECK(T, v8::Number);
+    value_.Set(i);
+  }
+
+  inline void Set(int32_t i) {
+    TYPE_CHECK(T, v8::Integer);
+    value_.Set(i);
+  }
+
+  inline void Set(uint32_t i) {
+    TYPE_CHECK(T, v8::Integer);
+    value_.Set(i);
+  }
+
+  // Fast JS primitive setters
+  inline void SetNull() {
+    TYPE_CHECK(T, v8::Primitive);
+    value_.SetNull();
+  }
+
+  inline void SetUndefined() {
+    TYPE_CHECK(T, v8::Primitive);
+    value_.SetUndefined();
+  }
+
+  inline void SetEmptyString() {
+    TYPE_CHECK(T, v8::String);
+    value_.SetEmptyString();
+  }
+
+  // Convenience getter for isolate
+  inline v8::Isolate *GetIsolate() const {
+    return value_.GetIsolate();
+  }
+
+  // Pointer setter: Uncompilable to prevent inadvertent misuse.
+  template<typename S>
+  inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); }
+};
+
+template<typename T>
+class FunctionCallbackInfo {
+  const v8::FunctionCallbackInfo<T> &info_;
+  const v8::Local<v8::Value> data_;
+
+ public:
+  explicit inline FunctionCallbackInfo(
+      const v8::FunctionCallbackInfo<T> &info
+    , v8::Local<v8::Value> data) :
+          info_(info)
+        , data_(data) {}
+
+  inline ReturnValue<T> GetReturnValue() const {
+    return ReturnValue<T>(info_.GetReturnValue());
+  }
+
+#if NODE_MAJOR_VERSION < 10
+  inline v8::Local<v8::Function> Callee() const { return info_.Callee(); }
+#endif
+  inline v8::Local<v8::Value> Data() const { return data_; }
+  inline v8::Local<v8::Object> Holder() const { return info_.Holder(); }
+  inline bool IsConstructCall() const { return info_.IsConstructCall(); }
+  inline int Length() const { return info_.Length(); }
+  inline v8::Local<v8::Value> operator[](int i) const { return info_[i]; }
+  inline v8::Local<v8::Object> This() const { return info_.This(); }
+  inline v8::Isolate *GetIsolate() const { return info_.GetIsolate(); }
+
+
+ protected:
+  static const int kHolderIndex = 0;
+  static const int kIsolateIndex = 1;
+  static const int kReturnValueDefaultValueIndex = 2;
+  static const int kReturnValueIndex = 3;
+  static const int kDataIndex = 4;
+  static const int kCalleeIndex = 5;
+  static const int kContextSaveIndex = 6;
+  static const int kArgsLength = 7;
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo)
+};
+
+template<typename T>
+class PropertyCallbackInfo {
+  const v8::PropertyCallbackInfo<T> &info_;
+  const v8::Local<v8::Value> data_;
+
+ public:
+  explicit inline PropertyCallbackInfo(
+      const v8::PropertyCallbackInfo<T> &info
+    , const v8::Local<v8::Value> data) :
+          info_(info)
+        , data_(data) {}
+
+  inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); }
+  inline v8::Local<v8::Value> Data() const { return data_; }
+  inline v8::Local<v8::Object> This() const { return info_.This(); }
+  inline v8::Local<v8::Object> Holder() const { return info_.Holder(); }
+  inline ReturnValue<T> GetReturnValue() const {
+    return ReturnValue<T>(info_.GetReturnValue());
+  }
+
+ protected:
+  static const int kHolderIndex = 0;
+  static const int kIsolateIndex = 1;
+  static const int kReturnValueDefaultValueIndex = 2;
+  static const int kReturnValueIndex = 3;
+  static const int kDataIndex = 4;
+  static const int kThisIndex = 5;
+  static const int kArgsLength = 6;
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfo)
+};
+
+namespace imp {
+static
+void FunctionCallbackWrapper(const v8::FunctionCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  FunctionCallback callback = reinterpret_cast<FunctionCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kFunctionIndex).As<v8::External>()->Value()));
+  FunctionCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  callback(cbinfo);
+}
+
+typedef void (*NativeFunction)(const v8::FunctionCallbackInfo<v8::Value> &);
+
+#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+static
+void GetterCallbackWrapper(
+    v8::Local<v8::Name> property
+  , const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  GetterCallback callback = reinterpret_cast<GetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kGetterIndex).As<v8::External>()->Value()));
+  callback(property.As<v8::String>(), cbinfo);
+}
+
+typedef void (*NativeGetter)
+    (v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void SetterCallbackWrapper(
+    v8::Local<v8::Name> property
+  , v8::Local<v8::Value> value
+  , const v8::PropertyCallbackInfo<void> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<void>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  SetterCallback callback = reinterpret_cast<SetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kSetterIndex).As<v8::External>()->Value()));
+  callback(property.As<v8::String>(), value, cbinfo);
+}
+
+typedef void (*NativeSetter)(
+    v8::Local<v8::Name>
+  , v8::Local<v8::Value>
+  , const v8::PropertyCallbackInfo<void> &);
+#else
+static
+void GetterCallbackWrapper(
+    v8::Local<v8::String> property
+  , const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  GetterCallback callback = reinterpret_cast<GetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kGetterIndex).As<v8::External>()->Value()));
+  callback(property, cbinfo);
+}
+
+typedef void (*NativeGetter)
+    (v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void SetterCallbackWrapper(
+    v8::Local<v8::String> property
+  , v8::Local<v8::Value> value
+  , const v8::PropertyCallbackInfo<void> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<void>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  SetterCallback callback = reinterpret_cast<SetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kSetterIndex).As<v8::External>()->Value()));
+  callback(property, value, cbinfo);
+}
+
+typedef void (*NativeSetter)(
+    v8::Local<v8::String>
+  , v8::Local<v8::Value>
+  , const v8::PropertyCallbackInfo<void> &);
+#endif
+
+#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+static
+void PropertyGetterCallbackWrapper(
+    v8::Local<v8::Name> property
+  , const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyGetterCallback callback = reinterpret_cast<PropertyGetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyGetterIndex)
+              .As<v8::External>()->Value()));
+  callback(property.As<v8::String>(), cbinfo);
+}
+
+typedef void (*NativePropertyGetter)
+    (v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void PropertySetterCallbackWrapper(
+    v8::Local<v8::Name> property
+  , v8::Local<v8::Value> value
+  , const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertySetterCallback callback = reinterpret_cast<PropertySetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertySetterIndex)
+              .As<v8::External>()->Value()));
+  callback(property.As<v8::String>(), value, cbinfo);
+}
+
+typedef void (*NativePropertySetter)(
+    v8::Local<v8::Name>
+  , v8::Local<v8::Value>
+  , const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void PropertyEnumeratorCallbackWrapper(
+    const v8::PropertyCallbackInfo<v8::Array> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Array>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyEnumeratorCallback callback =
+      reinterpret_cast<PropertyEnumeratorCallback>(reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyEnumeratorIndex)
+              .As<v8::External>()->Value()));
+  callback(cbinfo);
+}
+
+typedef void (*NativePropertyEnumerator)
+    (const v8::PropertyCallbackInfo<v8::Array> &);
+
+static
+void PropertyDeleterCallbackWrapper(
+    v8::Local<v8::Name> property
+  , const v8::PropertyCallbackInfo<v8::Boolean> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Boolean>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyDeleterCallback callback = reinterpret_cast<PropertyDeleterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyDeleterIndex)
+              .As<v8::External>()->Value()));
+  callback(property.As<v8::String>(), cbinfo);
+}
+
+typedef void (NativePropertyDeleter)
+    (v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Boolean> &);
+
+static
+void PropertyQueryCallbackWrapper(
+    v8::Local<v8::Name> property
+  , const v8::PropertyCallbackInfo<v8::Integer> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Integer>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyQueryCallback callback = reinterpret_cast<PropertyQueryCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyQueryIndex)
+              .As<v8::External>()->Value()));
+  callback(property.As<v8::String>(), cbinfo);
+}
+
+typedef void (*NativePropertyQuery)
+    (v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Integer> &);
+#else
+static
+void PropertyGetterCallbackWrapper(
+    v8::Local<v8::String> property
+  , const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyGetterCallback callback = reinterpret_cast<PropertyGetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyGetterIndex)
+              .As<v8::External>()->Value()));
+  callback(property, cbinfo);
+}
+
+typedef void (*NativePropertyGetter)
+    (v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void PropertySetterCallbackWrapper(
+    v8::Local<v8::String> property
+  , v8::Local<v8::Value> value
+  , const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertySetterCallback callback = reinterpret_cast<PropertySetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertySetterIndex)
+              .As<v8::External>()->Value()));
+  callback(property, value, cbinfo);
+}
+
+typedef void (*NativePropertySetter)(
+    v8::Local<v8::String>
+  , v8::Local<v8::Value>
+  , const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void PropertyEnumeratorCallbackWrapper(
+    const v8::PropertyCallbackInfo<v8::Array> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Array>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyEnumeratorCallback callback =
+      reinterpret_cast<PropertyEnumeratorCallback>(reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyEnumeratorIndex)
+              .As<v8::External>()->Value()));
+  callback(cbinfo);
+}
+
+typedef void (*NativePropertyEnumerator)
+    (const v8::PropertyCallbackInfo<v8::Array> &);
+
+static
+void PropertyDeleterCallbackWrapper(
+    v8::Local<v8::String> property
+  , const v8::PropertyCallbackInfo<v8::Boolean> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Boolean>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyDeleterCallback callback = reinterpret_cast<PropertyDeleterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyDeleterIndex)
+              .As<v8::External>()->Value()));
+  callback(property, cbinfo);
+}
+
+typedef void (NativePropertyDeleter)
+    (v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean> &);
+
+static
+void PropertyQueryCallbackWrapper(
+    v8::Local<v8::String> property
+  , const v8::PropertyCallbackInfo<v8::Integer> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Integer>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyQueryCallback callback = reinterpret_cast<PropertyQueryCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyQueryIndex)
+              .As<v8::External>()->Value()));
+  callback(property, cbinfo);
+}
+
+typedef void (*NativePropertyQuery)
+    (v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer> &);
+#endif
+
+static
+void IndexGetterCallbackWrapper(
+    uint32_t index, const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexGetterCallback callback = reinterpret_cast<IndexGetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertyGetterIndex)
+              .As<v8::External>()->Value()));
+  callback(index, cbinfo);
+}
+
+typedef void (*NativeIndexGetter)
+    (uint32_t, const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void IndexSetterCallbackWrapper(
+    uint32_t index
+  , v8::Local<v8::Value> value
+  , const v8::PropertyCallbackInfo<v8::Value> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexSetterCallback callback = reinterpret_cast<IndexSetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertySetterIndex)
+              .As<v8::External>()->Value()));
+  callback(index, value, cbinfo);
+}
+
+typedef void (*NativeIndexSetter)(
+    uint32_t
+  , v8::Local<v8::Value>
+  , const v8::PropertyCallbackInfo<v8::Value> &);
+
+static
+void IndexEnumeratorCallbackWrapper(
+    const v8::PropertyCallbackInfo<v8::Array> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Array>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexEnumeratorCallback callback = reinterpret_cast<IndexEnumeratorCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(
+              kIndexPropertyEnumeratorIndex).As<v8::External>()->Value()));
+  callback(cbinfo);
+}
+
+typedef void (*NativeIndexEnumerator)
+    (const v8::PropertyCallbackInfo<v8::Array> &);
+
+static
+void IndexDeleterCallbackWrapper(
+    uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Boolean>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexDeleterCallback callback = reinterpret_cast<IndexDeleterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertyDeleterIndex)
+              .As<v8::External>()->Value()));
+  callback(index, cbinfo);
+}
+
+typedef void (*NativeIndexDeleter)
+    (uint32_t, const v8::PropertyCallbackInfo<v8::Boolean> &);
+
+static
+void IndexQueryCallbackWrapper(
+    uint32_t index, const v8::PropertyCallbackInfo<v8::Integer> &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Integer>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexQueryCallback callback = reinterpret_cast<IndexQueryCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertyQueryIndex)
+              .As<v8::External>()->Value()));
+  callback(index, cbinfo);
+}
+
+typedef void (*NativeIndexQuery)
+    (uint32_t, const v8::PropertyCallbackInfo<v8::Integer> &);
+}  // end of namespace imp
+
+#endif  // NAN_CALLBACKS_12_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_callbacks_pre_12_inl.h b/input_devices/mag/node_modules/nan/nan_callbacks_pre_12_inl.h
new file mode 100644
index 00000000..c9ba4993
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_callbacks_pre_12_inl.h
@@ -0,0 +1,520 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_CALLBACKS_PRE_12_INL_H_
+#define NAN_CALLBACKS_PRE_12_INL_H_
+
+namespace imp {
+template<typename T> class ReturnValueImp;
+}  // end of namespace imp
+
+template<typename T>
+class ReturnValue {
+  v8::Isolate *isolate_;
+  v8::Persistent<T> *value_;
+  friend class imp::ReturnValueImp<T>;
+
+ public:
+  template <class S>
+  explicit inline ReturnValue(v8::Isolate *isolate, v8::Persistent<S> *p) :
+      isolate_(isolate), value_(p) {}
+  template <class S>
+  explicit inline ReturnValue(const ReturnValue<S>& that)
+      : isolate_(that.isolate_), value_(that.value_) {
+    TYPE_CHECK(T, S);
+  }
+
+  // Handle setters
+  template <typename S> inline void Set(const v8::Local<S> &handle) {
+    TYPE_CHECK(T, S);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(handle);
+  }
+
+  template <typename S> inline void Set(const Global<S> &handle) {
+    TYPE_CHECK(T, S);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(handle.persistent);
+    const_cast<Global<S> &>(handle).Reset();
+  }
+
+  // Fast primitive setters
+  inline void Set(bool value) {
+    v8::HandleScope scope;
+
+    TYPE_CHECK(T, v8::Boolean);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(v8::Boolean::New(value));
+  }
+
+  inline void Set(double i) {
+    v8::HandleScope scope;
+
+    TYPE_CHECK(T, v8::Number);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(v8::Number::New(i));
+  }
+
+  inline void Set(int32_t i) {
+    v8::HandleScope scope;
+
+    TYPE_CHECK(T, v8::Integer);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(v8::Int32::New(i));
+  }
+
+  inline void Set(uint32_t i) {
+    v8::HandleScope scope;
+
+    TYPE_CHECK(T, v8::Integer);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(v8::Uint32::NewFromUnsigned(i));
+  }
+
+  // Fast JS primitive setters
+  inline void SetNull() {
+    v8::HandleScope scope;
+
+    TYPE_CHECK(T, v8::Primitive);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(v8::Null());
+  }
+
+  inline void SetUndefined() {
+    v8::HandleScope scope;
+
+    TYPE_CHECK(T, v8::Primitive);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(v8::Undefined());
+  }
+
+  inline void SetEmptyString() {
+    v8::HandleScope scope;
+
+    TYPE_CHECK(T, v8::String);
+    value_->Dispose();
+    *value_ = v8::Persistent<T>::New(v8::String::Empty());
+  }
+
+  // Convenience getter for isolate
+  inline v8::Isolate *GetIsolate() const {
+    return isolate_;
+  }
+
+  // Pointer setter: Uncompilable to prevent inadvertent misuse.
+  template<typename S>
+  inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); }
+};
+
+template<typename T>
+class FunctionCallbackInfo {
+  const v8::Arguments &args_;
+  v8::Local<v8::Value> data_;
+  ReturnValue<T> return_value_;
+  v8::Persistent<T> retval_;
+
+ public:
+  explicit inline FunctionCallbackInfo(
+      const v8::Arguments &args
+    , v8::Local<v8::Value> data) :
+          args_(args)
+        , data_(data)
+        , return_value_(args.GetIsolate(), &retval_)
+        , retval_(v8::Persistent<T>::New(v8::Undefined())) {}
+
+  inline ~FunctionCallbackInfo() {
+    retval_.Dispose();
+    retval_.Clear();
+  }
+
+  inline ReturnValue<T> GetReturnValue() const {
+    return ReturnValue<T>(return_value_);
+  }
+
+  inline v8::Local<v8::Function> Callee() const { return args_.Callee(); }
+  inline v8::Local<v8::Value> Data() const { return data_; }
+  inline v8::Local<v8::Object> Holder() const { return args_.Holder(); }
+  inline bool IsConstructCall() const { return args_.IsConstructCall(); }
+  inline int Length() const { return args_.Length(); }
+  inline v8::Local<v8::Value> operator[](int i) const { return args_[i]; }
+  inline v8::Local<v8::Object> This() const { return args_.This(); }
+  inline v8::Isolate *GetIsolate() const { return args_.GetIsolate(); }
+
+
+ protected:
+  static const int kHolderIndex = 0;
+  static const int kIsolateIndex = 1;
+  static const int kReturnValueDefaultValueIndex = 2;
+  static const int kReturnValueIndex = 3;
+  static const int kDataIndex = 4;
+  static const int kCalleeIndex = 5;
+  static const int kContextSaveIndex = 6;
+  static const int kArgsLength = 7;
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo)
+};
+
+template<typename T>
+class PropertyCallbackInfoBase {
+  const v8::AccessorInfo &info_;
+  const v8::Local<v8::Value> data_;
+
+ public:
+  explicit inline PropertyCallbackInfoBase(
+      const v8::AccessorInfo &info
+    , const v8::Local<v8::Value> data) :
+          info_(info)
+        , data_(data) {}
+
+  inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); }
+  inline v8::Local<v8::Value> Data() const { return data_; }
+  inline v8::Local<v8::Object> This() const { return info_.This(); }
+  inline v8::Local<v8::Object> Holder() const { return info_.Holder(); }
+
+ protected:
+  static const int kHolderIndex = 0;
+  static const int kIsolateIndex = 1;
+  static const int kReturnValueDefaultValueIndex = 2;
+  static const int kReturnValueIndex = 3;
+  static const int kDataIndex = 4;
+  static const int kThisIndex = 5;
+  static const int kArgsLength = 6;
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfoBase)
+};
+
+template<typename T>
+class PropertyCallbackInfo : public PropertyCallbackInfoBase<T> {
+  ReturnValue<T> return_value_;
+  v8::Persistent<T> retval_;
+
+ public:
+  explicit inline PropertyCallbackInfo(
+      const v8::AccessorInfo &info
+    , const v8::Local<v8::Value> data) :
+          PropertyCallbackInfoBase<T>(info, data)
+        , return_value_(info.GetIsolate(), &retval_)
+        , retval_(v8::Persistent<T>::New(v8::Undefined())) {}
+
+  inline ~PropertyCallbackInfo() {
+    retval_.Dispose();
+    retval_.Clear();
+  }
+
+  inline ReturnValue<T> GetReturnValue() const { return return_value_; }
+};
+
+template<>
+class PropertyCallbackInfo<v8::Array> :
+    public PropertyCallbackInfoBase<v8::Array> {
+  ReturnValue<v8::Array> return_value_;
+  v8::Persistent<v8::Array> retval_;
+
+ public:
+  explicit inline PropertyCallbackInfo(
+      const v8::AccessorInfo &info
+    , const v8::Local<v8::Value> data) :
+          PropertyCallbackInfoBase<v8::Array>(info, data)
+        , return_value_(info.GetIsolate(), &retval_)
+        , retval_(v8::Persistent<v8::Array>::New(v8::Local<v8::Array>())) {}
+
+  inline ~PropertyCallbackInfo() {
+    retval_.Dispose();
+    retval_.Clear();
+  }
+
+  inline ReturnValue<v8::Array> GetReturnValue() const {
+    return return_value_;
+  }
+};
+
+template<>
+class PropertyCallbackInfo<v8::Boolean> :
+    public PropertyCallbackInfoBase<v8::Boolean> {
+  ReturnValue<v8::Boolean> return_value_;
+  v8::Persistent<v8::Boolean> retval_;
+
+ public:
+  explicit inline PropertyCallbackInfo(
+      const v8::AccessorInfo &info
+    , const v8::Local<v8::Value> data) :
+          PropertyCallbackInfoBase<v8::Boolean>(info, data)
+        , return_value_(info.GetIsolate(), &retval_)
+        , retval_(v8::Persistent<v8::Boolean>::New(v8::Local<v8::Boolean>())) {}
+
+  inline ~PropertyCallbackInfo() {
+    retval_.Dispose();
+    retval_.Clear();
+  }
+
+  inline ReturnValue<v8::Boolean> GetReturnValue() const {
+    return return_value_;
+  }
+};
+
+template<>
+class PropertyCallbackInfo<v8::Integer> :
+    public PropertyCallbackInfoBase<v8::Integer> {
+  ReturnValue<v8::Integer> return_value_;
+  v8::Persistent<v8::Integer> retval_;
+
+ public:
+  explicit inline PropertyCallbackInfo(
+      const v8::AccessorInfo &info
+    , const v8::Local<v8::Value> data) :
+          PropertyCallbackInfoBase<v8::Integer>(info, data)
+        , return_value_(info.GetIsolate(), &retval_)
+        , retval_(v8::Persistent<v8::Integer>::New(v8::Local<v8::Integer>())) {}
+
+  inline ~PropertyCallbackInfo() {
+    retval_.Dispose();
+    retval_.Clear();
+  }
+
+  inline ReturnValue<v8::Integer> GetReturnValue() const {
+    return return_value_;
+  }
+};
+
+namespace imp {
+template<typename T>
+class ReturnValueImp : public ReturnValue<T> {
+ public:
+  explicit ReturnValueImp(ReturnValue<T> that) :
+      ReturnValue<T>(that) {}
+  inline v8::Handle<T> Value() {
+      return *ReturnValue<T>::value_;
+  }
+};
+
+static
+v8::Handle<v8::Value> FunctionCallbackWrapper(const v8::Arguments &args) {
+  v8::Local<v8::Object> obj = args.Data().As<v8::Object>();
+  FunctionCallback callback = reinterpret_cast<FunctionCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kFunctionIndex).As<v8::External>()->Value()));
+  FunctionCallbackInfo<v8::Value>
+      cbinfo(args, obj->GetInternalField(kDataIndex));
+  callback(cbinfo);
+  return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Value> (*NativeFunction)(const v8::Arguments &);
+
+static
+v8::Handle<v8::Value> GetterCallbackWrapper(
+    v8::Local<v8::String> property, const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  GetterCallback callback = reinterpret_cast<GetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kGetterIndex).As<v8::External>()->Value()));
+  callback(property, cbinfo);
+  return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Value> (*NativeGetter)
+    (v8::Local<v8::String>, const v8::AccessorInfo &);
+
+static
+void SetterCallbackWrapper(
+    v8::Local<v8::String> property
+  , v8::Local<v8::Value> value
+  , const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<void>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  SetterCallback callback = reinterpret_cast<SetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kSetterIndex).As<v8::External>()->Value()));
+  callback(property, value, cbinfo);
+}
+
+typedef void (*NativeSetter)
+    (v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Value> PropertyGetterCallbackWrapper(
+    v8::Local<v8::String> property, const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyGetterCallback callback = reinterpret_cast<PropertyGetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyGetterIndex)
+              .As<v8::External>()->Value()));
+  callback(property, cbinfo);
+  return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Value> (*NativePropertyGetter)
+    (v8::Local<v8::String>, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Value> PropertySetterCallbackWrapper(
+    v8::Local<v8::String> property
+  , v8::Local<v8::Value> value
+  , const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertySetterCallback callback = reinterpret_cast<PropertySetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertySetterIndex)
+              .As<v8::External>()->Value()));
+  callback(property, value, cbinfo);
+  return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Value> (*NativePropertySetter)
+    (v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Array> PropertyEnumeratorCallbackWrapper(
+    const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Array>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyEnumeratorCallback callback =
+      reinterpret_cast<PropertyEnumeratorCallback>(reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyEnumeratorIndex)
+              .As<v8::External>()->Value()));
+  callback(cbinfo);
+  return ReturnValueImp<v8::Array>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Array> (*NativePropertyEnumerator)
+    (const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Boolean> PropertyDeleterCallbackWrapper(
+    v8::Local<v8::String> property
+  , const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Boolean>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyDeleterCallback callback = reinterpret_cast<PropertyDeleterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyDeleterIndex)
+              .As<v8::External>()->Value()));
+  callback(property, cbinfo);
+  return ReturnValueImp<v8::Boolean>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Boolean> (NativePropertyDeleter)
+    (v8::Local<v8::String>, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Integer> PropertyQueryCallbackWrapper(
+    v8::Local<v8::String> property, const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Integer>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  PropertyQueryCallback callback = reinterpret_cast<PropertyQueryCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kPropertyQueryIndex)
+              .As<v8::External>()->Value()));
+  callback(property, cbinfo);
+  return ReturnValueImp<v8::Integer>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Integer> (*NativePropertyQuery)
+    (v8::Local<v8::String>, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Value> IndexGetterCallbackWrapper(
+    uint32_t index, const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexGetterCallback callback = reinterpret_cast<IndexGetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertyGetterIndex)
+              .As<v8::External>()->Value()));
+  callback(index, cbinfo);
+  return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Value> (*NativeIndexGetter)
+    (uint32_t, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Value> IndexSetterCallbackWrapper(
+    uint32_t index
+  , v8::Local<v8::Value> value
+  , const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Value>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexSetterCallback callback = reinterpret_cast<IndexSetterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertySetterIndex)
+              .As<v8::External>()->Value()));
+  callback(index, value, cbinfo);
+  return ReturnValueImp<v8::Value>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Value> (*NativeIndexSetter)
+    (uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Array> IndexEnumeratorCallbackWrapper(
+    const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Array>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexEnumeratorCallback callback = reinterpret_cast<IndexEnumeratorCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertyEnumeratorIndex)
+              .As<v8::External>()->Value()));
+  callback(cbinfo);
+  return ReturnValueImp<v8::Array>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Array> (*NativeIndexEnumerator)
+    (const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Boolean> IndexDeleterCallbackWrapper(
+    uint32_t index, const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Boolean>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexDeleterCallback callback = reinterpret_cast<IndexDeleterCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertyDeleterIndex)
+              .As<v8::External>()->Value()));
+  callback(index, cbinfo);
+  return ReturnValueImp<v8::Boolean>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Boolean> (*NativeIndexDeleter)
+    (uint32_t, const v8::AccessorInfo &);
+
+static
+v8::Handle<v8::Integer> IndexQueryCallbackWrapper(
+    uint32_t index, const v8::AccessorInfo &info) {
+  v8::Local<v8::Object> obj = info.Data().As<v8::Object>();
+  PropertyCallbackInfo<v8::Integer>
+      cbinfo(info, obj->GetInternalField(kDataIndex));
+  IndexQueryCallback callback = reinterpret_cast<IndexQueryCallback>(
+      reinterpret_cast<intptr_t>(
+          obj->GetInternalField(kIndexPropertyQueryIndex)
+              .As<v8::External>()->Value()));
+  callback(index, cbinfo);
+  return ReturnValueImp<v8::Integer>(cbinfo.GetReturnValue()).Value();
+}
+
+typedef v8::Handle<v8::Integer> (*NativeIndexQuery)
+    (uint32_t, const v8::AccessorInfo &);
+}  // end of namespace imp
+
+#endif  // NAN_CALLBACKS_PRE_12_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_converters.h b/input_devices/mag/node_modules/nan/nan_converters.h
new file mode 100644
index 00000000..c0b32729
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_converters.h
@@ -0,0 +1,72 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_CONVERTERS_H_
+#define NAN_CONVERTERS_H_
+
+namespace imp {
+template<typename T> struct ToFactoryBase {
+  typedef MaybeLocal<T> return_t;
+};
+template<typename T> struct ValueFactoryBase { typedef Maybe<T> return_t; };
+
+template<typename T> struct ToFactory;
+
+template<>
+struct ToFactory<v8::Function> : ToFactoryBase<v8::Function> {
+  static inline return_t convert(v8::Local<v8::Value> val) {
+    if (val.IsEmpty() || !val->IsFunction()) return MaybeLocal<v8::Function>();
+    return MaybeLocal<v8::Function>(val.As<v8::Function>());
+  }
+};
+
+#define X(TYPE)                                                                \
+    template<>                                                                 \
+    struct ToFactory<v8::TYPE> : ToFactoryBase<v8::TYPE> {                     \
+      static inline return_t convert(v8::Local<v8::Value> val);                \
+    };
+
+X(Boolean)
+X(Number)
+X(String)
+X(Object)
+X(Integer)
+X(Uint32)
+X(Int32)
+
+#undef X
+
+#define X(TYPE)                                                                \
+    template<>                                                                 \
+    struct ToFactory<TYPE> : ValueFactoryBase<TYPE> {                          \
+      static inline return_t convert(v8::Local<v8::Value> val);                \
+    };
+
+X(bool)
+X(double)
+X(int64_t)
+X(uint32_t)
+X(int32_t)
+
+#undef X
+}  // end of namespace imp
+
+template<typename T>
+inline
+typename imp::ToFactory<T>::return_t To(v8::Local<v8::Value> val) {
+  return imp::ToFactory<T>::convert(val);
+}
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+# include "nan_converters_43_inl.h"
+#else
+# include "nan_converters_pre_43_inl.h"
+#endif
+
+#endif  // NAN_CONVERTERS_H_
diff --git a/input_devices/mag/node_modules/nan/nan_converters_43_inl.h b/input_devices/mag/node_modules/nan/nan_converters_43_inl.h
new file mode 100644
index 00000000..742f5432
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_converters_43_inl.h
@@ -0,0 +1,48 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_CONVERTERS_43_INL_H_
+#define NAN_CONVERTERS_43_INL_H_
+
+#define X(TYPE)                                                                \
+imp::ToFactory<v8::TYPE>::return_t                                             \
+imp::ToFactory<v8::TYPE>::convert(v8::Local<v8::Value> val) {                  \
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();                            \
+  v8::EscapableHandleScope scope(isolate);                                     \
+  return scope.Escape(                                                         \
+      val->To ## TYPE(isolate->GetCurrentContext())                            \
+          .FromMaybe(v8::Local<v8::TYPE>()));                                  \
+}
+
+X(Boolean)
+X(Number)
+X(String)
+X(Object)
+X(Integer)
+X(Uint32)
+X(Int32)
+
+#undef X
+
+#define X(TYPE, NAME)                                                          \
+imp::ToFactory<TYPE>::return_t                                                 \
+imp::ToFactory<TYPE>::convert(v8::Local<v8::Value> val) {                      \
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();                            \
+  v8::HandleScope scope(isolate);                                              \
+  return val->NAME ## Value(isolate->GetCurrentContext());                     \
+}
+
+X(bool, Boolean)
+X(double, Number)
+X(int64_t, Integer)
+X(uint32_t, Uint32)
+X(int32_t, Int32)
+
+#undef X
+
+#endif  // NAN_CONVERTERS_43_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_converters_pre_43_inl.h b/input_devices/mag/node_modules/nan/nan_converters_pre_43_inl.h
new file mode 100644
index 00000000..ae0518aa
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_converters_pre_43_inl.h
@@ -0,0 +1,42 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_CONVERTERS_PRE_43_INL_H_
+#define NAN_CONVERTERS_PRE_43_INL_H_
+
+#define X(TYPE)                                                                \
+imp::ToFactory<v8::TYPE>::return_t                                             \
+imp::ToFactory<v8::TYPE>::convert(v8::Local<v8::Value> val) {                  \
+  return val->To ## TYPE();                                                    \
+}
+
+X(Boolean)
+X(Number)
+X(String)
+X(Object)
+X(Integer)
+X(Uint32)
+X(Int32)
+
+#undef X
+
+#define X(TYPE, NAME)                                                          \
+imp::ToFactory<TYPE>::return_t                                                 \
+imp::ToFactory<TYPE>::convert(v8::Local<v8::Value> val) {                      \
+  return Just(val->NAME ## Value());                                           \
+}
+
+X(bool, Boolean)
+X(double, Number)
+X(int64_t, Integer)
+X(uint32_t, Uint32)
+X(int32_t, Int32)
+
+#undef X
+
+#endif  // NAN_CONVERTERS_PRE_43_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_define_own_property_helper.h b/input_devices/mag/node_modules/nan/nan_define_own_property_helper.h
new file mode 100644
index 00000000..d710ef22
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_define_own_property_helper.h
@@ -0,0 +1,29 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_DEFINE_OWN_PROPERTY_HELPER_H_
+#define NAN_DEFINE_OWN_PROPERTY_HELPER_H_
+
+namespace imp {
+
+inline Maybe<bool> DefineOwnPropertyHelper(
+    v8::PropertyAttribute current
+  , v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key
+  , v8::Handle<v8::Value> value
+  , v8::PropertyAttribute attribs = v8::None) {
+  return !(current & v8::DontDelete) ||                     // configurable OR
+                  (!(current & v8::ReadOnly) &&             // writable AND
+                   !((attribs ^ current) & ~v8::ReadOnly))  // same excluding RO
+             ? Just<bool>(obj->ForceSet(key, value, attribs))
+             : Nothing<bool>();
+}
+
+}  // end of namespace imp
+
+#endif  // NAN_DEFINE_OWN_PROPERTY_HELPER_H_
diff --git a/input_devices/mag/node_modules/nan/nan_implementation_12_inl.h b/input_devices/mag/node_modules/nan/nan_implementation_12_inl.h
new file mode 100644
index 00000000..1bf6e052
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_implementation_12_inl.h
@@ -0,0 +1,403 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_IMPLEMENTATION_12_INL_H_
+#define NAN_IMPLEMENTATION_12_INL_H_
+//==============================================================================
+// node v0.11 implementation
+//==============================================================================
+
+namespace imp {
+
+//=== Array ====================================================================
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New() {
+  return v8::Array::New(v8::Isolate::GetCurrent());
+}
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New(int length) {
+  return v8::Array::New(v8::Isolate::GetCurrent(), length);
+}
+
+//=== Boolean ==================================================================
+
+Factory<v8::Boolean>::return_t
+Factory<v8::Boolean>::New(bool value) {
+  return v8::Boolean::New(v8::Isolate::GetCurrent(), value);
+}
+
+//=== Boolean Object ===========================================================
+
+Factory<v8::BooleanObject>::return_t
+Factory<v8::BooleanObject>::New(bool value) {
+#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION)
+  return v8::BooleanObject::New(
+    v8::Isolate::GetCurrent(), value).As<v8::BooleanObject>();
+#else
+  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
+#endif
+}
+
+//=== Context ==================================================================
+
+Factory<v8::Context>::return_t
+Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
+                         , v8::Local<v8::ObjectTemplate> tmpl
+                         , v8::Local<v8::Value> obj) {
+  return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj);
+}
+
+//=== Date =====================================================================
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+Factory<v8::Date>::return_t
+Factory<v8::Date>::New(double value) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(v8::Date::New(isolate->GetCurrentContext(), value)
+      .FromMaybe(v8::Local<v8::Value>()).As<v8::Date>());
+}
+#else
+Factory<v8::Date>::return_t
+Factory<v8::Date>::New(double value) {
+  return v8::Date::New(v8::Isolate::GetCurrent(), value).As<v8::Date>();
+}
+#endif
+
+//=== External =================================================================
+
+Factory<v8::External>::return_t
+Factory<v8::External>::New(void * value) {
+  return v8::External::New(v8::Isolate::GetCurrent(), value);
+}
+
+//=== Function =================================================================
+
+Factory<v8::Function>::return_t
+Factory<v8::Function>::New( FunctionCallback callback
+                          , v8::Local<v8::Value> data) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  v8::Local<v8::ObjectTemplate> tpl = v8::ObjectTemplate::New(isolate);
+  tpl->SetInternalFieldCount(imp::kFunctionFieldCount);
+  v8::Local<v8::Object> obj = NewInstance(tpl).ToLocalChecked();
+
+  obj->SetInternalField(
+      imp::kFunctionIndex
+    , v8::External::New(isolate, reinterpret_cast<void *>(callback)));
+
+  v8::Local<v8::Value> val = v8::Local<v8::Value>::New(isolate, data);
+
+  if (!val.IsEmpty()) {
+    obj->SetInternalField(imp::kDataIndex, val);
+  }
+
+  return scope.Escape(v8::Function::New( isolate
+                          , imp::FunctionCallbackWrapper
+                          , obj));
+}
+
+//=== Function Template ========================================================
+
+Factory<v8::FunctionTemplate>::return_t
+Factory<v8::FunctionTemplate>::New( FunctionCallback callback
+                                  , v8::Local<v8::Value> data
+                                  , v8::Local<v8::Signature> signature) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  if (callback) {
+    v8::EscapableHandleScope scope(isolate);
+    v8::Local<v8::ObjectTemplate> tpl = v8::ObjectTemplate::New(isolate);
+    tpl->SetInternalFieldCount(imp::kFunctionFieldCount);
+    v8::Local<v8::Object> obj = NewInstance(tpl).ToLocalChecked();
+
+    obj->SetInternalField(
+        imp::kFunctionIndex
+      , v8::External::New(isolate, reinterpret_cast<void *>(callback)));
+    v8::Local<v8::Value> val = v8::Local<v8::Value>::New(isolate, data);
+
+    if (!val.IsEmpty()) {
+      obj->SetInternalField(imp::kDataIndex, val);
+    }
+
+    return scope.Escape(v8::FunctionTemplate::New( isolate
+                                    , imp::FunctionCallbackWrapper
+                                    , obj
+                                    , signature));
+  } else {
+    return v8::FunctionTemplate::New(isolate, 0, data, signature);
+  }
+}
+
+//=== Number ===================================================================
+
+Factory<v8::Number>::return_t
+Factory<v8::Number>::New(double value) {
+  return v8::Number::New(v8::Isolate::GetCurrent(), value);
+}
+
+//=== Number Object ============================================================
+
+Factory<v8::NumberObject>::return_t
+Factory<v8::NumberObject>::New(double value) {
+  return v8::NumberObject::New( v8::Isolate::GetCurrent()
+                              , value).As<v8::NumberObject>();
+}
+
+//=== Integer, Int32 and Uint32 ================================================
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(int32_t value) {
+  return To<T>(T::New(v8::Isolate::GetCurrent(), value));
+}
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(uint32_t value) {
+  return To<T>(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(int32_t value) {
+  return To<v8::Uint32>(
+      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(uint32_t value) {
+  return To<v8::Uint32>(
+      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
+}
+
+//=== Object ===================================================================
+
+Factory<v8::Object>::return_t
+Factory<v8::Object>::New() {
+  return v8::Object::New(v8::Isolate::GetCurrent());
+}
+
+//=== Object Template ==========================================================
+
+Factory<v8::ObjectTemplate>::return_t
+Factory<v8::ObjectTemplate>::New() {
+  return v8::ObjectTemplate::New(v8::Isolate::GetCurrent());
+}
+
+//=== RegExp ===================================================================
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+Factory<v8::RegExp>::return_t
+Factory<v8::RegExp>::New(
+    v8::Local<v8::String> pattern
+  , v8::RegExp::Flags flags) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(
+      v8::RegExp::New(isolate->GetCurrentContext(), pattern, flags)
+          .FromMaybe(v8::Local<v8::RegExp>()));
+}
+#else
+Factory<v8::RegExp>::return_t
+Factory<v8::RegExp>::New(
+    v8::Local<v8::String> pattern
+  , v8::RegExp::Flags flags) {
+  return v8::RegExp::New(pattern, flags);
+}
+#endif
+
+//=== Script ===================================================================
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  v8::ScriptCompiler::Source src(source);
+  return scope.Escape(
+      v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src)
+          .FromMaybe(v8::Local<v8::Script>()));
+}
+
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source
+                        , v8::ScriptOrigin const& origin) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  v8::ScriptCompiler::Source src(source, origin);
+  return scope.Escape(
+      v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src)
+          .FromMaybe(v8::Local<v8::Script>()));
+}
+#else
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source) {
+  v8::ScriptCompiler::Source src(source);
+  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
+}
+
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source
+                        , v8::ScriptOrigin const& origin) {
+  v8::ScriptCompiler::Source src(source, origin);
+  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
+}
+#endif
+
+//=== Signature ================================================================
+
+Factory<v8::Signature>::return_t
+Factory<v8::Signature>::New(Factory<v8::Signature>::FTH receiver) {
+  return v8::Signature::New(v8::Isolate::GetCurrent(), receiver);
+}
+
+//=== String ===================================================================
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New() {
+  return v8::String::Empty(v8::Isolate::GetCurrent());
+}
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const char * value, int length) {
+  return v8::String::NewFromUtf8(
+      v8::Isolate::GetCurrent(), value, v8::NewStringType::kNormal, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(std::string const& value) {
+  assert(value.size() <= INT_MAX && "string too long");
+  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(),
+      value.data(), v8::NewStringType::kNormal, static_cast<int>(value.size()));
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const uint16_t * value, int length) {
+  return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value,
+        v8::NewStringType::kNormal, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
+  return v8::String::NewExternalTwoByte(v8::Isolate::GetCurrent(), value);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(ExternalOneByteStringResource * value) {
+  return v8::String::NewExternalOneByte(v8::Isolate::GetCurrent(), value);
+}
+#else
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const char * value, int length) {
+  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value,
+                                 v8::String::kNormalString, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(
+    std::string const& value) /* NOLINT(build/include_what_you_use) */ {
+  assert(value.size() <= INT_MAX && "string too long");
+  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value.data(),
+                                 v8::String::kNormalString,
+                                 static_cast<int>(value.size()));
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const uint16_t * value, int length) {
+  return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value,
+                                    v8::String::kNormalString, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
+  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(ExternalOneByteStringResource * value) {
+  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
+}
+#endif
+
+//=== String Object ============================================================
+
+Factory<v8::StringObject>::return_t
+Factory<v8::StringObject>::New(v8::Local<v8::String> value) {
+#if V8_MAJOR_VERSION >= 7
+  return v8::StringObject::New(v8::Isolate::GetCurrent(), value).As<v8::StringObject>();
+#else
+  return v8::StringObject::New(value).As<v8::StringObject>();
+#endif
+}
+
+//=== Unbound Script ===========================================================
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+Factory<v8::UnboundScript>::return_t
+Factory<v8::UnboundScript>::New(v8::Local<v8::String> source) {
+  v8::ScriptCompiler::Source src(source);
+  return v8::ScriptCompiler::CompileUnboundScript(
+      v8::Isolate::GetCurrent(), &src);
+}
+
+Factory<v8::UnboundScript>::return_t
+Factory<v8::UnboundScript>::New( v8::Local<v8::String> source
+                               , v8::ScriptOrigin const& origin) {
+  v8::ScriptCompiler::Source src(source, origin);
+  return v8::ScriptCompiler::CompileUnboundScript(
+      v8::Isolate::GetCurrent(), &src);
+}
+#else
+Factory<v8::UnboundScript>::return_t
+Factory<v8::UnboundScript>::New(v8::Local<v8::String> source) {
+  v8::ScriptCompiler::Source src(source);
+  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
+}
+
+Factory<v8::UnboundScript>::return_t
+Factory<v8::UnboundScript>::New( v8::Local<v8::String> source
+                               , v8::ScriptOrigin const& origin) {
+  v8::ScriptCompiler::Source src(source, origin);
+  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
+}
+#endif
+
+}  // end of namespace imp
+
+//=== Presistents and Handles ==================================================
+
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+template <typename T>
+inline v8::Local<T> New(v8::Handle<T> h) {
+  return v8::Local<T>::New(v8::Isolate::GetCurrent(), h);
+}
+#endif
+
+template <typename T, typename M>
+inline v8::Local<T> New(v8::Persistent<T, M> const& p) {
+  return v8::Local<T>::New(v8::Isolate::GetCurrent(), p);
+}
+
+template <typename T, typename M>
+inline v8::Local<T> New(Persistent<T, M> const& p) {
+  return v8::Local<T>::New(v8::Isolate::GetCurrent(), p);
+}
+
+template <typename T>
+inline v8::Local<T> New(Global<T> const& p) {
+  return v8::Local<T>::New(v8::Isolate::GetCurrent(), p);
+}
+
+#endif  // NAN_IMPLEMENTATION_12_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_implementation_pre_12_inl.h b/input_devices/mag/node_modules/nan/nan_implementation_pre_12_inl.h
new file mode 100644
index 00000000..1472421a
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_implementation_pre_12_inl.h
@@ -0,0 +1,263 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_
+#define NAN_IMPLEMENTATION_PRE_12_INL_H_
+
+//==============================================================================
+// node v0.10 implementation
+//==============================================================================
+
+namespace imp {
+
+//=== Array ====================================================================
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New() {
+  return v8::Array::New();
+}
+
+Factory<v8::Array>::return_t
+Factory<v8::Array>::New(int length) {
+  return v8::Array::New(length);
+}
+
+//=== Boolean ==================================================================
+
+Factory<v8::Boolean>::return_t
+Factory<v8::Boolean>::New(bool value) {
+  return v8::Boolean::New(value)->ToBoolean();
+}
+
+//=== Boolean Object ===========================================================
+
+Factory<v8::BooleanObject>::return_t
+Factory<v8::BooleanObject>::New(bool value) {
+  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
+}
+
+//=== Context ==================================================================
+
+Factory<v8::Context>::return_t
+Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
+                         , v8::Local<v8::ObjectTemplate> tmpl
+                         , v8::Local<v8::Value> obj) {
+  v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
+  v8::Local<v8::Context> lctx = v8::Local<v8::Context>::New(ctx);
+  ctx.Dispose();
+  return lctx;
+}
+
+//=== Date =====================================================================
+
+Factory<v8::Date>::return_t
+Factory<v8::Date>::New(double value) {
+  return v8::Date::New(value).As<v8::Date>();
+}
+
+//=== External =================================================================
+
+Factory<v8::External>::return_t
+Factory<v8::External>::New(void * value) {
+  return v8::External::New(value);
+}
+
+//=== Function =================================================================
+
+Factory<v8::Function>::return_t
+Factory<v8::Function>::New( FunctionCallback callback
+                          , v8::Local<v8::Value> data) {
+  v8::HandleScope scope;
+
+  return scope.Close(Factory<v8::FunctionTemplate>::New(
+                         callback, data, v8::Local<v8::Signature>())
+                         ->GetFunction());
+}
+
+
+//=== FunctionTemplate =========================================================
+
+Factory<v8::FunctionTemplate>::return_t
+Factory<v8::FunctionTemplate>::New( FunctionCallback callback
+                                  , v8::Local<v8::Value> data
+                                  , v8::Local<v8::Signature> signature) {
+  if (callback) {
+    v8::HandleScope scope;
+
+    v8::Local<v8::ObjectTemplate> tpl = v8::ObjectTemplate::New();
+    tpl->SetInternalFieldCount(imp::kFunctionFieldCount);
+    v8::Local<v8::Object> obj = tpl->NewInstance();
+
+    obj->SetInternalField(
+        imp::kFunctionIndex
+      , v8::External::New(reinterpret_cast<void *>(callback)));
+
+    v8::Local<v8::Value> val = v8::Local<v8::Value>::New(data);
+
+    if (!val.IsEmpty()) {
+      obj->SetInternalField(imp::kDataIndex, val);
+    }
+
+    // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find
+    // a way. Have at it though...
+    return scope.Close(
+        v8::FunctionTemplate::New(imp::FunctionCallbackWrapper
+                                 , obj
+                                 , signature));
+  } else {
+    return v8::FunctionTemplate::New(0, data, signature);
+  }
+}
+
+//=== Number ===================================================================
+
+Factory<v8::Number>::return_t
+Factory<v8::Number>::New(double value) {
+  return v8::Number::New(value);
+}
+
+//=== Number Object ============================================================
+
+Factory<v8::NumberObject>::return_t
+Factory<v8::NumberObject>::New(double value) {
+  return v8::NumberObject::New(value).As<v8::NumberObject>();
+}
+
+//=== Integer, Int32 and Uint32 ================================================
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(int32_t value) {
+  return To<T>(T::New(value));
+}
+
+template <typename T>
+typename IntegerFactory<T>::return_t
+IntegerFactory<T>::New(uint32_t value) {
+  return To<T>(T::NewFromUnsigned(value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(int32_t value) {
+  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
+}
+
+Factory<v8::Uint32>::return_t
+Factory<v8::Uint32>::New(uint32_t value) {
+  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
+}
+
+
+//=== Object ===================================================================
+
+Factory<v8::Object>::return_t
+Factory<v8::Object>::New() {
+  return v8::Object::New();
+}
+
+//=== Object Template ==========================================================
+
+Factory<v8::ObjectTemplate>::return_t
+Factory<v8::ObjectTemplate>::New() {
+  return v8::ObjectTemplate::New();
+}
+
+//=== RegExp ===================================================================
+
+Factory<v8::RegExp>::return_t
+Factory<v8::RegExp>::New(
+    v8::Local<v8::String> pattern
+  , v8::RegExp::Flags flags) {
+  return v8::RegExp::New(pattern, flags);
+}
+
+//=== Script ===================================================================
+
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source) {
+  return v8::Script::New(source);
+}
+Factory<v8::Script>::return_t
+Factory<v8::Script>::New( v8::Local<v8::String> source
+                        , v8::ScriptOrigin const& origin) {
+  return v8::Script::New(source, const_cast<v8::ScriptOrigin*>(&origin));
+}
+
+//=== Signature ================================================================
+
+Factory<v8::Signature>::return_t
+Factory<v8::Signature>::New(Factory<v8::Signature>::FTH receiver) {
+  return v8::Signature::New(receiver);
+}
+
+//=== String ===================================================================
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New() {
+  return v8::String::Empty();
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const char * value, int length) {
+  return v8::String::New(value, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(
+    std::string const& value) /* NOLINT(build/include_what_you_use) */ {
+  assert(value.size() <= INT_MAX && "string too long");
+  return v8::String::New(value.data(), static_cast<int>(value.size()));
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(const uint16_t * value, int length) {
+  return v8::String::New(value, length);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
+  return v8::String::NewExternal(value);
+}
+
+Factory<v8::String>::return_t
+Factory<v8::String>::New(v8::String::ExternalAsciiStringResource * value) {
+  return v8::String::NewExternal(value);
+}
+
+//=== String Object ============================================================
+
+Factory<v8::StringObject>::return_t
+Factory<v8::StringObject>::New(v8::Local<v8::String> value) {
+  return v8::StringObject::New(value).As<v8::StringObject>();
+}
+
+}  // end of namespace imp
+
+//=== Presistents and Handles ==================================================
+
+template <typename T>
+inline v8::Local<T> New(v8::Handle<T> h) {
+  return v8::Local<T>::New(h);
+}
+
+template <typename T>
+inline v8::Local<T> New(v8::Persistent<T> const& p) {
+  return v8::Local<T>::New(p);
+}
+
+template <typename T, typename M>
+inline v8::Local<T> New(Persistent<T, M> const& p) {
+  return v8::Local<T>::New(p.persistent);
+}
+
+template <typename T>
+inline v8::Local<T> New(Global<T> const& p) {
+  return v8::Local<T>::New(p.persistent);
+}
+
+#endif  // NAN_IMPLEMENTATION_PRE_12_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_json.h b/input_devices/mag/node_modules/nan/nan_json.h
new file mode 100644
index 00000000..33ac8ba6
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_json.h
@@ -0,0 +1,166 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_JSON_H_
+#define NAN_JSON_H_
+
+#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
+#define NAN_JSON_H_NEED_PARSE 1
+#else
+#define NAN_JSON_H_NEED_PARSE 0
+#endif  // NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
+
+#if NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION
+#define NAN_JSON_H_NEED_STRINGIFY 0
+#else
+#define NAN_JSON_H_NEED_STRINGIFY 1
+#endif  // NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION
+
+class JSON {
+ public:
+  JSON() {
+#if NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY
+    Nan::HandleScope scope;
+
+    Nan::MaybeLocal<v8::Value> maybe_global_json = Nan::Get(
+      Nan::GetCurrentContext()->Global(),
+      Nan::New("JSON").ToLocalChecked()
+    );
+
+    assert(!maybe_global_json.IsEmpty() && "global JSON is empty");
+    v8::Local<v8::Value> val_global_json = maybe_global_json.ToLocalChecked();
+
+    assert(val_global_json->IsObject() && "global JSON is not an object");
+    Nan::MaybeLocal<v8::Object> maybe_obj_global_json =
+      Nan::To<v8::Object>(val_global_json);
+
+    assert(!maybe_obj_global_json.IsEmpty() && "global JSON object is empty");
+    v8::Local<v8::Object> global_json = maybe_obj_global_json.ToLocalChecked();
+
+#if NAN_JSON_H_NEED_PARSE
+    Nan::MaybeLocal<v8::Value> maybe_parse_method = Nan::Get(
+      global_json, Nan::New("parse").ToLocalChecked()
+    );
+
+    assert(!maybe_parse_method.IsEmpty() && "JSON.parse is empty");
+    v8::Local<v8::Value> parse_method = maybe_parse_method.ToLocalChecked();
+
+    assert(parse_method->IsFunction() && "JSON.parse is not a function");
+    parse_cb_.Reset(parse_method.As<v8::Function>());
+#endif  // NAN_JSON_H_NEED_PARSE
+
+#if NAN_JSON_H_NEED_STRINGIFY
+    Nan::MaybeLocal<v8::Value> maybe_stringify_method = Nan::Get(
+      global_json, Nan::New("stringify").ToLocalChecked()
+    );
+
+    assert(!maybe_stringify_method.IsEmpty() && "JSON.stringify is empty");
+    v8::Local<v8::Value> stringify_method =
+      maybe_stringify_method.ToLocalChecked();
+
+    assert(
+      stringify_method->IsFunction() && "JSON.stringify is not a function"
+    );
+    stringify_cb_.Reset(stringify_method.As<v8::Function>());
+#endif  // NAN_JSON_H_NEED_STRINGIFY
+#endif  // NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY
+  }
+
+  inline
+  Nan::MaybeLocal<v8::Value> Parse(v8::Local<v8::String> json_string) {
+    Nan::EscapableHandleScope scope;
+#if NAN_JSON_H_NEED_PARSE
+    return scope.Escape(parse(json_string));
+#else
+    Nan::MaybeLocal<v8::Value> result;
+#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && \
+    NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION
+    result = v8::JSON::Parse(json_string);
+#else
+#if NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION
+    v8::Local<v8::Context> context_or_isolate = Nan::GetCurrentContext();
+#else
+    v8::Isolate* context_or_isolate = v8::Isolate::GetCurrent();
+#endif  // NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION
+    result = v8::JSON::Parse(context_or_isolate, json_string);
+#endif  // NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION &&
+        // NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION
+    if (result.IsEmpty()) return v8::Local<v8::Value>();
+    return scope.Escape(result.ToLocalChecked());
+#endif  // NAN_JSON_H_NEED_PARSE
+  }
+
+  inline
+  Nan::MaybeLocal<v8::String> Stringify(v8::Local<v8::Object> json_object) {
+    Nan::EscapableHandleScope scope;
+    Nan::MaybeLocal<v8::String> result =
+#if NAN_JSON_H_NEED_STRINGIFY
+      Nan::To<v8::String>(stringify(json_object));
+#else
+      v8::JSON::Stringify(Nan::GetCurrentContext(), json_object);
+#endif  // NAN_JSON_H_NEED_STRINGIFY
+    if (result.IsEmpty()) return v8::Local<v8::String>();
+    return scope.Escape(result.ToLocalChecked());
+  }
+
+  inline
+  Nan::MaybeLocal<v8::String> Stringify(v8::Local<v8::Object> json_object,
+    v8::Local<v8::String> gap) {
+    Nan::EscapableHandleScope scope;
+    Nan::MaybeLocal<v8::String> result =
+#if NAN_JSON_H_NEED_STRINGIFY
+      Nan::To<v8::String>(stringify(json_object, gap));
+#else
+      v8::JSON::Stringify(Nan::GetCurrentContext(), json_object, gap);
+#endif  // NAN_JSON_H_NEED_STRINGIFY
+    if (result.IsEmpty()) return v8::Local<v8::String>();
+    return scope.Escape(result.ToLocalChecked());
+  }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(JSON)
+#if NAN_JSON_H_NEED_PARSE
+  Nan::Callback parse_cb_;
+#endif  // NAN_JSON_H_NEED_PARSE
+#if NAN_JSON_H_NEED_STRINGIFY
+  Nan::Callback stringify_cb_;
+#endif  // NAN_JSON_H_NEED_STRINGIFY
+
+#if NAN_JSON_H_NEED_PARSE
+  inline v8::Local<v8::Value> parse(v8::Local<v8::Value> arg) {
+    assert(!parse_cb_.IsEmpty() && "parse_cb_ is empty");
+    AsyncResource resource("nan:JSON.parse");
+    return parse_cb_.Call(1, &arg, &resource).FromMaybe(v8::Local<v8::Value>());
+  }
+#endif  // NAN_JSON_H_NEED_PARSE
+
+#if NAN_JSON_H_NEED_STRINGIFY
+  inline v8::Local<v8::Value> stringify(v8::Local<v8::Value> arg) {
+    assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty");
+    AsyncResource resource("nan:JSON.stringify");
+    return stringify_cb_.Call(1, &arg, &resource)
+        .FromMaybe(v8::Local<v8::Value>());
+  }
+
+  inline v8::Local<v8::Value> stringify(v8::Local<v8::Value> arg,
+    v8::Local<v8::String> gap) {
+    assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty");
+
+    v8::Local<v8::Value> argv[] = {
+      arg,
+      Nan::Null(),
+      gap
+    };
+    AsyncResource resource("nan:JSON.stringify");
+    return stringify_cb_.Call(3, argv, &resource)
+        .FromMaybe(v8::Local<v8::Value>());
+  }
+#endif  // NAN_JSON_H_NEED_STRINGIFY
+};
+
+#endif  // NAN_JSON_H_
diff --git a/input_devices/mag/node_modules/nan/nan_maybe_43_inl.h b/input_devices/mag/node_modules/nan/nan_maybe_43_inl.h
new file mode 100644
index 00000000..91783da6
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_maybe_43_inl.h
@@ -0,0 +1,369 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_MAYBE_43_INL_H_
+#define NAN_MAYBE_43_INL_H_
+
+template<typename T>
+using MaybeLocal = v8::MaybeLocal<T>;
+
+template<typename T>
+using Maybe = v8::Maybe<T>;
+
+template<typename T>
+inline Maybe<T> Nothing() {
+  return v8::Nothing<T>();
+}
+
+template<typename T>
+inline Maybe<T> Just(const T& t) {
+  return v8::Just<T>(t);
+}
+
+inline
+MaybeLocal<v8::String> ToDetailString(v8::Local<v8::Value> val) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(val->ToDetailString(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::String>()));
+}
+
+inline
+MaybeLocal<v8::Uint32> ToArrayIndex(v8::Local<v8::Value> val) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(val->ToArrayIndex(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::Uint32>()));
+}
+
+inline
+Maybe<bool> Equals(v8::Local<v8::Value> a, v8::Local<v8::Value>(b)) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return a->Equals(isolate->GetCurrentContext(), b);
+}
+
+inline
+MaybeLocal<v8::Object> NewInstance(v8::Local<v8::Function> h) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(h->NewInstance(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::Object>()));
+}
+
+inline
+MaybeLocal<v8::Object> NewInstance(
+      v8::Local<v8::Function> h
+    , int argc
+    , v8::Local<v8::Value> argv[]) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(h->NewInstance(isolate->GetCurrentContext(), argc, argv)
+                          .FromMaybe(v8::Local<v8::Object>()));
+}
+
+inline
+MaybeLocal<v8::Object> NewInstance(v8::Local<v8::ObjectTemplate> h) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(h->NewInstance(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::Object>()));
+}
+
+
+inline MaybeLocal<v8::Function> GetFunction(
+    v8::Local<v8::FunctionTemplate> t) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(t->GetFunction(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::Function>()));
+}
+
+inline Maybe<bool> Set(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::Value> key
+  , v8::Local<v8::Value> value) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->Set(isolate->GetCurrentContext(), key, value);
+}
+
+inline Maybe<bool> Set(
+    v8::Local<v8::Object> obj
+  , uint32_t index
+  , v8::Local<v8::Value> value) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->Set(isolate->GetCurrentContext(), index, value);
+}
+
+#if NODE_MODULE_VERSION < NODE_4_0_MODULE_VERSION
+#include "nan_define_own_property_helper.h"  // NOLINT(build/include)
+#endif
+
+inline Maybe<bool> DefineOwnProperty(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key
+  , v8::Local<v8::Value> value
+  , v8::PropertyAttribute attribs = v8::None) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+#if NODE_MODULE_VERSION >= NODE_4_0_MODULE_VERSION
+  return obj->DefineOwnProperty(isolate->GetCurrentContext(), key, value,
+                                attribs);
+#else
+  Maybe<v8::PropertyAttribute> maybeCurrent =
+      obj->GetPropertyAttributes(isolate->GetCurrentContext(), key);
+  if (maybeCurrent.IsNothing()) {
+    return Nothing<bool>();
+  }
+  v8::PropertyAttribute current = maybeCurrent.FromJust();
+  return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs);
+#endif
+}
+
+NAN_DEPRECATED inline Maybe<bool> ForceSet(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::Value> key
+  , v8::Local<v8::Value> value
+  , v8::PropertyAttribute attribs = v8::None) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION
+  return key->IsName()
+             ? obj->DefineOwnProperty(isolate->GetCurrentContext(),
+                                      key.As<v8::Name>(), value, attribs)
+             : Nothing<bool>();
+#else
+  return obj->ForceSet(isolate->GetCurrentContext(), key, value, attribs);
+#endif
+}
+
+inline MaybeLocal<v8::Value> Get(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::Value> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(obj->Get(isolate->GetCurrentContext(), key)
+                          .FromMaybe(v8::Local<v8::Value>()));
+}
+
+inline
+MaybeLocal<v8::Value> Get(v8::Local<v8::Object> obj, uint32_t index) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(obj->Get(isolate->GetCurrentContext(), index)
+                          .FromMaybe(v8::Local<v8::Value>()));
+}
+
+inline v8::PropertyAttribute GetPropertyAttributes(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::Value> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->GetPropertyAttributes(isolate->GetCurrentContext(), key)
+      .FromJust();
+}
+
+inline Maybe<bool> Has(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->Has(isolate->GetCurrentContext(), key);
+}
+
+inline Maybe<bool> Has(v8::Local<v8::Object> obj, uint32_t index) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->Has(isolate->GetCurrentContext(), index);
+}
+
+inline Maybe<bool> Delete(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->Delete(isolate->GetCurrentContext(), key);
+}
+
+inline
+Maybe<bool> Delete(v8::Local<v8::Object> obj, uint32_t index) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->Delete(isolate->GetCurrentContext(), index);
+}
+
+inline
+MaybeLocal<v8::Array> GetPropertyNames(v8::Local<v8::Object> obj) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(obj->GetPropertyNames(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::Array>()));
+}
+
+inline
+MaybeLocal<v8::Array> GetOwnPropertyNames(v8::Local<v8::Object> obj) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(obj->GetOwnPropertyNames(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::Array>()));
+}
+
+inline Maybe<bool> SetPrototype(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::Value> prototype) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->SetPrototype(isolate->GetCurrentContext(), prototype);
+}
+
+inline MaybeLocal<v8::String> ObjectProtoToString(
+    v8::Local<v8::Object> obj) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(obj->ObjectProtoToString(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::String>()));
+}
+
+inline Maybe<bool> HasOwnProperty(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->HasOwnProperty(isolate->GetCurrentContext(), key);
+}
+
+inline Maybe<bool> HasRealNamedProperty(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->HasRealNamedProperty(isolate->GetCurrentContext(), key);
+}
+
+inline Maybe<bool> HasRealIndexedProperty(
+    v8::Local<v8::Object> obj
+  , uint32_t index) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->HasRealIndexedProperty(isolate->GetCurrentContext(), index);
+}
+
+inline Maybe<bool> HasRealNamedCallbackProperty(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return obj->HasRealNamedCallbackProperty(isolate->GetCurrentContext(), key);
+}
+
+inline MaybeLocal<v8::Value> GetRealNamedPropertyInPrototypeChain(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(obj->GetRealNamedPropertyInPrototypeChain(
+                             isolate->GetCurrentContext(), key)
+                          .FromMaybe(v8::Local<v8::Value>()));
+}
+
+inline MaybeLocal<v8::Value> GetRealNamedProperty(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::String> key) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(
+      obj->GetRealNamedProperty(isolate->GetCurrentContext(), key)
+          .FromMaybe(v8::Local<v8::Value>()));
+}
+
+inline MaybeLocal<v8::Value> CallAsFunction(
+    v8::Local<v8::Object> obj
+  , v8::Local<v8::Object> recv
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(
+      obj->CallAsFunction(isolate->GetCurrentContext(), recv, argc, argv)
+          .FromMaybe(v8::Local<v8::Value>()));
+}
+
+inline MaybeLocal<v8::Value> CallAsConstructor(
+    v8::Local<v8::Object> obj
+  , int argc, v8::Local<v8::Value> argv[]) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(
+      obj->CallAsConstructor(isolate->GetCurrentContext(), argc, argv)
+          .FromMaybe(v8::Local<v8::Value>()));
+}
+
+inline
+MaybeLocal<v8::String> GetSourceLine(v8::Local<v8::Message> msg) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(msg->GetSourceLine(isolate->GetCurrentContext())
+                          .FromMaybe(v8::Local<v8::String>()));
+}
+
+inline Maybe<int> GetLineNumber(v8::Local<v8::Message> msg) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return msg->GetLineNumber(isolate->GetCurrentContext());
+}
+
+inline Maybe<int> GetStartColumn(v8::Local<v8::Message> msg) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return msg->GetStartColumn(isolate->GetCurrentContext());
+}
+
+inline Maybe<int> GetEndColumn(v8::Local<v8::Message> msg) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::HandleScope scope(isolate);
+  return msg->GetEndColumn(isolate->GetCurrentContext());
+}
+
+inline MaybeLocal<v8::Object> CloneElementAt(
+    v8::Local<v8::Array> array
+  , uint32_t index) {
+#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION)
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Value> elem;
+  v8::Local<v8::Object> obj;
+  if (!array->Get(context, index).ToLocal(&elem)) {
+    return scope.Escape(obj);
+  }
+  if (!elem->ToObject(context).ToLocal(&obj)) {
+    return scope.Escape(v8::Local<v8::Object>());
+  }
+  return scope.Escape(obj->Clone());
+#else
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(array->CloneElementAt(isolate->GetCurrentContext(), index)
+                          .FromMaybe(v8::Local<v8::Object>()));
+#endif
+}
+
+inline MaybeLocal<v8::Value> Call(
+    v8::Local<v8::Function> fun
+  , v8::Local<v8::Object> recv
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  return scope.Escape(fun->Call(isolate->GetCurrentContext(), recv, argc, argv)
+                          .FromMaybe(v8::Local<v8::Value>()));
+}
+
+#endif  // NAN_MAYBE_43_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_maybe_pre_43_inl.h b/input_devices/mag/node_modules/nan/nan_maybe_pre_43_inl.h
new file mode 100644
index 00000000..3847296d
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_maybe_pre_43_inl.h
@@ -0,0 +1,316 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_MAYBE_PRE_43_INL_H_
+#define NAN_MAYBE_PRE_43_INL_H_
+
+template<typename T>
+class MaybeLocal {
+ public:
+  inline MaybeLocal() : val_(v8::Local<T>()) {}
+
+  template<typename S>
+# if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
+  inline
+  MaybeLocal(v8::Local<S> that) : val_(that) {}  // NOLINT(runtime/explicit)
+# else
+  inline
+  MaybeLocal(v8::Local<S> that) :  // NOLINT(runtime/explicit)
+      val_(*reinterpret_cast<v8::Local<T>*>(&that)) {}
+# endif
+
+  inline bool IsEmpty() const { return val_.IsEmpty(); }
+
+  template<typename S>
+  inline bool ToLocal(v8::Local<S> *out) const {
+    *out = val_;
+    return !IsEmpty();
+  }
+
+  inline v8::Local<T> ToLocalChecked() const {
+#if defined(V8_ENABLE_CHECKS)
+    assert(!IsEmpty() && "ToLocalChecked is Empty");
+#endif  // V8_ENABLE_CHECKS
+    return val_;
+  }
+
+  template<typename S>
+  inline v8::Local<S> FromMaybe(v8::Local<S> default_value) const {
+    return IsEmpty() ? default_value : v8::Local<S>(val_);
+  }
+
+ private:
+  v8::Local<T> val_;
+};
+
+template<typename T>
+class Maybe {
+ public:
+  inline bool IsNothing() const { return !has_value_; }
+  inline bool IsJust() const { return has_value_; }
+
+  inline T FromJust() const {
+#if defined(V8_ENABLE_CHECKS)
+    assert(IsJust() && "FromJust is Nothing");
+#endif  // V8_ENABLE_CHECKS
+    return value_;
+  }
+
+  inline T FromMaybe(const T& default_value) const {
+    return has_value_ ? value_ : default_value;
+  }
+
+  inline bool operator==(const Maybe &other) const {
+    return (IsJust() == other.IsJust()) &&
+        (!IsJust() || FromJust() == other.FromJust());
+  }
+
+  inline bool operator!=(const Maybe &other) const {
+    return !operator==(other);
+  }
+
+ private:
+  Maybe() : has_value_(false) {}
+  explicit Maybe(const T& t) : has_value_(true), value_(t) {}
+  bool has_value_;
+  T value_;
+
+  template<typename U>
+  friend Maybe<U> Nothing();
+  template<typename U>
+  friend Maybe<U> Just(const U& u);
+};
+
+template<typename T>
+inline Maybe<T> Nothing() {
+  return Maybe<T>();
+}
+
+template<typename T>
+inline Maybe<T> Just(const T& t) {
+  return Maybe<T>(t);
+}
+
+inline
+MaybeLocal<v8::String> ToDetailString(v8::Handle<v8::Value> val) {
+  return MaybeLocal<v8::String>(val->ToDetailString());
+}
+
+inline
+MaybeLocal<v8::Uint32> ToArrayIndex(v8::Handle<v8::Value> val) {
+  return MaybeLocal<v8::Uint32>(val->ToArrayIndex());
+}
+
+inline
+Maybe<bool> Equals(v8::Handle<v8::Value> a, v8::Handle<v8::Value>(b)) {
+  return Just<bool>(a->Equals(b));
+}
+
+inline
+MaybeLocal<v8::Object> NewInstance(v8::Handle<v8::Function> h) {
+  return MaybeLocal<v8::Object>(h->NewInstance());
+}
+
+inline
+MaybeLocal<v8::Object> NewInstance(
+      v8::Local<v8::Function> h
+    , int argc
+    , v8::Local<v8::Value> argv[]) {
+  return MaybeLocal<v8::Object>(h->NewInstance(argc, argv));
+}
+
+inline
+MaybeLocal<v8::Object> NewInstance(v8::Handle<v8::ObjectTemplate> h) {
+  return MaybeLocal<v8::Object>(h->NewInstance());
+}
+
+inline
+MaybeLocal<v8::Function> GetFunction(v8::Handle<v8::FunctionTemplate> t) {
+  return MaybeLocal<v8::Function>(t->GetFunction());
+}
+
+inline Maybe<bool> Set(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::Value> key
+  , v8::Handle<v8::Value> value) {
+  return Just<bool>(obj->Set(key, value));
+}
+
+inline Maybe<bool> Set(
+    v8::Handle<v8::Object> obj
+  , uint32_t index
+  , v8::Handle<v8::Value> value) {
+  return Just<bool>(obj->Set(index, value));
+}
+
+#include "nan_define_own_property_helper.h"  // NOLINT(build/include)
+
+inline Maybe<bool> DefineOwnProperty(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key
+  , v8::Handle<v8::Value> value
+  , v8::PropertyAttribute attribs = v8::None) {
+  v8::PropertyAttribute current = obj->GetPropertyAttributes(key);
+  return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs);
+}
+
+NAN_DEPRECATED inline Maybe<bool> ForceSet(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::Value> key
+  , v8::Handle<v8::Value> value
+  , v8::PropertyAttribute attribs = v8::None) {
+  return Just<bool>(obj->ForceSet(key, value, attribs));
+}
+
+inline MaybeLocal<v8::Value> Get(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::Value> key) {
+  return MaybeLocal<v8::Value>(obj->Get(key));
+}
+
+inline MaybeLocal<v8::Value> Get(
+    v8::Handle<v8::Object> obj
+  , uint32_t index) {
+  return MaybeLocal<v8::Value>(obj->Get(index));
+}
+
+inline Maybe<v8::PropertyAttribute> GetPropertyAttributes(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::Value> key) {
+  return Just<v8::PropertyAttribute>(obj->GetPropertyAttributes(key));
+}
+
+inline Maybe<bool> Has(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key) {
+  return Just<bool>(obj->Has(key));
+}
+
+inline Maybe<bool> Has(
+    v8::Handle<v8::Object> obj
+  , uint32_t index) {
+  return Just<bool>(obj->Has(index));
+}
+
+inline Maybe<bool> Delete(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key) {
+  return Just<bool>(obj->Delete(key));
+}
+
+inline Maybe<bool> Delete(
+    v8::Handle<v8::Object> obj
+  , uint32_t index) {
+  return Just<bool>(obj->Delete(index));
+}
+
+inline
+MaybeLocal<v8::Array> GetPropertyNames(v8::Handle<v8::Object> obj) {
+  return MaybeLocal<v8::Array>(obj->GetPropertyNames());
+}
+
+inline
+MaybeLocal<v8::Array> GetOwnPropertyNames(v8::Handle<v8::Object> obj) {
+  return MaybeLocal<v8::Array>(obj->GetOwnPropertyNames());
+}
+
+inline Maybe<bool> SetPrototype(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::Value> prototype) {
+  return Just<bool>(obj->SetPrototype(prototype));
+}
+
+inline MaybeLocal<v8::String> ObjectProtoToString(
+    v8::Handle<v8::Object> obj) {
+  return MaybeLocal<v8::String>(obj->ObjectProtoToString());
+}
+
+inline Maybe<bool> HasOwnProperty(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key) {
+  return Just<bool>(obj->HasOwnProperty(key));
+}
+
+inline Maybe<bool> HasRealNamedProperty(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key) {
+  return Just<bool>(obj->HasRealNamedProperty(key));
+}
+
+inline Maybe<bool> HasRealIndexedProperty(
+    v8::Handle<v8::Object> obj
+  , uint32_t index) {
+  return Just<bool>(obj->HasRealIndexedProperty(index));
+}
+
+inline Maybe<bool> HasRealNamedCallbackProperty(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key) {
+  return Just<bool>(obj->HasRealNamedCallbackProperty(key));
+}
+
+inline MaybeLocal<v8::Value> GetRealNamedPropertyInPrototypeChain(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key) {
+  return MaybeLocal<v8::Value>(
+      obj->GetRealNamedPropertyInPrototypeChain(key));
+}
+
+inline MaybeLocal<v8::Value> GetRealNamedProperty(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::String> key) {
+  return MaybeLocal<v8::Value>(obj->GetRealNamedProperty(key));
+}
+
+inline MaybeLocal<v8::Value> CallAsFunction(
+    v8::Handle<v8::Object> obj
+  , v8::Handle<v8::Object> recv
+  , int argc
+  , v8::Handle<v8::Value> argv[]) {
+  return MaybeLocal<v8::Value>(obj->CallAsFunction(recv, argc, argv));
+}
+
+inline MaybeLocal<v8::Value> CallAsConstructor(
+    v8::Handle<v8::Object> obj
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+  return MaybeLocal<v8::Value>(obj->CallAsConstructor(argc, argv));
+}
+
+inline
+MaybeLocal<v8::String> GetSourceLine(v8::Handle<v8::Message> msg) {
+  return MaybeLocal<v8::String>(msg->GetSourceLine());
+}
+
+inline Maybe<int> GetLineNumber(v8::Handle<v8::Message> msg) {
+  return Just<int>(msg->GetLineNumber());
+}
+
+inline Maybe<int> GetStartColumn(v8::Handle<v8::Message> msg) {
+  return Just<int>(msg->GetStartColumn());
+}
+
+inline Maybe<int> GetEndColumn(v8::Handle<v8::Message> msg) {
+  return Just<int>(msg->GetEndColumn());
+}
+
+inline MaybeLocal<v8::Object> CloneElementAt(
+    v8::Handle<v8::Array> array
+  , uint32_t index) {
+  return MaybeLocal<v8::Object>(array->CloneElementAt(index));
+}
+
+inline MaybeLocal<v8::Value> Call(
+    v8::Local<v8::Function> fun
+  , v8::Local<v8::Object> recv
+  , int argc
+  , v8::Local<v8::Value> argv[]) {
+  return MaybeLocal<v8::Value>(fun->Call(recv, argc, argv));
+}
+
+#endif  // NAN_MAYBE_PRE_43_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_new.h b/input_devices/mag/node_modules/nan/nan_new.h
new file mode 100644
index 00000000..cdf8bbe4
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_new.h
@@ -0,0 +1,340 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_NEW_H_
+#define NAN_NEW_H_
+
+namespace imp {  // scnr
+
+// TODO(agnat): Generalize
+template <typename T> v8::Local<T> To(v8::Local<v8::Integer> i);
+
+template <>
+inline
+v8::Local<v8::Integer>
+To<v8::Integer>(v8::Local<v8::Integer> i) {
+  return Nan::To<v8::Integer>(i).ToLocalChecked();
+}
+
+template <>
+inline
+v8::Local<v8::Int32>
+To<v8::Int32>(v8::Local<v8::Integer> i) {
+  return Nan::To<v8::Int32>(i).ToLocalChecked();
+}
+
+template <>
+inline
+v8::Local<v8::Uint32>
+To<v8::Uint32>(v8::Local<v8::Integer> i) {
+  return Nan::To<v8::Uint32>(i).ToLocalChecked();
+}
+
+template <typename T> struct FactoryBase {
+  typedef v8::Local<T> return_t;
+};
+
+template <typename T> struct MaybeFactoryBase {
+  typedef MaybeLocal<T> return_t;
+};
+
+template <typename T> struct Factory;
+
+template <>
+struct Factory<v8::Array> : FactoryBase<v8::Array> {
+  static inline return_t New();
+  static inline return_t New(int length);
+};
+
+template <>
+struct Factory<v8::Boolean> : FactoryBase<v8::Boolean> {
+  static inline return_t New(bool value);
+};
+
+template <>
+struct Factory<v8::BooleanObject> : FactoryBase<v8::BooleanObject> {
+  static inline return_t New(bool value);
+};
+
+template <>
+struct Factory<v8::Context> : FactoryBase<v8::Context> {
+  static inline
+  return_t
+  New( v8::ExtensionConfiguration* extensions = NULL
+     , v8::Local<v8::ObjectTemplate> tmpl = v8::Local<v8::ObjectTemplate>()
+     , v8::Local<v8::Value> obj = v8::Local<v8::Value>());
+};
+
+template <>
+struct Factory<v8::Date> : MaybeFactoryBase<v8::Date> {
+  static inline return_t New(double value);
+};
+
+template <>
+struct Factory<v8::External> : FactoryBase<v8::External> {
+  static inline return_t New(void *value);
+};
+
+template <>
+struct Factory<v8::Function> : FactoryBase<v8::Function> {
+  static inline
+  return_t
+  New( FunctionCallback callback
+     , v8::Local<v8::Value> data = v8::Local<v8::Value>());
+};
+
+template <>
+struct Factory<v8::FunctionTemplate> : FactoryBase<v8::FunctionTemplate> {
+  static inline
+  return_t
+  New( FunctionCallback callback = NULL
+     , v8::Local<v8::Value> data = v8::Local<v8::Value>()
+     , v8::Local<v8::Signature> signature = v8::Local<v8::Signature>());
+};
+
+template <>
+struct Factory<v8::Number> : FactoryBase<v8::Number> {
+  static inline return_t New(double value);
+};
+
+template <>
+struct Factory<v8::NumberObject> : FactoryBase<v8::NumberObject> {
+  static inline return_t New(double value);
+};
+
+template <typename T>
+struct IntegerFactory : FactoryBase<T> {
+  typedef typename FactoryBase<T>::return_t return_t;
+  static inline return_t New(int32_t value);
+  static inline return_t New(uint32_t value);
+};
+
+template <>
+struct Factory<v8::Integer> : IntegerFactory<v8::Integer> {};
+
+template <>
+struct Factory<v8::Int32> : IntegerFactory<v8::Int32> {};
+
+template <>
+struct Factory<v8::Uint32> : FactoryBase<v8::Uint32> {
+  static inline return_t New(int32_t value);
+  static inline return_t New(uint32_t value);
+};
+
+template <>
+struct Factory<v8::Object> : FactoryBase<v8::Object> {
+  static inline return_t New();
+};
+
+template <>
+struct Factory<v8::ObjectTemplate> : FactoryBase<v8::ObjectTemplate> {
+  static inline return_t New();
+};
+
+template <>
+struct Factory<v8::RegExp> : MaybeFactoryBase<v8::RegExp> {
+  static inline return_t New(
+      v8::Local<v8::String> pattern, v8::RegExp::Flags flags);
+};
+
+template <>
+struct Factory<v8::Script> : MaybeFactoryBase<v8::Script> {
+  static inline return_t New( v8::Local<v8::String> source);
+  static inline return_t New( v8::Local<v8::String> source
+                            , v8::ScriptOrigin const& origin);
+};
+
+template <>
+struct Factory<v8::Signature> : FactoryBase<v8::Signature> {
+  typedef v8::Local<v8::FunctionTemplate> FTH;
+  static inline return_t New(FTH receiver = FTH());
+};
+
+template <>
+struct Factory<v8::String> : MaybeFactoryBase<v8::String> {
+  static inline return_t New();
+  static inline return_t New(const char *value, int length = -1);
+  static inline return_t New(const uint16_t *value, int length = -1);
+  static inline return_t New(std::string const& value);
+
+  static inline return_t New(v8::String::ExternalStringResource * value);
+  static inline return_t New(ExternalOneByteStringResource * value);
+};
+
+template <>
+struct Factory<v8::StringObject> : FactoryBase<v8::StringObject> {
+  static inline return_t New(v8::Local<v8::String> value);
+};
+
+}  // end of namespace imp
+
+#if (NODE_MODULE_VERSION >= 12)
+
+namespace imp {
+
+template <>
+struct Factory<v8::UnboundScript> : MaybeFactoryBase<v8::UnboundScript> {
+  static inline return_t New( v8::Local<v8::String> source);
+  static inline return_t New( v8::Local<v8::String> source
+                            , v8::ScriptOrigin const& origin);
+};
+
+}  // end of namespace imp
+
+# include "nan_implementation_12_inl.h"
+
+#else  // NODE_MODULE_VERSION >= 12
+
+# include "nan_implementation_pre_12_inl.h"
+
+#endif
+
+//=== API ======================================================================
+
+template <typename T>
+typename imp::Factory<T>::return_t
+New() {
+  return imp::Factory<T>::New();
+}
+
+template <typename T, typename A0>
+typename imp::Factory<T>::return_t
+New(A0 arg0) {
+  return imp::Factory<T>::New(arg0);
+}
+
+template <typename T, typename A0, typename A1>
+typename imp::Factory<T>::return_t
+New(A0 arg0, A1 arg1) {
+  return imp::Factory<T>::New(arg0, arg1);
+}
+
+template <typename T, typename A0, typename A1, typename A2>
+typename imp::Factory<T>::return_t
+New(A0 arg0, A1 arg1, A2 arg2) {
+  return imp::Factory<T>::New(arg0, arg1, arg2);
+}
+
+template <typename T, typename A0, typename A1, typename A2, typename A3>
+typename imp::Factory<T>::return_t
+New(A0 arg0, A1 arg1, A2 arg2, A3 arg3) {
+  return imp::Factory<T>::New(arg0, arg1, arg2, arg3);
+}
+
+// Note(agnat): When passing overloaded function pointers to template functions
+// as generic arguments the compiler needs help in picking the right overload.
+// These two functions handle New<Function> and New<FunctionTemplate> with
+// all argument variations.
+
+// v8::Function and v8::FunctionTemplate with one or two arguments
+template <typename T>
+typename imp::Factory<T>::return_t
+New( FunctionCallback callback
+      , v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
+    return imp::Factory<T>::New(callback, data);
+}
+
+// v8::Function and v8::FunctionTemplate with three arguments
+template <typename T, typename A2>
+typename imp::Factory<T>::return_t
+New( FunctionCallback callback
+      , v8::Local<v8::Value> data = v8::Local<v8::Value>()
+      , A2 a2 = A2()) {
+    return imp::Factory<T>::New(callback, data, a2);
+}
+
+// Convenience
+
+#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
+template <typename T> inline v8::Local<T> New(v8::Handle<T> h);
+#endif
+
+#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+template <typename T, typename M>
+    inline v8::Local<T> New(v8::Persistent<T, M> const& p);
+#else
+template <typename T> inline v8::Local<T> New(v8::Persistent<T> const& p);
+#endif
+template <typename T, typename M>
+inline v8::Local<T> New(Persistent<T, M> const& p);
+template <typename T>
+inline v8::Local<T> New(Global<T> const& p);
+
+inline
+imp::Factory<v8::Boolean>::return_t
+New(bool value) {
+  return New<v8::Boolean>(value);
+}
+
+inline
+imp::Factory<v8::Int32>::return_t
+New(int32_t value) {
+  return New<v8::Int32>(value);
+}
+
+inline
+imp::Factory<v8::Uint32>::return_t
+New(uint32_t value) {
+  return New<v8::Uint32>(value);
+}
+
+inline
+imp::Factory<v8::Number>::return_t
+New(double value) {
+  return New<v8::Number>(value);
+}
+
+inline
+imp::Factory<v8::String>::return_t
+New(std::string const& value) {  // NOLINT(build/include_what_you_use)
+  return New<v8::String>(value);
+}
+
+inline
+imp::Factory<v8::String>::return_t
+New(const char * value, int length) {
+  return New<v8::String>(value, length);
+}
+
+inline
+imp::Factory<v8::String>::return_t
+New(const uint16_t * value, int length) {
+  return New<v8::String>(value, length);
+}
+
+inline
+imp::Factory<v8::String>::return_t
+New(const char * value) {
+  return New<v8::String>(value);
+}
+
+inline
+imp::Factory<v8::String>::return_t
+New(const uint16_t * value) {
+  return New<v8::String>(value);
+}
+
+inline
+imp::Factory<v8::String>::return_t
+New(v8::String::ExternalStringResource * value) {
+  return New<v8::String>(value);
+}
+
+inline
+imp::Factory<v8::String>::return_t
+New(ExternalOneByteStringResource * value) {
+  return New<v8::String>(value);
+}
+
+inline
+imp::Factory<v8::RegExp>::return_t
+New(v8::Local<v8::String> pattern, v8::RegExp::Flags flags) {
+  return New<v8::RegExp>(pattern, flags);
+}
+
+#endif  // NAN_NEW_H_
diff --git a/input_devices/mag/node_modules/nan/nan_object_wrap.h b/input_devices/mag/node_modules/nan/nan_object_wrap.h
new file mode 100644
index 00000000..a4d96178
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_object_wrap.h
@@ -0,0 +1,155 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_OBJECT_WRAP_H_
+#define NAN_OBJECT_WRAP_H_
+
+class ObjectWrap {
+ public:
+  ObjectWrap() {
+    refs_ = 0;
+  }
+
+
+  virtual ~ObjectWrap() {
+    if (persistent().IsEmpty()) {
+      return;
+    }
+
+    assert(persistent().IsNearDeath());
+    persistent().ClearWeak();
+    persistent().Reset();
+  }
+
+
+  template <class T>
+  static inline T* Unwrap(v8::Local<v8::Object> object) {
+    assert(!object.IsEmpty());
+    assert(object->InternalFieldCount() > 0);
+    // Cast to ObjectWrap before casting to T.  A direct cast from void
+    // to T won't work right when T has more than one base class.
+    void* ptr = GetInternalFieldPointer(object, 0);
+    ObjectWrap* wrap = static_cast<ObjectWrap*>(ptr);
+    return static_cast<T*>(wrap);
+  }
+
+
+  inline v8::Local<v8::Object> handle() const {
+    return New(handle_);
+  }
+
+
+  inline Persistent<v8::Object>& persistent() {
+    return handle_;
+  }
+
+
+ protected:
+  inline void Wrap(v8::Local<v8::Object> object) {
+    assert(persistent().IsEmpty());
+    assert(object->InternalFieldCount() > 0);
+    SetInternalFieldPointer(object, 0, this);
+    persistent().Reset(object);
+    MakeWeak();
+  }
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+
+  inline void MakeWeak() {
+    persistent().v8::PersistentBase<v8::Object>::SetWeak(
+        this, WeakCallback, v8::WeakCallbackType::kParameter);
+    persistent().MarkIndependent();
+  }
+
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+
+  inline void MakeWeak() {
+    persistent().v8::PersistentBase<v8::Object>::SetWeak(this, WeakCallback);
+    persistent().MarkIndependent();
+  }
+
+#else
+
+  inline void MakeWeak() {
+    persistent().persistent.MakeWeak(this, WeakCallback);
+    persistent().MarkIndependent();
+  }
+
+#endif
+
+  /* Ref() marks the object as being attached to an event loop.
+   * Refed objects will not be garbage collected, even if
+   * all references are lost.
+   */
+  virtual void Ref() {
+    assert(!persistent().IsEmpty());
+    persistent().ClearWeak();
+    refs_++;
+  }
+
+  /* Unref() marks an object as detached from the event loop.  This is its
+   * default state.  When an object with a "weak" reference changes from
+   * attached to detached state it will be freed. Be careful not to access
+   * the object after making this call as it might be gone!
+   * (A "weak reference" means an object that only has a
+   * persistant handle.)
+   *
+   * DO NOT CALL THIS FROM DESTRUCTOR
+   */
+  virtual void Unref() {
+    assert(!persistent().IsEmpty());
+    assert(!persistent().IsWeak());
+    assert(refs_ > 0);
+    if (--refs_ == 0)
+      MakeWeak();
+  }
+
+  int refs_;  // ro
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap)
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+
+  static void
+  WeakCallback(v8::WeakCallbackInfo<ObjectWrap> const& info) {
+    ObjectWrap* wrap = info.GetParameter();
+    assert(wrap->refs_ == 0);
+    assert(wrap->handle_.IsNearDeath());
+    wrap->handle_.Reset();
+    delete wrap;
+  }
+
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+
+  static void
+  WeakCallback(v8::WeakCallbackData<v8::Object, ObjectWrap> const& data) {
+    ObjectWrap* wrap = data.GetParameter();
+    assert(wrap->refs_ == 0);
+    assert(wrap->handle_.IsNearDeath());
+    wrap->handle_.Reset();
+    delete wrap;
+  }
+
+#else
+
+  static void WeakCallback(v8::Persistent<v8::Value> value, void *data) {
+    ObjectWrap *wrap = static_cast<ObjectWrap*>(data);
+    assert(wrap->refs_ == 0);
+    assert(wrap->handle_.IsNearDeath());
+    wrap->handle_.Reset();
+    delete wrap;
+  }
+
+#endif
+  Persistent<v8::Object> handle_;
+};
+
+
+#endif  // NAN_OBJECT_WRAP_H_
diff --git a/input_devices/mag/node_modules/nan/nan_persistent_12_inl.h b/input_devices/mag/node_modules/nan/nan_persistent_12_inl.h
new file mode 100644
index 00000000..d9649e86
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_persistent_12_inl.h
@@ -0,0 +1,132 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_PERSISTENT_12_INL_H_
+#define NAN_PERSISTENT_12_INL_H_
+
+template<typename T, typename M> class Persistent :
+    public v8::Persistent<T, M> {
+ public:
+  inline Persistent() : v8::Persistent<T, M>() {}
+
+  template<typename S> inline Persistent(v8::Local<S> that) :
+      v8::Persistent<T, M>(v8::Isolate::GetCurrent(), that) {}
+
+  template<typename S, typename M2>
+  inline
+  Persistent(const v8::Persistent<S, M2> &that) :  // NOLINT(runtime/explicit)
+      v8::Persistent<T, M2>(v8::Isolate::GetCurrent(), that) {}
+
+  inline void Reset() { v8::PersistentBase<T>::Reset(); }
+
+  template <typename S>
+  inline void Reset(const v8::Local<S> &other) {
+    v8::PersistentBase<T>::Reset(v8::Isolate::GetCurrent(), other);
+  }
+
+  template <typename S>
+  inline void Reset(const v8::PersistentBase<S> &other) {
+    v8::PersistentBase<T>::Reset(v8::Isolate::GetCurrent(), other);
+  }
+
+  template<typename P>
+  inline void SetWeak(
+    P *parameter
+    , typename WeakCallbackInfo<P>::Callback callback
+    , WeakCallbackType type);
+
+ private:
+  inline T *operator*() const { return *PersistentBase<T>::persistent; }
+
+  template<typename S, typename M2>
+  inline void Copy(const Persistent<S, M2> &that) {
+    TYPE_CHECK(T, S);
+
+    this->Reset();
+
+    if (!that.IsEmpty()) {
+      this->Reset(that);
+      M::Copy(that, this);
+    }
+  }
+};
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+template<typename T>
+class Global : public v8::Global<T> {
+ public:
+  inline Global() : v8::Global<T>() {}
+
+  template<typename S> inline Global(v8::Local<S> that) :
+    v8::Global<T>(v8::Isolate::GetCurrent(), that) {}
+
+  template<typename S>
+  inline
+  Global(const v8::PersistentBase<S> &that) :  // NOLINT(runtime/explicit)
+      v8::Global<S>(v8::Isolate::GetCurrent(), that) {}
+
+  inline void Reset() { v8::PersistentBase<T>::Reset(); }
+
+  template <typename S>
+  inline void Reset(const v8::Local<S> &other) {
+    v8::PersistentBase<T>::Reset(v8::Isolate::GetCurrent(), other);
+  }
+
+  template <typename S>
+  inline void Reset(const v8::PersistentBase<S> &other) {
+    v8::PersistentBase<T>::Reset(v8::Isolate::GetCurrent(), other);
+  }
+
+  template<typename P>
+  inline void SetWeak(
+    P *parameter
+    , typename WeakCallbackInfo<P>::Callback callback
+    , WeakCallbackType type) {
+    reinterpret_cast<Persistent<T>*>(this)->SetWeak(
+        parameter, callback, type);
+  }
+};
+#else
+template<typename T>
+class Global : public v8::UniquePersistent<T> {
+ public:
+  inline Global() : v8::UniquePersistent<T>() {}
+
+  template<typename S> inline Global(v8::Local<S> that) :
+    v8::UniquePersistent<T>(v8::Isolate::GetCurrent(), that) {}
+
+  template<typename S>
+  inline
+  Global(const v8::PersistentBase<S> &that) :  // NOLINT(runtime/explicit)
+      v8::UniquePersistent<S>(v8::Isolate::GetCurrent(), that) {}
+
+  inline void Reset() { v8::PersistentBase<T>::Reset(); }
+
+  template <typename S>
+  inline void Reset(const v8::Local<S> &other) {
+    v8::PersistentBase<T>::Reset(v8::Isolate::GetCurrent(), other);
+  }
+
+  template <typename S>
+  inline void Reset(const v8::PersistentBase<S> &other) {
+    v8::PersistentBase<T>::Reset(v8::Isolate::GetCurrent(), other);
+  }
+
+  template<typename P>
+  inline void SetWeak(
+    P *parameter
+    , typename WeakCallbackInfo<P>::Callback callback
+    , WeakCallbackType type) {
+    reinterpret_cast<Persistent<T>*>(this)->SetWeak(
+        parameter, callback, type);
+  }
+};
+#endif
+
+#endif  // NAN_PERSISTENT_12_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_persistent_pre_12_inl.h b/input_devices/mag/node_modules/nan/nan_persistent_pre_12_inl.h
new file mode 100644
index 00000000..4c9c59da
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_persistent_pre_12_inl.h
@@ -0,0 +1,242 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_PERSISTENT_PRE_12_INL_H_
+#define NAN_PERSISTENT_PRE_12_INL_H_
+
+template<typename T>
+class PersistentBase {
+  v8::Persistent<T> persistent;
+  template<typename U>
+  friend v8::Local<U> New(const PersistentBase<U> &p);
+  template<typename U, typename M>
+  friend v8::Local<U> New(const Persistent<U, M> &p);
+  template<typename U>
+  friend v8::Local<U> New(const Global<U> &p);
+  template<typename S> friend class ReturnValue;
+
+ public:
+  inline PersistentBase() :
+      persistent() {}
+
+  inline void Reset() {
+    persistent.Dispose();
+    persistent.Clear();
+  }
+
+  template<typename S>
+  inline void Reset(const v8::Local<S> &other) {
+    TYPE_CHECK(T, S);
+
+    if (!persistent.IsEmpty()) {
+      persistent.Dispose();
+    }
+
+    if (other.IsEmpty()) {
+      persistent.Clear();
+    } else {
+      persistent = v8::Persistent<T>::New(other);
+    }
+  }
+
+  template<typename S>
+  inline void Reset(const PersistentBase<S> &other) {
+    TYPE_CHECK(T, S);
+
+    if (!persistent.IsEmpty()) {
+      persistent.Dispose();
+    }
+
+    if (other.IsEmpty()) {
+      persistent.Clear();
+    } else {
+      persistent = v8::Persistent<T>::New(other.persistent);
+    }
+  }
+
+  inline bool IsEmpty() const { return persistent.IsEmpty(); }
+
+  inline void Empty() { persistent.Clear(); }
+
+  template<typename S>
+  inline bool operator==(const PersistentBase<S> &that) const {
+    return this->persistent == that.persistent;
+  }
+
+  template<typename S>
+  inline bool operator==(const v8::Local<S> &that) const {
+    return this->persistent == that;
+  }
+
+  template<typename S>
+  inline bool operator!=(const PersistentBase<S> &that) const {
+    return !operator==(that);
+  }
+
+  template<typename S>
+  inline bool operator!=(const v8::Local<S> &that) const {
+    return !operator==(that);
+  }
+
+  template<typename P>
+  inline void SetWeak(
+    P *parameter
+    , typename WeakCallbackInfo<P>::Callback callback
+    , WeakCallbackType type);
+
+  inline void ClearWeak() { persistent.ClearWeak(); }
+
+  inline void MarkIndependent() { persistent.MarkIndependent(); }
+
+  inline bool IsIndependent() const { return persistent.IsIndependent(); }
+
+  inline bool IsNearDeath() const { return persistent.IsNearDeath(); }
+
+  inline bool IsWeak() const { return persistent.IsWeak(); }
+
+ private:
+  inline explicit PersistentBase(v8::Persistent<T> that) :
+      persistent(that) { }
+  inline explicit PersistentBase(T *val) : persistent(val) {}
+  template<typename S, typename M> friend class Persistent;
+  template<typename S> friend class Global;
+  friend class ObjectWrap;
+};
+
+template<typename T>
+class NonCopyablePersistentTraits {
+ public:
+  typedef Persistent<T, NonCopyablePersistentTraits<T> >
+      NonCopyablePersistent;
+  static const bool kResetInDestructor = false;
+  template<typename S, typename M>
+  inline static void Copy(const Persistent<S, M> &source,
+                             NonCopyablePersistent *dest) {
+    Uncompilable<v8::Object>();
+  }
+
+  template<typename O> inline static void Uncompilable() {
+    TYPE_CHECK(O, v8::Primitive);
+  }
+};
+
+template<typename T>
+struct CopyablePersistentTraits {
+  typedef Persistent<T, CopyablePersistentTraits<T> > CopyablePersistent;
+  static const bool kResetInDestructor = true;
+  template<typename S, typename M>
+  static inline void Copy(const Persistent<S, M> &source,
+                             CopyablePersistent *dest) {}
+};
+
+template<typename T, typename M> class Persistent :
+    public PersistentBase<T> {
+ public:
+  inline Persistent() {}
+
+  template<typename S> inline Persistent(v8::Handle<S> that)
+      : PersistentBase<T>(v8::Persistent<T>::New(that)) {
+    TYPE_CHECK(T, S);
+  }
+
+  inline Persistent(const Persistent &that) : PersistentBase<T>() {
+    Copy(that);
+  }
+
+  template<typename S, typename M2>
+  inline Persistent(const Persistent<S, M2> &that) :
+      PersistentBase<T>() {
+    Copy(that);
+  }
+
+  inline Persistent &operator=(const Persistent &that) {
+    Copy(that);
+    return *this;
+  }
+
+  template <class S, class M2>
+  inline Persistent &operator=(const Persistent<S, M2> &that) {
+    Copy(that);
+    return *this;
+  }
+
+  inline ~Persistent() {
+    if (M::kResetInDestructor) this->Reset();
+  }
+
+ private:
+  inline T *operator*() const { return *PersistentBase<T>::persistent; }
+
+  template<typename S, typename M2>
+  inline void Copy(const Persistent<S, M2> &that) {
+    TYPE_CHECK(T, S);
+
+    this->Reset();
+
+    if (!that.IsEmpty()) {
+      this->persistent = v8::Persistent<T>::New(that.persistent);
+      M::Copy(that, this);
+    }
+  }
+};
+
+template<typename T>
+class Global : public PersistentBase<T> {
+  struct RValue {
+    inline explicit RValue(Global* obj) : object(obj) {}
+    Global* object;
+  };
+
+ public:
+  inline Global() : PersistentBase<T>(0) { }
+
+  template <typename S>
+  inline Global(v8::Local<S> that)  // NOLINT(runtime/explicit)
+      : PersistentBase<T>(v8::Persistent<T>::New(that)) {
+    TYPE_CHECK(T, S);
+  }
+
+  template <typename S>
+  inline Global(const PersistentBase<S> &that)  // NOLINT(runtime/explicit)
+    : PersistentBase<T>(that) {
+    TYPE_CHECK(T, S);
+  }
+  /**
+   * Move constructor.
+   */
+  inline Global(RValue rvalue)  // NOLINT(runtime/explicit)
+    : PersistentBase<T>(rvalue.object->persistent) {
+    rvalue.object->Reset();
+  }
+  inline ~Global() { this->Reset(); }
+  /**
+   * Move via assignment.
+   */
+  template<typename S>
+  inline Global &operator=(Global<S> rhs) {
+    TYPE_CHECK(T, S);
+    this->Reset(rhs.persistent);
+    rhs.Reset();
+    return *this;
+  }
+  /**
+   * Cast operator for moves.
+   */
+  inline operator RValue() { return RValue(this); }
+  /**
+   * Pass allows returning uniques from functions, etc.
+   */
+  Global Pass() { return Global(RValue(this)); }
+
+ private:
+  Global(Global &);
+  void operator=(Global &);
+  template<typename S> friend class ReturnValue;
+};
+
+#endif  // NAN_PERSISTENT_PRE_12_INL_H_
diff --git a/input_devices/mag/node_modules/nan/nan_private.h b/input_devices/mag/node_modules/nan/nan_private.h
new file mode 100644
index 00000000..15f44cc8
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_private.h
@@ -0,0 +1,73 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_PRIVATE_H_
+#define NAN_PRIVATE_H_
+
+inline Maybe<bool>
+HasPrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key) {
+  HandleScope scope;
+#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);
+  return object->HasPrivate(context, private_key);
+#else
+  return Just(!object->GetHiddenValue(key).IsEmpty());
+#endif
+}
+
+inline MaybeLocal<v8::Value>
+GetPrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key) {
+#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::EscapableHandleScope scope(isolate);
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);
+  v8::MaybeLocal<v8::Value> v = object->GetPrivate(context, private_key);
+  return scope.Escape(v.ToLocalChecked());
+#else
+  EscapableHandleScope scope;
+  v8::Local<v8::Value> v = object->GetHiddenValue(key);
+  if (v.IsEmpty()) {
+    v = Undefined();
+  }
+  return scope.Escape(v);
+#endif
+}
+
+inline Maybe<bool> SetPrivate(
+    v8::Local<v8::Object> object,
+    v8::Local<v8::String> key,
+    v8::Local<v8::Value> value) {
+#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION
+  HandleScope scope;
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);
+  return object->SetPrivate(context, private_key, value);
+#else
+  return Just(object->SetHiddenValue(key, value));
+#endif
+}
+
+inline Maybe<bool> DeletePrivate(
+    v8::Local<v8::Object> object,
+    v8::Local<v8::String> key) {
+#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION
+  HandleScope scope;
+  v8::Isolate *isolate = v8::Isolate::GetCurrent();
+  v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);
+  return object->DeletePrivate(isolate->GetCurrentContext(), private_key);
+#else
+  return Just(object->DeleteHiddenValue(key));
+#endif
+}
+
+#endif  // NAN_PRIVATE_H_
+
diff --git a/input_devices/mag/node_modules/nan/nan_string_bytes.h b/input_devices/mag/node_modules/nan/nan_string_bytes.h
new file mode 100644
index 00000000..a2e6437d
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_string_bytes.h
@@ -0,0 +1,305 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+#ifndef NAN_STRING_BYTES_H_
+#define NAN_STRING_BYTES_H_
+
+// Decodes a v8::Local<v8::String> or Buffer to a raw char*
+
+namespace imp {
+
+using v8::Local;
+using v8::Object;
+using v8::String;
+using v8::Value;
+
+
+//// Base 64 ////
+
+#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
+
+
+
+//// HEX ////
+
+static bool contains_non_ascii_slow(const char* buf, size_t len) {
+  for (size_t i = 0; i < len; ++i) {
+    if (buf[i] & 0x80) return true;
+  }
+  return false;
+}
+
+
+static bool contains_non_ascii(const char* src, size_t len) {
+  if (len < 16) {
+    return contains_non_ascii_slow(src, len);
+  }
+
+  const unsigned bytes_per_word = sizeof(void*);
+  const unsigned align_mask = bytes_per_word - 1;
+  const unsigned unaligned = reinterpret_cast<uintptr_t>(src) & align_mask;
+
+  if (unaligned > 0) {
+    const unsigned n = bytes_per_word - unaligned;
+    if (contains_non_ascii_slow(src, n)) return true;
+    src += n;
+    len -= n;
+  }
+
+
+#if defined(__x86_64__) || defined(_WIN64)
+  const uintptr_t mask = 0x8080808080808080ll;
+#else
+  const uintptr_t mask = 0x80808080l;
+#endif
+
+  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
+
+  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
+    if (srcw[i] & mask) return true;
+  }
+
+  const unsigned remainder = len & align_mask;
+  if (remainder > 0) {
+    const size_t offset = len - remainder;
+    if (contains_non_ascii_slow(src + offset, remainder)) return true;
+  }
+
+  return false;
+}
+
+
+static void force_ascii_slow(const char* src, char* dst, size_t len) {
+  for (size_t i = 0; i < len; ++i) {
+    dst[i] = src[i] & 0x7f;
+  }
+}
+
+
+static void force_ascii(const char* src, char* dst, size_t len) {
+  if (len < 16) {
+    force_ascii_slow(src, dst, len);
+    return;
+  }
+
+  const unsigned bytes_per_word = sizeof(void*);
+  const unsigned align_mask = bytes_per_word - 1;
+  const unsigned src_unalign = reinterpret_cast<uintptr_t>(src) & align_mask;
+  const unsigned dst_unalign = reinterpret_cast<uintptr_t>(dst) & align_mask;
+
+  if (src_unalign > 0) {
+    if (src_unalign == dst_unalign) {
+      const unsigned unalign = bytes_per_word - src_unalign;
+      force_ascii_slow(src, dst, unalign);
+      src += unalign;
+      dst += unalign;
+      len -= src_unalign;
+    } else {
+      force_ascii_slow(src, dst, len);
+      return;
+    }
+  }
+
+#if defined(__x86_64__) || defined(_WIN64)
+  const uintptr_t mask = ~0x8080808080808080ll;
+#else
+  const uintptr_t mask = ~0x80808080l;
+#endif
+
+  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
+  uintptr_t* dstw = reinterpret_cast<uintptr_t*>(dst);
+
+  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
+    dstw[i] = srcw[i] & mask;
+  }
+
+  const unsigned remainder = len & align_mask;
+  if (remainder > 0) {
+    const size_t offset = len - remainder;
+    force_ascii_slow(src + offset, dst + offset, remainder);
+  }
+}
+
+
+static size_t base64_encode(const char* src,
+                            size_t slen,
+                            char* dst,
+                            size_t dlen) {
+  // We know how much we'll write, just make sure that there's space.
+  assert(dlen >= base64_encoded_size(slen) &&
+      "not enough space provided for base64 encode");
+
+  dlen = base64_encoded_size(slen);
+
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned i;
+  unsigned k;
+  unsigned n;
+
+  static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                              "abcdefghijklmnopqrstuvwxyz"
+                              "0123456789+/";
+
+  i = 0;
+  k = 0;
+  n = slen / 3 * 3;
+
+  while (i < n) {
+    a = src[i + 0] & 0xff;
+    b = src[i + 1] & 0xff;
+    c = src[i + 2] & 0xff;
+
+    dst[k + 0] = table[a >> 2];
+    dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
+    dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
+    dst[k + 3] = table[c & 0x3f];
+
+    i += 3;
+    k += 4;
+  }
+
+  if (n != slen) {
+    switch (slen - n) {
+      case 1:
+        a = src[i + 0] & 0xff;
+        dst[k + 0] = table[a >> 2];
+        dst[k + 1] = table[(a & 3) << 4];
+        dst[k + 2] = '=';
+        dst[k + 3] = '=';
+        break;
+
+      case 2:
+        a = src[i + 0] & 0xff;
+        b = src[i + 1] & 0xff;
+        dst[k + 0] = table[a >> 2];
+        dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
+        dst[k + 2] = table[(b & 0x0f) << 2];
+        dst[k + 3] = '=';
+        break;
+    }
+  }
+
+  return dlen;
+}
+
+
+static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) {
+  // We know how much we'll write, just make sure that there's space.
+  assert(dlen >= slen * 2 &&
+      "not enough space provided for hex encode");
+
+  dlen = slen * 2;
+  for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {
+    static const char hex[] = "0123456789abcdef";
+    uint8_t val = static_cast<uint8_t>(src[i]);
+    dst[k + 0] = hex[val >> 4];
+    dst[k + 1] = hex[val & 15];
+  }
+
+  return dlen;
+}
+
+
+
+static Local<Value> Encode(const char* buf,
+                           size_t buflen,
+                           enum Encoding encoding) {
+  assert(buflen <= node::Buffer::kMaxLength);
+  if (!buflen && encoding != BUFFER)
+    return New("").ToLocalChecked();
+
+  Local<String> val;
+  switch (encoding) {
+    case BUFFER:
+      return CopyBuffer(buf, buflen).ToLocalChecked();
+
+    case ASCII:
+      if (contains_non_ascii(buf, buflen)) {
+        char* out = new char[buflen];
+        force_ascii(buf, out, buflen);
+        val = New<String>(out, buflen).ToLocalChecked();
+        delete[] out;
+      } else {
+        val = New<String>(buf, buflen).ToLocalChecked();
+      }
+      break;
+
+    case UTF8:
+      val = New<String>(buf, buflen).ToLocalChecked();
+      break;
+
+    case BINARY: {
+      // TODO(isaacs) use ExternalTwoByteString?
+      const unsigned char *cbuf = reinterpret_cast<const unsigned char*>(buf);
+      uint16_t * twobytebuf = new uint16_t[buflen];
+      for (size_t i = 0; i < buflen; i++) {
+        // XXX is the following line platform independent?
+        twobytebuf[i] = cbuf[i];
+      }
+      val = New<String>(twobytebuf, buflen).ToLocalChecked();
+      delete[] twobytebuf;
+      break;
+    }
+
+    case BASE64: {
+      size_t dlen = base64_encoded_size(buflen);
+      char* dst = new char[dlen];
+
+      size_t written = base64_encode(buf, buflen, dst, dlen);
+      assert(written == dlen);
+
+      val = New<String>(dst, dlen).ToLocalChecked();
+      delete[] dst;
+      break;
+    }
+
+    case UCS2: {
+      const uint16_t* data = reinterpret_cast<const uint16_t*>(buf);
+      val = New<String>(data, buflen / 2).ToLocalChecked();
+      break;
+    }
+
+    case HEX: {
+      size_t dlen = buflen * 2;
+      char* dst = new char[dlen];
+      size_t written = hex_encode(buf, buflen, dst, dlen);
+      assert(written == dlen);
+
+      val = New<String>(dst, dlen).ToLocalChecked();
+      delete[] dst;
+      break;
+    }
+
+    default:
+      assert(0 && "unknown encoding");
+      break;
+  }
+
+  return val;
+}
+
+#undef base64_encoded_size
+
+}  // end of namespace imp
+
+#endif  // NAN_STRING_BYTES_H_
diff --git a/input_devices/mag/node_modules/nan/nan_typedarray_contents.h b/input_devices/mag/node_modules/nan/nan_typedarray_contents.h
new file mode 100644
index 00000000..d28ae323
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_typedarray_contents.h
@@ -0,0 +1,90 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_TYPEDARRAY_CONTENTS_H_
+#define NAN_TYPEDARRAY_CONTENTS_H_
+
+template<typename T>
+class TypedArrayContents {
+ public:
+  inline explicit TypedArrayContents(v8::Local<v8::Value> from) :
+      length_(0), data_(NULL) {
+    HandleScope scope;
+
+    size_t length = 0;
+    void*  data = NULL;
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+
+    if (from->IsArrayBufferView()) {
+      v8::Local<v8::ArrayBufferView> array =
+        v8::Local<v8::ArrayBufferView>::Cast(from);
+
+      const size_t    byte_length = array->ByteLength();
+      const ptrdiff_t byte_offset = array->ByteOffset();
+      v8::Local<v8::ArrayBuffer> buffer = array->Buffer();
+
+      length = byte_length / sizeof(T);
+      data   = static_cast<char*>(buffer->GetContents().Data()) + byte_offset;
+    }
+
+#else
+
+    if (from->IsObject() && !from->IsNull()) {
+      v8::Local<v8::Object> array = v8::Local<v8::Object>::Cast(from);
+
+      MaybeLocal<v8::Value> buffer = Get(array,
+        New<v8::String>("buffer").ToLocalChecked());
+      MaybeLocal<v8::Value> byte_length = Get(array,
+        New<v8::String>("byteLength").ToLocalChecked());
+      MaybeLocal<v8::Value> byte_offset = Get(array,
+        New<v8::String>("byteOffset").ToLocalChecked());
+
+      if (!buffer.IsEmpty() &&
+          !byte_length.IsEmpty() && byte_length.ToLocalChecked()->IsUint32() &&
+          !byte_offset.IsEmpty() && byte_offset.ToLocalChecked()->IsUint32()) {
+        data = array->GetIndexedPropertiesExternalArrayData();
+        if(data) {
+          length = byte_length.ToLocalChecked()->Uint32Value() / sizeof(T);
+        }
+      }
+    }
+
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1900 || __cplusplus >= 201103L
+    assert(reinterpret_cast<uintptr_t>(data) % alignof (T) == 0);
+#elif defined(_MSC_VER) && _MSC_VER >= 1600 || defined(__GNUC__)
+    assert(reinterpret_cast<uintptr_t>(data) % __alignof(T) == 0);
+#else
+    assert(reinterpret_cast<uintptr_t>(data) % sizeof (T) == 0);
+#endif
+
+    length_ = length;
+    data_   = static_cast<T*>(data);
+  }
+
+  inline size_t length() const      { return length_; }
+  inline T* operator*()             { return data_;   }
+  inline const T* operator*() const { return data_;   }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(TypedArrayContents)
+
+  //Disable heap allocation
+  void *operator new(size_t size);
+  void operator delete(void *, size_t) {
+    abort();
+  }
+
+  size_t  length_;
+  T*      data_;
+};
+
+#endif  // NAN_TYPEDARRAY_CONTENTS_H_
diff --git a/input_devices/mag/node_modules/nan/nan_weak.h b/input_devices/mag/node_modules/nan/nan_weak.h
new file mode 100644
index 00000000..744ffd6e
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/nan_weak.h
@@ -0,0 +1,432 @@
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+#ifndef NAN_WEAK_H_
+#define NAN_WEAK_H_
+
+static const int kInternalFieldsInWeakCallback = 2;
+static const int kNoInternalFieldIndex = -1;
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
+    v8::WeakCallbackInfo<WeakCallbackInfo<T> > const&
+# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
+    NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
+# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
+# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
+#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
+# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
+    v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
+# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
+    NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
+# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
+# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
+#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
+    v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
+# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
+    v8::InternalFieldsCallbackData<WeakCallbackInfo<T>, void> const&
+# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
+# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+# define NAN_WEAK_CALLBACK_DATA_TYPE_ \
+    v8::WeakCallbackData<S, WeakCallbackInfo<T> > const&
+# define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_
+#else
+# define NAN_WEAK_CALLBACK_DATA_TYPE_ void *
+# define NAN_WEAK_CALLBACK_SIG_ \
+    v8::Persistent<v8::Value>, NAN_WEAK_CALLBACK_DATA_TYPE_
+#endif
+
+template<typename T>
+class WeakCallbackInfo {
+ public:
+  typedef void (*Callback)(const WeakCallbackInfo<T>& data);
+  WeakCallbackInfo(
+      Persistent<v8::Value> *persistent
+    , Callback callback
+    , void *parameter
+    , void *field1 = 0
+    , void *field2 = 0) :
+        callback_(callback), isolate_(0), parameter_(parameter) {
+    std::memcpy(&persistent_, persistent, sizeof (v8::Persistent<v8::Value>));
+    internal_fields_[0] = field1;
+    internal_fields_[1] = field2;
+  }
+  inline v8::Isolate *GetIsolate() const { return isolate_; }
+  inline T *GetParameter() const { return static_cast<T*>(parameter_); }
+  inline void *GetInternalField(int index) const {
+    assert((index == 0 || index == 1) && "internal field index out of bounds");
+    if (index == 0) {
+      return internal_fields_[0];
+    } else {
+      return internal_fields_[1];
+    }
+  }
+
+ private:
+  NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo)
+  Callback callback_;
+  v8::Isolate *isolate_;
+  void *parameter_;
+  void *internal_fields_[kInternalFieldsInWeakCallback];
+  v8::Persistent<v8::Value> persistent_;
+  template<typename S, typename M> friend class Persistent;
+  template<typename S> friend class PersistentBase;
+#if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION
+# if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+  template<typename S>
+  static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
+  template<typename S>
+  static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
+# else
+  static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
+  static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
+# endif
+#else
+# if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                     \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+  template<bool isFirstPass>
+  static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
+  template<bool isFirstPass>
+  static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
+# else
+  static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
+  static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
+# endif
+  static WeakCallbackInfo *unwrapparameter(
+      NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data);
+  static WeakCallbackInfo *unwraptwofield(
+      NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data);
+#endif
+};
+
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+
+template<typename T>
+template<bool isFirstPass>
+void
+WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
+  WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
+  if (isFirstPass) {
+    cbinfo->persistent_.Reset();
+    data.SetSecondPassCallback(invokeparameter<false>);
+  } else {
+    cbinfo->callback_(*cbinfo);
+    delete cbinfo;
+  }
+}
+
+template<typename T>
+template<bool isFirstPass>
+void
+WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
+  WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
+  if (isFirstPass) {
+    cbinfo->persistent_.Reset();
+    data.SetSecondPassCallback(invoketwofield<false>);
+  } else {
+    cbinfo->callback_(*cbinfo);
+    delete cbinfo;
+  }
+}
+
+template<typename T>
+WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
+    NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
+  WeakCallbackInfo<T> *cbinfo =
+      static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
+  cbinfo->isolate_ = data.GetIsolate();
+  return cbinfo;
+}
+
+template<typename T>
+WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
+    NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
+  WeakCallbackInfo<T> *cbinfo =
+      static_cast<WeakCallbackInfo<T>*>(data.GetInternalField(0));
+  cbinfo->isolate_ = data.GetIsolate();
+  return cbinfo;
+}
+
+#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
+#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
+#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
+#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
+# elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+
+template<typename T>
+void
+WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
+  WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
+  cbinfo->persistent_.Reset();
+  cbinfo->callback_(*cbinfo);
+  delete cbinfo;
+}
+
+template<typename T>
+void
+WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
+  WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
+  cbinfo->persistent_.Reset();
+  cbinfo->callback_(*cbinfo);
+  delete cbinfo;
+}
+
+template<typename T>
+WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
+    NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
+  WeakCallbackInfo<T> *cbinfo =
+       static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
+  cbinfo->isolate_ = data.GetIsolate();
+  return cbinfo;
+}
+
+template<typename T>
+WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
+    NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
+  WeakCallbackInfo<T> *cbinfo =
+       static_cast<WeakCallbackInfo<T>*>(data.GetInternalField1());
+  cbinfo->isolate_ = data.GetIsolate();
+  return cbinfo;
+}
+
+#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
+#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
+#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
+#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+
+template<typename T>
+template<typename S>
+void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
+  WeakCallbackInfo<T> *cbinfo = unwrap(data);
+  cbinfo->persistent_.Reset();
+  cbinfo->callback_(*cbinfo);
+  delete cbinfo;
+}
+
+template<typename T>
+template<typename S>
+WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
+    NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
+  void *parameter = data.GetParameter();
+  WeakCallbackInfo<T> *cbinfo =
+      static_cast<WeakCallbackInfo<T>*>(parameter);
+  cbinfo->isolate_ = data.GetIsolate();
+  return cbinfo;
+}
+
+#undef NAN_WEAK_CALLBACK_SIG_
+#undef NAN_WEAK_CALLBACK_DATA_TYPE_
+#else
+
+template<typename T>
+void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
+  WeakCallbackInfo<T> *cbinfo = unwrap(data);
+  cbinfo->persistent_.Dispose();
+  cbinfo->persistent_.Clear();
+  cbinfo->callback_(*cbinfo);
+  delete cbinfo;
+}
+
+template<typename T>
+WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
+    NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
+  WeakCallbackInfo<T> *cbinfo =
+      static_cast<WeakCallbackInfo<T>*>(data);
+  cbinfo->isolate_ = v8::Isolate::GetCurrent();
+  return cbinfo;
+}
+
+#undef NAN_WEAK_CALLBACK_SIG_
+#undef NAN_WEAK_CALLBACK_DATA_TYPE_
+#endif
+
+#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \
+  (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
+template<typename T, typename M>
+template<typename P>
+inline void Persistent<T, M>::SetWeak(
+    P *parameter
+  , typename WeakCallbackInfo<P>::Callback callback
+  , WeakCallbackType type) {
+  WeakCallbackInfo<P> *wcbd;
+  if (type == WeakCallbackType::kParameter) {
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , parameter);
+    v8::PersistentBase<T>::SetWeak(
+        wcbd
+      , WeakCallbackInfo<P>::template invokeparameter<true>
+      , type);
+  } else {
+    v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
+    assert((*self)->IsObject());
+    int count = (*self)->InternalFieldCount();
+    void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
+    for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
+      internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
+    }
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , 0
+      , internal_fields[0]
+      , internal_fields[1]);
+    (*self)->SetAlignedPointerInInternalField(0, wcbd);
+    v8::PersistentBase<T>::SetWeak(
+        static_cast<WeakCallbackInfo<P>*>(0)
+      , WeakCallbackInfo<P>::template invoketwofield<true>
+      , type);
+  }
+}
+#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
+template<typename T, typename M>
+template<typename P>
+inline void Persistent<T, M>::SetWeak(
+    P *parameter
+  , typename WeakCallbackInfo<P>::Callback callback
+  , WeakCallbackType type) {
+  WeakCallbackInfo<P> *wcbd;
+  if (type == WeakCallbackType::kParameter) {
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , parameter);
+    v8::PersistentBase<T>::SetPhantom(
+        wcbd
+      , WeakCallbackInfo<P>::invokeparameter);
+  } else {
+    v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
+    assert((*self)->IsObject());
+    int count = (*self)->InternalFieldCount();
+    void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
+    for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
+      internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
+    }
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , 0
+      , internal_fields[0]
+      , internal_fields[1]);
+    (*self)->SetAlignedPointerInInternalField(0, wcbd);
+    v8::PersistentBase<T>::SetPhantom(
+        static_cast<WeakCallbackInfo<P>*>(0)
+      , WeakCallbackInfo<P>::invoketwofield
+      , 0
+      , count > 1 ? 1 : kNoInternalFieldIndex);
+  }
+}
+#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
+template<typename T, typename M>
+template<typename P>
+inline void Persistent<T, M>::SetWeak(
+    P *parameter
+  , typename WeakCallbackInfo<P>::Callback callback
+  , WeakCallbackType type) {
+  WeakCallbackInfo<P> *wcbd;
+  if (type == WeakCallbackType::kParameter) {
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , parameter);
+    v8::PersistentBase<T>::SetPhantom(
+        wcbd
+      , WeakCallbackInfo<P>::invokeparameter);
+  } else {
+    v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
+    assert((*self)->IsObject());
+    int count = (*self)->InternalFieldCount();
+    void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
+    for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
+      internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
+    }
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , 0
+      , internal_fields[0]
+      , internal_fields[1]);
+    (*self)->SetAlignedPointerInInternalField(0, wcbd);
+    v8::PersistentBase<T>::SetPhantom(
+        WeakCallbackInfo<P>::invoketwofield
+      , 0
+      , count > 1 ? 1 : kNoInternalFieldIndex);
+  }
+}
+#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
+template<typename T, typename M>
+template<typename P>
+inline void Persistent<T, M>::SetWeak(
+    P *parameter
+  , typename WeakCallbackInfo<P>::Callback callback
+  , WeakCallbackType type) {
+  WeakCallbackInfo<P> *wcbd;
+  if (type == WeakCallbackType::kParameter) {
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , parameter);
+    v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
+  } else {
+    v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
+    assert((*self)->IsObject());
+    int count = (*self)->InternalFieldCount();
+    void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
+    for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
+      internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i);
+    }
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , 0
+      , internal_fields[0]
+      , internal_fields[1]);
+    v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
+  }
+}
+#else
+template<typename T>
+template<typename P>
+inline void PersistentBase<T>::SetWeak(
+    P *parameter
+  , typename WeakCallbackInfo<P>::Callback callback
+  , WeakCallbackType type) {
+  WeakCallbackInfo<P> *wcbd;
+  if (type == WeakCallbackType::kParameter) {
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , parameter);
+    persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
+  } else {
+    v8::Local<T>* self = reinterpret_cast<v8::Local<T>*>(this);
+    assert((*self)->IsObject());
+    int count = (*self)->InternalFieldCount();
+    void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
+    for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
+      internal_fields[i] = (*self)->GetPointerFromInternalField(i);
+    }
+    wcbd = new WeakCallbackInfo<P>(
+        reinterpret_cast<Persistent<v8::Value>*>(this)
+      , callback
+      , 0
+      , internal_fields[0]
+      , internal_fields[1]);
+    persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
+  }
+}
+#endif
+
+#endif  // NAN_WEAK_H_
diff --git a/input_devices/mag/node_modules/nan/package.json b/input_devices/mag/node_modules/nan/package.json
new file mode 100644
index 00000000..204bf882
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/package.json
@@ -0,0 +1,135 @@
+{
+  "_args": [
+    [
+      "nan@^2.9.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/bindings"
+    ]
+  ],
+  "_from": "nan@>=2.9.2 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "nan@2.11.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/nan",
+  "_nodeVersion": "9.6.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/nan_2.11.1_1538208593407_0.7919453530392533"
+  },
+  "_npmUser": {
+    "email": "bbyholm@abo.fi",
+    "name": "kkoopa"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "nan",
+    "raw": "nan@^2.9.2",
+    "rawSpec": "^2.9.2",
+    "scope": null,
+    "spec": ">=2.9.2 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/bindings"
+  ],
+  "_resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
+  "_shasum": "90e22bccb8ca57ea4cd37cc83d3819b52eea6766",
+  "_shrinkwrap": null,
+  "_spec": "nan@^2.9.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/bindings",
+  "bugs": {
+    "url": "https://github.com/nodejs/nan/issues"
+  },
+  "contributors": [
+    {
+      "name": "Rod Vagg",
+      "email": "r@va.gg",
+      "url": "https://github.com/rvagg"
+    },
+    {
+      "name": "Benjamin Byholm",
+      "email": "bbyholm@abo.fi",
+      "url": "https://github.com/kkoopa/"
+    },
+    {
+      "name": "Trevor Norris",
+      "email": "trev.norris@gmail.com",
+      "url": "https://github.com/trevnorris"
+    },
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "https://github.com/TooTallNate"
+    },
+    {
+      "name": "Brett Lawson",
+      "email": "brett19@gmail.com",
+      "url": "https://github.com/brett19"
+    },
+    {
+      "name": "Ben Noordhuis",
+      "email": "info@bnoordhuis.nl",
+      "url": "https://github.com/bnoordhuis"
+    },
+    {
+      "name": "David Siegel",
+      "email": "david@artcom.de",
+      "url": "https://github.com/agnat"
+    },
+    {
+      "name": "Michael Ira Krufky",
+      "email": "mkrufky@gmail.com",
+      "url": "https://github.com/mkrufky"
+    }
+  ],
+  "dependencies": {},
+  "description": "Native Abstractions for Node.js: C++ header for Node 0.8 -> 10 compatibility",
+  "devDependencies": {
+    "bindings": "~1.2.1",
+    "commander": "^2.8.1",
+    "glob": "^5.0.14",
+    "node-gyp": "~3.6.2",
+    "readable-stream": "^2.1.4",
+    "request": "=2.81.0",
+    "tap": "~0.7.1",
+    "xtend": "~4.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 47,
+    "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrzNSCRA9TVsSAnZWagAA0vgQAJoa+4F+vH2jgoMAIh2M\nduUOqUMSIKBSqcO1+OzZj8Xi1NTQXKnuxwUpcLfG7kUFSTXMNQ5pqXv4om8/\nViw9to8ZE5wAlK3Uqejk5qaQgVNmxeWtO91R85q3KNI6l1Z4qaRVJN13GwnS\nS1iwDlG/3dKLWAAcoJjP20uCHSvFmEsR+FJy0G5y76s+QSJNFI0TmZRXpowJ\nTezFZsBU/EFRBKKIv//nNvuSxh1/TITrD72sshjpjWdwWqJK0T9emtuBOGFT\nhjsYWGeykfu3HjxBwrzG4hNhyO7nQCl59TRoiPKyqNb70W9RvjJAcldwcMqX\nBddgZ5lZq4+qw+KBGnkoHvO5cS6CQoe3cgFNILGq1NNbPc22Kwp5CVdy1TXv\nC7BcutM20izHrQeBnilZTy+PFBx3eNixWJHFyVDZeGrF47t2jqKvcLEm1eF8\n7pA6/VxXDvE2D+MBjfpAWfSbZ0bR0jhDYvly+1DufutyCd+G6JzR04FsGg1y\nk873NoJ6P9WlZhzvnLBaoWOaQP8XOcxcugSQPP8lTA4hDmQwXY9K8Rwi6Ry2\nw+wGn2WAUQXQhKHJto6dJiIZyJ/yt0h5rjGnwzraXReQQXcTif2dSkvpAgPK\nRXVMRKQIh3us3mU6rSXwg08T4NopJLDLdEuwYYvoKy7xPZLx5uzP/phWLJsb\nG33O\r\n=ig8G\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "90e22bccb8ca57ea4cd37cc83d3819b52eea6766",
+    "tarball": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
+    "unpackedSize": 487268
+  },
+  "gitHead": "85a74a1a724ddffdb81f709b745d5707a8a0f699",
+  "homepage": "https://github.com/nodejs/nan#readme",
+  "license": "MIT",
+  "main": "include_dirs.js",
+  "maintainers": [
+    {
+      "name": "kkoopa",
+      "email": "bbyholm@abo.fi"
+    },
+    {
+      "name": "rvagg",
+      "email": "rod@vagg.org"
+    }
+  ],
+  "name": "nan",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/nodejs/nan.git"
+  },
+  "scripts": {
+    "docs": "doc/.build.sh",
+    "rebuild-tests": "node-gyp rebuild --msvs_version=2015 --directory test",
+    "test": "tap --gc --stderr test/js/*-test.js",
+    "test:worker": "node --experimental-worker test/tap-as-worker.js --gc --stderr test/js/*-test.js"
+  },
+  "version": "2.11.1"
+}
diff --git a/input_devices/mag/node_modules/nan/tools/1to2.js b/input_devices/mag/node_modules/nan/tools/1to2.js
new file mode 100755
index 00000000..337f8bf2
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/tools/1to2.js
@@ -0,0 +1,412 @@
+#!/usr/bin/env node
+/*********************************************************************
+ * NAN - Native Abstractions for Node.js
+ *
+ * Copyright (c) 2018 NAN contributors
+ *
+ * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
+ ********************************************************************/
+
+var commander = require('commander'),
+    fs = require('fs'),
+    glob = require('glob'),
+    groups = [],
+    total = 0,
+    warning1 = '/* ERROR: Rewrite using Buffer */\n',
+    warning2 = '\\/\\* ERROR\\: Rewrite using Buffer \\*\\/\\n',
+    length,
+    i;
+
+fs.readFile(__dirname + '/package.json', 'utf8', function (err, data) {
+  if (err) {
+    throw err;
+  }
+
+  commander
+      .version(JSON.parse(data).version)
+      .usage('[options] <file ...>')
+      .parse(process.argv);
+
+  if (!process.argv.slice(2).length) {
+    commander.outputHelp();
+  }
+});
+
+/* construct strings representing regular expressions
+   each expression contains a unique group allowing for identification of the match
+   the index of this key group, relative to the regular expression in question,
+    is indicated by the first array member */
+
+/* simple substistutions, key group is the entire match, 0 */
+groups.push([0, [
+  '_NAN_',
+  'NODE_SET_METHOD',
+  'NODE_SET_PROTOTYPE_METHOD',
+  'NanAsciiString',
+  'NanEscapeScope',
+  'NanReturnValue',
+  'NanUcs2String'].join('|')]);
+
+/* substitutions of parameterless macros, key group is 1 */
+groups.push([1, ['(', [
+  'NanEscapableScope',
+  'NanReturnNull',
+  'NanReturnUndefined',
+  'NanScope'].join('|'), ')\\(\\)'].join('')]);
+
+/* replace TryCatch with NanTryCatch once, gobbling possible namespace, key group 2 */
+groups.push([2, '(?:(?:v8\\:\\:)?|(Nan)?)(TryCatch)']);
+
+/* NanNew("string") will likely not fail a ToLocalChecked(), key group 1 */ 
+groups.push([1, ['(NanNew)', '(\\("[^\\"]*"[^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]);
+
+/* Removed v8 APIs, warn that the code needs rewriting using node::Buffer, key group 2 */
+groups.push([2, ['(', warning2, ')?', '^.*?(', [
+      'GetIndexedPropertiesExternalArrayDataLength',
+      'GetIndexedPropertiesExternalArrayData',
+      'GetIndexedPropertiesExternalArrayDataType',
+      'GetIndexedPropertiesPixelData',
+      'GetIndexedPropertiesPixelDataLength',
+      'HasIndexedPropertiesInExternalArrayData',
+      'HasIndexedPropertiesInPixelData',
+      'SetIndexedPropertiesToExternalArrayData',
+      'SetIndexedPropertiesToPixelData'].join('|'), ')'].join('')]);
+
+/* No need for NanScope in V8-exposed methods, key group 2 */
+groups.push([2, ['((', [
+      'NAN_METHOD',
+      'NAN_GETTER',
+      'NAN_SETTER',
+      'NAN_PROPERTY_GETTER',
+      'NAN_PROPERTY_SETTER',
+      'NAN_PROPERTY_ENUMERATOR',
+      'NAN_PROPERTY_DELETER',
+      'NAN_PROPERTY_QUERY',
+      'NAN_INDEX_GETTER',
+      'NAN_INDEX_SETTER',
+      'NAN_INDEX_ENUMERATOR',
+      'NAN_INDEX_DELETER',
+      'NAN_INDEX_QUERY'].join('|'), ')\\([^\\)]*\\)\\s*\\{)\\s*NanScope\\(\\)\\s*;'].join('')]);
+
+/* v8::Value::ToXXXXXXX returns v8::MaybeLocal<T>, key group 3 */
+groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->(', [
+      'Boolean',
+      'Number',
+      'String',
+      'Object',
+      'Integer',
+      'Uint32',
+      'Int32'].join('|'), ')\\('].join('')]);
+
+/* v8::Value::XXXXXXXValue returns v8::Maybe<T>, key group 3 */
+groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->((?:', [
+      'Boolean',
+      'Number',
+      'Integer',
+      'Uint32',
+      'Int32'].join('|'), ')Value)\\('].join('')]);
+
+/* NAN_WEAK_CALLBACK macro was removed, write out callback definition, key group 1 */
+groups.push([1, '(NAN_WEAK_CALLBACK)\\(([^\\s\\)]+)\\)']);
+
+/* node::ObjectWrap and v8::Persistent have been replaced with Nan implementations, key group 1 */
+groups.push([1, ['(', [
+  'NanDisposePersistent',
+  'NanObjectWrapHandle'].join('|'), ')\\s*\\(\\s*([^\\s\\)]+)'].join('')]);
+
+/* Since NanPersistent there is no need for NanMakeWeakPersistent, key group 1 */
+groups.push([1, '(NanMakeWeakPersistent)\\s*\\(\\s*([^\\s,]+)\\s*,\\s*']);
+
+/* Many methods of v8::Object and others now return v8::MaybeLocal<T>, key group 3 */
+groups.push([3, ['([\\s])([^\\s]+)->(', [
+  'GetEndColumn',
+  'GetFunction',
+  'GetLineNumber',
+  'NewInstance',
+  'GetPropertyNames',
+  'GetOwnPropertyNames',
+  'GetSourceLine',
+  'GetStartColumn',
+  'ObjectProtoToString',
+  'ToArrayIndex',
+  'ToDetailString',
+  'CallAsConstructor',
+  'CallAsFunction',
+  'CloneElementAt',
+  'Delete',
+  'ForceSet',
+  'Get',
+  'GetPropertyAttributes',
+  'GetRealNamedProperty',
+  'GetRealNamedPropertyInPrototypeChain',
+  'Has',
+  'HasOwnProperty',
+  'HasRealIndexedProperty',
+  'HasRealNamedCallbackProperty',
+  'HasRealNamedProperty',
+  'Set',
+  'SetAccessor',
+  'SetIndexedPropertyHandler',
+  'SetNamedPropertyHandler',
+  'SetPrototype'].join('|'), ')\\('].join('')]);
+
+/* You should get an error if any of these fail anyways,
+   or handle the error better, it is indicated either way, key group 2 */
+groups.push([2, ['NanNew(<(?:v8\\:\\:)?(', ['Date', 'String', 'RegExp'].join('|'), ')>)(\\([^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]);
+
+/* v8::Value::Equals now returns a v8::Maybe, key group 3 */
+groups.push([3, '([\\s\\(\\)])([^\\s\\(\\)]+)->(Equals)\\(([^\\s\\)]+)']);
+
+/* NanPersistent makes this unnecessary, key group 1 */
+groups.push([1, '(NanAssignPersistent)(?:<v8\\:\\:[^>]+>)?\\(([^,]+),\\s*']);
+
+/* args has been renamed to info, key group 2 */
+groups.push([2, '(\\W)(args)(\\W)'])
+
+/* node::ObjectWrap was replaced with NanObjectWrap, key group 2 */
+groups.push([2, '(\\W)(?:node\\:\\:)?(ObjectWrap)(\\W)']);
+
+/* v8::Persistent was replaced with NanPersistent, key group 2 */
+groups.push([2, '(\\W)(?:v8\\:\\:)?(Persistent)(\\W)']);
+
+/* counts the number of capturing groups in a well-formed regular expression,
+   ignoring non-capturing groups and escaped parentheses */
+function groupcount(s) {
+  var positive = s.match(/\((?!\?)/g),
+      negative = s.match(/\\\(/g);
+  return (positive ? positive.length : 0) - (negative ? negative.length : 0);
+}
+
+/* compute the absolute position of each key group in the joined master RegExp */
+for (i = 1, length = groups.length; i < length; i++) {
+	total += groupcount(groups[i - 1][1]);
+	groups[i][0] += total;
+}
+
+/* create the master RegExp, whis is the union of all the groups' expressions */
+master = new RegExp(groups.map(function (a) { return a[1]; }).join('|'), 'gm');
+
+/* replacement function for String.replace, receives 21 arguments */
+function replace() {
+	/* simple expressions */
+      switch (arguments[groups[0][0]]) {
+        case '_NAN_':
+          return 'NAN_';
+        case 'NODE_SET_METHOD':
+          return 'NanSetMethod';
+        case 'NODE_SET_PROTOTYPE_METHOD':
+          return 'NanSetPrototypeMethod';
+        case 'NanAsciiString':
+          return 'NanUtf8String';
+        case 'NanEscapeScope':
+          return 'scope.Escape';
+        case 'NanReturnNull':
+          return 'info.GetReturnValue().SetNull';
+        case 'NanReturnValue':
+          return 'info.GetReturnValue().Set';
+        case 'NanUcs2String':
+          return 'v8::String::Value';
+        default:
+      }
+
+      /* macros without arguments */
+      switch (arguments[groups[1][0]]) {
+        case 'NanEscapableScope':
+          return 'NanEscapableScope scope'
+        case 'NanReturnUndefined':
+          return 'return';
+        case 'NanScope':
+          return 'NanScope scope';
+        default:
+      }
+
+      /* TryCatch, emulate negative backref */
+      if (arguments[groups[2][0]] === 'TryCatch') {
+        return arguments[groups[2][0] - 1] ? arguments[0] : 'NanTryCatch';
+      }
+
+      /* NanNew("foo") --> NanNew("foo").ToLocalChecked() */
+      if (arguments[groups[3][0]] === 'NanNew') {
+        return [arguments[0], '.ToLocalChecked()'].join('');
+      }
+
+      /* insert warning for removed functions as comment on new line above */
+      switch (arguments[groups[4][0]]) {
+        case 'GetIndexedPropertiesExternalArrayData':
+        case 'GetIndexedPropertiesExternalArrayDataLength':
+        case 'GetIndexedPropertiesExternalArrayDataType':
+        case 'GetIndexedPropertiesPixelData':
+        case 'GetIndexedPropertiesPixelDataLength':
+        case 'HasIndexedPropertiesInExternalArrayData':
+        case 'HasIndexedPropertiesInPixelData':
+        case 'SetIndexedPropertiesToExternalArrayData':
+        case 'SetIndexedPropertiesToPixelData':
+          return arguments[groups[4][0] - 1] ? arguments[0] : [warning1, arguments[0]].join('');
+        default:
+      }
+
+     /* remove unnecessary NanScope() */
+      switch (arguments[groups[5][0]]) {
+        case 'NAN_GETTER':
+        case 'NAN_METHOD':
+        case 'NAN_SETTER':
+        case 'NAN_INDEX_DELETER':
+        case 'NAN_INDEX_ENUMERATOR':
+        case 'NAN_INDEX_GETTER':
+        case 'NAN_INDEX_QUERY':
+        case 'NAN_INDEX_SETTER':
+        case 'NAN_PROPERTY_DELETER':
+        case 'NAN_PROPERTY_ENUMERATOR':
+        case 'NAN_PROPERTY_GETTER':
+        case 'NAN_PROPERTY_QUERY':
+        case 'NAN_PROPERTY_SETTER':
+          return arguments[groups[5][0] - 1];
+        default:
+      }
+
+      /* Value converstion */
+      switch (arguments[groups[6][0]]) {
+        case 'Boolean':
+        case 'Int32':
+        case 'Integer':
+        case 'Number':
+        case 'Object':
+        case 'String':
+        case 'Uint32':
+          return [arguments[groups[6][0] - 2], 'NanTo<v8::', arguments[groups[6][0]], '>(',  arguments[groups[6][0] - 1]].join('');
+        default:
+      }
+
+      /* other value conversion */
+      switch (arguments[groups[7][0]]) {
+        case 'BooleanValue':
+          return [arguments[groups[7][0] - 2], 'NanTo<bool>(', arguments[groups[7][0] - 1]].join('');
+        case 'Int32Value':
+          return [arguments[groups[7][0] - 2], 'NanTo<int32_t>(', arguments[groups[7][0] - 1]].join('');
+        case 'IntegerValue':
+          return [arguments[groups[7][0] - 2], 'NanTo<int64_t>(', arguments[groups[7][0] - 1]].join('');
+        case 'Uint32Value':
+          return [arguments[groups[7][0] - 2], 'NanTo<uint32_t>(', arguments[groups[7][0] - 1]].join('');
+        default:
+      }
+
+      /* NAN_WEAK_CALLBACK */
+      if (arguments[groups[8][0]] === 'NAN_WEAK_CALLBACK') {
+        return ['template<typename T>\nvoid ',
+          arguments[groups[8][0] + 1], '(const NanWeakCallbackInfo<T> &data)'].join('');
+      }
+
+      /* use methods on NAN classes instead */
+      switch (arguments[groups[9][0]]) {
+        case 'NanDisposePersistent':
+          return [arguments[groups[9][0] + 1], '.Reset('].join('');
+        case 'NanObjectWrapHandle':
+          return [arguments[groups[9][0] + 1], '->handle('].join('');
+        default:
+      }
+
+      /* use method on NanPersistent instead */
+      if (arguments[groups[10][0]] === 'NanMakeWeakPersistent') {
+        return arguments[groups[10][0] + 1] + '.SetWeak(';
+      }
+
+      /* These return Maybes, the upper ones take no arguments */
+      switch (arguments[groups[11][0]]) {
+        case 'GetEndColumn':
+        case 'GetFunction':
+        case 'GetLineNumber':
+        case 'GetOwnPropertyNames':
+        case 'GetPropertyNames':
+        case 'GetSourceLine':
+        case 'GetStartColumn':
+        case 'NewInstance':
+        case 'ObjectProtoToString':
+        case 'ToArrayIndex':
+        case 'ToDetailString':
+          return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1]].join('');
+        case 'CallAsConstructor':
+        case 'CallAsFunction':
+        case 'CloneElementAt':
+        case 'Delete':
+        case 'ForceSet':
+        case 'Get':
+        case 'GetPropertyAttributes':
+        case 'GetRealNamedProperty':
+        case 'GetRealNamedPropertyInPrototypeChain':
+        case 'Has':
+        case 'HasOwnProperty':
+        case 'HasRealIndexedProperty':
+        case 'HasRealNamedCallbackProperty':
+        case 'HasRealNamedProperty':
+        case 'Set':
+        case 'SetAccessor':
+        case 'SetIndexedPropertyHandler':
+        case 'SetNamedPropertyHandler':
+        case 'SetPrototype':
+          return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1], ', '].join('');
+        default:
+      }
+
+      /* Automatic ToLocalChecked(), take it or leave it */
+      switch (arguments[groups[12][0]]) {
+        case 'Date':
+        case 'String':
+        case 'RegExp':
+          return ['NanNew', arguments[groups[12][0] - 1], arguments[groups[12][0] + 1], '.ToLocalChecked()'].join('');
+        default:
+      }
+
+      /* NanEquals is now required for uniformity */
+      if (arguments[groups[13][0]] === 'Equals') {
+        return [arguments[groups[13][0] - 1], 'NanEquals(', arguments[groups[13][0] - 1], ', ', arguments[groups[13][0] + 1]].join('');
+      }
+
+      /* use method on replacement class instead */
+      if (arguments[groups[14][0]] === 'NanAssignPersistent') {
+        return [arguments[groups[14][0] + 1], '.Reset('].join('');
+      }
+
+      /* args --> info */
+      if (arguments[groups[15][0]] === 'args') {
+        return [arguments[groups[15][0] - 1], 'info', arguments[groups[15][0] + 1]].join('');
+      }
+
+      /* ObjectWrap --> NanObjectWrap */
+      if (arguments[groups[16][0]] === 'ObjectWrap') {
+        return [arguments[groups[16][0] - 1], 'NanObjectWrap', arguments[groups[16][0] + 1]].join('');
+      }
+
+      /* Persistent --> NanPersistent */
+      if (arguments[groups[17][0]] === 'Persistent') {
+        return [arguments[groups[17][0] - 1], 'NanPersistent', arguments[groups[17][0] + 1]].join('');
+      }
+
+      /* This should not happen. A switch is probably missing a case if it does. */
+      throw 'Unhandled match: ' + arguments[0];
+}
+
+/* reads a file, runs replacement and writes it back */
+function processFile(file) {
+  fs.readFile(file, {encoding: 'utf8'}, function (err, data) {
+    if (err) {
+      throw err;
+    }
+
+    /* run replacement twice, might need more runs */
+    fs.writeFile(file, data.replace(master, replace).replace(master, replace), function (err) {
+      if (err) {
+        throw err;
+      }
+    });
+  });
+}
+
+/* process file names from command line and process the identified files */
+for (i = 2, length = process.argv.length; i < length; i++) {
+  glob(process.argv[i], function (err, matches) {
+    if (err) {
+      throw err;
+    }
+    matches.forEach(processFile);
+  });
+}
diff --git a/input_devices/mag/node_modules/nan/tools/README.md b/input_devices/mag/node_modules/nan/tools/README.md
new file mode 100644
index 00000000..7f07e4b8
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/tools/README.md
@@ -0,0 +1,14 @@
+1to2 naively converts source code files from NAN 1 to NAN 2. There will be erroneous conversions,
+false positives and missed opportunities. The input files are rewritten in place. Make sure that
+you have backups. You will have to manually review the changes afterwards and do some touchups.
+
+```sh
+$ tools/1to2.js
+
+  Usage: 1to2 [options] <file ...>
+
+  Options:
+
+    -h, --help     output usage information
+    -V, --version  output the version number
+```
diff --git a/input_devices/mag/node_modules/nan/tools/package.json b/input_devices/mag/node_modules/nan/tools/package.json
new file mode 100644
index 00000000..2dcdd789
--- /dev/null
+++ b/input_devices/mag/node_modules/nan/tools/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "1to2",
+  "version": "1.0.0",
+  "description": "NAN 1 -> 2 Migration Script",
+  "main": "1to2.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/nodejs/nan.git"
+  },
+  "contributors": [
+    "Benjamin Byholm <bbyholm@abo.fi> (https://github.com/kkoopa/)",
+    "Mathias Küsel (https://github.com/mathiask88/)"
+  ],
+  "dependencies": {
+    "glob": "~5.0.10",
+    "commander": "~2.8.1"
+  },
+  "license": "MIT"
+}
diff --git a/input_devices/mag/node_modules/napi-build-utils/LICENSE b/input_devices/mag/node_modules/napi-build-utils/LICENSE
new file mode 100644
index 00000000..8e0248a4
--- /dev/null
+++ b/input_devices/mag/node_modules/napi-build-utils/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 inspiredware
+
+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/input_devices/mag/node_modules/napi-build-utils/README.md b/input_devices/mag/node_modules/napi-build-utils/README.md
new file mode 100644
index 00000000..1097b7f7
--- /dev/null
+++ b/input_devices/mag/node_modules/napi-build-utils/README.md
@@ -0,0 +1,48 @@
+# napi-build-utils
+
+[![npm](https://img.shields.io/npm/v/napi-build-utils.svg)](https://www.npmjs.com/package/napi-build-utils)
+![Node version](https://img.shields.io/node/v/prebuild.svg)
+[![Build Status](https://travis-ci.org/inspiredware/napi-build-utils.svg?branch=master)](https://travis-ci.org/inspiredware/napi-build-utils) 
+[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) 
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 
+
+A set of utilities to assist developers of tools that build [N-API](https://nodejs.org/api/n-api.html#n_api_n_api) native add-ons.
+
+## Background
+
+This module is targeted to developers creating tools that build N-API native add-ons. 
+
+It implements a set of functions that aid in determining the N-API version supported by the currently running Node instance and the set of N-API versions against which the N-API native add-on is designed to be built. Other functions determine whether a particular N-API version can be built and can issue console warnings for unsupported N-API versions. 
+
+Unlike the modules this code is designed to facilite building, this module is written entirely in JavaScript. 
+
+## Quick start
+
+```bash
+$ npm install napi-build-utils
+```
+
+The module exports a set of functions documented [here](./index.md). For exmaple:
+
+```javascript
+var napiBuildUtils = require('napi-build-utils');
+var napiVersion = napiBuildUtils.getNapiVersion(); // N-API version supported by Node, or undefined.
+```
+
+## Declaring supported N-API versions
+
+Native modules that are designed to work with [N-API](https://nodejs.org/api/n-api.html#n_api_n_api) must explicitly declare the N-API version(s) against which they are coded to build. This is accomplished by including a `binary.napi_versions` property in the module's `package.json` file. For example:
+
+```json
+"binary": {
+  "napi_versions": [2,3]
+}
+``` 
+
+In the absence of a need to compile against a specific N-API version, the value `3` is a good choice as this is the N-API version that was supported when N-API left experimental status. 
+
+Modules that are built against a specific N-API version will continue to operate indefinitely, even as later versions of N-API are introduced. 
+
+## Support
+
+If you run into problems or limitations, please file an issue and we'll take a look. Pull requests are also welcome.  
diff --git a/input_devices/mag/node_modules/napi-build-utils/index.js b/input_devices/mag/node_modules/napi-build-utils/index.js
new file mode 100644
index 00000000..5b27678d
--- /dev/null
+++ b/input_devices/mag/node_modules/napi-build-utils/index.js
@@ -0,0 +1,213 @@
+'use strict'
+// Copyright (c) 2018 inspiredware
+
+var path = require('path')
+var pkg = require(path.resolve('package.json'))
+
+var versionArray = process.version
+  .substr(1)
+  .replace(/-.*$/, '')
+  .split('.')
+  .map(function (item) {
+    return +item
+  })
+
+/**
+ *
+ * A set of utilities to assist developers of tools that build
+ * [N-API](https://nodejs.org/api/n-api.html#n_api_n_api) native add-ons.
+ *
+ * The main repository can be found
+ * [here](https://github.com/inspiredware/napi-build-utils#napi-build-utils).
+ *
+ * @module napi-build-utils
+ */
+
+/**
+ * Implements a consistent name of `napi` for N-API runtimes.
+ *
+ * @param {string} runtime The runtime string.
+ * @returns {boolean}
+ */
+exports.isNapiRuntime = function (runtime) {
+  return runtime === 'napi'
+}
+
+/**
+ * Determines whether the specified N-API version is supported
+ * by both the currently running Node instance and the package.
+ *
+ * @param {string} napiVerison The N-API version to check.
+ * @returns {boolean}
+ */
+exports.isSupportedVersion = function (napiVerison) {
+  var version = parseInt(napiVerison, 10)
+  return version <= exports.getNapiVersion() && exports.packageSupportsVersion(version)
+}
+
+/**
+ * Determines whether the specified N-API version is supported by the package.
+ * The N-API version must be preseent in the `package.json`
+ * `binary.napi_versions` array.
+ *
+ * @param {number} napiVerison The N-API version to check.
+ * @returns {boolean}
+ * @private
+ */
+exports.packageSupportsVersion = function (napiVerison) {
+  if (pkg.binary && pkg.binary.napi_versions &&
+      pkg.binary.napi_versions instanceof Array) {
+    for (var i = 0; i < pkg.binary.napi_versions.length; i++) {
+      if (pkg.binary.napi_versions[i] === napiVerison) return true
+    };
+  };
+  return false
+}
+
+/**
+ * Issues a warning to the supplied log if the N-API version is not supported
+ * by the current Node instance or if the N-API version is not supported
+ * by the package.
+ *
+ * @param {string} napiVerison The N-API version to check.
+ * @param {Object} log The log object to which the warnings are to be issued.
+ * Must implement the `warn` method.
+ */
+exports.logUnsupportedVersion = function (napiVerison, log) {
+  if (!exports.isSupportedVersion(napiVerison)) {
+    if (exports.packageSupportsVersion(napiVerison)) {
+      log.warn('This Node instance does not support N-API version ' + napiVerison)
+    } else {
+      log.warn('This package does not support N-API version ' + napiVerison)
+    }
+  }
+}
+
+/**
+ * Issues warnings to the supplied log for those N-API versions not supported
+ * by the N-API runtime or the package.
+ *
+ * Note that this function is specific to the
+ * [`prebuild`](https://github.com/prebuild/prebuild#prebuild) package.
+ *
+ * `target` is the list of targets to be built and is determined in one of
+ * three ways from the command line arguments:
+ * (1) `--target` specifies a specific target to build.
+ * (2) `--all` specifies all N-API versions supported by the package.
+ * (3) Neither of these specifies to build the single "best version available."
+ *
+ * `prebuild` is an array of objects in the form `{runtime: 'napi': target: '2'}`.
+ * The array contains the list of N-API versions that are supported by both the
+ * package being built and the currently running Node instance.
+ *
+ * The objective of this function is to issue a warning for those items that appear
+ * in the `target` argument but not in the `prebuild` argument.
+ * If a specific target is supported by the package (`packageSupportsVersion`) but
+ * but note in `prebuild`, the assumption is that the target is not supported by
+ * Node.
+ *
+ * @param {(Array<string>|string)} target The N-API version(s) to check. Target is
+ * @param {Object} prebuild A config object created by the `prebuild` package.
+ * @param {Object} log The log object to which the warnings are to be issued.
+ * Must implement the `warn` method.
+ * @private
+ */
+exports.logMissingNapiVersions = function (target, prebuild, log) {
+  if (exports.getNapiBuildVersions()) {
+    var targets = [].concat(target)
+    targets.forEach(function (napiVersion) {
+      if (!prebuildExists(prebuild, napiVersion)) {
+        if (exports.packageSupportsVersion(parseInt(napiVersion, 10))) {
+          log.warn('This Node instance does not support N-API version ' + napiVersion)
+        } else {
+          log.warn('This package does not support N-API version ' + napiVersion)
+        }
+      }
+    })
+  } else {
+    log.error('Builds with runtime \'napi\' require a binary.napi_versions ' +
+              'property on the package.json file')
+  }
+}
+
+/**
+ * Determines whether the specified N-API version exists in the prebuild
+ * configuration object.
+ *
+ * Note that this function is speicifc to the `prebuild` and `prebuild-install`
+ * packages.
+ *
+ * @param {Object} prebuild A config object created by the `prebuild` package.
+ * @param {string} napiVersion The N-APi version to be checked.
+ * @return {boolean}
+ * @private
+ */
+var prebuildExists = function (prebuild, napiVersion) {
+  if (prebuild) {
+    for (var i = 0; i < prebuild.length; i++) {
+      if (prebuild[i].target === napiVersion) return true
+    }
+  }
+  return false
+}
+
+/**
+ * Returns the best N-API version to build given the highest N-API
+ * version supported by the current Node instance and the N-API versions
+ * supported by the package, or undefined if a suitable N-API version
+ * cannot be determined.
+ *
+ * The best build version is the greatest N-API version supported by
+ * the package that is less than or equal to the highest N-API version
+ * supported by the current Node instance.
+ *
+ * @returns {number|undefined}
+ */
+exports.getBestNapiBuildVersion = function () {
+  var bestNapiBuildVersion = 0
+  var napiBuildVersions = exports.getNapiBuildVersions(pkg)
+  if (napiBuildVersions) {
+    var ourNapiVersion = exports.getNapiVersion()
+    napiBuildVersions.forEach(function (napiBuildVersion) {
+      if (napiBuildVersion > bestNapiBuildVersion &&
+        napiBuildVersion <= ourNapiVersion) {
+        bestNapiBuildVersion = napiBuildVersion
+      }
+    })
+  }
+  return bestNapiBuildVersion === 0 ? undefined : bestNapiBuildVersion
+}
+
+/**
+ * Returns an array of N-APi versions supported by the package.
+ *
+ * @returns {Array<string>}
+ */
+exports.getNapiBuildVersions = function () {
+  var napiBuildVersions = []
+  // remove duplicates, convert to text
+  if (pkg.binary && pkg.binary.napi_versions) {
+    pkg.binary.napi_versions.forEach(function (napiVersion) {
+      var duplicated = napiBuildVersions.indexOf('' + napiVersion) !== -1
+      if (!duplicated) {
+        napiBuildVersions.push('' + napiVersion)
+      }
+    })
+  }
+  return napiBuildVersions.length ? napiBuildVersions : undefined
+}
+
+/**
+ * Returns the highest N-API version supported by the current node instance
+ * or undefined if N-API is not supported.
+ *
+ * @returns {string|undefined}
+ */
+exports.getNapiVersion = function () {
+  var version = process.versions.napi // string, can be undefined
+  if (!version) { // this code should never need to be updated
+    if (versionArray[0] === 9 && versionArray[1] >= 3) version = '2' // 9.3.0+
+    else if (versionArray[0] === 8) version = '1' // 8.0.0+
+  }
+  return version
+}
diff --git a/input_devices/mag/node_modules/napi-build-utils/index.md b/input_devices/mag/node_modules/napi-build-utils/index.md
new file mode 100644
index 00000000..9cb45ac3
--- /dev/null
+++ b/input_devices/mag/node_modules/napi-build-utils/index.md
@@ -0,0 +1,81 @@
+<a name="module_napi-build-utils"></a>
+
+## napi-build-utils
+A set of utilities to assist developers of tools that build
+[N-API](https://nodejs.org/api/n-api.html#n_api_n_api) native add-ons.
+
+The main repository can be found
+[here](https://github.com/inspiredware/napi-build-utils#napi-build-utils).
+
+
+* [napi-build-utils](#module_napi-build-utils)
+    * [.isNapiRuntime(runtime)](#module_napi-build-utils.isNapiRuntime) ⇒ <code>boolean</code>
+    * [.isSupportedVersion(napiVerison)](#module_napi-build-utils.isSupportedVersion) ⇒ <code>boolean</code>
+    * [.logUnsupportedVersion(napiVerison, log)](#module_napi-build-utils.logUnsupportedVersion)
+    * [.getBestNapiBuildVersion()](#module_napi-build-utils.getBestNapiBuildVersion) ⇒ <code>number</code> \| <code>undefined</code>
+    * [.getNapiBuildVersions()](#module_napi-build-utils.getNapiBuildVersions) ⇒ <code>Array.&lt;string&gt;</code>
+    * [.getNapiVersion()](#module_napi-build-utils.getNapiVersion) ⇒ <code>string</code> \| <code>undefined</code>
+
+<a name="module_napi-build-utils.isNapiRuntime"></a>
+
+### napi-build-utils.isNapiRuntime(runtime) ⇒ <code>boolean</code>
+Implements a consistent name of `napi` for N-API runtimes.
+
+**Kind**: static method of [<code>napi-build-utils</code>](#module_napi-build-utils)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| runtime | <code>string</code> | The runtime string. |
+
+<a name="module_napi-build-utils.isSupportedVersion"></a>
+
+### napi-build-utils.isSupportedVersion(napiVerison) ⇒ <code>boolean</code>
+Determines whether the specified N-API version is supported
+by both the currently running Node instance and the package.
+
+**Kind**: static method of [<code>napi-build-utils</code>](#module_napi-build-utils)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| napiVerison | <code>string</code> | The N-API version to check. |
+
+<a name="module_napi-build-utils.logUnsupportedVersion"></a>
+
+### napi-build-utils.logUnsupportedVersion(napiVerison, log)
+Issues a warning to the supplied log if the N-API version is not supported
+by the current Node instance or if the N-API version is not supported
+by the package.
+
+**Kind**: static method of [<code>napi-build-utils</code>](#module_napi-build-utils)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| napiVerison | <code>string</code> | The N-API version to check. |
+| log | <code>Object</code> | The log object to which the warnings are to be issued. Must implement the `warn` method. |
+
+<a name="module_napi-build-utils.getBestNapiBuildVersion"></a>
+
+### napi-build-utils.getBestNapiBuildVersion() ⇒ <code>number</code> \| <code>undefined</code>
+Returns the best N-API version to build given the highest N-API
+version supported by the current Node instance and the N-API versions
+supported by the package, or undefined if a suitable N-API version
+cannot be determined.
+
+The best build version is the greatest N-API version supported by
+the package that is less than or equal to the highest N-API version
+supported by the current Node instance.
+
+**Kind**: static method of [<code>napi-build-utils</code>](#module_napi-build-utils)  
+<a name="module_napi-build-utils.getNapiBuildVersions"></a>
+
+### napi-build-utils.getNapiBuildVersions() ⇒ <code>Array.&lt;string&gt;</code>
+Returns an array of N-APi versions supported by the package.
+
+**Kind**: static method of [<code>napi-build-utils</code>](#module_napi-build-utils)  
+<a name="module_napi-build-utils.getNapiVersion"></a>
+
+### napi-build-utils.getNapiVersion() ⇒ <code>string</code> \| <code>undefined</code>
+Returns the highest N-API version supported by the current node instance
+or undefined if N-API is not supported.
+
+**Kind**: static method of [<code>napi-build-utils</code>](#module_napi-build-utils)  
diff --git a/input_devices/mag/node_modules/napi-build-utils/napi-build-utils-1.0.0.tgz b/input_devices/mag/node_modules/napi-build-utils/napi-build-utils-1.0.0.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..a6a9e9c39cf3c9cf9191bcaa3ff76008c0523579
GIT binary patch
literal 26382
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

literal 0
HcmV?d00001

diff --git a/input_devices/mag/node_modules/napi-build-utils/package.json b/input_devices/mag/node_modules/napi-build-utils/package.json
new file mode 100644
index 00000000..32fd369f
--- /dev/null
+++ b/input_devices/mag/node_modules/napi-build-utils/package.json
@@ -0,0 +1,99 @@
+{
+  "_args": [
+    [
+      "napi-build-utils@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "napi-build-utils@>=1.0.1 <2.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "napi-build-utils@1.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/napi-build-utils",
+  "_nodeVersion": "9.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/napi-build-utils_1.0.1_1536796507380_0.010627767909799024"
+  },
+  "_npmUser": {
+    "email": "jim@inspiredware.com",
+    "name": "inspiredware"
+  },
+  "_npmVersion": "6.4.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "napi-build-utils",
+    "raw": "napi-build-utils@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.1.tgz",
+  "_shasum": "1381a0f92c39d66bf19852e7873432fc2123e508",
+  "_shrinkwrap": null,
+  "_spec": "napi-build-utils@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "name": "Jim Schlight"
+  },
+  "binary": {
+    "napi_versions": [
+      2,
+      2,
+      3
+    ],
+    "note": "napi-build-tools is not an N-API module. This entry is for unit testing."
+  },
+  "bugs": {
+    "url": "https://github.com/inspiredware/napi-build-utils/issues"
+  },
+  "dependencies": {},
+  "description": "A set of utilities to assist developers of tools that build N-API native add-ons",
+  "devDependencies": {
+    "chai": "^4.1.2",
+    "jsdoc-to-markdown": "^4.0.1",
+    "mocha": "^5.2.0",
+    "standard": "^12.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 6,
+    "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmadcCRA9TVsSAnZWagAAgJwP/RXkZJLEz0oEmMjJAuEZ\n7dIutrjcMCBbxc4LLI3DrOb/3G7L4ciAh29XUEK22lFj0orypOEIhdR+MjRv\nikvti/0fnSn+1pdnutPGKc09vFn75/RPGC5yskSKyyJvNqS1K+1E7/WBncSW\n6smgo1Ulgy84hGzbLG3ENQM1iVkk0TxrC0nNyA4vW0cO8bFQUFZYPOPex1VN\nx8eeWK6YO/i0WGB6nxLyj5FBh4poUDy2/PaltEbmZ+8rgRwMKyBTgjbhbohS\n2Zq5OatlqNmMyp5nZU31vFQzNyS7pUDjxkv/9Ajh/nOs7TVo6XG6/rF30F97\n0gowjnNqrivUOxLkwrPyfZhwSpzB/cejRXD0CCu3Is8842BsrClIV1yPvVLI\nFlw6SuzFgJnXg03Ud3VuxgCYEtOkcoIaXp5ad2+gIOQkjHUQdKRnHxprYPJq\nnvMAli+Dzh/DDmYvuNiXN8f5p3gTloxV8w8O989LJKpdXUuYqzk1onrFwhHg\nClEgNw+CwpECYIWPar9WqIBSX+5ZznbnYKgygdabAvMRE4AtmpVXslyDpm9m\nAMz2i6Hp60ZvHXntuZAPDKgTmRmI1B1JNm9YSM2CXTu33QZnrxoEvQeP1C8e\nTn86oTscblKONY1bi+6h5aEBjrKI5ux98tC3Hny9a1RGSwp75d3ddea2GTS0\n1D1a\r\n=L4mj\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "1381a0f92c39d66bf19852e7873432fc2123e508",
+    "tarball": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.1.tgz",
+    "unpackedSize": 41857
+  },
+  "gitHead": "9258d6192437620313306cc143290dd39f652891",
+  "homepage": "https://github.com/inspiredware/napi-build-utils#readme",
+  "keywords": [
+    "n-api"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "inspiredware",
+      "email": "jim@inspiredware.com"
+    }
+  ],
+  "name": "napi-build-utils",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/inspiredware/napi-build-utils.git"
+  },
+  "scripts": {
+    "doc": "jsdoc2md index.js >index.md",
+    "lint": "standard",
+    "prepublishOnly": "npm run test && npm run doc",
+    "test": "mocha test/ && npm run lint"
+  },
+  "version": "1.0.1"
+}
diff --git a/input_devices/mag/node_modules/node-abi/.travis.yml b/input_devices/mag/node_modules/node-abi/.travis.yml
new file mode 100644
index 00000000..6f637f77
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/.travis.yml
@@ -0,0 +1,19 @@
+language: node_js
+cache:
+  directories:
+    - ~/.npm
+notifications:
+  email: false
+node_js:
+  - '10'
+  - '9'
+  - '8'
+  - '6'
+  - '4'
+  - '0.12'
+  - '0.10'
+after_success:
+  - npm run travis-deploy-once "npm run semantic-release"
+branches:
+  except:
+    - /^v\d+\.\d+\.\d+$/
diff --git a/input_devices/mag/node_modules/node-abi/CODE_OF_CONDUCT.md b/input_devices/mag/node_modules/node-abi/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..a28ec15d
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/CODE_OF_CONDUCT.md
@@ -0,0 +1,73 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+  advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+  address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at lukas.geiger94@gmail.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct/
+
+[homepage]: https://www.contributor-covenant.org
diff --git a/input_devices/mag/node_modules/node-abi/CONTRIBUTING.md b/input_devices/mag/node_modules/node-abi/CONTRIBUTING.md
new file mode 100644
index 00000000..3a83ae98
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/CONTRIBUTING.md
@@ -0,0 +1,53 @@
+# Contributing to `node-abi`
+
+:+1::tada: First off, thanks for taking the time to contribute to `node-abi`! :tada::+1:
+
+## Commit Message Guidelines
+
+This module uses [`semantic-release`](https://github.com/semantic-release/semantic-release) to automatically release new versions via Travis.
+Therefor we have very precise rules over how our git commit messages can be formatted.
+
+Each commit message consists of a **header**, a **body** and a **footer**.  The header has a special
+format that includes a **type**, a **scope** and a **subject** ([full explanation](https://github.com/stevemao/conventional-changelog-angular/blob/master/convention.md)):
+
+```
+<type>(<scope>): <subject>
+<BLANK LINE>
+<body>
+<BLANK LINE>
+<footer>
+```
+
+### Type
+
+Must be one of the following:
+
+- **feat**: A new feature. **Will trigger a new release**
+- **fix**: A bug fix or a addition to one of the target arrays. **Will trigger a new release**
+- **docs**: Documentation only changes
+- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
+- **refactor**: A code change that neither fixes a bug nor adds a feature
+- **perf**: A code change that improves performance
+- **test**: Adding missing or correcting existing tests
+- **chore**: Changes to the build process or auxiliary tools and libraries such as documentation generation
+
+
+### Patch Release
+
+```
+fix(electron): Support Electron 1.8.0
+```
+
+### ~~Minor~~ Feature Release
+
+```
+feat: add .getTarget(abi, runtime)
+```
+
+### ~~Major~~ Breaking Release
+
+```
+feat: Add amazing new feature
+
+BREAKING CHANGE: This removes support for Node 0.10 and 0.12.
+```
diff --git a/input_devices/mag/node_modules/node-abi/LICENSE b/input_devices/mag/node_modules/node-abi/LICENSE
new file mode 100644
index 00000000..5513de0d
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Lukas Geiger
+
+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/input_devices/mag/node_modules/node-abi/README.md b/input_devices/mag/node_modules/node-abi/README.md
new file mode 100644
index 00000000..abab6003
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/README.md
@@ -0,0 +1,50 @@
+# Node.js ABI
+
+[![Build Status](https://travis-ci.org/lgeiger/node-abi.svg?branch=v1.0.0)](https://travis-ci.org/lgeiger/node-abi) [![Greenkeeper badge](https://badges.greenkeeper.io/lgeiger/node-abi.svg)](https://greenkeeper.io/)
+
+
+Get the Node ABI for a given target and runtime, and vice versa.
+
+## Installation
+```
+npm install node-abi
+```
+
+## Usage
+```javascript
+const nodeAbi = require('node-abi')
+
+nodeAbi.getAbi('7.2.0', 'node')
+// '51'
+nodeAbi.getAbi('1.4.10', 'electron')
+// '50'
+nodeAbi.getTarget('51', 'node')
+// '7.2.0'
+nodeAbi.getTarget('50', 'electron')
+// '1.4.15'
+
+nodeAbi.allTargets
+// [
+//  { runtime: 'node', target: '0.10.48', abi: '11', lts: false },
+//  { runtime: 'node', target: '0.12.17', abi: '14', lts: false },
+//  { runtime: 'node', target: '4.6.1', abi: '46', lts: true },
+//  { runtime: 'node', target: '5.12.0', abi: '47', lts: false },
+//  { runtime: 'node', target: '6.9.4', abi: '48', lts: true },
+//  { runtime: 'node', target: '7.4.0', abi: '51', lts: false },
+//  { runtime: 'electron', target: '1.0.2', abi: '47', lts: false },
+//  { runtime: 'electron', target: '1.2.8', abi: '48', lts: false },
+//  { runtime: 'electron', target: '1.3.13', abi: '49', lts: false },
+//  { runtime: 'electron', target: '1.4.15', abi: '50', lts: false }
+// ]
+nodeAbi.deprecatedTargets
+nodeAbi.supportedTargets
+nodeAbi.additionalTargets
+nodeAbi.futureTargets
+// ...
+```
+
+## References
+
+- https://github.com/lgeiger/electron-abi
+- https://nodejs.org/en/download/releases/
+- https://github.com/nodejs/LTS
diff --git a/input_devices/mag/node_modules/node-abi/index.js b/input_devices/mag/node_modules/node-abi/index.js
new file mode 100644
index 00000000..1f657b32
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/index.js
@@ -0,0 +1,112 @@
+var semver = require('semver')
+
+function getNextTarget (runtime, targets) {
+  if (targets == null) targets = allTargets
+  var latest = targets.filter(function (t) { return t.runtime === runtime }).slice(-1)[0]
+  var increment = runtime === 'electron' ? 'minor' : 'major'
+  return semver.inc(latest.target, increment)
+}
+
+function getAbi (target, runtime) {
+  if (target === String(Number(target))) return target
+  if (target) target = target.replace(/^v/, '')
+  if (!runtime) runtime = 'node'
+
+  if (runtime === 'node') {
+    if (!target) return process.versions.modules
+    if (target === process.versions.node) return process.versions.modules
+  }
+
+  var abi
+
+  for (var i = 0; i < allTargets.length; i++) {
+    var t = allTargets[i]
+    if (t.runtime !== runtime) continue
+    if (semver.lte(t.target, target)) abi = t.abi
+    else break
+  }
+
+  if (abi && semver.lt(target, getNextTarget(runtime))) return abi
+  throw new Error('Could not detect abi for version ' + target + ' and runtime ' + runtime + '.  Updating "node-abi" might help solve this issue if it is a new release of ' + runtime)
+}
+
+function getTarget (abi, runtime) {
+  if (abi && abi !== String(Number(abi))) return abi
+  if (!runtime) runtime = 'node'
+
+  if (runtime === 'node' && !abi) return process.versions.node
+
+  var match = allTargets
+    .filter(function (t) {
+      return t.abi === abi && t.runtime === runtime
+    })
+    .map(function (t) {
+      return t.target
+    })
+  if (match.length) return match[0]
+
+  throw new Error('Could not detect target for abi ' + abi + ' and runtime ' + runtime)
+}
+
+var supportedTargets = [
+  {runtime: 'node', target: '5.0.0', abi: '47', lts: false},
+  {runtime: 'node', target: '6.0.0', abi: '48', lts: false},
+  {runtime: 'node', target: '7.0.0', abi: '51', lts: false},
+  {runtime: 'node', target: '8.0.0', abi: '57', lts: new Date() < new Date(2019, 4, 31)},
+  {runtime: 'node', target: '9.0.0', abi: '59', lts: false},
+  {runtime: 'node', target: '10.0.0', abi: '64', lts: new Date(2018, 10, 1) < new Date() < new Date(2020, 4, 31)},
+  {runtime: 'electron', target: '0.36.0', abi: '47', lts: false},
+  {runtime: 'electron', target: '1.1.0', abi: '48', lts: false},
+  {runtime: 'electron', target: '1.3.0', abi: '49', lts: false},
+  {runtime: 'electron', target: '1.4.0', abi: '50', lts: false},
+  {runtime: 'electron', target: '1.5.0', abi: '51', lts: false},
+  {runtime: 'electron', target: '1.6.0', abi: '53', lts: false},
+  {runtime: 'electron', target: '1.7.0', abi: '54', lts: false},
+  {runtime: 'electron', target: '1.8.0', abi: '57', lts: false},
+  {runtime: 'electron', target: '2.0.0', abi: '57', lts: false},
+  {runtime: 'electron', target: '3.0.0', abi: '64', lts: false}
+]
+
+var additionalTargets = [
+  {runtime: 'node-webkit', target: '0.13.0', abi: '47', lts: false},
+  {runtime: 'node-webkit', target: '0.15.0', abi: '48', lts: false},
+  {runtime: 'node-webkit', target: '0.18.3', abi: '51', lts: false},
+  {runtime: 'node-webkit', target: '0.23.0', abi: '57', lts: false},
+  {runtime: 'node-webkit', target: '0.26.5', abi: '59', lts: false}
+]
+
+var deprecatedTargets = [
+  {runtime: 'node', target: '0.2.0', abi: '1', lts: false},
+  {runtime: 'node', target: '0.9.1', abi: '0x000A', lts: false},
+  {runtime: 'node', target: '0.9.9', abi: '0x000B', lts: false},
+  {runtime: 'node', target: '0.10.4', abi: '11', lts: false},
+  {runtime: 'node', target: '0.11.0', abi: '0x000C', lts: false},
+  {runtime: 'node', target: '0.11.8', abi: '13', lts: false},
+  {runtime: 'node', target: '0.11.11', abi: '14', lts: false},
+  {runtime: 'node', target: '1.0.0', abi: '42', lts: false},
+  {runtime: 'node', target: '1.1.0', abi: '43', lts: false},
+  {runtime: 'node', target: '2.0.0', abi: '44', lts: false},
+  {runtime: 'node', target: '3.0.0', abi: '45', lts: false},
+  {runtime: 'node', target: '4.0.0', abi: '46', lts: false},
+  {runtime: 'electron', target: '0.30.0', abi: '44', lts: false},
+  {runtime: 'electron', target: '0.31.0', abi: '45', lts: false},
+  {runtime: 'electron', target: '0.33.0', abi: '46', lts: false}
+]
+
+var futureTargets = [
+  {runtime: 'electron', target: '4.0.0-beta.0', abi: '64', lts: false}
+]
+
+var allTargets = deprecatedTargets
+  .concat(supportedTargets)
+  .concat(additionalTargets)
+  .concat(futureTargets)
+
+exports.getAbi = getAbi
+exports.getTarget = getTarget
+exports.deprecatedTargets = deprecatedTargets
+exports.supportedTargets = supportedTargets
+exports.additionalTargets = additionalTargets
+exports.futureTargets = futureTargets
+exports.allTargets = allTargets
+exports._getNextTarget = getNextTarget
diff --git a/input_devices/mag/node_modules/node-abi/package.json b/input_devices/mag/node_modules/node-abi/package.json
new file mode 100644
index 00000000..ecf436fe
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/package.json
@@ -0,0 +1,107 @@
+{
+  "_args": [
+    [
+      "node-abi@^2.2.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "node-abi@>=2.2.0 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "node-abi@2.4.5",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/node-abi",
+  "_nodeVersion": "10.11.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/node-abi_2.4.5_1538408459743_0.758087005640742"
+  },
+  "_npmUser": {
+    "email": "lukas.geiger94@gmail.com",
+    "name": "lgeiger"
+  },
+  "_npmVersion": "6.4.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "node-abi",
+    "raw": "node-abi@^2.2.0",
+    "rawSpec": "^2.2.0",
+    "scope": null,
+    "spec": ">=2.2.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.5.tgz",
+  "_shasum": "1fd1fb66641bf3c4dcf55a5490ba10c467ead80c",
+  "_shrinkwrap": null,
+  "_spec": "node-abi@^2.2.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "name": "Lukas Geiger"
+  },
+  "bugs": {
+    "url": "https://github.com/lgeiger/node-abi/issues"
+  },
+  "dependencies": {
+    "semver": "^5.4.1"
+  },
+  "description": "Get the Node ABI for a given target and runtime, and vice versa.",
+  "devDependencies": {
+    "semantic-release": "^15.8.0",
+    "tape": "^4.6.3",
+    "travis-deploy-once": "^5.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 8,
+    "integrity": "sha512-aa/UC6Nr3+tqhHGRsAuw/edz7/q9nnetBrKWxj6rpTtm+0X9T1qU7lIEHMS3yN9JwAbRiKUbRRFy1PLz/y3aaA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbskAMCRA9TVsSAnZWagAAyTkP/2nvY7c9kGc2pXO3Uxcj\niABpuz74BQJJO2tLFhycjqp26XKuRaPHjgenQ7Dk5pwmNf2VVehZ1RlfuUgq\nhsba26u45k45lqhHksnl2Pc8+it0B5YUVBkWvfpw7MCQESU+slkA5DKnylH6\n/rCn9tSVPKl9ReDvB820rPzm0dToLlLcjgneaAvo8bTdhWs5FMwvuMBkGcqk\nVvU7kCzxMDGQ8K97y3DJW1pylKRU+4Hr8FSEQ4NFYEp9hIIEjYrS2MSWej4C\n7CViwKPvZjFS+JFuzLYUcUC/tJRnQnmj+O1iQ8Rt6hpjlBZQNCC3KmnWys+y\nPjkaGUIxGXHDgwmkcCTHErupvmhqFktThxQyhXw8knV226RgZWKVCFy4+ury\nTDO31h/DBaKK/zppurr+hLv+jlXXPN4Yjj7mRLJ+527ScxOzwng8Btv6EC3x\neTBw+p7m/R2KX8eRn5S9Vym0IDnRLC94G0SmLBNhKrgzSlnkRDmSk8YCy8Bn\nza3y1mNPh9LYs18dA9m/yucBzY/cHo+mqfEwMi7i7WbbeP0Bk6T+Wtk0a6w/\nErficuIY0X7OnDk5ewggb6rQljSpze471XXOr7ScbVHROj6A5tLcyofrewDs\nUecojde8/exs73cJME44RB6mIb7nwDEgRfe7P5/ATMBXP1654+JoUJ+xDjAo\nVKLj\r\n=lYnA\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "1fd1fb66641bf3c4dcf55a5490ba10c467ead80c",
+    "tarball": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.5.tgz",
+    "unpackedSize": 18810
+  },
+  "gitHead": "d11b1aad31f715135b871a21423fe465f3929537",
+  "homepage": "https://github.com/lgeiger/node-abi#readme",
+  "keywords": [
+    "abi",
+    "electron",
+    "node",
+    "node_module_version",
+    "v8"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "juliangruber",
+      "email": "julian@juliangruber.com"
+    },
+    {
+      "name": "lgeiger",
+      "email": "lukas.geiger94@gmail.com"
+    },
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    },
+    {
+      "name": "marshallofsound",
+      "email": "samuel.r.attard@gmail.com"
+    }
+  ],
+  "name": "node-abi",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/lgeiger/node-abi.git"
+  },
+  "scripts": {
+    "semantic-release": "semantic-release",
+    "test": "tape test/index.js",
+    "travis-deploy-once": "travis-deploy-once"
+  },
+  "version": "2.4.5"
+}
diff --git a/input_devices/mag/node_modules/node-abi/test/index.js b/input_devices/mag/node_modules/node-abi/test/index.js
new file mode 100644
index 00000000..c230e1be
--- /dev/null
+++ b/input_devices/mag/node_modules/node-abi/test/index.js
@@ -0,0 +1,151 @@
+var test = require('tape')
+var semver = require('semver')
+var getAbi = require('../index').getAbi
+var getTarget = require('../index').getTarget
+var getNextTarget = require('../index')._getNextTarget
+var allTargets = require('../index').allTargets
+
+test('getNextTarget gets the next unsopported target', function (t) {
+  var mockTargets = [
+    {runtime: 'node', target: '7.0.0', abi: '51', lts: false},
+    {runtime: 'node', target: '8.0.0', abi: '57', lts: false},
+    {runtime: 'electron', target: '0.36.0', abi: '47', lts: false},
+    {runtime: 'electron', target: '1.1.0', abi: '48', lts: false}
+  ]
+  t.equal(getNextTarget('node', mockTargets), '9.0.0')
+  t.equal(getNextTarget('electron', mockTargets), '1.2.0')
+  t.end()
+})
+
+test('getTarget calculates correct Node target', function (t) {
+  t.equal(getTarget(undefined), process.versions.node)
+  t.equal(getTarget(null), process.versions.node)
+  t.equal(getTarget('11'), '0.10.4')
+  t.equal(getTarget('14'), '0.11.11')
+  t.equal(getTarget('46'), '4.0.0')
+  t.equal(getTarget('47'), '5.0.0')
+  t.equal(getTarget('48'), '6.0.0')
+  t.equal(getTarget('51'), '7.0.0')
+  t.end()
+})
+
+test('getTarget calculates correct Electron target', function (t) {
+  t.throws(getTarget.bind(null, '14', 'electron'))
+  t.equal(getTarget('47', 'electron'), '0.36.0')
+  t.equal(getTarget('48', 'electron'), '1.1.0')
+  t.equal(getTarget('49', 'electron'), '1.3.0')
+  t.equal(getTarget('50', 'electron'), '1.4.0')
+  t.end()
+})
+
+test('getTarget calculates correct Node-Webkit target', function (t) {
+  t.throws(getTarget.bind(null, '14', 'ode-webkit'))
+  t.equal(getTarget('47', 'node-webkit'), '0.13.0')
+  t.equal(getTarget('48', 'node-webkit'), '0.15.0')
+  t.equal(getTarget('51', 'node-webkit'), '0.18.3')
+  t.equal(getTarget('57', 'node-webkit'), '0.23.0')
+  t.equal(getTarget('59', 'node-webkit'), '0.26.5')
+  t.end()
+})
+
+test('getAbi calculates correct Node ABI', function (t) {
+  t.equal(getAbi(undefined), process.versions.modules)
+  t.equal(getAbi(null), process.versions.modules)
+  t.throws(function () { getAbi('a.b.c') })
+  t.throws(function () { getAbi(getNextTarget('node')) })
+  t.equal(getAbi('7.2.0'), '51')
+  t.equal(getAbi('7.0.0'), '51')
+  t.equal(getAbi('6.9.9'), '48')
+  t.equal(getAbi('6.0.0'), '48')
+  t.equal(getAbi('5.9.9'), '47')
+  t.equal(getAbi('5.0.0'), '47')
+  t.equal(getAbi('4.9.9'), '46')
+  t.equal(getAbi('4.0.0'), '46')
+  t.equal(getAbi('0.12.17'), '14')
+  t.equal(getAbi('0.12.0'), '14')
+  t.equal(getAbi('0.11.16'), '14')
+  t.equal(getAbi('0.11.11'), '14')
+  t.equal(getAbi('0.11.10'), '13')
+  t.equal(getAbi('0.11.8'), '13')
+  t.equal(getAbi('0.11.7'), '0x000C')
+  t.equal(getAbi('0.11.0'), '0x000C')
+  t.equal(getAbi('0.10.48'), '11')
+  t.equal(getAbi('0.10.30'), '11')
+  t.equal(getAbi('0.10.4'), '11')
+  t.equal(getAbi('0.10.3'), '0x000B')
+  t.equal(getAbi('0.10.1'), '0x000B')
+  t.equal(getAbi('0.10.0'), '0x000B')
+  t.equal(getAbi('0.9.12'), '0x000B')
+  t.equal(getAbi('0.9.9'), '0x000B')
+  t.equal(getAbi('0.9.8'), '0x000A')
+  t.equal(getAbi('0.9.1'), '0x000A')
+  t.equal(getAbi('0.9.0'), '1')
+  t.equal(getAbi('0.8.0'), '1')
+  t.equal(getAbi('0.2.0'), '1')
+  t.end()
+})
+
+test('getAbi calculates correct Electron ABI', function (t) {
+  t.throws(function () { getAbi(undefined, 'electron') })
+  t.throws(function () { getAbi(getNextTarget('electron'), 'electron') })
+  t.equal(getAbi('1.4.0', 'electron'), '50')
+  t.equal(getAbi('1.3.0', 'electron'), '49')
+  t.equal(getAbi('1.2.0', 'electron'), '48')
+  t.equal(getAbi('1.1.0', 'electron'), '48')
+  t.equal(getAbi('1.0.0', 'electron'), '47')
+  t.equal(getAbi('0.37.0', 'electron'), '47')
+  t.equal(getAbi('0.36.0', 'electron'), '47')
+  t.equal(getAbi('0.35.0', 'electron'), '46')
+  t.equal(getAbi('0.34.0', 'electron'), '46')
+  t.equal(getAbi('0.33.0', 'electron'), '46')
+  t.equal(getAbi('0.32.0', 'electron'), '45')
+  t.equal(getAbi('0.31.0', 'electron'), '45')
+  t.equal(getAbi('0.30.0', 'electron'), '44')
+  t.end()
+})
+
+test('getAbi calculates correct Node-Webkit ABI', function (t) {
+  t.throws(function () { getAbi(undefined, 'node-webkit') })
+  t.throws(function () { getAbi(getNextTarget('node-webkit'), 'node-webkit') })
+  t.equal(getAbi('0.13.0', 'node-webkit'), '47')
+  t.equal(getAbi('0.14.0', 'node-webkit'), '47')
+  t.equal(getAbi('0.15.0', 'node-webkit'), '48')
+  t.equal(getAbi('0.16.0', 'node-webkit'), '48')
+  t.equal(getAbi('0.17.0', 'node-webkit'), '48')
+  t.equal(getAbi('0.18.2', 'node-webkit'), '48')
+  t.equal(getAbi('0.18.3', 'node-webkit'), '51')
+  t.equal(getAbi('0.19.0', 'node-webkit'), '51')
+  t.equal(getAbi('0.20.0', 'node-webkit'), '51')
+  t.equal(getAbi('0.21.0', 'node-webkit'), '51')
+  t.equal(getAbi('0.22.0', 'node-webkit'), '51')
+  t.equal(getAbi('0.23.0', 'node-webkit'), '57')
+  t.equal(getAbi('0.24.0', 'node-webkit'), '57')
+  t.equal(getAbi('0.25.0', 'node-webkit'), '57')
+  t.equal(getAbi('0.26.4', 'node-webkit'), '57')
+  t.equal(getAbi('0.26.5', 'node-webkit'), '59')
+  t.end()
+})
+
+test('getAbi supports leading v', function (t) {
+  t.equal(getAbi('v7.2.0'), '51')
+  t.end()
+})
+
+test('getAbi returns abi if passed as target', function (t) {
+  t.equal(getAbi('57'), '57')
+  t.end()
+})
+
+test('allTargets are sorted', function (t) {
+  var electron = allTargets.filter(function (t) { return t.runtime === 'electron' })
+  var node = allTargets.filter(function (t) { return t.runtime === 'node' })
+  var nodeWebkit = allTargets.filter(function (t) { return t.runtime === 'node-webkit' })
+  function sort (t1, t2) {
+    return semver.compare(t1.target, t2.target)
+  }
+
+  t.deepEqual(electron, electron.slice().sort(sort))
+  t.deepEqual(node, node.slice().sort(sort))
+  t.deepEqual(nodeWebkit, nodeWebkit.slice().sort(sort))
+  t.end()
+})
diff --git a/input_devices/mag/node_modules/noop-logger/.npmignore b/input_devices/mag/node_modules/noop-logger/.npmignore
new file mode 100644
index 00000000..b512c09d
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/.npmignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/noop-logger/History.md b/input_devices/mag/node_modules/noop-logger/History.md
new file mode 100644
index 00000000..5eaa2d6c
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/History.md
@@ -0,0 +1,16 @@
+
+0.1.1 / 2016-02-16
+==================
+
+  * add logger.verbose
+
+0.1.0 / 2014-04-04
+==================
+
+ * add ci
+ * add critical, alert and emergency
+ * docs
+
+0.0.1 - February 27, 2013
+-------------------------
+:sparkles:
diff --git a/input_devices/mag/node_modules/noop-logger/Makefile b/input_devices/mag/node_modules/noop-logger/Makefile
new file mode 100644
index 00000000..e3672785
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/Makefile
@@ -0,0 +1,8 @@
+
+node_modules: package.json
+	@npm install
+
+test: node_modules
+	@./node_modules/.bin/mocha --reporter spec
+
+.PHONY: test
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/noop-logger/Readme.md b/input_devices/mag/node_modules/noop-logger/Readme.md
new file mode 100644
index 00000000..ae6b4c7f
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/Readme.md
@@ -0,0 +1,27 @@
+[![Build Status](https://circleci.com/gh/segmentio/noop-logger.png?circle-token=3281390270513cae0e50fd18b8d972eb48a56879)](https://circleci.com/gh/segmentio/noop-logger)
+
+# noop-logger
+
+  A logger that does exactly nothing, useful when you want to test modules that require a logger to be passed in.
+
+## Installation
+
+    $ npm install noop-logger
+
+## API
+
+  Exposes the following noops:
+
+  - `logger.debug`
+  - `logger.info`
+  - `logger.warn`
+  - `logger.error`
+  - `logger.critical`
+  - `logger.alert`
+  - `logger.emergency`
+  - `logger.notice`
+  - `logger.fatal`
+
+## License
+
+  MIT
diff --git a/input_devices/mag/node_modules/noop-logger/circle.yml b/input_devices/mag/node_modules/noop-logger/circle.yml
new file mode 100644
index 00000000..82c53e90
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/circle.yml
@@ -0,0 +1,9 @@
+machine:
+  node:
+    version: 0.10.26
+checkout:
+  post:
+    - echo "_auth = `printf $AUTH`" > npmrc
+dependencies:
+  override:
+    - npm install --userconfig npmrc --registry https://segmentio.registry.nodejitsu.com --no-strict-ssl --always-auth
diff --git a/input_devices/mag/node_modules/noop-logger/lib/index.js b/input_devices/mag/node_modules/noop-logger/lib/index.js
new file mode 100644
index 00000000..9028eca8
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/lib/index.js
@@ -0,0 +1,25 @@
+
+/**
+ * Methods.
+ */
+
+var methods = [
+  'debug',
+  'info',
+  'warn',
+  'error',
+  'critical',
+  'alert',
+  'emergency',
+  'notice',
+  'verbose',
+  'fatal'
+];
+
+/**
+ * Expose methods.
+ */
+
+methods.forEach(function(method){
+  exports[method] = function(){};
+});
diff --git a/input_devices/mag/node_modules/noop-logger/package.json b/input_devices/mag/node_modules/noop-logger/package.json
new file mode 100644
index 00000000..d979ffc6
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/package.json
@@ -0,0 +1,78 @@
+{
+  "_args": [
+    [
+      "noop-logger@^0.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "noop-logger@>=0.1.1 <0.2.0",
+  "_id": "noop-logger@0.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/noop-logger",
+  "_nodeVersion": "4.2.4",
+  "_npmOperationalInternal": {
+    "host": "packages-6-west.internal.npmjs.com",
+    "tmp": "tmp/noop-logger-0.1.1.tgz_1455640849747_0.5082028021570295"
+  },
+  "_npmUser": {
+    "email": "tools+npm@segment.com",
+    "name": "segment"
+  },
+  "_npmVersion": "2.14.12",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "noop-logger",
+    "raw": "noop-logger@^0.1.1",
+    "rawSpec": "^0.1.1",
+    "scope": null,
+    "spec": ">=0.1.1 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
+  "_shasum": "94a2b1633c4f1317553007d8966fd0e841b6a4c2",
+  "_shrinkwrap": null,
+  "_spec": "noop-logger@^0.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "bugs": {
+    "url": "https://github.com/segmentio/noop-logger/issues"
+  },
+  "dependencies": {},
+  "description": "A logger that does exactly nothing.",
+  "devDependencies": {
+    "mocha": "1.x"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "94a2b1633c4f1317553007d8966fd0e841b6a4c2",
+    "tarball": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz"
+  },
+  "gitHead": "992174718b157fdfd6f9fd065b53ff7aa4696cf5",
+  "homepage": "https://github.com/segmentio/noop-logger#readme",
+  "license": "MIT",
+  "main": "lib/index.js",
+  "maintainers": [
+    {
+      "name": "segmentio",
+      "email": "team@segment.io"
+    },
+    {
+      "name": "segment",
+      "email": "tj@segment.io"
+    }
+  ],
+  "name": "noop-logger",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/segmentio/noop-logger.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.1"
+}
diff --git a/input_devices/mag/node_modules/noop-logger/test/index.js b/input_devices/mag/node_modules/noop-logger/test/index.js
new file mode 100644
index 00000000..e9eac5bc
--- /dev/null
+++ b/input_devices/mag/node_modules/noop-logger/test/index.js
@@ -0,0 +1,18 @@
+
+var assert = require('assert');
+var logger = require('..');
+
+describe('noop-logger', function(){
+  it('should expose methods', function(){
+    assert.equal('function', typeof logger.debug);
+    assert.equal('function', typeof logger.info);
+    assert.equal('function', typeof logger.warn);
+    assert.equal('function', typeof logger.error);
+    assert.equal('function', typeof logger.critical);
+    assert.equal('function', typeof logger.alert);
+    assert.equal('function', typeof logger.emergency);
+    assert.equal('function', typeof logger.notice);
+    assert.equal('function', typeof logger.verbose);
+    assert.equal('function', typeof logger.fatal);
+  });
+});
diff --git a/input_devices/mag/node_modules/npmlog/CHANGELOG.md b/input_devices/mag/node_modules/npmlog/CHANGELOG.md
new file mode 100644
index 00000000..51e4abc0
--- /dev/null
+++ b/input_devices/mag/node_modules/npmlog/CHANGELOG.md
@@ -0,0 +1,49 @@
+### v4.0.2
+
+* Added installation instructions.
+
+### v4.0.1
+
+* Fix bugs where `log.progressEnabled` got out of sync with how `gauge` kept
+  track of these things resulting in a progressbar that couldn't be disabled.
+
+### v4.0.0
+
+* Allow creating log levels that are an empty string or 0.
+
+### v3.1.2
+
+* Update to `gauge@1.6.0` adding support for default values for template
+  items.
+
+### v3.1.1
+
+* Update to `gauge@1.5.3` to fix to `1.x` compatibility when it comes to
+  when a progress bar is enabled.  In `1.x` if you didn't have a TTY the
+  progress bar was never shown.  In `2.x` it merely defaults to disabled,
+  but you can enable it explicitly if you still want progress updates.
+
+### v3.1.0
+
+* Update to `gauge@2.5.2`:
+  * Updates the `signal-exit` dependency which fixes an incompatibility with
+    the node profiler.
+  * Uses externalizes its ansi code generation in `console-control-strings`
+* Make the default progress bar include the last line printed, colored as it
+  would be when printing to a tty.
+
+### v3.0.0
+
+* Switch to `gauge@2.0.0`, for better performance, better look.
+* Set stderr/stdout blocking if they're tty's, so that we can hide a
+  progress bar going to stderr and then safely print to stdout.  Without
+  this the two can end up overlapping producing confusing and sometimes
+  corrupted output.
+
+### v2.0.0
+
+* Make the `error` event non-fatal so that folks can use it as a prefix.
+
+### v1.0.0
+
+* Add progress bar with `gauge@1.1.0`
diff --git a/input_devices/mag/node_modules/npmlog/LICENSE b/input_devices/mag/node_modules/npmlog/LICENSE
new file mode 100644
index 00000000..19129e31
--- /dev/null
+++ b/input_devices/mag/node_modules/npmlog/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/npmlog/README.md b/input_devices/mag/node_modules/npmlog/README.md
new file mode 100644
index 00000000..268a4af4
--- /dev/null
+++ b/input_devices/mag/node_modules/npmlog/README.md
@@ -0,0 +1,216 @@
+# npmlog
+
+The logger util that npm uses.
+
+This logger is very basic.  It does the logging for npm.  It supports
+custom levels and colored output.
+
+By default, logs are written to stderr.  If you want to send log messages
+to outputs other than streams, then you can change the `log.stream`
+member, or you can just listen to the events that it emits, and do
+whatever you want with them.
+
+# Installation
+
+```console
+npm install npmlog --save
+```
+
+# Basic Usage
+
+```javascript
+var log = require('npmlog')
+
+// additional stuff ---------------------------+
+// message ----------+                         |
+// prefix ----+      |                         |
+// level -+   |      |                         |
+//        v   v      v                         v
+    log.info('fyi', 'I have a kitty cat: %j', myKittyCat)
+```
+
+## log.level
+
+* {String}
+
+The level to display logs at.  Any logs at or above this level will be
+displayed.  The special level `silent` will prevent anything from being
+displayed ever.
+
+## log.record
+
+* {Array}
+
+An array of all the log messages that have been entered.
+
+## log.maxRecordSize
+
+* {Number}
+
+The maximum number of records to keep.  If log.record gets bigger than
+10% over this value, then it is sliced down to 90% of this value.
+
+The reason for the 10% window is so that it doesn't have to resize a
+large array on every log entry.
+
+## log.prefixStyle
+
+* {Object}
+
+A style object that specifies how prefixes are styled.  (See below)
+
+## log.headingStyle
+
+* {Object}
+
+A style object that specifies how the heading is styled.  (See below)
+
+## log.heading
+
+* {String} Default: ""
+
+If set, a heading that is printed at the start of every line.
+
+## log.stream
+
+* {Stream} Default: `process.stderr`
+
+The stream where output is written.
+
+## log.enableColor()
+
+Force colors to be used on all messages, regardless of the output
+stream.
+
+## log.disableColor()
+
+Disable colors on all messages.
+
+## log.enableProgress()
+
+Enable the display of log activity spinner and progress bar
+
+## log.disableProgress()
+
+Disable the display of a progress bar
+
+## log.enableUnicode()
+
+Force the unicode theme to be used for the progress bar.
+
+## log.disableUnicode()
+
+Disable the use of unicode in the progress bar.
+
+## log.setGaugeTemplate(template)
+
+Set a template for outputting the progress bar. See the [gauge documentation] for details.
+
+[gauge documentation]: https://npmjs.com/package/gauge
+
+## log.setGaugeThemeset(themes)
+
+Select a themeset to pick themes from for the progress bar. See the [gauge documentation] for details.
+
+## log.pause()
+
+Stop emitting messages to the stream, but do not drop them.
+
+## log.resume()
+
+Emit all buffered messages that were written while paused.
+
+## log.log(level, prefix, message, ...)
+
+* `level` {String} The level to emit the message at
+* `prefix` {String} A string prefix.  Set to "" to skip.
+* `message...` Arguments to `util.format`
+
+Emit a log message at the specified level.
+
+## log\[level](prefix, message, ...)
+
+For example,
+
+* log.silly(prefix, message, ...)
+* log.verbose(prefix, message, ...)
+* log.info(prefix, message, ...)
+* log.http(prefix, message, ...)
+* log.warn(prefix, message, ...)
+* log.error(prefix, message, ...)
+
+Like `log.log(level, prefix, message, ...)`.  In this way, each level is
+given a shorthand, so you can do `log.info(prefix, message)`.
+
+## log.addLevel(level, n, style, disp)
+
+* `level` {String} Level indicator
+* `n` {Number} The numeric level
+* `style` {Object} Object with fg, bg, inverse, etc.
+* `disp` {String} Optional replacement for `level` in the output.
+
+Sets up a new level with a shorthand function and so forth.
+
+Note that if the number is `Infinity`, then setting the level to that
+will cause all log messages to be suppressed.  If the number is
+`-Infinity`, then the only way to show it is to enable all log messages.
+
+## log.newItem(name, todo, weight)
+
+* `name` {String} Optional; progress item name.
+* `todo` {Number} Optional; total amount of work to be done. Default 0.
+* `weight` {Number} Optional; the weight of this item relative to others. Default 1.
+
+This adds a new `are-we-there-yet` item tracker to the progress tracker. The
+object returned has the `log[level]` methods but is otherwise an
+`are-we-there-yet` `Tracker` object.
+
+## log.newStream(name, todo, weight)
+
+This adds a new `are-we-there-yet` stream tracker to the progress tracker. The
+object returned has the `log[level]` methods but is otherwise an
+`are-we-there-yet` `TrackerStream` object.
+
+## log.newGroup(name, weight)
+
+This adds a new `are-we-there-yet` tracker group to the progress tracker. The
+object returned has the `log[level]` methods but is otherwise an
+`are-we-there-yet` `TrackerGroup` object.
+
+# Events
+
+Events are all emitted with the message object.
+
+* `log` Emitted for all messages
+* `log.<level>` Emitted for all messages with the `<level>` level.
+* `<prefix>` Messages with prefixes also emit their prefix as an event.
+
+# Style Objects
+
+Style objects can have the following fields:
+
+* `fg` {String} Color for the foreground text
+* `bg` {String} Color for the background
+* `bold`, `inverse`, `underline` {Boolean} Set the associated property
+* `bell` {Boolean} Make a noise (This is pretty annoying, probably.)
+
+# Message Objects
+
+Every log event is emitted with a message object, and the `log.record`
+list contains all of them that have been created.  They have the
+following fields:
+
+* `id` {Number}
+* `level` {String}
+* `prefix` {String}
+* `message` {String} Result of `util.format()`
+* `messageRaw` {Array} Arguments to `util.format()`
+
+# Blocking TTYs
+
+We use [`set-blocking`](https://npmjs.com/package/set-blocking) to set
+stderr and stdout blocking if they are tty's and have the setBlocking call.
+This is a work around for an issue in early versions of Node.js 6.x, which
+made stderr and stdout non-blocking on OSX. (They are always blocking
+Windows and were never blocking on Linux.) `npmlog` needs them to be blocking
+so that it can allow output to stdout and stderr to be interlaced.
diff --git a/input_devices/mag/node_modules/npmlog/log.js b/input_devices/mag/node_modules/npmlog/log.js
new file mode 100644
index 00000000..341f3313
--- /dev/null
+++ b/input_devices/mag/node_modules/npmlog/log.js
@@ -0,0 +1,309 @@
+'use strict'
+var Progress = require('are-we-there-yet')
+var Gauge = require('gauge')
+var EE = require('events').EventEmitter
+var log = exports = module.exports = new EE()
+var util = require('util')
+
+var setBlocking = require('set-blocking')
+var consoleControl = require('console-control-strings')
+
+setBlocking(true)
+var stream = process.stderr
+Object.defineProperty(log, 'stream', {
+  set: function (newStream) {
+    stream = newStream
+    if (this.gauge) this.gauge.setWriteTo(stream, stream)
+  },
+  get: function () {
+    return stream
+  }
+})
+
+// by default, decide based on tty-ness.
+var colorEnabled
+log.useColor = function () {
+  return colorEnabled != null ? colorEnabled : stream.isTTY
+}
+
+log.enableColor = function () {
+  colorEnabled = true
+  this.gauge.setTheme({hasColor: colorEnabled, hasUnicode: unicodeEnabled})
+}
+log.disableColor = function () {
+  colorEnabled = false
+  this.gauge.setTheme({hasColor: colorEnabled, hasUnicode: unicodeEnabled})
+}
+
+// default level
+log.level = 'info'
+
+log.gauge = new Gauge(stream, {
+  enabled: false, // no progress bars unless asked
+  theme: {hasColor: log.useColor()},
+  template: [
+    {type: 'progressbar', length: 20},
+    {type: 'activityIndicator', kerning: 1, length: 1},
+    {type: 'section', default: ''},
+    ':',
+    {type: 'logline', kerning: 1, default: ''}
+  ]
+})
+
+log.tracker = new Progress.TrackerGroup()
+
+// we track this separately as we may need to temporarily disable the
+// display of the status bar for our own loggy purposes.
+log.progressEnabled = log.gauge.isEnabled()
+
+var unicodeEnabled
+
+log.enableUnicode = function () {
+  unicodeEnabled = true
+  this.gauge.setTheme({hasColor: this.useColor(), hasUnicode: unicodeEnabled})
+}
+
+log.disableUnicode = function () {
+  unicodeEnabled = false
+  this.gauge.setTheme({hasColor: this.useColor(), hasUnicode: unicodeEnabled})
+}
+
+log.setGaugeThemeset = function (themes) {
+  this.gauge.setThemeset(themes)
+}
+
+log.setGaugeTemplate = function (template) {
+  this.gauge.setTemplate(template)
+}
+
+log.enableProgress = function () {
+  if (this.progressEnabled) return
+  this.progressEnabled = true
+  this.tracker.on('change', this.showProgress)
+  if (this._pause) return
+  this.gauge.enable()
+}
+
+log.disableProgress = function () {
+  if (!this.progressEnabled) return
+  this.progressEnabled = false
+  this.tracker.removeListener('change', this.showProgress)
+  this.gauge.disable()
+}
+
+var trackerConstructors = ['newGroup', 'newItem', 'newStream']
+
+var mixinLog = function (tracker) {
+  // mixin the public methods from log into the tracker
+  // (except: conflicts and one's we handle specially)
+  Object.keys(log).forEach(function (P) {
+    if (P[0] === '_') return
+    if (trackerConstructors.filter(function (C) { return C === P }).length) return
+    if (tracker[P]) return
+    if (typeof log[P] !== 'function') return
+    var func = log[P]
+    tracker[P] = function () {
+      return func.apply(log, arguments)
+    }
+  })
+  // if the new tracker is a group, make sure any subtrackers get
+  // mixed in too
+  if (tracker instanceof Progress.TrackerGroup) {
+    trackerConstructors.forEach(function (C) {
+      var func = tracker[C]
+      tracker[C] = function () { return mixinLog(func.apply(tracker, arguments)) }
+    })
+  }
+  return tracker
+}
+
+// Add tracker constructors to the top level log object
+trackerConstructors.forEach(function (C) {
+  log[C] = function () { return mixinLog(this.tracker[C].apply(this.tracker, arguments)) }
+})
+
+log.clearProgress = function (cb) {
+  if (!this.progressEnabled) return cb && process.nextTick(cb)
+  this.gauge.hide(cb)
+}
+
+log.showProgress = function (name, completed) {
+  if (!this.progressEnabled) return
+  var values = {}
+  if (name) values.section = name
+  var last = log.record[log.record.length - 1]
+  if (last) {
+    values.subsection = last.prefix
+    var disp = log.disp[last.level] || last.level
+    var logline = this._format(disp, log.style[last.level])
+    if (last.prefix) logline += ' ' + this._format(last.prefix, this.prefixStyle)
+    logline += ' ' + last.message.split(/\r?\n/)[0]
+    values.logline = logline
+  }
+  values.completed = completed || this.tracker.completed()
+  this.gauge.show(values)
+}.bind(log) // bind for use in tracker's on-change listener
+
+// temporarily stop emitting, but don't drop
+log.pause = function () {
+  this._paused = true
+  if (this.progressEnabled) this.gauge.disable()
+}
+
+log.resume = function () {
+  if (!this._paused) return
+  this._paused = false
+
+  var b = this._buffer
+  this._buffer = []
+  b.forEach(function (m) {
+    this.emitLog(m)
+  }, this)
+  if (this.progressEnabled) this.gauge.enable()
+}
+
+log._buffer = []
+
+var id = 0
+log.record = []
+log.maxRecordSize = 10000
+log.log = function (lvl, prefix, message) {
+  var l = this.levels[lvl]
+  if (l === undefined) {
+    return this.emit('error', new Error(util.format(
+      'Undefined log level: %j', lvl)))
+  }
+
+  var a = new Array(arguments.length - 2)
+  var stack = null
+  for (var i = 2; i < arguments.length; i++) {
+    var arg = a[i - 2] = arguments[i]
+
+    // resolve stack traces to a plain string.
+    if (typeof arg === 'object' && arg &&
+        (arg instanceof Error) && arg.stack) {
+
+      Object.defineProperty(arg, 'stack', {
+        value: stack = arg.stack + '',
+        enumerable: true,
+        writable: true
+      })
+    }
+  }
+  if (stack) a.unshift(stack + '\n')
+  message = util.format.apply(util, a)
+
+  var m = { id: id++,
+            level: lvl,
+            prefix: String(prefix || ''),
+            message: message,
+            messageRaw: a }
+
+  this.emit('log', m)
+  this.emit('log.' + lvl, m)
+  if (m.prefix) this.emit(m.prefix, m)
+
+  this.record.push(m)
+  var mrs = this.maxRecordSize
+  var n = this.record.length - mrs
+  if (n > mrs / 10) {
+    var newSize = Math.floor(mrs * 0.9)
+    this.record = this.record.slice(-1 * newSize)
+  }
+
+  this.emitLog(m)
+}.bind(log)
+
+log.emitLog = function (m) {
+  if (this._paused) {
+    this._buffer.push(m)
+    return
+  }
+  if (this.progressEnabled) this.gauge.pulse(m.prefix)
+  var l = this.levels[m.level]
+  if (l === undefined) return
+  if (l < this.levels[this.level]) return
+  if (l > 0 && !isFinite(l)) return
+
+  // If 'disp' is null or undefined, use the lvl as a default
+  // Allows: '', 0 as valid disp
+  var disp = log.disp[m.level] != null ? log.disp[m.level] : m.level
+  this.clearProgress()
+  m.message.split(/\r?\n/).forEach(function (line) {
+    if (this.heading) {
+      this.write(this.heading, this.headingStyle)
+      this.write(' ')
+    }
+    this.write(disp, log.style[m.level])
+    var p = m.prefix || ''
+    if (p) this.write(' ')
+    this.write(p, this.prefixStyle)
+    this.write(' ' + line + '\n')
+  }, this)
+  this.showProgress()
+}
+
+log._format = function (msg, style) {
+  if (!stream) return
+
+  var output = ''
+  if (this.useColor()) {
+    style = style || {}
+    var settings = []
+    if (style.fg) settings.push(style.fg)
+    if (style.bg) settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1))
+    if (style.bold) settings.push('bold')
+    if (style.underline) settings.push('underline')
+    if (style.inverse) settings.push('inverse')
+    if (settings.length) output += consoleControl.color(settings)
+    if (style.beep) output += consoleControl.beep()
+  }
+  output += msg
+  if (this.useColor()) {
+    output += consoleControl.color('reset')
+  }
+  return output
+}
+
+log.write = function (msg, style) {
+  if (!stream) return
+
+  stream.write(this._format(msg, style))
+}
+
+log.addLevel = function (lvl, n, style, disp) {
+  // If 'disp' is null or undefined, use the lvl as a default
+  if (disp == null) disp = lvl
+  this.levels[lvl] = n
+  this.style[lvl] = style
+  if (!this[lvl]) {
+    this[lvl] = function () {
+      var a = new Array(arguments.length + 1)
+      a[0] = lvl
+      for (var i = 0; i < arguments.length; i++) {
+        a[i + 1] = arguments[i]
+      }
+      return this.log.apply(this, a)
+    }.bind(this)
+  }
+  this.disp[lvl] = disp
+}
+
+log.prefixStyle = { fg: 'magenta' }
+log.headingStyle = { fg: 'white', bg: 'black' }
+
+log.style = {}
+log.levels = {}
+log.disp = {}
+log.addLevel('silly', -Infinity, { inverse: true }, 'sill')
+log.addLevel('verbose', 1000, { fg: 'blue', bg: 'black' }, 'verb')
+log.addLevel('info', 2000, { fg: 'green' })
+log.addLevel('timing', 2500, { fg: 'green', bg: 'black' })
+log.addLevel('http', 3000, { fg: 'green', bg: 'black' })
+log.addLevel('notice', 3500, { fg: 'blue', bg: 'black' })
+log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN')
+log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!')
+log.addLevel('silent', Infinity)
+
+// allow 'error' prefix
+log.on('error', function () {})
diff --git a/input_devices/mag/node_modules/npmlog/package.json b/input_devices/mag/node_modules/npmlog/package.json
new file mode 100644
index 00000000..ffde2c7c
--- /dev/null
+++ b/input_devices/mag/node_modules/npmlog/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "npmlog@^4.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "npmlog@>=4.0.1 <5.0.0",
+  "_id": "npmlog@4.1.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/npmlog",
+  "_nodeVersion": "8.1.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/npmlog-4.1.2.tgz_1498519394438_0.33615764300338924"
+  },
+  "_npmUser": {
+    "email": "me@re-becca.org",
+    "name": "iarna"
+  },
+  "_npmVersion": "5.0.4",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "npmlog",
+    "raw": "npmlog@^4.0.1",
+    "rawSpec": "^4.0.1",
+    "scope": null,
+    "spec": ">=4.0.1 <5.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+  "_shasum": "08a7f2a8bf734604779a9efa4ad5cc717abb954b",
+  "_shrinkwrap": null,
+  "_spec": "npmlog@^4.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "i@izs.me",
+    "name": "Isaac Z. Schlueter",
+    "url": "http://blog.izs.me/"
+  },
+  "bugs": {
+    "url": "https://github.com/npm/npmlog/issues"
+  },
+  "dependencies": {
+    "are-we-there-yet": "~1.1.2",
+    "console-control-strings": "~1.1.0",
+    "gauge": "~2.7.3",
+    "set-blocking": "~2.0.0"
+  },
+  "description": "logger for npm",
+  "devDependencies": {
+    "standard": "~7.1.2",
+    "tap": "~5.7.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+    "shasum": "08a7f2a8bf734604779a9efa4ad5cc717abb954b",
+    "tarball": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz"
+  },
+  "files": [
+    "log.js"
+  ],
+  "gitHead": "f7f9516d35b873c4e45b1aaeb78cff4e43b72c31",
+  "homepage": "https://github.com/npm/npmlog#readme",
+  "license": "ISC",
+  "main": "log.js",
+  "maintainers": [
+    {
+      "name": "zkat",
+      "email": "kat@sykosomatic.org"
+    },
+    {
+      "name": "othiym23",
+      "email": "ogd@aoaioxxysz.net"
+    },
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    },
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    }
+  ],
+  "name": "npmlog",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/npm/npmlog.git"
+  },
+  "scripts": {
+    "test": "standard && tap test/*.js"
+  },
+  "version": "4.1.2"
+}
diff --git a/input_devices/mag/node_modules/number-is-nan/index.js b/input_devices/mag/node_modules/number-is-nan/index.js
new file mode 100644
index 00000000..79be4b9c
--- /dev/null
+++ b/input_devices/mag/node_modules/number-is-nan/index.js
@@ -0,0 +1,4 @@
+'use strict';
+module.exports = Number.isNaN || function (x) {
+	return x !== x;
+};
diff --git a/input_devices/mag/node_modules/number-is-nan/license b/input_devices/mag/node_modules/number-is-nan/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/number-is-nan/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/number-is-nan/package.json b/input_devices/mag/node_modules/number-is-nan/package.json
new file mode 100644
index 00000000..5c1302e2
--- /dev/null
+++ b/input_devices/mag/node_modules/number-is-nan/package.json
@@ -0,0 +1,95 @@
+{
+  "_args": [
+    [
+      "number-is-nan@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-fullwidth-code-point"
+    ]
+  ],
+  "_from": "number-is-nan@>=1.0.0 <2.0.0",
+  "_id": "number-is-nan@1.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/number-is-nan",
+  "_nodeVersion": "4.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/number-is-nan-1.0.1.tgz_1475212313367_0.9480371843092144"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.15.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "number-is-nan",
+    "raw": "number-is-nan@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/is-fullwidth-code-point"
+  ],
+  "_resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+  "_shasum": "097b602b53422a522c1afb8790318336941a011d",
+  "_shrinkwrap": null,
+  "_spec": "number-is-nan@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/is-fullwidth-code-point",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/number-is-nan/issues"
+  },
+  "dependencies": {},
+  "description": "ES2015 Number.isNaN() ponyfill",
+  "devDependencies": {
+    "ava": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "097b602b53422a522c1afb8790318336941a011d",
+    "tarball": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ed9cdac3f428cc929b61bb230da42c87477af4b9",
+  "homepage": "https://github.com/sindresorhus/number-is-nan#readme",
+  "keywords": [
+    "ecmascript",
+    "es2015",
+    "is",
+    "nan",
+    "not",
+    "number",
+    "polyfill",
+    "ponyfill",
+    "shim"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "number-is-nan",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/number-is-nan.git"
+  },
+  "scripts": {
+    "test": "ava"
+  },
+  "version": "1.0.1"
+}
diff --git a/input_devices/mag/node_modules/number-is-nan/readme.md b/input_devices/mag/node_modules/number-is-nan/readme.md
new file mode 100644
index 00000000..24635087
--- /dev/null
+++ b/input_devices/mag/node_modules/number-is-nan/readme.md
@@ -0,0 +1,28 @@
+# number-is-nan [![Build Status](https://travis-ci.org/sindresorhus/number-is-nan.svg?branch=master)](https://travis-ci.org/sindresorhus/number-is-nan)
+
+> ES2015 [`Number.isNaN()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) [ponyfill](https://ponyfill.com)
+
+
+## Install
+
+```
+$ npm install --save number-is-nan
+```
+
+
+## Usage
+
+```js
+var numberIsNan = require('number-is-nan');
+
+numberIsNan(NaN);
+//=> true
+
+numberIsNan('unicorn');
+//=> false
+```
+
+
+## License
+
+MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/object-assign/index.js b/input_devices/mag/node_modules/object-assign/index.js
new file mode 100644
index 00000000..0930cf88
--- /dev/null
+++ b/input_devices/mag/node_modules/object-assign/index.js
@@ -0,0 +1,90 @@
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+'use strict';
+/* eslint-disable no-unused-vars */
+var getOwnPropertySymbols = Object.getOwnPropertySymbols;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var propIsEnumerable = Object.prototype.propertyIsEnumerable;
+
+function toObject(val) {
+	if (val === null || val === undefined) {
+		throw new TypeError('Object.assign cannot be called with null or undefined');
+	}
+
+	return Object(val);
+}
+
+function shouldUseNative() {
+	try {
+		if (!Object.assign) {
+			return false;
+		}
+
+		// Detect buggy property enumeration order in older V8 versions.
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=4118
+		var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
+		test1[5] = 'de';
+		if (Object.getOwnPropertyNames(test1)[0] === '5') {
+			return false;
+		}
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+		var test2 = {};
+		for (var i = 0; i < 10; i++) {
+			test2['_' + String.fromCharCode(i)] = i;
+		}
+		var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
+			return test2[n];
+		});
+		if (order2.join('') !== '0123456789') {
+			return false;
+		}
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+		var test3 = {};
+		'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
+			test3[letter] = letter;
+		});
+		if (Object.keys(Object.assign({}, test3)).join('') !==
+				'abcdefghijklmnopqrst') {
+			return false;
+		}
+
+		return true;
+	} catch (err) {
+		// We don't expect any of the above to throw, but better to be safe.
+		return false;
+	}
+}
+
+module.exports = shouldUseNative() ? Object.assign : function (target, source) {
+	var from;
+	var to = toObject(target);
+	var symbols;
+
+	for (var s = 1; s < arguments.length; s++) {
+		from = Object(arguments[s]);
+
+		for (var key in from) {
+			if (hasOwnProperty.call(from, key)) {
+				to[key] = from[key];
+			}
+		}
+
+		if (getOwnPropertySymbols) {
+			symbols = getOwnPropertySymbols(from);
+			for (var i = 0; i < symbols.length; i++) {
+				if (propIsEnumerable.call(from, symbols[i])) {
+					to[symbols[i]] = from[symbols[i]];
+				}
+			}
+		}
+	}
+
+	return to;
+};
diff --git a/input_devices/mag/node_modules/object-assign/license b/input_devices/mag/node_modules/object-assign/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/object-assign/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/object-assign/package.json b/input_devices/mag/node_modules/object-assign/package.json
new file mode 100644
index 00000000..afba4aca
--- /dev/null
+++ b/input_devices/mag/node_modules/object-assign/package.json
@@ -0,0 +1,110 @@
+{
+  "_args": [
+    [
+      "object-assign@^4.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge"
+    ]
+  ],
+  "_from": "object-assign@>=4.1.0 <5.0.0",
+  "_id": "object-assign@4.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-assign",
+  "_nodeVersion": "4.6.2",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/object-assign-4.1.1.tgz_1484580915042_0.07107710791751742"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.15.11",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "object-assign",
+    "raw": "object-assign@^4.1.0",
+    "rawSpec": "^4.1.0",
+    "scope": null,
+    "spec": ">=4.1.0 <5.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge"
+  ],
+  "_resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+  "_shasum": "2109adc7965887cfc05cbbd442cac8bfbb360863",
+  "_shrinkwrap": null,
+  "_spec": "object-assign@^4.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/object-assign/issues"
+  },
+  "dependencies": {},
+  "description": "ES2015 `Object.assign()` ponyfill",
+  "devDependencies": {
+    "ava": "^0.16.0",
+    "lodash": "^4.16.4",
+    "matcha": "^0.7.0",
+    "xo": "^0.16.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "2109adc7965887cfc05cbbd442cac8bfbb360863",
+    "tarball": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "a89774b252c91612203876984bbd6addbe3b5a0e",
+  "homepage": "https://github.com/sindresorhus/object-assign#readme",
+  "keywords": [
+    "assign",
+    "browser",
+    "ecmascript",
+    "es2015",
+    "extend",
+    "harmony",
+    "object",
+    "polyfill",
+    "ponyfill",
+    "prollyfill",
+    "properties",
+    "shim"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "gaearon",
+      "email": "dan.abramov@gmail.com"
+    },
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    },
+    {
+      "name": "spicyj",
+      "email": "ben@benalpert.com"
+    }
+  ],
+  "name": "object-assign",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/object-assign.git"
+  },
+  "scripts": {
+    "bench": "matcha bench.js",
+    "test": "xo && ava"
+  },
+  "version": "4.1.1"
+}
diff --git a/input_devices/mag/node_modules/object-assign/readme.md b/input_devices/mag/node_modules/object-assign/readme.md
new file mode 100644
index 00000000..1be09d35
--- /dev/null
+++ b/input_devices/mag/node_modules/object-assign/readme.md
@@ -0,0 +1,61 @@
+# object-assign [![Build Status](https://travis-ci.org/sindresorhus/object-assign.svg?branch=master)](https://travis-ci.org/sindresorhus/object-assign)
+
+> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com)
+
+
+## Use the built-in
+
+Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari),
+support `Object.assign()` :tada:. If you target only those environments, then by all
+means, use `Object.assign()` instead of this package.
+
+
+## Install
+
+```
+$ npm install --save object-assign
+```
+
+
+## Usage
+
+```js
+const objectAssign = require('object-assign');
+
+objectAssign({foo: 0}, {bar: 1});
+//=> {foo: 0, bar: 1}
+
+// multiple sources
+objectAssign({foo: 0}, {bar: 1}, {baz: 2});
+//=> {foo: 0, bar: 1, baz: 2}
+
+// overwrites equal keys
+objectAssign({foo: 0}, {foo: 1}, {foo: 2});
+//=> {foo: 2}
+
+// ignores null and undefined sources
+objectAssign({foo: 0}, null, {bar: 1}, undefined);
+//=> {foo: 0, bar: 1}
+```
+
+
+## API
+
+### objectAssign(target, [source, ...])
+
+Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones.
+
+
+## Resources
+
+- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign)
+
+
+## Related
+
+- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()`
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/object-copy/LICENSE b/input_devices/mag/node_modules/object-copy/LICENSE
new file mode 100644
index 00000000..e28e6032
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/object-copy/index.js b/input_devices/mag/node_modules/object-copy/index.js
new file mode 100644
index 00000000..f9faa223
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/index.js
@@ -0,0 +1,174 @@
+'use strict';
+
+var typeOf = require('kind-of');
+var copyDescriptor = require('copy-descriptor');
+var define = require('define-property');
+
+/**
+ * Copy static properties, prototype properties, and descriptors from one object to another.
+ *
+ * ```js
+ * function App() {}
+ * var proto = App.prototype;
+ * App.prototype.set = function() {};
+ * App.prototype.get = function() {};
+ *
+ * var obj = {};
+ * copy(obj, proto);
+ * ```
+ * @param {Object} `receiver`
+ * @param {Object} `provider`
+ * @param {String|Array} `omit` One or more properties to omit
+ * @return {Object}
+ * @api public
+ */
+
+function copy(receiver, provider, omit) {
+  if (!isObject(receiver)) {
+    throw new TypeError('expected receiving object to be an object.');
+  }
+  if (!isObject(provider)) {
+    throw new TypeError('expected providing object to be an object.');
+  }
+
+  var props = nativeKeys(provider);
+  var keys = Object.keys(provider);
+  var len = props.length;
+  omit = arrayify(omit);
+
+  while (len--) {
+    var key = props[len];
+
+    if (has(keys, key)) {
+      define(receiver, key, provider[key]);
+    } else if (!(key in receiver) && !has(omit, key)) {
+      copyDescriptor(receiver, provider, key);
+    }
+  }
+};
+
+/**
+ * Return true if the given value is an object or function
+ */
+
+function isObject(val) {
+  return typeOf(val) === 'object' || typeof val === 'function';
+}
+
+/**
+ * Returns true if an array has any of the given elements, or an
+ * object has any of the give keys.
+ *
+ * ```js
+ * has(['a', 'b', 'c'], 'c');
+ * //=> true
+ *
+ * has(['a', 'b', 'c'], ['c', 'z']);
+ * //=> true
+ *
+ * has({a: 'b', c: 'd'}, ['c', 'z']);
+ * //=> true
+ * ```
+ * @param {Object} `obj`
+ * @param {String|Array} `val`
+ * @return {Boolean}
+ */
+
+function has(obj, val) {
+  val = arrayify(val);
+  var len = val.length;
+
+  if (isObject(obj)) {
+    for (var key in obj) {
+      if (val.indexOf(key) > -1) {
+        return true;
+      }
+    }
+
+    var keys = nativeKeys(obj);
+    return has(keys, val);
+  }
+
+  if (Array.isArray(obj)) {
+    var arr = obj;
+    while (len--) {
+      if (arr.indexOf(val[len]) > -1) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  throw new TypeError('expected an array or object.');
+}
+
+/**
+ * Cast the given value to an array.
+ *
+ * ```js
+ * arrayify('foo');
+ * //=> ['foo']
+ *
+ * arrayify(['foo']);
+ * //=> ['foo']
+ * ```
+ *
+ * @param {String|Array} `val`
+ * @return {Array}
+ */
+
+function arrayify(val) {
+  return val ? (Array.isArray(val) ? val : [val]) : [];
+}
+
+/**
+ * Returns true if a value has a `contructor`
+ *
+ * ```js
+ * hasConstructor({});
+ * //=> true
+ *
+ * hasConstructor(Object.create(null));
+ * //=> false
+ * ```
+ * @param  {Object} `value`
+ * @return {Boolean}
+ */
+
+function hasConstructor(val) {
+  return isObject(val) && typeof val.constructor !== 'undefined';
+}
+
+/**
+ * Get the native `ownPropertyNames` from the constructor of the
+ * given `object`. An empty array is returned if the object does
+ * not have a constructor.
+ *
+ * ```js
+ * nativeKeys({a: 'b', b: 'c', c: 'd'})
+ * //=> ['a', 'b', 'c']
+ *
+ * nativeKeys(function(){})
+ * //=> ['length', 'caller']
+ * ```
+ *
+ * @param  {Object} `obj` Object that has a `constructor`.
+ * @return {Array} Array of keys.
+ */
+
+function nativeKeys(val) {
+  if (!hasConstructor(val)) return [];
+  return Object.getOwnPropertyNames(val);
+}
+
+/**
+ * Expose `copy`
+ */
+
+module.exports = copy;
+
+/**
+ * Expose `copy.has` for tests
+ */
+
+module.exports.has = has;
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/define-property/LICENSE b/input_devices/mag/node_modules/object-copy/node_modules/define-property/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/define-property/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/object-copy/node_modules/define-property/README.md b/input_devices/mag/node_modules/object-copy/node_modules/define-property/README.md
new file mode 100644
index 00000000..8cac698a
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/define-property/README.md
@@ -0,0 +1,77 @@
+# define-property [![NPM version](https://badge.fury.io/js/define-property.svg)](http://badge.fury.io/js/define-property)
+
+> Define a non-enumerable property on an object.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i define-property --save
+```
+
+## Usage
+
+**Params**
+
+* `obj`: The object on which to define the property.
+* `prop`: The name of the property to be defined or modified.
+* `descriptor`: The descriptor for the property being defined or modified.
+
+```js
+var define = require('define-property');
+var obj = {};
+define(obj, 'foo', function(val) {
+  return val.toUpperCase();
+});
+
+console.log(obj);
+//=> {}
+
+console.log(obj.foo('bar'));
+//=> 'BAR'
+```
+
+**get/set**
+
+```js
+define(obj, 'foo', {
+  get: function() {},
+  set: function() {}
+});
+```
+
+## Related projects
+
+* [delegate-object](https://www.npmjs.com/package/delegate-object): Copy properties from an object to another object, where properties with function values will be… [more](https://www.npmjs.com/package/delegate-object) | [homepage](https://github.com/doowb/delegate-object)
+* [forward-object](https://www.npmjs.com/package/forward-object): Copy properties from an object to another object, where properties with function values will be… [more](https://www.npmjs.com/package/forward-object) | [homepage](https://github.com/doowb/forward-object)
+* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep)
+* [mixin-object](https://www.npmjs.com/package/mixin-object): Mixin the own and inherited properties of other objects onto the first object. Pass an… [more](https://www.npmjs.com/package/mixin-object) | [homepage](https://github.com/jonschlinkert/mixin-object)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/define-property/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on August 31, 2015._
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/define-property/index.js b/input_devices/mag/node_modules/object-copy/node_modules/define-property/index.js
new file mode 100644
index 00000000..3e0e5e13
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/define-property/index.js
@@ -0,0 +1,31 @@
+/*!
+ * define-property <https://github.com/jonschlinkert/define-property>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var isDescriptor = require('is-descriptor');
+
+module.exports = function defineProperty(obj, prop, val) {
+  if (typeof obj !== 'object' && typeof obj !== 'function') {
+    throw new TypeError('expected an object or function.');
+  }
+
+  if (typeof prop !== 'string') {
+    throw new TypeError('expected `prop` to be a string.');
+  }
+
+  if (isDescriptor(val) && ('set' in val || 'get' in val)) {
+    return Object.defineProperty(obj, prop, val);
+  }
+
+  return Object.defineProperty(obj, prop, {
+    configurable: true,
+    enumerable: false,
+    writable: true,
+    value: val
+  });
+};
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/define-property/package.json b/input_devices/mag/node_modules/object-copy/node_modules/define-property/package.json
new file mode 100644
index 00000000..f5032750
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/define-property/package.json
@@ -0,0 +1,105 @@
+{
+  "_args": [
+    [
+      "define-property@^0.2.5",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy"
+    ]
+  ],
+  "_from": "define-property@>=0.2.5 <0.3.0",
+  "_id": "define-property@0.2.5",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-copy/define-property",
+  "_nodeVersion": "0.12.4",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "define-property",
+    "raw": "define-property@^0.2.5",
+    "rawSpec": "^0.2.5",
+    "scope": null,
+    "spec": ">=0.2.5 <0.3.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/object-copy"
+  ],
+  "_resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+  "_shasum": "c35b1ef918ec3c990f9a5bc57be04aacec5c8116",
+  "_shrinkwrap": null,
+  "_spec": "define-property@^0.2.5",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/define-property/issues"
+  },
+  "dependencies": {
+    "is-descriptor": "^0.1.0"
+  },
+  "description": "Define a non-enumerable property on an object.",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "^7.0.4"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "c35b1ef918ec3c990f9a5bc57be04aacec5c8116",
+    "tarball": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "5bf4e5e9d8d1fdf8fba07fff4bdf13a5d6df8ae4",
+  "homepage": "https://github.com/jonschlinkert/define-property",
+  "keywords": [
+    "define",
+    "define-property",
+    "enumerable",
+    "key",
+    "non",
+    "non-enumerable",
+    "object",
+    "prop",
+    "property",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "define-property",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/define-property.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "related": {
+      "list": [
+        "delegate-object",
+        "forward-object",
+        "mixin-deep",
+        "mixin-object"
+      ]
+    }
+  },
+  "version": "0.2.5"
+}
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/LICENSE b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/README.md b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/README.md
new file mode 100644
index 00000000..3743fe6b
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/README.md
@@ -0,0 +1,123 @@
+# is-accessor-descriptor [![NPM version](https://img.shields.io/npm/v/is-accessor-descriptor.svg)](https://www.npmjs.com/package/is-accessor-descriptor) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-accessor-descriptor.svg)](https://travis-ci.org/jonschlinkert/is-accessor-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.
+
+- [Install](#install)
+- [Usage](#usage)
+- [Examples](#examples)
+- [API](#api)
+- [Related projects](#related-projects)
+- [Running tests](#running-tests)
+- [Contributing](#contributing)
+- [Author](#author)
+- [License](#license)
+
+_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm i is-accessor-descriptor --save
+```
+
+## Usage
+
+```js
+var isAccessor = require('is-accessor-descriptor');
+
+isAccessor({get: function() {}});
+//=> true
+```
+
+You may also pass an object and property name to check if the property is an accessor:
+
+```js
+isAccessor(foo, 'bar');
+```
+
+## Examples
+
+`false` when not an object
+
+```js
+isAccessor('a')
+isAccessor(null)
+isAccessor([])
+//=> false
+```
+
+`true` when the object has valid properties
+
+and the properties all have the correct JavaScript types:
+
+```js
+isAccessor({get: noop, set: noop})
+isAccessor({get: noop})
+isAccessor({set: noop})
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isAccessor({get: noop, set: noop, bar: 'baz'})
+isAccessor({get: noop, writable: true})
+isAccessor({get: noop, value: true})
+//=> false
+```
+
+`false` when an accessor is not a function
+
+```js
+isAccessor({get: noop, set: 'baz'})
+isAccessor({get: 'foo', set: noop})
+isAccessor({get: 'foo', bar: 'baz'})
+isAccessor({get: 'foo', set: 'baz'})
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isAccessor({get: noop, set: noop, enumerable: 'foo'})
+isAccessor({set: noop, configurable: 'foo'})
+isAccessor({get: noop, configurable: 'foo'})
+//=> false
+```
+
+## Related projects
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor)
+* [is-data-descriptor](https://www.npmjs.com/package/is-data-descriptor): Returns true if a value has the characteristics of a valid JavaScript data descriptor. | [homepage](https://github.com/jonschlinkert/is-data-descriptor)
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://www.npmjs.com/package/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor)
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/is-accessor-descriptor/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 [Jon Schlinkert](https://github.com/jonschlinkert)
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb](https://github.com/verbose/verb) on December 28, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/index.js b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/index.js
new file mode 100644
index 00000000..2ca4af8b
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/index.js
@@ -0,0 +1,69 @@
+/*!
+ * is-accessor-descriptor <https://github.com/jonschlinkert/is-accessor-descriptor>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+// accessor descriptor properties
+var accessor = {
+  get: 'function',
+  set: 'function',
+  configurable: 'boolean',
+  enumerable: 'boolean'
+};
+
+function isAccessorDescriptor(obj, prop) {
+  if (typeof prop === 'string') {
+    var val = Object.getOwnPropertyDescriptor(obj, prop);
+    return typeof val !== 'undefined';
+  }
+
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+
+  if (has(obj, 'value') || has(obj, 'writable')) {
+    return false;
+  }
+
+  if (!has(obj, 'get') || typeof obj.get !== 'function') {
+    return false;
+  }
+
+  // tldr: it's valid to have "set" be undefined
+  // "set" might be undefined if `Object.getOwnPropertyDescriptor`
+  // was used to get the value, and only `get` was defined by the user
+  if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') {
+    return false;
+  }
+
+  for (var key in obj) {
+    if (!accessor.hasOwnProperty(key)) {
+      continue;
+    }
+
+    if (typeOf(obj[key]) === accessor[key]) {
+      continue;
+    }
+
+    if (typeof obj[key] !== 'undefined') {
+      return false;
+    }
+  }
+  return true;
+}
+
+function has(obj, key) {
+  return {}.hasOwnProperty.call(obj, key);
+}
+
+/**
+ * Expose `isAccessorDescriptor`
+ */
+
+module.exports = isAccessorDescriptor;
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/package.json b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/package.json
new file mode 100644
index 00000000..c6737e36
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-accessor-descriptor/package.json
@@ -0,0 +1,115 @@
+{
+  "_args": [
+    [
+      "is-accessor-descriptor@^0.1.6",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "is-accessor-descriptor@>=0.1.6 <0.2.0",
+  "_id": "is-accessor-descriptor@0.1.6",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-copy/is-accessor-descriptor",
+  "_nodeVersion": "5.0.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.3.6",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-accessor-descriptor",
+    "raw": "is-accessor-descriptor@^0.1.6",
+    "rawSpec": "^0.1.6",
+    "scope": null,
+    "spec": ">=0.1.6 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/object-copy/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+  "_shasum": "a9e12cb3ae8d876727eeef3843f8a0897b5c98d6",
+  "_shrinkwrap": null,
+  "_spec": "is-accessor-descriptor@^0.1.6",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-accessor-descriptor/issues"
+  },
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a9e12cb3ae8d876727eeef3843f8a0897b5c98d6",
+    "tarball": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e64ae49c456c9f31dab47934b0183e2a9938b5bd",
+  "homepage": "https://github.com/jonschlinkert/is-accessor-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-accessor-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-accessor-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    }
+  },
+  "version": "0.1.6"
+}
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/LICENSE b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/README.md b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/README.md
new file mode 100644
index 00000000..41e1643f
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/README.md
@@ -0,0 +1,128 @@
+# is-data-descriptor [![NPM version](https://img.shields.io/npm/v/is-data-descriptor.svg)](https://www.npmjs.com/package/is-data-descriptor) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-data-descriptor.svg)](https://travis-ci.org/jonschlinkert/is-data-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript data descriptor.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm i is-data-descriptor --save
+```
+
+## Usage
+
+```js
+var isDataDesc = require('is-data-descriptor');
+```
+
+## Examples
+
+`true` when the descriptor has valid properties with valid values.
+
+```js
+// `value` can be anything
+isDataDesc({value: 'foo'})
+isDataDesc({value: function() {}})
+isDataDesc({value: true})
+//=> true
+```
+
+`false` when not an object
+
+```js
+isDataDesc('a')
+//=> false
+isDataDesc(null)
+//=> false
+isDataDesc([])
+//=> false
+```
+
+`false` when the object has invalid properties
+
+```js
+isDataDesc({value: 'foo', bar: 'baz'})
+//=> false
+isDataDesc({value: 'foo', bar: 'baz'})
+//=> false
+isDataDesc({value: 'foo', get: function(){}})
+//=> false
+isDataDesc({get: function(){}, value: 'foo'})
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDataDesc({value: 'foo', enumerable: 'foo'})
+//=> false
+isDataDesc({value: 'foo', configurable: 'foo'})
+//=> false
+isDataDesc({value: 'foo', writable: 'foo'})
+//=> false
+```
+
+## Valid properties
+
+The only valid data descriptor properties are the following:
+
+* `configurable` (required)
+* `enumerable` (required)
+* `value` (optional)
+* `writable` (optional)
+
+To be a valid data descriptor, either `value` or `writable` must be defined.
+
+**Invalid properties**
+
+A descriptor may have additional _invalid_ properties (an error will **not** be thrown).
+
+```js
+var foo = {};
+
+Object.defineProperty(foo, 'bar', {
+  enumerable: true,
+  whatever: 'blah', // invalid, but doesn't cause an error
+  get: function() {
+    return 'baz';
+  }
+});
+
+console.log(foo.bar);
+//=> 'baz'
+```
+
+## Related projects
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor)
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://www.npmjs.com/package/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor)
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/is-data-descriptor/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 [Jon Schlinkert](https://github.com/jonschlinkert)
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb](https://github.com/verbose/verb) on December 28, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/index.js b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/index.js
new file mode 100644
index 00000000..d4d09c92
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/index.js
@@ -0,0 +1,55 @@
+/*!
+ * is-data-descriptor <https://github.com/jonschlinkert/is-data-descriptor>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+// data descriptor properties
+var data = {
+  configurable: 'boolean',
+  enumerable: 'boolean',
+  writable: 'boolean'
+};
+
+function isDataDescriptor(obj, prop) {
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+
+  if (typeof prop === 'string') {
+    var val = Object.getOwnPropertyDescriptor(obj, prop);
+    return typeof val !== 'undefined';
+  }
+
+  if (!('value' in obj) && !('writable' in obj)) {
+    return false;
+  }
+
+  for (var key in obj) {
+    if (key === 'value') continue;
+
+    if (!data.hasOwnProperty(key)) {
+      continue;
+    }
+
+    if (typeOf(obj[key]) === data[key]) {
+      continue;
+    }
+
+    if (typeof obj[key] !== 'undefined') {
+      return false;
+    }
+  }
+  return true;
+}
+
+/**
+ * Expose `isDataDescriptor`
+ */
+
+module.exports = isDataDescriptor;
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/package.json b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/package.json
new file mode 100644
index 00000000..3e36b6ae
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-data-descriptor/package.json
@@ -0,0 +1,114 @@
+{
+  "_args": [
+    [
+      "is-data-descriptor@^0.1.4",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "is-data-descriptor@>=0.1.4 <0.2.0",
+  "_id": "is-data-descriptor@0.1.4",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-copy/is-data-descriptor",
+  "_nodeVersion": "5.0.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.3.6",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-data-descriptor",
+    "raw": "is-data-descriptor@^0.1.4",
+    "rawSpec": "^0.1.4",
+    "scope": null,
+    "spec": ">=0.1.4 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/object-copy/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+  "_shasum": "0b5ee648388e2c860282e793f1856fec3f301b56",
+  "_shrinkwrap": null,
+  "_spec": "is-data-descriptor@^0.1.4",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-data-descriptor/issues"
+  },
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript data descriptor.",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "0b5ee648388e2c860282e793f1856fec3f301b56",
+    "tarball": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e6317dbcb27a95281a60120bac83f5938dda4e2c",
+  "homepage": "https://github.com/jonschlinkert/is-data-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-data-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-data-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    }
+  },
+  "version": "0.1.4"
+}
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/LICENSE b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/LICENSE
new file mode 100644
index 00000000..c0d7f136
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/README.md b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/README.md
new file mode 100644
index 00000000..658e5330
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/README.md
@@ -0,0 +1,193 @@
+# is-descriptor [![NPM version](https://img.shields.io/npm/v/is-descriptor.svg?style=flat)](https://www.npmjs.com/package/is-descriptor) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-descriptor.svg?style=flat)](https://npmjs.org/package/is-descriptor) [![NPM total downloads](https://img.shields.io/npm/dt/is-descriptor.svg?style=flat)](https://npmjs.org/package/is-descriptor) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-descriptor.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-descriptor
+```
+
+## Usage
+
+```js
+var isDescriptor = require('is-descriptor');
+
+isDescriptor({value: 'foo'})
+//=> true
+isDescriptor({get: function(){}, set: function(){}})
+//=> true
+isDescriptor({get: 'foo', set: function(){}})
+//=> false
+```
+
+You may also check for a descriptor by passing an object as the first argument and property name (`string`) as the second argument.
+
+```js
+var obj = {};
+obj.foo = 'abc';
+
+Object.defineProperty(obj, 'bar', {
+  value: 'xyz'
+});
+
+isDescriptor(obj, 'foo');
+//=> true
+isDescriptor(obj, 'bar');
+//=> true
+```
+
+## Examples
+
+### value type
+
+`false` when not an object
+
+```js
+isDescriptor('a');
+//=> false
+isDescriptor(null);
+//=> false
+isDescriptor([]);
+//=> false
+```
+
+### data descriptor
+
+`true` when the object has valid properties with valid values.
+
+```js
+isDescriptor({value: 'foo'});
+//=> true
+isDescriptor({value: noop});
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isDescriptor({value: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({value: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({value: 'foo', get: noop});
+//=> false
+isDescriptor({get: noop, value: noop});
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDescriptor({value: 'foo', enumerable: 'foo'});
+//=> false
+isDescriptor({value: 'foo', configurable: 'foo'});
+//=> false
+isDescriptor({value: 'foo', writable: 'foo'});
+//=> false
+```
+
+### accessor descriptor
+
+`true` when the object has valid properties with valid values.
+
+```js
+isDescriptor({get: noop, set: noop});
+//=> true
+isDescriptor({get: noop});
+//=> true
+isDescriptor({set: noop});
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isDescriptor({get: noop, set: noop, bar: 'baz'});
+//=> false
+isDescriptor({get: noop, writable: true});
+//=> false
+isDescriptor({get: noop, value: true});
+//=> false
+```
+
+`false` when an accessor is not a function
+
+```js
+isDescriptor({get: noop, set: 'baz'});
+//=> false
+isDescriptor({get: 'foo', set: noop});
+//=> false
+isDescriptor({get: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({get: 'foo', set: 'baz'});
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDescriptor({get: noop, set: noop, enumerable: 'foo'});
+//=> false
+isDescriptor({set: noop, configurable: 'foo'});
+//=> false
+isDescriptor({get: noop, configurable: 'foo'});
+//=> false
+```
+
+## About
+
+### Related projects
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.")
+* [is-data-descriptor](https://www.npmjs.com/package/is-data-descriptor): Returns true if a value has the characteristics of a valid JavaScript data descriptor. | [homepage](https://github.com/jonschlinkert/is-data-descriptor "Returns true if a value has the characteristics of a valid JavaScript data descriptor.")
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://github.com/jonschlinkert/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 24 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [doowb](https://github.com/doowb) |
+| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 22, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/index.js b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/index.js
new file mode 100644
index 00000000..c9b91d76
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/index.js
@@ -0,0 +1,22 @@
+/*!
+ * is-descriptor <https://github.com/jonschlinkert/is-descriptor>
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+var isAccessor = require('is-accessor-descriptor');
+var isData = require('is-data-descriptor');
+
+module.exports = function isDescriptor(obj, key) {
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+  if ('get' in obj) {
+    return isAccessor(obj, key);
+  }
+  return isData(obj, key);
+};
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/README.md b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/README.md
new file mode 100644
index 00000000..170bf304
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/README.md
@@ -0,0 +1,342 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Release history
+
+### v4.0.0
+
+**Added**
+
+* `promise` support
+
+### v5.0.0
+
+**Added**
+
+* `Set Iterator` and `Map Iterator` support
+
+**Fixed**
+
+* Now returns `generatorfunction` for generator functions
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of is more correct than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly tests instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+<details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+<details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+<details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 82 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike](https://github.com/charlike) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on October 13, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/index.js b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/index.js
new file mode 100644
index 00000000..fc5cde96
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/index.js
@@ -0,0 +1,147 @@
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  var type = typeof val;
+
+  // primitivies
+  if (type === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (type === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (type === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (type === 'function' || val instanceof Function) {
+    if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') {
+      return 'generatorfunction';
+    }
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+  if (type === '[object Promise]') {
+    return 'promise';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+  
+  if (type === '[object Map Iterator]') {
+    return 'mapiterator';
+  }
+  if (type === '[object Set Iterator]') {
+    return 'setiterator';
+  }
+  if (type === '[object String Iterator]') {
+    return 'stringiterator';
+  }
+  if (type === '[object Array Iterator]') {
+    return 'arrayiterator';
+  }
+  
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  return val.constructor
+    && typeof val.constructor.isBuffer === 'function'
+    && val.constructor.isBuffer(val);
+}
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/package.json b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/package.json
new file mode 100644
index 00000000..be4b2a19
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of/package.json
@@ -0,0 +1,179 @@
+{
+  "_args": [
+    [
+      "kind-of@^5.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "kind-of@>=5.0.0 <6.0.0",
+  "_id": "kind-of@5.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-copy/is-descriptor/kind-of",
+  "_nodeVersion": "8.7.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-5.1.0.tgz_1507878225264_0.114781056297943"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.4.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^5.0.0",
+    "rawSpec": "^5.0.0",
+    "scope": null,
+    "spec": ">=5.0.0 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/object-copy/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+  "_shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^5.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.1.1",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^0.1.12",
+    "matched": "^0.4.4",
+    "mocha": "^3.4.2",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+    "shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ed479b6ee194dc1edff852f17095ae1de40bafbc",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "5.1.0"
+}
diff --git a/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/package.json b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/package.json
new file mode 100644
index 00000000..6c2ce564
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/node_modules/is-descriptor/package.json
@@ -0,0 +1,142 @@
+{
+  "_args": [
+    [
+      "is-descriptor@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/define-property"
+    ]
+  ],
+  "_from": "is-descriptor@>=0.1.0 <0.2.0",
+  "_id": "is-descriptor@0.1.6",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-copy/is-descriptor",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-descriptor-0.1.6.tgz_1500744018543_0.5760307745076716"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-descriptor",
+    "raw": "is-descriptor@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/object-copy/define-property"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+  "_shasum": "366d8240dde487ca51823b1ab9f07a10a78251ca",
+  "_shrinkwrap": null,
+  "_spec": "is-descriptor@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/object-copy/node_modules/define-property",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-descriptor/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "url": "https://github.com/wtgtybhertgeghgtwtg"
+    }
+  ],
+  "dependencies": {
+    "is-accessor-descriptor": "^0.1.6",
+    "is-data-descriptor": "^0.1.4",
+    "kind-of": "^5.0.0"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.4.2"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+    "shasum": "366d8240dde487ca51823b1ab9f07a10a78251ca",
+    "tarball": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "7559403830553097fcdd56ae93fe69d4ef2b21db",
+  "homepage": "https://github.com/jonschlinkert/is-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.1.6"
+}
diff --git a/input_devices/mag/node_modules/object-copy/package.json b/input_devices/mag/node_modules/object-copy/package.json
new file mode 100644
index 00000000..aa0a76b2
--- /dev/null
+++ b/input_devices/mag/node_modules/object-copy/package.json
@@ -0,0 +1,107 @@
+{
+  "_args": [
+    [
+      "object-copy@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend"
+    ]
+  ],
+  "_from": "object-copy@>=0.1.0 <0.2.0",
+  "_id": "object-copy@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-copy",
+  "_nodeVersion": "6.2.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/object-copy-0.1.0.tgz_1465495667685_0.612287495052442"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.8.9",
+  "_phantomChildren": {
+    "kind-of": "3.2.2"
+  },
+  "_requested": {
+    "name": "object-copy",
+    "raw": "object-copy@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend"
+  ],
+  "_resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+  "_shasum": "7e7d858b781bd7c991a41ba975ed3812754e998c",
+  "_shrinkwrap": null,
+  "_spec": "object-copy@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/object-copy/issues"
+  },
+  "dependencies": {
+    "copy-descriptor": "^0.1.0",
+    "define-property": "^0.2.5",
+    "kind-of": "^3.0.3"
+  },
+  "description": "Copy static properties, prototype properties, and descriptors from one object to another.",
+  "devDependencies": {
+    "gulp-format-md": "*",
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "7e7d858b781bd7c991a41ba975ed3812754e998c",
+    "tarball": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "15b972a4a7137f6bf47886c68e73a2fffa8eacf2",
+  "homepage": "https://github.com/jonschlinkert/object-copy",
+  "keywords": [
+    "copy",
+    "object"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "object-copy",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/object-copy.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": []
+    }
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/object-visit/LICENSE b/input_devices/mag/node_modules/object-visit/LICENSE
new file mode 100644
index 00000000..ec85897e
--- /dev/null
+++ b/input_devices/mag/node_modules/object-visit/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, 2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/object-visit/README.md b/input_devices/mag/node_modules/object-visit/README.md
new file mode 100644
index 00000000..64015cb9
--- /dev/null
+++ b/input_devices/mag/node_modules/object-visit/README.md
@@ -0,0 +1,83 @@
+# object-visit [![NPM version](https://img.shields.io/npm/v/object-visit.svg?style=flat)](https://www.npmjs.com/package/object-visit) [![NPM monthly downloads](https://img.shields.io/npm/dm/object-visit.svg?style=flat)](https://npmjs.org/package/object-visit) [![NPM total downloads](https://img.shields.io/npm/dt/object-visit.svg?style=flat)](https://npmjs.org/package/object-visit) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/object-visit.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/object-visit)
+
+> Call a specified method on each value in the given object.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save object-visit
+```
+
+## Usage
+
+```js
+var visit = require('object-visit');
+
+var ctx = {
+  data: {},
+  set: function (key, value) {
+    if (typeof key === 'object') {
+      visit(ctx, 'set', key);
+    } else {
+      ctx.data[key] = value;
+    }
+  }
+};
+
+ctx.set('a', 'a');
+ctx.set('b', 'b');
+ctx.set('c', 'c');
+ctx.set({d: {e: 'f'}});
+
+console.log(ctx.data);
+//=> {a: 'a', b: 'b', c: 'c', d: { e: 'f' }};
+```
+
+## About
+
+### Related projects
+
+* [base-methods](https://www.npmjs.com/package/base-methods): base-methods is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting… [more](https://github.com/jonschlinkert/base-methods) | [homepage](https://github.com/jonschlinkert/base-methods "base-methods is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting with a handful of common methods, like `set`, `get`, `del` and `use`.")
+* [collection-visit](https://www.npmjs.com/package/collection-visit): Visit a method over the items in an object, or map visit over the objects… [more](https://github.com/jonschlinkert/collection-visit) | [homepage](https://github.com/jonschlinkert/collection-visit "Visit a method over the items in an object, or map visit over the objects in an array.")
+* [define-property](https://www.npmjs.com/package/define-property): Define a non-enumerable property on an object. | [homepage](https://github.com/jonschlinkert/define-property "Define a non-enumerable property on an object.")
+* [map-visit](https://www.npmjs.com/package/map-visit): Map `visit` over an array of objects. | [homepage](https://github.com/jonschlinkert/map-visit "Map `visit` over an array of objects.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 30, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/object-visit/index.js b/input_devices/mag/node_modules/object-visit/index.js
new file mode 100644
index 00000000..fcaeda92
--- /dev/null
+++ b/input_devices/mag/node_modules/object-visit/index.js
@@ -0,0 +1,33 @@
+/*!
+ * object-visit <https://github.com/jonschlinkert/object-visit>
+ *
+ * Copyright (c) 2015, 2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var isObject = require('isobject');
+
+module.exports = function visit(thisArg, method, target, val) {
+  if (!isObject(thisArg) && typeof thisArg !== 'function') {
+    throw new Error('object-visit expects `thisArg` to be an object.');
+  }
+
+  if (typeof method !== 'string') {
+    throw new Error('object-visit expects `method` name to be a string');
+  }
+
+  if (typeof thisArg[method] !== 'function') {
+    return thisArg;
+  }
+
+  var args = [].slice.call(arguments, 3);
+  target = target || {};
+
+  for (var key in target) {
+    var arr = [key, target[key]].concat(args);
+    thisArg[method].apply(thisArg, arr);
+  }
+  return thisArg;
+};
diff --git a/input_devices/mag/node_modules/object-visit/package.json b/input_devices/mag/node_modules/object-visit/package.json
new file mode 100644
index 00000000..64d7d4d5
--- /dev/null
+++ b/input_devices/mag/node_modules/object-visit/package.json
@@ -0,0 +1,124 @@
+{
+  "_args": [
+    [
+      "object-visit@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/collection-visit"
+    ]
+  ],
+  "_from": "object-visit@>=1.0.0 <2.0.0",
+  "_id": "object-visit@1.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/object-visit",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/object-visit-1.0.1.tgz_1496118320846_0.49384314101189375"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.6.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "object-visit",
+    "raw": "object-visit@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/collection-visit",
+    "/map-visit"
+  ],
+  "_resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+  "_shasum": "f79c4493af0c5377b59fe39d395e41042dd045bb",
+  "_shrinkwrap": null,
+  "_spec": "object-visit@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/collection-visit",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/object-visit/issues"
+  },
+  "dependencies": {
+    "isobject": "^3.0.0"
+  },
+  "description": "Call a specified method on each value in the given object.",
+  "devDependencies": {
+    "gulp": "^3.9.1",
+    "gulp-eslint": "^3.0.1",
+    "gulp-format-md": "^0.1.12",
+    "gulp-istanbul": "^1.1.1",
+    "gulp-mocha": "^3.0.0",
+    "mocha": "^3.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "f79c4493af0c5377b59fe39d395e41042dd045bb",
+    "tarball": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "2220cd6ea35008481c9e252488bcbde9ebca0983",
+  "homepage": "https://github.com/jonschlinkert/object-visit",
+  "keywords": [
+    "context",
+    "function",
+    "helper",
+    "key",
+    "method",
+    "object",
+    "value",
+    "visit",
+    "visitor"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "object-visit",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/object-visit.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "base-methods",
+        "collection-visit",
+        "define-property",
+        "map-visit"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.1"
+}
diff --git a/input_devices/mag/node_modules/once/LICENSE b/input_devices/mag/node_modules/once/LICENSE
new file mode 100644
index 00000000..19129e31
--- /dev/null
+++ b/input_devices/mag/node_modules/once/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/once/README.md b/input_devices/mag/node_modules/once/README.md
new file mode 100644
index 00000000..1f1ffca9
--- /dev/null
+++ b/input_devices/mag/node_modules/once/README.md
@@ -0,0 +1,79 @@
+# once
+
+Only call a function once.
+
+## usage
+
+```javascript
+var once = require('once')
+
+function load (file, cb) {
+  cb = once(cb)
+  loader.load('file')
+  loader.once('load', cb)
+  loader.once('error', cb)
+}
+```
+
+Or add to the Function.prototype in a responsible way:
+
+```javascript
+// only has to be done once
+require('once').proto()
+
+function load (file, cb) {
+  cb = cb.once()
+  loader.load('file')
+  loader.once('load', cb)
+  loader.once('error', cb)
+}
+```
+
+Ironically, the prototype feature makes this module twice as
+complicated as necessary.
+
+To check whether you function has been called, use `fn.called`. Once the
+function is called for the first time the return value of the original
+function is saved in `fn.value` and subsequent calls will continue to
+return this value.
+
+```javascript
+var once = require('once')
+
+function load (cb) {
+  cb = once(cb)
+  var stream = createStream()
+  stream.once('data', cb)
+  stream.once('end', function () {
+    if (!cb.called) cb(new Error('not found'))
+  })
+}
+```
+
+## `once.strict(func)`
+
+Throw an error if the function is called twice.
+
+Some functions are expected to be called only once. Using `once` for them would
+potentially hide logical errors.
+
+In the example below, the `greet` function has to call the callback only once:
+
+```javascript
+function greet (name, cb) {
+  // return is missing from the if statement
+  // when no name is passed, the callback is called twice
+  if (!name) cb('Hello anonymous')
+  cb('Hello ' + name)
+}
+
+function log (msg) {
+  console.log(msg)
+}
+
+// this will print 'Hello anonymous' but the logical error will be missed
+greet(null, once(msg))
+
+// once.strict will print 'Hello anonymous' and throw an error when the callback will be called the second time
+greet(null, once.strict(msg))
+```
diff --git a/input_devices/mag/node_modules/once/once.js b/input_devices/mag/node_modules/once/once.js
new file mode 100644
index 00000000..23540673
--- /dev/null
+++ b/input_devices/mag/node_modules/once/once.js
@@ -0,0 +1,42 @@
+var wrappy = require('wrappy')
+module.exports = wrappy(once)
+module.exports.strict = wrappy(onceStrict)
+
+once.proto = once(function () {
+  Object.defineProperty(Function.prototype, 'once', {
+    value: function () {
+      return once(this)
+    },
+    configurable: true
+  })
+
+  Object.defineProperty(Function.prototype, 'onceStrict', {
+    value: function () {
+      return onceStrict(this)
+    },
+    configurable: true
+  })
+})
+
+function once (fn) {
+  var f = function () {
+    if (f.called) return f.value
+    f.called = true
+    return f.value = fn.apply(this, arguments)
+  }
+  f.called = false
+  return f
+}
+
+function onceStrict (fn) {
+  var f = function () {
+    if (f.called)
+      throw new Error(f.onceError)
+    f.called = true
+    return f.value = fn.apply(this, arguments)
+  }
+  var name = fn.name || 'Function wrapped with `once`'
+  f.onceError = name + " shouldn't be called more than once"
+  f.called = false
+  return f
+}
diff --git a/input_devices/mag/node_modules/once/package.json b/input_devices/mag/node_modules/once/package.json
new file mode 100644
index 00000000..2823f4af
--- /dev/null
+++ b/input_devices/mag/node_modules/once/package.json
@@ -0,0 +1,95 @@
+{
+  "_args": [
+    [
+      "once@^1.3.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/pump"
+    ]
+  ],
+  "_from": "once@>=1.3.1 <2.0.0",
+  "_id": "once@1.4.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/once",
+  "_nodeVersion": "6.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/once-1.4.0.tgz_1473196269128_0.537820661207661"
+  },
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "3.10.7",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "once",
+    "raw": "once@^1.3.1",
+    "rawSpec": "^1.3.1",
+    "scope": null,
+    "spec": ">=1.3.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/end-of-stream",
+    "/pump",
+    "/simple-get",
+    "/tar-fs/pump"
+  ],
+  "_resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+  "_shasum": "583b1aa775961d4b113ac17d9c50baef9dd76bd1",
+  "_shrinkwrap": null,
+  "_spec": "once@^1.3.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/pump",
+  "author": {
+    "email": "i@izs.me",
+    "name": "Isaac Z. Schlueter",
+    "url": "http://blog.izs.me/"
+  },
+  "bugs": {
+    "url": "https://github.com/isaacs/once/issues"
+  },
+  "dependencies": {
+    "wrappy": "1"
+  },
+  "description": "Run a function exactly one time",
+  "devDependencies": {
+    "tap": "^7.0.1"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "dist": {
+    "shasum": "583b1aa775961d4b113ac17d9c50baef9dd76bd1",
+    "tarball": "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
+  },
+  "files": [
+    "once.js"
+  ],
+  "gitHead": "0e614d9f5a7e6f0305c625f6b581f6d80b33b8a6",
+  "homepage": "https://github.com/isaacs/once#readme",
+  "keywords": [
+    "function",
+    "once",
+    "one",
+    "single"
+  ],
+  "license": "ISC",
+  "main": "once.js",
+  "maintainers": [
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    }
+  ],
+  "name": "once",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/once.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "version": "1.4.0"
+}
diff --git a/input_devices/mag/node_modules/os-homedir/index.js b/input_devices/mag/node_modules/os-homedir/index.js
new file mode 100644
index 00000000..33066166
--- /dev/null
+++ b/input_devices/mag/node_modules/os-homedir/index.js
@@ -0,0 +1,24 @@
+'use strict';
+var os = require('os');
+
+function homedir() {
+	var env = process.env;
+	var home = env.HOME;
+	var user = env.LOGNAME || env.USER || env.LNAME || env.USERNAME;
+
+	if (process.platform === 'win32') {
+		return env.USERPROFILE || env.HOMEDRIVE + env.HOMEPATH || home || null;
+	}
+
+	if (process.platform === 'darwin') {
+		return home || (user ? '/Users/' + user : null);
+	}
+
+	if (process.platform === 'linux') {
+		return home || (process.getuid() === 0 ? '/root' : (user ? '/home/' + user : null));
+	}
+
+	return home || null;
+}
+
+module.exports = typeof os.homedir === 'function' ? os.homedir : homedir;
diff --git a/input_devices/mag/node_modules/os-homedir/license b/input_devices/mag/node_modules/os-homedir/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/os-homedir/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/os-homedir/package.json b/input_devices/mag/node_modules/os-homedir/package.json
new file mode 100644
index 00000000..6051f98f
--- /dev/null
+++ b/input_devices/mag/node_modules/os-homedir/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "os-homedir@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "os-homedir@>=1.0.1 <2.0.0",
+  "_id": "os-homedir@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/os-homedir",
+  "_nodeVersion": "6.6.0",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/os-homedir-1.0.2.tgz_1475211519628_0.7873868853785098"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "3.10.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "os-homedir",
+    "raw": "os-homedir@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+  "_shasum": "ffbc4988336e0e833de0c168c7ef152121aa7fb3",
+  "_shrinkwrap": null,
+  "_spec": "os-homedir@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/os-homedir/issues"
+  },
+  "dependencies": {},
+  "description": "Node.js 4 `os.homedir()` ponyfill",
+  "devDependencies": {
+    "ava": "*",
+    "path-exists": "^2.0.0",
+    "xo": "^0.16.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "ffbc4988336e0e833de0c168c7ef152121aa7fb3",
+    "tarball": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "b1b0ae70a5965fef7005ff6509a5dd1a78c95e36",
+  "homepage": "https://github.com/sindresorhus/os-homedir#readme",
+  "keywords": [
+    "builtin",
+    "core",
+    "dir",
+    "directory",
+    "folder",
+    "home",
+    "homedir",
+    "os",
+    "path",
+    "polyfill",
+    "ponyfill",
+    "shim",
+    "user"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "os-homedir",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/os-homedir.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/os-homedir/readme.md b/input_devices/mag/node_modules/os-homedir/readme.md
new file mode 100644
index 00000000..856ae615
--- /dev/null
+++ b/input_devices/mag/node_modules/os-homedir/readme.md
@@ -0,0 +1,31 @@
+# os-homedir [![Build Status](https://travis-ci.org/sindresorhus/os-homedir.svg?branch=master)](https://travis-ci.org/sindresorhus/os-homedir)
+
+> Node.js 4 [`os.homedir()`](https://nodejs.org/api/os.html#os_os_homedir) [ponyfill](https://ponyfill.com)
+
+
+## Install
+
+```
+$ npm install --save os-homedir
+```
+
+
+## Usage
+
+```js
+const osHomedir = require('os-homedir');
+
+console.log(osHomedir());
+//=> '/Users/sindresorhus'
+```
+
+
+## Related
+
+- [user-home](https://github.com/sindresorhus/user-home) - Same as this module but caches the result
+- [home-or-tmp](https://github.com/sindresorhus/home-or-tmp) - Get the user home directory with fallback to the system temp directory
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/pointer-symbol/LICENSE b/input_devices/mag/node_modules/pointer-symbol/LICENSE
new file mode 100644
index 00000000..9a1c8567
--- /dev/null
+++ b/input_devices/mag/node_modules/pointer-symbol/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/pointer-symbol/README.md b/input_devices/mag/node_modules/pointer-symbol/README.md
new file mode 100644
index 00000000..0448d2bc
--- /dev/null
+++ b/input_devices/mag/node_modules/pointer-symbol/README.md
@@ -0,0 +1,81 @@
+# pointer-symbol [![NPM version](https://img.shields.io/npm/v/pointer-symbol.svg?style=flat)](https://www.npmjs.com/package/pointer-symbol) [![NPM monthly downloads](https://img.shields.io/npm/dm/pointer-symbol.svg?style=flat)](https://npmjs.org/package/pointer-symbol) [![NPM total downloads](https://img.shields.io/npm/dt/pointer-symbol.svg?style=flat)](https://npmjs.org/package/pointer-symbol)
+
+> Cross-platform pointer symbols for prompts.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save pointer-symbol
+```
+
+## Usage
+
+If you have any rendering issues on your platform, please create an [issue or pull request](../../issues).
+
+```js
+var pointer = require('pointer-symbol');
+
+console.log(pointer());
+// cygwin, msys, win32 
+// '>'
+
+// linux
+// '‣'
+
+// everything else
+// '❯'
+
+console.log(pointer({small: true}));
+// cygwin, msys, win32 
+// '»'
+
+// linux
+// '‣'
+
+// everything else
+// '›'
+```
+
+## About
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 23, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/pointer-symbol/index.js b/input_devices/mag/node_modules/pointer-symbol/index.js
new file mode 100644
index 00000000..3c6461c6
--- /dev/null
+++ b/input_devices/mag/node_modules/pointer-symbol/index.js
@@ -0,0 +1,20 @@
+'use strict';
+
+module.exports = function(options) {
+  if (options && typeof options.pointer === 'string') {
+    return options.pointer.trim();
+  }
+
+  var small = options && options.small;
+  switch (process.platform) {
+    case 'cygwin':
+    case 'msys':
+    case 'win32':
+      return small ? '»' : '>';
+    case 'linux':
+      return small ? '‣' : '‣';
+    default: {
+      return small ? '›' : '❯';
+    }
+  }
+};
diff --git a/input_devices/mag/node_modules/pointer-symbol/package.json b/input_devices/mag/node_modules/pointer-symbol/package.json
new file mode 100644
index 00000000..d89d7926
--- /dev/null
+++ b/input_devices/mag/node_modules/pointer-symbol/package.json
@@ -0,0 +1,102 @@
+{
+  "_args": [
+    [
+      "pointer-symbol@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "pointer-symbol@>=1.0.0 <2.0.0",
+  "_id": "pointer-symbol@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/pointer-symbol",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/pointer-symbol-1.0.0.tgz_1495572641078_0.5288200853392482"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.6.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "pointer-symbol",
+    "raw": "pointer-symbol@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/pointer-symbol/-/pointer-symbol-1.0.0.tgz",
+  "_shasum": "60f9110204ea7a929b62644a21315543cbb3d447",
+  "_shrinkwrap": null,
+  "_spec": "pointer-symbol@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/pointer-symbol/issues"
+  },
+  "dependencies": {},
+  "description": "Cross-platform pointer symbols for prompts.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "60f9110204ea7a929b62644a21315543cbb3d447",
+    "tarball": "https://registry.npmjs.org/pointer-symbol/-/pointer-symbol-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e572a749d89a88c388f4906c78d0c8d9c73e4507",
+  "homepage": "https://github.com/enquirer/pointer-symbol",
+  "keywords": [
+    "pointer",
+    "prompt",
+    "symbol"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "pointer-symbol",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/pointer-symbol.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/prebuild-install/.travis.yml b/input_devices/mag/node_modules/prebuild-install/.travis.yml
new file mode 100644
index 00000000..377b86be
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/.travis.yml
@@ -0,0 +1,10 @@
+language: node_js
+
+os:
+  - linux
+  - osx
+
+node_js:
+  - 6
+  - 8
+  - 10
diff --git a/input_devices/mag/node_modules/prebuild-install/CONTRIBUTING.md b/input_devices/mag/node_modules/prebuild-install/CONTRIBUTING.md
new file mode 100644
index 00000000..f89c7c99
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/CONTRIBUTING.md
@@ -0,0 +1,8 @@
+# Contributing to prebuild
+
+* no commits direct to master
+* all commits as pull requests (one or several per PR)
+* each commit solves one identifiable problem
+* never merge one's own PRs, another contributor does this
+
+
diff --git a/input_devices/mag/node_modules/prebuild-install/LICENSE b/input_devices/mag/node_modules/prebuild-install/LICENSE
new file mode 100644
index 00000000..66a4d2a1
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Mathias Buus
+
+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/input_devices/mag/node_modules/prebuild-install/README.md b/input_devices/mag/node_modules/prebuild-install/README.md
new file mode 100644
index 00000000..69935f6d
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/README.md
@@ -0,0 +1,102 @@
+# prebuild-install
+
+> A command line tool to easily install prebuilt binaries for multiple version of node/iojs on a specific platform.
+
+[![npm](https://img.shields.io/npm/v/prebuild-install.svg)](https://www.npmjs.com/package/prebuild-install)
+![Node version](https://img.shields.io/node/v/prebuild-install.svg)
+[![Build Status](https://travis-ci.org/prebuild/prebuild-install.svg?branch=master)](https://travis-ci.org/prebuild/prebuild-install)
+[![Build status](https://ci.appveyor.com/api/projects/status/6v6hxxwgjrr99pc8/branch/master?svg=true)](https://ci.appveyor.com/project/mathiask88/prebuild-install)
+[![david](https://david-dm.org/prebuild/prebuild-install.svg)](https://david-dm.org/prebuild/prebuild-install)
+[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
+
+`prebuild-install` supports installing prebuilt binaries from GitHub by default.
+
+## Usage
+
+Change your package.json install script to:
+```json
+{
+  "scripts": {
+    "install": "prebuild-install || node-gyp rebuild"
+  }
+}
+```
+
+### Requirements
+
+You need to provide prebuilds made by [`prebuild`](https://github.com/prebuild/prebuild).
+
+### Help
+```
+prebuild-install [options]
+
+  --download    -d  [url]       (download prebuilds, no url means github)
+  --target      -t  version     (version to install for)
+  --runtime     -r  runtime     (Node runtime [node, napi or electron] to build or install for, default is node)
+  --path        -p  path        (make a prebuild-install here)
+  --token       -T  gh-token    (github token for private repos)
+  --tag-prefix <prefix>         (github tag prefix, default is "v")
+  --build-from-source           (skip prebuild download)
+  --verbose                     (log verbosely)
+  --libc                        (use provided libc rather than system default)
+  --debug                       (set Debug or Release configuration)
+  --version                     (print prebuild-install version and exit)
+```
+
+When `prebuild-install` is run via an `npm` script, options
+`--build-from-source`, `--debug` and `--download`, may be passed through via
+arguments given to the `npm` command.
+
+### Private Repositories
+
+`prebuild-install` supports downloading prebuilds from private GitHub repositories using the `-T <github-token>`:
+
+```
+$ prebuild-install -T <github-token>
+```
+
+If you don't want to use the token on cli you can put it in `~/.prebuild-installrc`:
+
+```
+token=<github-token>
+```
+
+Alternatively you can specify it in the `prebuild-install_token` environment variable.
+
+Note that using a GitHub token uses the API to resolve the correct release meaning that you are subject to the ([GitHub Rate Limit](https://developer.github.com/v3/rate_limit/)).
+
+### Create GitHub Token
+
+To create a token:
+
+* Go to [this page](https://github.com/settings/tokens)
+* Click the `Generate new token` button
+* Give the token a name and click the `Generate token` button, see below
+
+![prebuild-token](https://cloud.githubusercontent.com/assets/13285808/20844584/d0b85268-b8c0-11e6-8b08-2b19522165a9.png)
+
+The default scopes should be fine.
+
+### Custom binaries
+The end user can override binary download location through environment variables in their .npmrc file.
+The variable needs to meet the mask `% your package name %_binary_host` or `% your package name %_binary_host_mirror`. For example:
+```
+leveldown_binary_host=http://overriden-host.com/overriden-path
+```
+Note that the package version subpath and file name will still be appended.
+So if you are installing `leveldown@1.2.3` the resulting url will be:
+```
+http://overriden-host.com/overriden-path/v1.2.3/leveldown-v1.2.3-node-v57-win32-x64.tar.gz
+```
+
+### Cache
+
+All prebuilt binaries are cached to minimize traffic. So first `prebuild-install` picks binaries from the cache and if no binary could be found, it will be downloaded. Depending on the environment, the cache folder is determined in the following order:
+
+* `${npm_config_cache}/_prebuilds`
+* `${APP_DATA}/npm-cache/_prebuilds`
+* `${HOME}/.npm/_prebuilds`
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/prebuild-install/appveyor.yml b/input_devices/mag/node_modules/prebuild-install/appveyor.yml
new file mode 100644
index 00000000..88e60425
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/appveyor.yml
@@ -0,0 +1,38 @@
+# http://www.appveyor.com/docs/appveyor-yml
+
+# Don't actually build
+build: off
+
+# Skip tag builds
+skip_tags: true
+
+# Set build version format
+version: "{build}"
+
+# Set up build environment
+environment:
+  # Test against these versions of Node.js
+  matrix:
+    - nodejs_version: "10"
+    - nodejs_version: "8"
+    - nodejs_version: "6"
+
+# Build on both platforms
+platform:
+  - x86
+  - x64
+
+# Install scripts (runs after repo cloning)
+install:
+  # Get the latest version of $env:nodejs_version
+  - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) $env:platform
+  # Output useful info for debugging
+  - node --version
+  - npm --version
+  # Install modules
+  - npm install
+
+# Post-install test scripts
+test_script:
+  # Run module tests
+  - npm test
diff --git a/input_devices/mag/node_modules/prebuild-install/asset.js b/input_devices/mag/node_modules/prebuild-install/asset.js
new file mode 100644
index 00000000..6ff8c72f
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/asset.js
@@ -0,0 +1,48 @@
+var get = require('simple-get')
+var util = require('./util')
+var proxy = require('./proxy')
+var noop = Object.assign({
+  http: function () {},
+  silly: function () {}
+}, require('noop-logger'))
+
+function findAssetId (opts, cb) {
+  var downloadUrl = util.getDownloadUrl(opts)
+  var apiUrl = util.getApiUrl(opts)
+  var log = opts.log || noop
+
+  log.http('request', 'GET ' + apiUrl)
+  var reqOpts = proxy({
+    url: apiUrl,
+    json: true,
+    headers: {
+      'User-Agent': 'simple-get',
+      Authorization: 'token ' + opts.token
+    }
+  }, opts)
+
+  var req = get.concat(reqOpts, function (err, res, data) {
+    if (err) return cb(err)
+    log.http(res.statusCode, apiUrl)
+    if (res.statusCode !== 200) return cb(err)
+
+    // Find asset id in release
+    for (var release of data) {
+      if (release.tag_name === opts['tag-prefix'] + opts.pkg.version) {
+        for (var asset of release.assets) {
+          if (asset.browser_download_url === downloadUrl) {
+            return cb(null, asset.id)
+          }
+        }
+      }
+    }
+
+    cb(new Error('Could not find GitHub release for version'))
+  })
+
+  req.setTimeout(30 * 1000, function () {
+    req.abort()
+  })
+}
+
+module.exports = findAssetId
diff --git a/input_devices/mag/node_modules/prebuild-install/bin.js b/input_devices/mag/node_modules/prebuild-install/bin.js
new file mode 100755
index 00000000..9fabb5ca
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/bin.js
@@ -0,0 +1,79 @@
+#!/usr/bin/env node
+
+var path = require('path')
+var fs = require('fs')
+var whichPmRuns = require('which-pm-runs')
+var napi = require('napi-build-utils')
+
+var pkg = require(path.resolve('package.json'))
+var rc = require('./rc')(pkg)
+var log = require('./log')(rc, process.env)
+var download = require('./download')
+var asset = require('./asset')
+var util = require('./util')
+
+var prebuildClientVersion = require('./package.json').version
+if (rc.version) {
+  console.log(prebuildClientVersion)
+  process.exit(0)
+}
+
+if (rc.path) process.chdir(rc.path)
+
+if (!fs.existsSync('package.json')) {
+  log.error('setup', 'No package.json found. Aborting...')
+  process.exit(1)
+}
+
+if (rc.help) {
+  console.error(fs.readFileSync(path.join(__dirname, 'help.txt'), 'utf-8'))
+  process.exit(0)
+}
+
+log.info('begin', 'Prebuild-install version', prebuildClientVersion)
+
+var opts = Object.assign({}, rc, {pkg: pkg, log: log})
+
+if (napi.isNapiRuntime(rc.runtime)) napi.logUnsupportedVersion(rc.target, log)
+
+var pm = whichPmRuns()
+var isNpm = !pm || pm.name === 'npm'
+
+if (!isNpm && /node_modules/.test(process.cwd())) {
+  // From yarn repository
+} else if (opts.force) {
+  log.warn('install', 'prebuilt binaries enforced with --force!')
+  log.warn('install', 'prebuilt binaries may be out of date!')
+} else if (!(typeof pkg._from === 'string')) {
+  log.info('install', 'installing standalone, skipping download.')
+  process.exit(1)
+} else if (pkg._from.length > 4 && pkg._from.substr(0, 4) === 'git+') {
+  log.info('install', 'installing from git repository, skipping download.')
+  process.exit(1)
+} else if (opts.compile === true || opts.prebuild === false) {
+  log.info('install', '--build-from-source specified, not attempting download.')
+  process.exit(1)
+}
+
+var startDownload = function (downloadUrl) {
+  download(downloadUrl, opts, function (err) {
+    if (err) {
+      log.warn('install', err.message)
+      return process.exit(1)
+    }
+    log.info('install', 'Successfully installed prebuilt binary!')
+  })
+}
+
+if (opts.token) {
+  asset(opts, function (err, assetId) {
+    if (err) {
+      log.warn('install', err.message)
+      return process.exit(1)
+    }
+
+    startDownload(util.getAssetUrl(opts, assetId))
+  })
+} else {
+  startDownload(util.getDownloadUrl(opts))
+}
diff --git a/input_devices/mag/node_modules/prebuild-install/download.js b/input_devices/mag/node_modules/prebuild-install/download.js
new file mode 100644
index 00000000..a796420f
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/download.js
@@ -0,0 +1,130 @@
+var path = require('path')
+var fs = require('fs')
+var get = require('simple-get')
+var pump = require('pump')
+var tfs = require('tar-fs')
+var noop = Object.assign({
+  http: function () {},
+  silly: function () {}
+}, require('noop-logger'))
+var zlib = require('zlib')
+var util = require('./util')
+var error = require('./error')
+var proxy = require('./proxy')
+var mkdirp = require('mkdirp')
+
+function downloadPrebuild (downloadUrl, opts, cb) {
+  var cachedPrebuild = util.cachedPrebuild(downloadUrl)
+  var tempFile = util.tempFile(cachedPrebuild)
+  var log = opts.log || noop
+
+  ensureNpmCacheDir(function (err) {
+    if (err) return onerror(err)
+
+    log.info('looking for cached prebuild @', cachedPrebuild)
+    fs.access(cachedPrebuild, fs.R_OK | fs.W_OK, function (err) {
+      if (!(err && err.code === 'ENOENT')) {
+        log.info('found cached prebuild')
+        return unpack()
+      }
+
+      log.http('request', 'GET ' + downloadUrl)
+      var reqOpts = proxy({ url: downloadUrl }, opts)
+
+      if (opts.token) {
+        reqOpts.url += '?access_token=' + opts.token
+        reqOpts.headers = {
+          'User-Agent': 'simple-get',
+          'Accept': 'application/octet-stream'
+        }
+      }
+
+      var req = get(reqOpts, function (err, res) {
+        if (err) return onerror(err)
+        log.http(res.statusCode, downloadUrl)
+        if (res.statusCode !== 200) return onerror()
+        mkdirp(util.prebuildCache(), function () {
+          log.info('downloading to @', tempFile)
+          pump(res, fs.createWriteStream(tempFile), function (err) {
+            if (err) return onerror(err)
+            fs.rename(tempFile, cachedPrebuild, function (err) {
+              if (err) return cb(err)
+              log.info('renaming to @', cachedPrebuild)
+              unpack()
+            })
+          })
+        })
+      })
+
+      req.setTimeout(30 * 1000, function () {
+        req.abort()
+      })
+    })
+
+    function onerror (err) {
+      fs.unlink(tempFile, function () {
+        cb(err || error.noPrebuilts(opts))
+      })
+    }
+  })
+
+  function unpack () {
+    var binaryName
+
+    var updateName = opts.updateName || function (entry) {
+      if (/\.node$/i.test(entry.name)) binaryName = entry.name
+    }
+
+    log.info('unpacking @', cachedPrebuild)
+
+    var options = {
+      readable: true,
+      writable: true,
+      hardlinkAsFilesFallback: true
+    }
+    var extract = tfs.extract(opts.path, options).on('entry', updateName)
+
+    pump(fs.createReadStream(cachedPrebuild), zlib.createGunzip(), extract,
+    function (err) {
+      if (err) return cb(err)
+
+      var resolved
+      if (binaryName) {
+        try {
+          resolved = path.resolve(opts.path || '.', binaryName)
+        } catch (err) {
+          return cb(err)
+        }
+        log.info('unpack', 'resolved to ' + resolved)
+
+        if (opts.runtime === 'node' && opts.platform === process.platform && opts.abi === process.versions.modules && opts.arch === process.arch) {
+          try {
+            require(resolved)
+          } catch (err) {
+            return cb(err)
+          }
+          log.info('unpack', 'required ' + resolved + ' successfully')
+        }
+      }
+
+      cb(null, resolved)
+    })
+  }
+
+  function ensureNpmCacheDir (cb) {
+    var cacheFolder = util.npmCache()
+    fs.access(cacheFolder, fs.R_OK | fs.W_OK, function (err) {
+      if (err && err.code === 'ENOENT') {
+        return makeNpmCacheDir()
+      }
+      cb(err)
+    })
+
+    function makeNpmCacheDir () {
+      log.info('npm cache directory missing, creating it...')
+      mkdirp(cacheFolder, cb)
+    }
+  }
+}
+
+module.exports = downloadPrebuild
diff --git a/input_devices/mag/node_modules/prebuild-install/error.js b/input_devices/mag/node_modules/prebuild-install/error.js
new file mode 100644
index 00000000..8bec48eb
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/error.js
@@ -0,0 +1,13 @@
+exports.noPrebuilts = function (opts) {
+  return new Error([
+    'No prebuilt binaries found',
+    '(target=' + opts.target,
+    'runtime=' + opts.runtime,
+    'arch=' + opts.arch,
+    'platform=' + opts.platform + ')'
+  ].join(' '))
+}
+
+exports.invalidArchive = function () {
+  return new Error('Missing .node file in archive')
+}
diff --git a/input_devices/mag/node_modules/prebuild-install/help.txt b/input_devices/mag/node_modules/prebuild-install/help.txt
new file mode 100644
index 00000000..912bcce9
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/help.txt
@@ -0,0 +1,14 @@
+prebuild-install [options]
+
+  --download    -d  [url]       (download prebuilds, no url means github)
+  --target      -t  version     (version to install for)
+  --runtime     -r  runtime     (Node runtime [node or electron] to build or install for, default is node)
+  --path        -p  path        (make a prebuild-install here)
+  --token       -T  gh-token    (github token for private repos)
+  --tag-prefix <prefix>         (github tag prefix, default is "v")
+  --force                       (always use prebuilt binaries when available)
+  --build-from-source           (skip prebuild download)
+  --verbose                     (log verbosely)
+  --libc                        (use provided libc rather than system default)
+  --debug                       (set Debug or Release configuration)
+  --version                     (print prebuild-install version and exit)
diff --git a/input_devices/mag/node_modules/prebuild-install/index.js b/input_devices/mag/node_modules/prebuild-install/index.js
new file mode 100644
index 00000000..b5fc28a7
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/index.js
@@ -0,0 +1 @@
+exports.download = require('./download')
diff --git a/input_devices/mag/node_modules/prebuild-install/log.js b/input_devices/mag/node_modules/prebuild-install/log.js
new file mode 100644
index 00000000..707705c6
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/log.js
@@ -0,0 +1,13 @@
+var log = require('npmlog')
+
+module.exports = function (rc, env) {
+  log.heading = 'prebuild-install'
+
+  if (rc.verbose) {
+    log.level = 'verbose'
+  } else {
+    log.level = env.npm_config_loglevel || 'notice'
+  }
+
+  return log
+}
diff --git a/input_devices/mag/node_modules/prebuild-install/package.json b/input_devices/mag/node_modules/prebuild-install/package.json
new file mode 100644
index 00000000..a1551122
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/package.json
@@ -0,0 +1,178 @@
+{
+  "_args": [
+    [
+      "prebuild-install@^5.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/bindings"
+    ]
+  ],
+  "_from": "prebuild-install@>=5.1.0 <6.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "prebuild-install@5.2.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prebuild-install",
+  "_nodeVersion": "10.9.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prebuild-install_5.2.1_1539881859328_0.5110587660633801"
+  },
+  "_npmUser": {
+    "email": "ralphtheninja@riseup.net",
+    "name": "ralphtheninja"
+  },
+  "_npmVersion": "6.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "prebuild-install",
+    "raw": "prebuild-install@^5.1.0",
+    "rawSpec": "^5.1.0",
+    "scope": null,
+    "spec": ">=5.1.0 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/@serialport/bindings"
+  ],
+  "_resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.2.1.tgz",
+  "_shasum": "87ba8cf17c65360a75eefeb3519e87973bf9791d",
+  "_shrinkwrap": null,
+  "_spec": "prebuild-install@^5.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/@serialport/bindings",
+  "author": {
+    "name": "Mathias Buus",
+    "url": "@mafintosh"
+  },
+  "bin": {
+    "prebuild-install": "./bin.js"
+  },
+  "bugs": {
+    "url": "https://github.com/prebuild/prebuild-install/issues"
+  },
+  "contributors": [
+    {
+      "name": "Julian Gruber",
+      "email": "julian@juliangruber.com",
+      "url": "https://github.com/juliangruber"
+    },
+    {
+      "name": "Brett Lawson",
+      "email": "brett19@gmail.com",
+      "url": "https://github.com/brett19"
+    },
+    {
+      "name": "Pieter Hintjens",
+      "email": "ph@imatix.com",
+      "url": "https://github.com/hintjens"
+    },
+    {
+      "name": "Lars-Magnus Skog",
+      "email": "ralphtheninja@riseup.net",
+      "url": "https://github.com/ralphtheninja"
+    },
+    {
+      "name": "Jesús Leganés Combarro",
+      "email": "piranna@gmail.com",
+      "url": "https://github.com/piranna"
+    },
+    {
+      "name": "Mathias Küsel",
+      "email": "mathiask@hotmail.de",
+      "url": "https://github.com/mathiask88"
+    },
+    {
+      "name": "Lukas Geiger",
+      "email": "lukas.geiger94@gmail.com",
+      "url": "https://github.com/lgeiger"
+    }
+  ],
+  "dependencies": {
+    "detect-libc": "^1.0.3",
+    "expand-template": "^1.0.2",
+    "github-from-package": "0.0.0",
+    "minimist": "^1.2.0",
+    "mkdirp": "^0.5.1",
+    "napi-build-utils": "^1.0.1",
+    "node-abi": "^2.2.0",
+    "noop-logger": "^0.1.1",
+    "npmlog": "^4.0.1",
+    "os-homedir": "^1.0.1",
+    "pump": "^2.0.1",
+    "rc": "^1.2.7",
+    "simple-get": "^2.7.0",
+    "tar-fs": "^1.13.0",
+    "tunnel-agent": "^0.6.0",
+    "which-pm-runs": "^1.0.0"
+  },
+  "description": "A command line tool to easily install prebuilt binaries for multiple version of node/iojs on a specific platform",
+  "devDependencies": {
+    "a-native-module": "^1.0.0",
+    "nock": "^9.2.5",
+    "nsp": "^3.2.1",
+    "rimraf": "^2.5.2",
+    "standard": "^10.0.3",
+    "tape": "^4.5.1",
+    "verify-travis-appveyor": "^2.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 16,
+    "integrity": "sha512-9DAccsInWHB48TBQi2eJkLPE049JuAI6FjIH0oIrij4bpDVEbX6JvlWRAcAAlUqBHhjgq0jNqA3m3bBXWm9v6w==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbyLuECRA9TVsSAnZWagAAlyoP/31h5AhIiEBPOnXnlXl6\n5D6UwATOQQd53DXr5zLWcsCEF2brwiuH7tH29NyysTxYLjnE1NNEY7QFzlEA\n/RHOG+AiAvXjxfZAJh9AE05fsFMeH3J8UdVYdwCfrvuvcxbMud7WGCabvpFj\nUm0HTsEnhl9TXCZZNXsY670Sb1lFmG49M0/0xcvuZtyv2yfTuaw4H2GU6ED/\nwEETe/BexuGZra5+wE0N4McLKUJ18sVI+8zWIiBtT2XIWM0CBvMRwZtu0Qjq\nAAuqdsBO/hjuPsYFZryRlndGA9WtbcA69/uzO6w7DitgAeFRdobR3LpesCO4\n12SJhK2j2FBDBsJiIKbpBy1jxtJQ+ePqtzOa9DFeuUU7UYrSYb6jpSSNhzrG\niBttYNLiJ8A6xVKKeArzIWyQiRlvFNuagAhMoAh0hNd99ZF1rSvSqeWJjPLM\nr1JDcuTRPnuWkpJkENQpFJkjGNEJeLdBfHnWguvzlJR0bmoYbgdQlx9pW31D\nThlSIN/Jso7BATiVhw1d3YO20+vql2TRy2LXyKxgkWUYL8viivT/gN14PtfR\n68aJZD+vykpVUuQs1LkRy69iHlCqBGHE5Kx7NcVyAavid4Xe9DT9YbPeWTpR\nZ6frKRYJa6Wjkp5TUK8ZUkdaSMJeV8uS33E/KpvNt7jjPs8eCqQduOGANPXD\npi+z\r\n=D/qj\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "87ba8cf17c65360a75eefeb3519e87973bf9791d",
+    "tarball": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.2.1.tgz",
+    "unpackedSize": 23279
+  },
+  "engines": {
+    "node": ">=6"
+  },
+  "gitHead": "0da7f4e7d838dfcf4f197350a3de960ee66b20fa",
+  "homepage": "https://github.com/prebuild/prebuild-install",
+  "keywords": [
+    "addon",
+    "binaries",
+    "bindings",
+    "c",
+    "c++",
+    "devops",
+    "module",
+    "napi",
+    "native",
+    "prebuilt"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    },
+    {
+      "name": "mathiask",
+      "email": "mathiask@hotmail.de"
+    },
+    {
+      "name": "piranna",
+      "email": "piranna@gmail.com"
+    },
+    {
+      "name": "ralphtheninja",
+      "email": "ralphtheninja@riseup.net"
+    },
+    {
+      "name": "vweevers",
+      "email": "dev@vincentweevers.nl"
+    }
+  ],
+  "name": "prebuild-install",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/prebuild/prebuild-install.git"
+  },
+  "scripts": {
+    "audit": "nsp check",
+    "lint": "standard",
+    "test": "verify-travis-appveyor && tape test/*-test.js && npm run audit && npm run lint"
+  },
+  "version": "5.2.1"
+}
diff --git a/input_devices/mag/node_modules/prebuild-install/proxy.js b/input_devices/mag/node_modules/prebuild-install/proxy.js
new file mode 100644
index 00000000..c30f1e17
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/proxy.js
@@ -0,0 +1,36 @@
+var url = require('url')
+var tunnel = require('tunnel-agent')
+var noop = Object.assign({
+  http: function () {},
+  silly: function () {}
+}, require('noop-logger'))
+
+function applyProxy (reqOpts, opts) {
+  var log = opts.log || noop
+
+  var proxy = opts['https-proxy'] || opts.proxy
+
+  if (proxy) {
+    var parsedDownloadUrl = url.parse(reqOpts.url)
+    var parsedProxy = url.parse(proxy)
+    var uriProtocol = (parsedDownloadUrl.protocol === 'https:' ? 'https' : 'http')
+    var proxyProtocol = (parsedProxy.protocol === 'https:' ? 'Https' : 'Http')
+    var tunnelFnName = [uriProtocol, proxyProtocol].join('Over')
+    reqOpts.agent = tunnel[tunnelFnName]({
+      proxy: {
+        host: parsedProxy.hostname,
+        port: +parsedProxy.port,
+        proxyAuth: parsedProxy.auth
+      }
+    })
+    log.http('request', 'Proxy setup detected (Host: ' +
+    parsedProxy.hostname + ', Port: ' +
+      parsedProxy.port + ', Authentication: ' +
+      (parsedProxy.auth ? 'Yes' : 'No') + ')' +
+      ' Tunneling with ' + tunnelFnName)
+  }
+
+  return reqOpts
+}
+
+module.exports = applyProxy
diff --git a/input_devices/mag/node_modules/prebuild-install/rc.js b/input_devices/mag/node_modules/prebuild-install/rc.js
new file mode 100644
index 00000000..496ea09a
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/rc.js
@@ -0,0 +1,79 @@
+var minimist = require('minimist')
+var getAbi = require('node-abi').getAbi
+var detectLibc = require('detect-libc')
+var napi = require('napi-build-utils')
+
+var env = process.env
+
+var libc = env.LIBC || (detectLibc.isNonGlibcLinux && detectLibc.family) || ''
+
+// Get `prebuild-install` arguments that were passed to the `npm` command
+if (env.npm_config_argv) {
+  var npmargs = ['prebuild', 'compile', 'build-from-source', 'debug']
+  try {
+    var npmArgv = JSON.parse(env.npm_config_argv).cooked
+    for (var i = 0; i < npmargs.length; ++i) {
+      if (npmArgv.indexOf('--' + npmargs[i]) !== -1) {
+        process.argv.push('--' + npmargs[i])
+      }
+      if (npmArgv.indexOf('--no-' + npmargs[i]) !== -1) {
+        process.argv.push('--no-' + npmargs[i])
+      }
+    }
+    if ((i = npmArgv.indexOf('--download')) !== -1) {
+      process.argv.push(npmArgv[i], npmArgv[i + 1])
+    }
+  } catch (e) { }
+}
+
+// Get the configuration
+module.exports = function (pkg) {
+  var pkgConf = pkg.config || {}
+  var rc = require('rc')('prebuild-install', {
+    target: pkgConf.target || env.npm_config_target || process.versions.node,
+    runtime: pkgConf.runtime || env.npm_config_runtime || 'node',
+    arch: pkgConf.arch || env.npm_config_arch || process.arch,
+    libc: libc,
+    platform: env.npm_config_platform || process.platform,
+    debug: false,
+    force: false,
+    verbose: false,
+    prebuild: true,
+    compile: false,
+    path: '.',
+    proxy: env.npm_config_proxy || env['HTTP_PROXY'],
+    'https-proxy': env.npm_config_https_proxy || env['HTTPS_PROXY'],
+    'local-address': env.npm_config_local_address,
+    'tag-prefix': 'v'
+  }, minimist(process.argv, {
+    alias: {
+      target: 't',
+      runtime: 'r',
+      help: 'h',
+      arch: 'a',
+      path: 'p',
+      version: 'v',
+      download: 'd',
+      'build-from-source': 'compile',
+      compile: 'c',
+      token: 'T'
+    }
+  }))
+
+  if (rc.path === true) {
+    delete rc.path
+  }
+
+  if (napi.isNapiRuntime(rc.runtime) && rc.target === process.versions.node) {
+    rc.target = napi.getBestNapiBuildVersion()
+  }
+
+  rc.abi = napi.isNapiRuntime(rc.runtime) ? rc.target : getAbi(rc.target, rc.runtime)
+
+  return rc
+}
+
+// Print the configuration values when executed standalone for testing purposses
+if (!module.parent) {
+  console.log(JSON.stringify(module.exports({}), null, 2))
+}
diff --git a/input_devices/mag/node_modules/prebuild-install/util.js b/input_devices/mag/node_modules/prebuild-install/util.js
new file mode 100644
index 00000000..21fbb5bd
--- /dev/null
+++ b/input_devices/mag/node_modules/prebuild-install/util.js
@@ -0,0 +1,97 @@
+var path = require('path')
+var github = require('github-from-package')
+var home = require('os-homedir')
+var crypto = require('crypto')
+var expandTemplate = require('expand-template')()
+
+function getDownloadUrl (opts) {
+  var pkgName = opts.pkg.name.replace(/^@\w+\//, '')
+  return expandTemplate(urlTemplate(opts), {
+    name: pkgName,
+    package_name: pkgName,
+    version: opts.pkg.version,
+    major: opts.pkg.version.split('.')[0],
+    minor: opts.pkg.version.split('.')[1],
+    patch: opts.pkg.version.split('.')[2],
+    prerelease: opts.pkg.version.split('-')[1],
+    build: opts.pkg.version.split('+')[1],
+    abi: opts.abi || process.versions.modules,
+    node_abi: process.versions.modules,
+    runtime: opts.runtime || 'node',
+    platform: opts.platform,
+    arch: opts.arch,
+    libc: opts.libc || process.env.LIBC || '',
+    configuration: (opts.debug ? 'Debug' : 'Release'),
+    module_name: opts.pkg.binary && opts.pkg.binary.module_name,
+    tag_prefix: opts['tag-prefix'] || 'v'
+  })
+}
+
+function getApiUrl (opts) {
+  return github(opts.pkg).replace('github.com', 'api.github.com/repos') + '/releases'
+}
+
+function getAssetUrl (opts, assetId) {
+  return getApiUrl(opts) + '/assets/' + assetId
+}
+
+function urlTemplate (opts) {
+  if (typeof opts.download === 'string') {
+    return opts.download
+  }
+
+  var packageName = '{name}-v{version}-{runtime}-v{abi}-{platform}{libc}-{arch}.tar.gz'
+  var hostMirrorUrl = getHostMirrorUrl(opts)
+
+  if (hostMirrorUrl) {
+    return hostMirrorUrl + '/{tag_prefix}{version}/' + packageName
+  }
+
+  if (opts.pkg.binary && opts.pkg.binary.host) {
+    return [
+      opts.pkg.binary.host,
+      opts.pkg.binary.remote_path,
+      opts.pkg.binary.package_name || packageName
+    ].map(function (path) {
+      return trimSlashes(path)
+    }).filter(Boolean).join('/')
+  }
+
+  return github(opts.pkg) + '/releases/download/{tag_prefix}{version}/' + packageName
+}
+
+function getHostMirrorUrl (opts) {
+  var propName = 'npm_config_' + opts.pkg.name + '_binary_host'
+  return process.env[propName] || process.env[propName + '_mirror']
+}
+
+function trimSlashes (str) {
+  if (str) return str.replace(/^\.\/|^\/|\/$/g, '')
+}
+
+function cachedPrebuild (url) {
+  var digest = crypto.createHash('md5').update(url).digest('hex').slice(0, 6)
+  return path.join(prebuildCache(), digest + '-' + path.basename(url).replace(/[^a-zA-Z0-9.]+/g, '-'))
+}
+
+function npmCache () {
+  var env = process.env
+  return env.npm_config_cache || (env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(home(), '.npm'))
+}
+
+function prebuildCache () {
+  return path.join(npmCache(), '_prebuilds')
+}
+
+function tempFile (cached) {
+  return cached + '.' + process.pid + '-' + Math.random().toString(16).slice(2) + '.tmp'
+}
+
+exports.getDownloadUrl = getDownloadUrl
+exports.getApiUrl = getApiUrl
+exports.getAssetUrl = getAssetUrl
+exports.urlTemplate = urlTemplate
+exports.cachedPrebuild = cachedPrebuild
+exports.prebuildCache = prebuildCache
+exports.npmCache = npmCache
+exports.tempFile = tempFile
diff --git a/input_devices/mag/node_modules/process-nextick-args/index.js b/input_devices/mag/node_modules/process-nextick-args/index.js
new file mode 100644
index 00000000..5f585e8e
--- /dev/null
+++ b/input_devices/mag/node_modules/process-nextick-args/index.js
@@ -0,0 +1,44 @@
+'use strict';
+
+if (!process.version ||
+    process.version.indexOf('v0.') === 0 ||
+    process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
+  module.exports = { nextTick: nextTick };
+} else {
+  module.exports = process
+}
+
+function nextTick(fn, arg1, arg2, arg3) {
+  if (typeof fn !== 'function') {
+    throw new TypeError('"callback" argument must be a function');
+  }
+  var len = arguments.length;
+  var args, i;
+  switch (len) {
+  case 0:
+  case 1:
+    return process.nextTick(fn);
+  case 2:
+    return process.nextTick(function afterTickOne() {
+      fn.call(null, arg1);
+    });
+  case 3:
+    return process.nextTick(function afterTickTwo() {
+      fn.call(null, arg1, arg2);
+    });
+  case 4:
+    return process.nextTick(function afterTickThree() {
+      fn.call(null, arg1, arg2, arg3);
+    });
+  default:
+    args = new Array(len - 1);
+    i = 0;
+    while (i < args.length) {
+      args[i++] = arguments[i];
+    }
+    return process.nextTick(function afterTick() {
+      fn.apply(null, args);
+    });
+  }
+}
+
diff --git a/input_devices/mag/node_modules/process-nextick-args/license.md b/input_devices/mag/node_modules/process-nextick-args/license.md
new file mode 100644
index 00000000..c67e3532
--- /dev/null
+++ b/input_devices/mag/node_modules/process-nextick-args/license.md
@@ -0,0 +1,19 @@
+# Copyright (c) 2015 Calvin Metcalf
+
+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/input_devices/mag/node_modules/process-nextick-args/package.json b/input_devices/mag/node_modules/process-nextick-args/package.json
new file mode 100644
index 00000000..29050de9
--- /dev/null
+++ b/input_devices/mag/node_modules/process-nextick-args/package.json
@@ -0,0 +1,79 @@
+{
+  "_args": [
+    [
+      "process-nextick-args@~2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream"
+    ]
+  ],
+  "_from": "process-nextick-args@>=2.0.0 <2.1.0",
+  "_id": "process-nextick-args@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/process-nextick-args",
+  "_nodeVersion": "8.6.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/process-nextick-args-2.0.0.tgz_1513027423688_0.4807069287635386"
+  },
+  "_npmUser": {
+    "email": "calvin.metcalf@gmail.com",
+    "name": "cwmma"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "process-nextick-args",
+    "raw": "process-nextick-args@~2.0.0",
+    "rawSpec": "~2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <2.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readable-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+  "_shasum": "a37d732f4271b4ab1ad070d35508e8290788ffaa",
+  "_shrinkwrap": null,
+  "_spec": "process-nextick-args@~2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream",
+  "author": "",
+  "bugs": {
+    "url": "https://github.com/calvinmetcalf/process-nextick-args/issues"
+  },
+  "dependencies": {},
+  "description": "process.nextTick but always with args",
+  "devDependencies": {
+    "tap": "~0.2.6"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+    "shasum": "a37d732f4271b4ab1ad070d35508e8290788ffaa",
+    "tarball": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "8407900951af3e7651fca50f127f0e4ddc01ad55",
+  "homepage": "https://github.com/calvinmetcalf/process-nextick-args",
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "cwmma",
+      "email": "calvin.metcalf@gmail.com"
+    }
+  ],
+  "name": "process-nextick-args",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/calvinmetcalf/process-nextick-args.git"
+  },
+  "scripts": {
+    "test": "node test.js"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/process-nextick-args/readme.md b/input_devices/mag/node_modules/process-nextick-args/readme.md
new file mode 100644
index 00000000..ecb432c9
--- /dev/null
+++ b/input_devices/mag/node_modules/process-nextick-args/readme.md
@@ -0,0 +1,18 @@
+process-nextick-args
+=====
+
+[![Build Status](https://travis-ci.org/calvinmetcalf/process-nextick-args.svg?branch=master)](https://travis-ci.org/calvinmetcalf/process-nextick-args)
+
+```bash
+npm install --save process-nextick-args
+```
+
+Always be able to pass arguments to process.nextTick, no matter the platform
+
+```js
+var pna = require('process-nextick-args');
+
+pna.nextTick(function (a, b, c) {
+  console.log(a, b, c);
+}, 'step', 3,  'profit');
+```
diff --git a/input_devices/mag/node_modules/promirepl/.npmignore b/input_devices/mag/node_modules/promirepl/.npmignore
new file mode 100644
index 00000000..71883d86
--- /dev/null
+++ b/input_devices/mag/node_modules/promirepl/.npmignore
@@ -0,0 +1,3 @@
+.idea/
+node_modules/
+npm-debug.log
diff --git a/input_devices/mag/node_modules/promirepl/LICENSE b/input_devices/mag/node_modules/promirepl/LICENSE
new file mode 100644
index 00000000..0cfb56bf
--- /dev/null
+++ b/input_devices/mag/node_modules/promirepl/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 David M. Lee, II
+
+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/input_devices/mag/node_modules/promirepl/README.md b/input_devices/mag/node_modules/promirepl/README.md
new file mode 100644
index 00000000..257b74b6
--- /dev/null
+++ b/input_devices/mag/node_modules/promirepl/README.md
@@ -0,0 +1,78 @@
+# promirepl
+
+A promise infused REPL.
+
+Promirepl provides a Node.js REPL which will automagically unwrap [promise][]
+values. It also is Node module, with a function that can add these magical
+promise inspecting capabilities to your own custom REPLs.
+
+This allows you to use promise based APIs from the REPL just as easily as old
+fashioned synchronous APIs, without a lot of messing around with callbacks and
+`console.log` to get at asynchronous values from the REPL.
+
+## Usage
+
+Promirepl can be installed with `npm install -g promirepl`. This installs the
+`prominode` executable, which starts a Node.js REPL that has magical promise
+unwraping capabilities.
+
+Whenever a value evaluates to a promise (well, technically a [thenable][]),
+promirepl will wait for the promise to resolve. If the promise is fulfilled,
+it will evaluate to the promise's value. If the promise is rejected, it will
+work as a thrown error.
+
+If you want to stop waiting on a promise, just hit escape.
+
+If you would like to disable the promirepl magic, just use the `.promise`
+command to toggle promise unwrapping.
+
+    $ npm install -g promirepl
+    $ prominode
+    > var Promise = require('es6-promise').Promise
+
+Whenever a value evaluates to a promise (well, technically a [thenable][]),
+promirepl will wait for the promise to resolve. If the promise is fulfilled,
+it will evaluate to the promise's value.
+
+    > Promise.resolve('hello')
+    'hello'
+
+    > new Promise(function (resolve) {
+    ... setTimeout(function () { resolve('some time later'); }, 3000);
+    ... })
+    { promise: 'some time later' }
+
+If the promise is rejected, it will evaluate as a thrown error.
+
+    > Promise.reject(new Error('boom'))
+    Promise rejected: Error: boom
+        at repl:1:16
+        at REPLServer.defaultEval (repl.js:135:27)
+
+If you would like to stop waiting on a promise, hit escape.
+
+    > new Promise(function () {})
+    Hit escape to stop waiting on promise
+    break.
+
+If you would like to disable promise unwrapping, enter the `.promise` command.
+
+    > .promise
+    Promise auto-eval disabled
+
+    > Promise.resolve('hello')
+    {}
+
+    > Promise.reject(new Error('boom'))
+    {}
+
+## Programmatic Usage
+
+If you would like to use promirepl within your own custom REPL, just use the
+exported `promirepl` function.
+
+    var customRepl = createCustomRepl();
+    require('promirepl').promirepl(customRepl.start({}));
+
+ [promise]: https://promisesaplus.com/
+ [thenable]: https://promisesaplus.com/#point-7
diff --git a/input_devices/mag/node_modules/promirepl/bin/prominode.js b/input_devices/mag/node_modules/promirepl/bin/prominode.js
new file mode 100755
index 00000000..b84e837a
--- /dev/null
+++ b/input_devices/mag/node_modules/promirepl/bin/prominode.js
@@ -0,0 +1,8 @@
+#!/usr/bin/env node
+// Copyright 2014, David M. Lee, II
+'use strict';
+
+var repl = require("repl");
+var promirepl = require('../index').promirepl;
+
+promirepl(repl.start({}));
diff --git a/input_devices/mag/node_modules/promirepl/index.js b/input_devices/mag/node_modules/promirepl/index.js
new file mode 100644
index 00000000..4fb8ca15
--- /dev/null
+++ b/input_devices/mag/node_modules/promirepl/index.js
@@ -0,0 +1,73 @@
+// Copyright 2014, David M. Lee, II
+'use strict';
+
+/**
+ * Add promise support to a repl.
+ */
+module.exports.promirepl = function (repl) {
+  var realEval = repl.eval;
+  var promiseEval = function (cmd, context, filename, callback) {
+    realEval.call(repl, cmd, context, filename, function (err, res) {
+      // Error response
+      if (err) {
+        return callback(err);
+      }
+
+      // Non-thenable response
+      if (!res || typeof res.then != 'function') {
+        return callback(null, res);
+      }
+
+      // Thenable detected; extract value/error from it
+
+      // Start listening for escape characters, to quit waiting on the promise
+      var cancel = function (chunk, key) {
+        repl.outputStream.write('break.\n');
+        if (key.name === 'escape') {
+          process.stdin.removeListener('keypress', cancel);
+          callback(null, res);
+          // Ensure we don't call the callback again
+          callback = function () {};
+        }
+      };
+      process.stdin.on('keypress', cancel);
+
+      // Start a timer indicating that escape can be used to quit
+      var hangTimer = setTimeout(function () {
+        repl.outputStream.write('Hit escape to stop waiting on promise\n');
+      }, 5000);
+
+      res.then(function (val) {
+        process.stdin.removeListener('keypress', cancel);
+        clearTimeout(hangTimer);
+        callback(null, val)
+      }, function (err) {
+        process.stdin.removeListener('keypress', cancel);
+        clearTimeout(hangTimer);
+        repl.outputStream.write('Promise rejected: ');
+        callback(err);
+      }).then(null, function (uncaught) {
+        // Rethrow uncaught exceptions
+        process.nextTick(function () {
+          throw uncaught;
+        });
+      });
+    });
+  };
+
+  repl.eval = promiseEval;
+
+  repl.commands['.promise'] = {
+    help: 'Toggle auto-promise unwrapping',
+    action: function () {
+      if (repl.eval === promiseEval) {
+        this.outputStream.write('Promise auto-eval disabled\n');
+        repl.eval = realEval;
+      } else {
+        this.outputStream.write('Promise auto-eval enabled\n');
+        repl.eval = promiseEval;
+      }
+      this.displayPrompt();
+    }
+  }
+};
diff --git a/input_devices/mag/node_modules/promirepl/package.json b/input_devices/mag/node_modules/promirepl/package.json
new file mode 100644
index 00000000..4051fa85
--- /dev/null
+++ b/input_devices/mag/node_modules/promirepl/package.json
@@ -0,0 +1,77 @@
+{
+  "_args": [
+    [
+      "promirepl@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "promirepl@>=1.0.1 <2.0.0",
+  "_id": "promirepl@1.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/promirepl",
+  "_npmUser": {
+    "email": "leedm777@yahoo.com",
+    "name": "leedm777"
+  },
+  "_npmVersion": "2.0.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "promirepl",
+    "raw": "promirepl@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/promirepl/-/promirepl-1.0.1.tgz",
+  "_shasum": "2951aaeba2bf3fe2274ff63a16d94c04ca60872e",
+  "_shrinkwrap": null,
+  "_spec": "promirepl@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "author": {
+    "name": "David M. Lee, II"
+  },
+  "bin": {
+    "prominode": "./bin/prominode.js"
+  },
+  "bugs": {
+    "url": "https://github.com/building5/node-promirepl/issues"
+  },
+  "dependencies": {},
+  "description": "Promise infused REPL",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "shasum": "2951aaeba2bf3fe2274ff63a16d94c04ca60872e",
+    "tarball": "https://registry.npmjs.org/promirepl/-/promirepl-1.0.1.tgz"
+  },
+  "gitHead": "8d9e8e918cd2ee055ab20a354f2a36804a3ca52b",
+  "homepage": "https://github.com/building5/node-promirepl",
+  "keywords": [
+    "promises",
+    "repl"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "leedm777",
+      "email": "leedm777@yahoo.com"
+    }
+  ],
+  "name": "promirepl",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/building5/node-promirepl.git"
+  },
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "version": "1.0.1"
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/LICENSE b/input_devices/mag/node_modules/prompt-actions/LICENSE
new file mode 100644
index 00000000..9a1c8567
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/prompt-actions/README.md b/input_devices/mag/node_modules/prompt-actions/README.md
new file mode 100644
index 00000000..a3c5bbec
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/README.md
@@ -0,0 +1,78 @@
+# prompt-actions [![NPM version](https://img.shields.io/npm/v/prompt-actions.svg?style=flat)](https://www.npmjs.com/package/prompt-actions) [![NPM monthly downloads](https://img.shields.io/npm/dm/prompt-actions.svg?style=flat)](https://npmjs.org/package/prompt-actions) [![NPM total downloads](https://img.shields.io/npm/dt/prompt-actions.svg?style=flat)](https://npmjs.org/package/prompt-actions) [![Linux Build Status](https://img.shields.io/travis/enquirer/prompt-actions.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/prompt-actions)
+
+> Action manager for prompt-base.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-actions
+```
+
+<details>
+<summary><strong>What does this do?</strong></summary>
+
+Used by [prompt-base](https://github.com/enquirer/prompt-base) for toggling choices and updating the pointer position on prompts.
+
+This is a separate module so that it is easier to maintain and unit test, and so that it can also be used by custom prompts when needed.
+
+</details>
+
+## Usage
+
+Add this library to your custom [prompt][base-prompt] with the following line of code:
+
+```js
+var Actions = require('prompt-actions');
+```
+
+## About
+
+### Related projects
+
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. | [homepage](http://enquirer.io "Intuitive, plugin-based prompt system for node.js.")
+* [prompt-base](https://www.npmjs.com/package/prompt-base): Base prompt module used for creating custom prompts. | [homepage](https://github.com/enquirer/prompt-base "Base prompt module used for creating custom prompts.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+* [prompt-grid](https://www.npmjs.com/package/prompt-grid): Prompt that allows the user to re-arrange the cells in a grid in the terminal. | [homepage](https://github.com/enquirer/prompt-grid "Prompt that allows the user to re-arrange the cells in a grid in the terminal.")
+* [prompt-sort](https://www.npmjs.com/package/prompt-sort): Prompt that allows the user to re-order items in a list of choices. | [homepage](https://github.com/enquirer/prompt-sort "Prompt that allows the user to re-order items in a list of choices.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on June 02, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-actions/index.js b/input_devices/mag/node_modules/prompt-actions/index.js
new file mode 100644
index 00000000..1b921697
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/index.js
@@ -0,0 +1,267 @@
+'use strict';
+
+var debug = require('debug')('prompt-actions');
+
+/**
+ * Create an instance of `Actions` with an instance of [prompt-base][].
+ * Any of the methods may be overridden in custom prompts.
+ *
+ * ```js
+ * var Actions = require('prompt-actions');
+ * var Base = require('prompt-base');
+ * var prompt = new Prompt('Favorite flavor?' ['chocolate', 'vanilla']);
+ * var actions = new Actions(prompt);
+ * ```
+ * @param {Object} `prompt` Instance of [prompt-base][].
+ * @api public
+ */
+
+function Actions(prompt) {
+  debug('initializing from <%s>', __filename);
+  this.prompt = prompt;
+  this.options = this.prompt.options;
+}
+
+/**
+ * Handle <kbd>number</kbd> keypress events. Toggles the choice at
+ * corresponding row, starting at `1`. Because of this (1-based index)
+ * we need to decrement the returned position by `1`, so that
+ * the "real" position is correct.
+ *
+ * @return {Number} Returns `choices.position`
+ * @api public
+ */
+
+Actions.prototype.number = function(pos, key) {
+  pos = this.position(pos, key);
+  if (pos >= 0 && pos <= this.choices.length) {
+    this.choices.position = pos - 1;
+    this.choices.radio();
+  }
+  return pos - 1;
+};
+
+/**
+ * Handle <kbd>space</kbd> keypress events. Toggles the choice at the
+ * current position (e.g. on the same row as the pointer).
+ *
+ * @return {Number} Returns `choices.position`
+ * @api public
+ */
+
+Actions.prototype.space = function(pos) {
+  pos = this.position(pos);
+  this.choices.radio();
+  return pos;
+};
+
+/**
+ * Handle <kbd>tab</kbd> keypress events. By default, this is
+ * just an identity function that returns the cursor position
+ * on `tab` keypress events. This may be overridden in custom
+ * prompts.
+ *
+ * ```js
+ * var Prompt = require('prompt-base');
+ * function MyPrompt() {
+ *   Prompt.apply(this, arguments);
+ *   this.action('tab', function() {
+ *     // do custom tab stuff
+ *   });
+ * }
+ * // inherit prompt-base
+ * Prompt.extend(MyPrompt);
+ * ```
+ *
+ * @return {Number} Returns `choices.position`
+ * @api public
+ */
+
+Actions.prototype.tab = function(pos) {
+  return this.position(pos);
+};
+
+/**
+ * Handle <kbd>a</kbd> keypress events. If all choices are already checked,
+ * this will disable all choices. If zero to any other number of
+ * choices is checked, this will enable all choices.
+ *
+ * @return {Number} Returns `choices.position`
+ * @api public
+ */
+
+Actions.prototype.a = function(pos) {
+  this.choices[this.choices.all ? 'uncheck' : 'check']();
+  this.choices.update();
+  return this.position(pos);
+};
+
+/**
+ * Handle <kbd>i</kbd> keypress events. The <kbd>i</kbd>
+ * keypress toggles all choices. If the pointer is inside a
+ * choice group, only choices in that group will be toggled.
+ *
+ * @return {Number} Returns `choices.position`
+ * @api public
+ */
+
+Actions.prototype.i = function(pos) {
+  this.choices.toggle();
+  this.choices.update();
+  return this.position(pos);
+};
+
+/**
+ * Handle <kdb>down</kdb> keypress events. <kdb>down</kdb> moves the
+ * cursor down one row, and <kdb>shift</kdb>+<kdb>down</kdb> will
+ * increase the number of rows visible in the terminal by one row.
+ *
+ * @return {Number} Returns the updated `choices.position`.
+ * @api public
+ */
+
+Actions.prototype.down = function(pos, key) {
+  pos = this.position(pos);
+  if (key && key.shift === true) {
+    if (this.options.expandChoices !== false) {
+      return this.addRow();
+    }
+    this.moveDown(pos);
+  }
+  return (pos < this.choices.length - 1) ? pos + 1 : 0;
+};
+
+/**
+ * Handle <kdb>up</kdb> keypress events. <kdb>up</kdb> moves the
+ * cursor up one row, and <kdb>shift</kdb>+<kdb>up</kdb> will
+ * reduce the number of rows visible in the terminal by one row.
+ *
+ * @return {Number} Returns the updated `choices.position`.
+ * @api public
+ */
+
+Actions.prototype.up = function(pos, key) {
+  pos = this.position(pos);
+  if (key && key.shift === true) {
+    if (this.options.expandChoices !== false) {
+      return this.removeRow();
+    }
+    this.moveUp(pos);
+  }
+  return (pos > 0) ? pos - 1 : this.choices.length - 1;
+};
+
+/**
+ * Move the currently selected item up.
+ */
+
+Actions.prototype.moveUp = function(pos) {
+  var len = this.choices.length;
+  pos = this.position(pos);
+  if (pos > 0) {
+    this.choices.swap(pos - 1, pos);
+  } else {
+    this.choices.swap(pos, len - 1);
+  }
+  return pos;
+};
+
+/**
+ * Move the currently selected item down.
+ */
+
+Actions.prototype.moveDown = function(pos) {
+  var len = this.choices.length;
+  pos = this.position(pos);
+  if (pos < len - 1) {
+    this.choices.swap(pos + 1, pos);
+  } else {
+    this.choices.swap(pos, 0);
+  }
+  return pos;
+};
+
+/**
+ * Move the currently selected item up.
+ */
+
+Actions.prototype.addRow = function() {
+  if (this.choices.options.limit < this.choices.length) {
+    this.choices.options.limit++;
+  }
+};
+
+/**
+ * Move the currently selected item up.
+ */
+
+Actions.prototype.removeRow = function() {
+  if (this.choices.options.limit > 0) {
+    this.choices.options.limit--;
+  }
+};
+
+/**
+ * Handle <kbd>enter</kbd> keypress events. By default this is a
+ * noop since <kbd>enter</kbd> keypress events are typically ignored
+ * to allow the `line` event to be handled when an answer is submitted.
+ *
+ * @return {Number} Returns `choices.position`
+ * @api public
+ */
+
+Actions.prototype.enter = function(pos, key) {
+  return this.position(pos);
+};
+
+/**
+ * Returns the current choices position
+ *
+ * @return {Number} Returns `choices.position`
+ * @api public
+ */
+
+Actions.prototype.identity = function(pos) {
+  return this.position(pos);
+};
+
+/**
+ * Helper for getting the current corsor position.
+ *
+ * @param {Number} `pos` (optional) Current position
+ * @return {Number} Returns given `pos` or `choices.position`
+ * @api public
+ */
+
+Actions.prototype.position = function(pos, key) {
+  if (key && key.name === 'number' && key.hasOwnProperty('value')) {
+    pos = Number(key.value);
+  }
+  if (typeof pos === 'number') {
+    if (pos >= 0 && pos <= this.choices.length) {
+      this.choices.position = pos;
+    }
+    return pos;
+  }
+  return this.choices.position;
+};
+
+/**
+ * Getter for getting the choices array from the question.
+ *
+ * @name .choices
+ * @return {Object} Choices object
+ * @api public
+ */
+
+Object.defineProperty(Actions.prototype, 'choices', {
+  get: function() {
+    return this.prompt.choices;
+  }
+});
+
+/**
+ * Expose `Actions`
+ */
+
+module.exports = Actions;
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.coveralls.yml b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.eslintrc b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+  "rules": {
+    "no-console": 0,
+    "no-empty": [1, { "allowEmptyCatch": true }]
+  },
+  "extends": "eslint:recommended"
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.npmignore b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.travis.yml b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+  - "6"
+  - "5"
+  - "4"
+
+install:
+  - make node_modules
+
+script:
+  - make lint
+  - make test
+  - make coveralls
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/CHANGELOG.md b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+  * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+  * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+  * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+  * Fix: Inline extend function in node implementation (#452, @dougwilson)
+  * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+  
+  * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+  * Misc: clean up browser reference checks (#447, @thebigredgeek)
+  * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+  * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+  * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+  * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+  * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+  * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+  * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+  * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+  * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+  * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+  * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+  * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+  * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+  * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+  * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+  * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+  * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+  * Docs: fixed README typo (#391, @lurch)
+  * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+  * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+  * Fix: wrong reference in bower file (@thebigredgeek)
+  * Fix: webworker compatibility (@thebigredgeek)
+  * Fix: output formatting issue (#388, @kribblo)
+  * Fix: babel-loader compatibility (#383, @escwald)
+  * Misc: removed built asset from repo and publications (@thebigredgeek)
+  * Misc: moved source files to /src (#378, @yamikuronue)
+  * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+  * Test: coveralls integration (#378, @yamikuronue)
+  * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+  * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+  * Fix: custom log function (#379, @hsiliev)
+  * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+  * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+  * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+  * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+  * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+  * Fix: browser colors (#367, @tootallnate)
+  * Misc: travis ci integration (@thebigredgeek)
+  * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+  * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+  * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+  * Fix: revert "handle regex special characters" (@tootallnate)
+  * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+  * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+  * Improvement: allow colors in workers (#335, @botverse)
+  * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+  * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+  * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+  * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+  * Fix: be super-safe in index.js as well (@TooTallNate)
+  * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+  * Fix: Added electron compatibility (#324, @paulcbetts)
+  * Improvement: Added performance optimizations (@tootallnate)
+  * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+  * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+  * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+  * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+  * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+  * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+  * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+  * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+  * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+  * Readme: fix USE_COLORS to DEBUG_COLORS
+  * Readme: Doc fixes for format string sugar (#269, @mlucool)
+  * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+  * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+  * Readme: better docs for browser support (#224, @matthewmueller)
+  * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+  * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+  * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+  * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+  * package: update "ms" to v0.7.1 (#202, @dougwilson)
+  * README: add logging to file example (#193, @DanielOchoa)
+  * README: fixed a typo (#191, @amir-s)
+  * browser: expose `storage` (#190, @stephenmathieson)
+  * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+  * Updated stdout/stderr example (#186)
+  * Updated example/stdout.js to match debug current behaviour
+  * Renamed example/stderr.js to stdout.js
+  * Update Readme.md (#184)
+  * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+  * dist: recompile
+  * update "ms" to v0.7.0
+  * package: update "browserify" to v9.0.3
+  * component: fix "ms.js" repo location
+  * changed bower package name
+  * updated documentation about using debug in a browser
+  * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+  * browser: use `typeof` to check for `console` existence
+  * browser: check for `console.log` truthiness (fix IE 8/9)
+  * browser: add support for Chrome apps
+  * Readme: added Windows usage remarks
+  * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+  * node: implement `DEBUG_FD` env variable support
+  * package: update "browserify" to v6.1.0
+  * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+  * package: update "browserify" to v5.11.0
+  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+  * dist: recompile
+  * example: remove `console.info()` log usage
+  * example: add "Content-Type" UTF-8 header to browser example
+  * browser: place %c marker after the space character
+  * browser: reset the "content" color via `color: inherit`
+  * browser: add colors support for Firefox >= v31
+  * debug: prefer an instance `log()` function over the global one (#119)
+  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+  * Add support for multiple wildcards in namespaces (#122, @seegno)
+  * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+  * browser: update color palette (#113, @gscottolson)
+  * common: make console logging function configurable (#108, @timoxley)
+  * node: fix %o colors on old node <= 0.8.x
+  * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+  * browser: use `removeItem()` to clear localStorage
+  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+  * package: add "contributors" section
+  * node: fix comment typo
+  * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+  * make ms diff be global, not be scope
+  * debug: ignore empty strings in enable()
+  * node: make DEBUG_COLORS able to disable coloring
+  * *: export the `colors` array
+  * npmignore: don't publish the `dist` dir
+  * Makefile: refactor to use browserify
+  * package: add "browserify" as a dev dependency
+  * Readme: add Web Inspector Colors section
+  * node: reset terminal color for the debug content
+  * node: map "%o" to `util.inspect()`
+  * browser: map "%j" to `JSON.stringify()`
+  * debug: add custom "formatters"
+  * debug: use "ms" module for humanizing the diff
+  * Readme: add "bash" syntax highlighting
+  * browser: add Firebug color support
+  * browser: add colors for WebKit browsers
+  * node: apply log to `console`
+  * rewrite: abstract common logic for Node & browsers
+  * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+  * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+  * add `enable()` method for nodejs. Closes #27
+  * change from stderr to stdout
+  * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+  * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+  * fix: catch localStorage security error when cookies are blocked (Chrome)
+  * add debug(err) support. Closes #46
+  * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/LICENSE b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/prompt-actions/node_modules/debug/Makefile b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+	@NODE_ENV= $(PKG) install
+	@touch node_modules
+
+lint: .FORCE
+	eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+	istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+	mkdir -p dist
+
+	@$(BROWSERIFY) \
+		--standalone debug \
+		. > dist/debug.js
+
+	karma start --single-run
+	rimraf dist
+
+test: .FORCE
+	concurrently \
+		"make test-node" \
+		"make test-browser"
+
+coveralls:
+	cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/README.md b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) 
+[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+  ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+
+## Conventions
+
+  If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+  When running through Node.js, you can set a few environment variables that will
+  change the behavior of the debug logging:
+
+| Name      | Purpose                                         |
+|-----------|-------------------------------------------------|
+| `DEBUG`   | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+  __Note:__ The environment variables beginning with `DEBUG_` end up being
+  converted into an Options object that gets used with `%o`/`%O` formatters.
+  See the Node.js documentation for
+  [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+  for the complete list.
+
+## Formatters
+
+
+  Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O`      | Pretty-print an Object on multiple lines. |
+| `%o`      | Pretty-print an Object all on a single line. |
+| `%s`      | String. |
+| `%d`      | Number (both integer and float). |
+| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%`      | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+  You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+  return v.toString('hex')
+}
+
+// …elsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+//   foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+  You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+  or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+  if you don't want to build it yourself.
+
+  Debug's enable state is currently persisted by `localStorage`.
+  Consider the situation shown below where you have `worker:a` and `worker:b`,
+  and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+  Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+  option. These are WebKit web inspectors, Firefox ([since version
+  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+  and the Firebug plugin for Firefox (any version).
+
+  Colored output looks something like:
+
+  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
+
+
+## Output streams
+
+  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+ 
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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/input_devices/mag/node_modules/prompt-actions/node_modules/debug/component.json b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+  "name": "debug",
+  "repo": "visionmedia/debug",
+  "description": "small debugging utility",
+  "version": "2.6.9",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "main": "src/browser.js",
+  "scripts": [
+    "src/browser.js",
+    "src/debug.js"
+  ],
+  "dependencies": {
+    "rauchg/ms.js": "0.7.1"
+  }
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/karma.conf.js b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['mocha', 'chai', 'sinon'],
+
+
+    // list of files / patterns to load in the browser
+    files: [
+      'dist/debug.js',
+      'test/*spec.js'
+    ],
+
+
+    // list of files to exclude
+    exclude: [
+      'src/node.js'
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['progress'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false,
+
+    // Concurrency level
+    // how many browser should be started simultaneous
+    concurrency: Infinity
+  })
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/node.js b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/package.json b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/package.json
new file mode 100644
index 00000000..2e099252
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/package.json
@@ -0,0 +1,128 @@
+{
+  "_args": [
+    [
+      "debug@^2.6.8",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-actions"
+    ]
+  ],
+  "_from": "debug@>=2.6.8 <3.0.0",
+  "_id": "debug@2.6.9",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-actions/debug",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196"
+  },
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "debug",
+    "raw": "debug@^2.6.8",
+    "rawSpec": "^2.6.8",
+    "scope": null,
+    "spec": ">=2.6.8 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-actions"
+  ],
+  "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+  "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+  "_shrinkwrap": null,
+  "_spec": "debug@^2.6.8",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-actions",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "browser": "./src/browser.js",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "component": {
+    "scripts": {
+      "debug/debug.js": "debug.js",
+      "debug/index.js": "browser.js"
+    }
+  },
+  "contributors": [
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "http://n8.io"
+    },
+    {
+      "name": "Andrew Rhyne",
+      "email": "rhyneandrew@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "ms": "2.0.0"
+  },
+  "description": "small debugging utility",
+  "devDependencies": {
+    "browserify": "9.0.3",
+    "chai": "^3.5.0",
+    "concurrently": "^3.1.0",
+    "coveralls": "^2.11.15",
+    "eslint": "^3.12.1",
+    "istanbul": "^0.4.5",
+    "karma": "^1.3.0",
+    "karma-chai": "^0.1.0",
+    "karma-mocha": "^1.3.0",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "karma-sinon": "^1.0.5",
+    "mocha": "^3.2.0",
+    "mocha-lcov-reporter": "^1.2.0",
+    "rimraf": "^2.5.4",
+    "sinon": "^1.17.6",
+    "sinon-chai": "^2.8.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+    "shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+    "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
+  },
+  "gitHead": "13abeae468fea297d0dccc50bc55590809241083",
+  "homepage": "https://github.com/visionmedia/debug#readme",
+  "keywords": [
+    "debug",
+    "debugger",
+    "log"
+  ],
+  "license": "MIT",
+  "main": "./src/index.js",
+  "maintainers": [
+    {
+      "name": "thebigredgeek",
+      "email": "rhyneandrew@gmail.com"
+    },
+    {
+      "name": "kolban",
+      "email": "kolban1@kolban.com"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    }
+  ],
+  "name": "debug",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "version": "2.6.9"
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/browser.js b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+               && 'undefined' != typeof chrome.storage
+                  ? chrome.storage.local
+                  : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+  'lightseagreen',
+  'forestgreen',
+  'goldenrod',
+  'dodgerblue',
+  'darkorchid',
+  'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+  // NB: In an Electron preload script, document will be defined but not fully
+  // initialized. Since we know we're in Chrome, we'll just detect this case
+  // explicitly
+  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+    return true;
+  }
+
+  // is webkit? http://stackoverflow.com/a/16459606/376773
+  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+    // is firebug? http://stackoverflow.com/a/398120/376773
+    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+    // is firefox >= v31?
+    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+    // double check webkit in userAgent just in case we are in a worker
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+  try {
+    return JSON.stringify(v);
+  } catch (err) {
+    return '[UnexpectedJSONParseError]: ' + err.message;
+  }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var useColors = this.useColors;
+
+  args[0] = (useColors ? '%c' : '')
+    + this.namespace
+    + (useColors ? ' %c' : ' ')
+    + args[0]
+    + (useColors ? '%c ' : ' ')
+    + '+' + exports.humanize(this.diff);
+
+  if (!useColors) return;
+
+  var c = 'color: ' + this.color;
+  args.splice(1, 0, c, 'color: inherit')
+
+  // the final "%c" is somewhat tricky, because there could be other
+  // arguments passed either before or after the %c, so we need to
+  // figure out the correct index to insert the CSS into
+  var index = 0;
+  var lastC = 0;
+  args[0].replace(/%[a-zA-Z%]/g, function(match) {
+    if ('%%' === match) return;
+    index++;
+    if ('%c' === match) {
+      // we only are interested in the *last* %c
+      // (the user may have provided their own)
+      lastC = index;
+    }
+  });
+
+  args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+  // this hackery is required for IE8/9, where
+  // the `console.log` function doesn't have 'apply'
+  return 'object' === typeof console
+    && console.log
+    && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  try {
+    if (null == namespaces) {
+      exports.storage.removeItem('debug');
+    } else {
+      exports.storage.debug = namespaces;
+    }
+  } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  var r;
+  try {
+    r = exports.storage.debug;
+  } catch(e) {}
+
+  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+  if (!r && typeof process !== 'undefined' && 'env' in process) {
+    r = process.env.DEBUG;
+  }
+
+  return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+  try {
+    return window.localStorage;
+  } catch (e) {}
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/debug.js b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+  var hash = 0, i;
+
+  for (i in namespace) {
+    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
+    hash |= 0; // Convert to 32bit integer
+  }
+
+  return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+  function debug() {
+    // disabled?
+    if (!debug.enabled) return;
+
+    var self = debug;
+
+    // set `diff` timestamp
+    var curr = +new Date();
+    var ms = curr - (prevTime || curr);
+    self.diff = ms;
+    self.prev = prevTime;
+    self.curr = curr;
+    prevTime = curr;
+
+    // turn the `arguments` into a proper Array
+    var args = new Array(arguments.length);
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i];
+    }
+
+    args[0] = exports.coerce(args[0]);
+
+    if ('string' !== typeof args[0]) {
+      // anything else let's inspect with %O
+      args.unshift('%O');
+    }
+
+    // apply any `formatters` transformations
+    var index = 0;
+    args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+      // if we encounter an escaped % then don't increase the array index
+      if (match === '%%') return match;
+      index++;
+      var formatter = exports.formatters[format];
+      if ('function' === typeof formatter) {
+        var val = args[index];
+        match = formatter.call(self, val);
+
+        // now we need to remove `args[index]` since it's inlined in the `format`
+        args.splice(index, 1);
+        index--;
+      }
+      return match;
+    });
+
+    // apply env-specific formatting (colors, etc.)
+    exports.formatArgs.call(self, args);
+
+    var logFn = debug.log || exports.log || console.log.bind(console);
+    logFn.apply(self, args);
+  }
+
+  debug.namespace = namespace;
+  debug.enabled = exports.enabled(namespace);
+  debug.useColors = exports.useColors();
+  debug.color = selectColor(namespace);
+
+  // env-specific initialization logic for debug instances
+  if ('function' === typeof exports.init) {
+    exports.init(debug);
+  }
+
+  return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+  exports.save(namespaces);
+
+  exports.names = [];
+  exports.skips = [];
+
+  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+  var len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    if (!split[i]) continue; // ignore empty strings
+    namespaces = split[i].replace(/\*/g, '.*?');
+    if (namespaces[0] === '-') {
+      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+    } else {
+      exports.names.push(new RegExp('^' + namespaces + '$'));
+    }
+  }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+  exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+  var i, len;
+  for (i = 0, len = exports.skips.length; i < len; i++) {
+    if (exports.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (i = 0, len = exports.names.length; i < len; i++) {
+    if (exports.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/index.js b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+  module.exports = require('./browser.js');
+} else {
+  module.exports = require('./node.js');
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/inspector-log.js b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+  const stdout = console._stdout;
+  console._stdout = nullStream;
+  console.log.apply(console, arguments);
+  console._stdout = stdout;
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/node.js b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+  return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+  // camel-case
+  var prop = key
+    .substring(6)
+    .toLowerCase()
+    .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+  // coerce string value into JS value
+  var val = process.env[key];
+  if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+  else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+  else if (val === 'null') val = null;
+  else val = Number(val);
+
+  obj[prop] = val;
+  return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ *   $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+  util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+             2 === fd ? process.stderr :
+             createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+  return 'colors' in exports.inspectOpts
+    ? Boolean(exports.inspectOpts.colors)
+    : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts)
+    .split('\n').map(function(str) {
+      return str.trim()
+    }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var name = this.namespace;
+  var useColors = this.useColors;
+
+  if (useColors) {
+    var c = this.color;
+    var prefix = '  \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+    args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+    args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+  } else {
+    args[0] = new Date().toUTCString()
+      + ' ' + name + ' ' + args[0];
+  }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+  return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  if (null == namespaces) {
+    // If you set a process.env field to null or undefined, it gets cast to the
+    // string 'null' or 'undefined'. Just delete instead.
+    delete process.env.DEBUG;
+  } else {
+    process.env.DEBUG = namespaces;
+  }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+  var stream;
+  var tty_wrap = process.binding('tty_wrap');
+
+  // Note stream._type is used for test-module-load-list.js
+
+  switch (tty_wrap.guessHandleType(fd)) {
+    case 'TTY':
+      stream = new tty.WriteStream(fd);
+      stream._type = 'tty';
+
+      // Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    case 'FILE':
+      var fs = require('fs');
+      stream = new fs.SyncWriteStream(fd, { autoClose: false });
+      stream._type = 'fs';
+      break;
+
+    case 'PIPE':
+    case 'TCP':
+      var net = require('net');
+      stream = new net.Socket({
+        fd: fd,
+        readable: false,
+        writable: true
+      });
+
+      // FIXME Should probably have an option in net.Socket to create a
+      // stream from an existing fd which is writable only. But for now
+      // we'll just add this hack and set the `readable` member to false.
+      // Test: ./node test/fixtures/echo.js < /etc/passwd
+      stream.readable = false;
+      stream.read = null;
+      stream._type = 'pipe';
+
+      // FIXME Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    default:
+      // Probably an error on in uv_guess_handle()
+      throw new Error('Implement me. Unknown stream file type!');
+  }
+
+  // For supporting legacy API we put the FD here.
+  stream.fd = fd;
+
+  stream._isStdio = true;
+
+  return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+  debug.inspectOpts = {};
+
+  var keys = Object.keys(exports.inspectOpts);
+  for (var i = 0; i < keys.length; i++) {
+    debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+  }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/ms/index.js b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+  options = options || {};
+  var type = typeof val;
+  if (type === 'string' && val.length > 0) {
+    return parse(val);
+  } else if (type === 'number' && isNaN(val) === false) {
+    return options.long ? fmtLong(val) : fmtShort(val);
+  }
+  throw new Error(
+    'val is not a non-empty string or a valid number. val=' +
+      JSON.stringify(val)
+  );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  str = String(str);
+  if (str.length > 100) {
+    return;
+  }
+  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+    str
+  );
+  if (!match) {
+    return;
+  }
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'yrs':
+    case 'yr':
+    case 'y':
+      return n * y;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'hrs':
+    case 'hr':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'mins':
+    case 'min':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 'secs':
+    case 'sec':
+    case 's':
+      return n * s;
+    case 'milliseconds':
+    case 'millisecond':
+    case 'msecs':
+    case 'msec':
+    case 'ms':
+      return n;
+    default:
+      return undefined;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+  if (ms >= d) {
+    return Math.round(ms / d) + 'd';
+  }
+  if (ms >= h) {
+    return Math.round(ms / h) + 'h';
+  }
+  if (ms >= m) {
+    return Math.round(ms / m) + 'm';
+  }
+  if (ms >= s) {
+    return Math.round(ms / s) + 's';
+  }
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+  return plural(ms, d, 'day') ||
+    plural(ms, h, 'hour') ||
+    plural(ms, m, 'minute') ||
+    plural(ms, s, 'second') ||
+    ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+  if (ms < n) {
+    return;
+  }
+  if (ms < n * 1.5) {
+    return Math.floor(ms / n) + ' ' + name;
+  }
+  return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/ms/license.md b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/input_devices/mag/node_modules/prompt-actions/node_modules/ms/package.json b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/package.json
new file mode 100644
index 00000000..0633217d
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "ms@2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-actions/node_modules/debug"
+    ]
+  ],
+  "_from": "ms@2.0.0",
+  "_id": "ms@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-actions/ms",
+  "_nodeVersion": "7.8.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945"
+  },
+  "_npmUser": {
+    "email": "leo@zeit.co",
+    "name": "leo"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ms",
+    "raw": "ms@2.0.0",
+    "rawSpec": "2.0.0",
+    "scope": null,
+    "spec": "2.0.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/prompt-actions/debug"
+  ],
+  "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+  "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+  "_shrinkwrap": null,
+  "_spec": "ms@2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-actions/node_modules/debug",
+  "bugs": {
+    "url": "https://github.com/zeit/ms/issues"
+  },
+  "dependencies": {},
+  "description": "Tiny milisecond conversion utility",
+  "devDependencies": {
+    "eslint": "3.19.0",
+    "expect.js": "0.3.1",
+    "husky": "0.13.3",
+    "lint-staged": "3.4.1",
+    "mocha": "3.4.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+    "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
+  },
+  "eslintConfig": {
+    "env": {
+      "es6": true,
+      "node": true
+    },
+    "extends": "eslint:recommended"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4",
+  "homepage": "https://github.com/zeit/ms#readme",
+  "license": "MIT",
+  "lint-staged": {
+    "*.js": [
+      "git add",
+      "npm run lint",
+      "prettier --single-quote --write"
+    ]
+  },
+  "main": "./index",
+  "maintainers": [
+    {
+      "name": "leo",
+      "email": "leo@zeit.co"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "name": "ms",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zeit/ms.git"
+  },
+  "scripts": {
+    "lint": "eslint lib/* bin/*",
+    "precommit": "lint-staged",
+    "test": "mocha tests.js"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-actions/node_modules/ms/readme.md b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days')  // 172800000
+ms('1d')      // 86400000
+ms('10h')     // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h')      // 7200000
+ms('1m')      // 60000
+ms('5s')      // 5000
+ms('1y')      // 31557600000
+ms('100')     // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000)             // "1m"
+ms(2 * 60000)         // "2m"
+ms(ms('10 hours'))    // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true })             // "1 minute"
+ms(2 * 60000, { long: true })         // "2 minutes"
+ms(ms('10 hours'), { long: true })    // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/input_devices/mag/node_modules/prompt-actions/package.json b/input_devices/mag/node_modules/prompt-actions/package.json
new file mode 100644
index 00000000..936ae3d5
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-actions/package.json
@@ -0,0 +1,124 @@
+{
+  "_args": [
+    [
+      "prompt-actions@^3.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "prompt-actions@>=3.0.2 <4.0.0",
+  "_id": "prompt-actions@3.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-actions",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prompt-actions-3.0.2.tgz_1496422381976_0.12540486687794328"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.0.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "prompt-actions",
+    "raw": "prompt-actions@^3.0.2",
+    "rawSpec": "^3.0.2",
+    "scope": null,
+    "spec": ">=3.0.2 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base"
+  ],
+  "_resolved": "https://registry.npmjs.org/prompt-actions/-/prompt-actions-3.0.2.tgz",
+  "_shasum": "537eee52241c940379f354a06eae8528e44ceeba",
+  "_shrinkwrap": null,
+  "_spec": "prompt-actions@^3.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/prompt-actions/issues"
+  },
+  "dependencies": {
+    "debug": "^2.6.8"
+  },
+  "description": "Action manager for prompt-base.",
+  "devDependencies": {
+    "gulp": "^3.9.1",
+    "gulp-eslint": "^3.0.1",
+    "gulp-format-md": "^0.1.12",
+    "gulp-istanbul": "^1.1.1",
+    "gulp-mocha": "^3.0.1",
+    "is-windows": "^1.0.1",
+    "mocha": "^3.4.2",
+    "prompt-choices": "^4.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-dhz2Fl7vK+LPpmnQ/S/eSut4BnH4NZDLyddHKi5uTU/2PDn3grEMGkgsll16V5RpVUh/yxdiam0xsM0RD4xvtg==",
+    "shasum": "537eee52241c940379f354a06eae8528e44ceeba",
+    "tarball": "https://registry.npmjs.org/prompt-actions/-/prompt-actions-3.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "d272c8f645714cd3a1dfe815e0a5b94edbbf939d",
+  "homepage": "https://github.com/enquirer/prompt-actions",
+  "keywords": [
+    "actions",
+    "prompt"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "prompt-actions",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/prompt-actions.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "base-prompt",
+      "prompt-base"
+    ],
+    "related": {
+      "list": [
+        "enquirer",
+        "prompt-base",
+        "prompt-choices",
+        "prompt-grid",
+        "prompt-sort"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.0.2"
+}
diff --git a/input_devices/mag/node_modules/prompt-base/LICENSE b/input_devices/mag/node_modules/prompt-base/LICENSE
new file mode 100644
index 00000000..ece74b5e
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-base/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-base/README.md b/input_devices/mag/node_modules/prompt-base/README.md
new file mode 100644
index 00000000..51414e3d
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-base/README.md
@@ -0,0 +1,675 @@
+# prompt-base [![NPM version](https://img.shields.io/npm/v/prompt-base.svg?style=flat)](https://www.npmjs.com/package/prompt-base) [![NPM monthly downloads](https://img.shields.io/npm/dm/prompt-base.svg?style=flat)](https://npmjs.org/package/prompt-base) [![NPM total downloads](https://img.shields.io/npm/dt/prompt-base.svg?style=flat)](https://npmjs.org/package/prompt-base) [![Linux Build Status](https://img.shields.io/travis/enquirer/prompt-base.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/prompt-base) [![Windows Build Status](https://img.shields.io/appveyor/ci/enquirer/prompt-base.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/enquirer/prompt-base)
+
+> Base prompt module used for creating custom prompts.
+
+Follow this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), for updates on this project and others.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-base
+```
+
+## Release history
+
+See [the changelog](changelog.md) for detailed release history.
+
+## What is this?
+
+prompt-base is a node.js library for creating command line prompts. You can use prompt-base directly for simple input prompts, or as a "base" for creating [custom prompts](#in-the-wild):
+
+## Usage
+
+See the [examples folder](./examples) for additional usage examples.
+
+```js
+var Prompt = require('prompt-base');
+var prompt = new Prompt({
+  name: 'color',
+  message: 'What is your favorite color?'
+});
+
+// promise
+prompt.run()
+  .then(function(answer) {
+    console.log(answer);
+    //=> 'blue'
+  })
+
+// or async
+prompt.ask(function(answer) {
+  console.log(answer);
+  //=> 'blue'
+});
+```
+
+You can also pass a string directly to the main export:
+
+```js
+var prompt = require('prompt-base')('What is your favorite color?');
+  
+prompt.run()
+  .then(function(answer) {
+    console.log(answer);
+  })
+```
+
+## Custom prompts
+
+**Inherit**
+
+```js
+var Prompt = require('prompt-base');
+
+function CustomPrompt(/*question, answers, rl*/) {
+  Prompt.apply(this, arguments);
+}
+
+Prompt.extend(CustomPrompt);
+```
+
+## API
+
+### [Prompt](index.js#L35)
+
+Create a new Prompt with the given `question` object, `answers` and optional instance of [readline-ui](https://github.com/enquirer/readline-ui).
+
+**Params**
+
+* `question` **{Object}**: Plain object or instance of [prompt-question](https://github.com/enquirer/prompt-question).
+* `answers` **{Object}**: Optionally pass an answers object from a prompt manager (like [enquirer](http://enquirer.io)).
+* `ui` **{Object}**: Optionally pass an instance of [readline-ui](https://github.com/enquirer/readline-ui). If not passed, an instance is created for you.
+
+**Example**
+
+```js
+var prompt = new Prompt({
+  name: 'color',
+  message: 'What is your favorite color?'
+});
+
+prompt.ask(function(answer) {
+  console.log(answer);
+  //=> 'blue'
+});
+```
+
+### [.transform](index.js#L101)
+
+Modify the answer value before it's returned. Must return a string or promise.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+var answers = {};
+var Prompt = require('prompt-base');
+var prompt = new Prompt({
+  name: 'name',
+  message: 'What is your name?',
+  transform: function(input) {
+    return input.toUpperCase();
+  }
+});
+```
+
+### [.validate](index.js#L139)
+
+Validate user input on `keypress` events and the answer value when it's submitted by the `line` event (when the user hits <kbd>enter</kbd>. This may be overridden in custom prompts. If the function returns `false`, either `question.errorMessage` or the default validation error message (`invalid input`) is used. Must return a boolean, string or promise.
+
+* `returns` **{Boolean}**
+
+**Example**
+
+```js
+var Prompt = require('prompt-base');
+var prompt = new Prompt({
+  name: 'first',
+  message: 'What is your name?',
+  errorMessage: 'alphabetical characters only',
+  validate: function(input) {
+    var str = input ? input.trim() : '';
+    var isValid = /^[a-z]+$/i.test(str);
+    if (this.state === 'submitted') {
+      return str.length > 10 && isValid;
+    }
+    return isValid;
+  }
+});
+```
+
+### [.when](index.js#L167)
+
+A custom `.when` function may be defined to determine
+whether or not a question should be asked at all. Must
+return a boolean, undefined, or a promise.
+
+* `returns` **{Boolean}**
+
+**Example**
+
+```js
+var answers = {};
+var Prompt = require('prompt-base');
+var prompt = new Prompt({
+  name: 'name',
+  message: 'What is your name?',
+  when: function(answers) {
+    return !answers.name;
+  }
+});
+```
+
+### [.ask](index.js#L193)
+
+Run the prompt with the given `callback` function.
+
+**Params**
+
+* `callback` **{Function}**
+* `returns` **{undefined}**
+
+**Example**
+
+```js
+var Prompt = require('prompt-base');
+var prompt = new Prompt({
+  name: 'name',
+  message: 'What is your name?'
+});
+
+prompt.ask(function(answer) {
+  console.log(answer);
+});
+```
+
+### [.run](index.js#L235)
+
+Run the prompt and resolve answers. If [when](#when) is defined and returns false, the prompt will be skipped.
+
+**Params**
+
+* `answers` **{Object}**: (optional) When supplied, the answer value will be added to a property where the key is the question name.
+* `returns` **{Promise}**
+
+**Example**
+
+```js
+var answers = {};
+var Prompt = require('prompt-base');
+var prompt = new Prompt({
+  name: 'name',
+  message: 'What is your name?'
+});
+
+prompt.run(answers)
+  .then(function(answer) {
+    console.log(answer);
+    console.log(answers);
+  });
+```
+
+### [.getDefault](index.js#L273)
+
+Get the answer to use. This can be overridden in custom prompts.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+console.log(prompt.getDefault());
+```
+
+### [.getError](index.js#L306)
+
+Get the error message to use. This can be overridden in custom prompts.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+console.log(prompt.getError());
+```
+
+### [.getHelp](index.js#L320)
+
+Get the help message to use. This can be overridden in custom prompts.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+console.log(prompt.getHelp());
+```
+
+### [.getAnswer](index.js#L334)
+
+Get the answer to use. This can be overridden in custom prompts.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+console.log(prompt.getAnswer());
+```
+
+### [.render](index.js#L356)
+
+(Re-)render the prompt message, along with any help or error messages, user input, choices, list items, and so on. This is called to render the initial prompt, then it's called again each time the prompt changes, such as on keypress events (when the user enters input, or a multiple-choice option is selected). This method may be overridden in custom prompts, but it's recommended that you override the more specific render "status" methods instead.
+
+* `returns` **{undefined}**
+
+**Example**
+
+```js
+prompt.ui.on('keypress', prompt.render.bind(prompt));
+```
+
+### [.renderMessage](index.js#L434)
+
+Format the prompt message.
+
+* `returns` **{String}**
+
+**Example**
+
+```js
+var answers = {};
+var Prompt = require('prompt-base');
+var prompt = new Prompt({
+  name: 'name',
+  message: 'What is your name?',
+  transform: function(input) {
+    return input.toUpperCase();
+  }
+});
+```
+
+### [.renderHelp](index.js#L452)
+
+Called by [render](#render) to render a help message when the
+`prompt.status` is `initialized` or `help` (usually when the
+prompt is first rendered). Calling this method changes the
+`prompt.status` to `"interacted"`, and as such, by default, the
+message is only displayed until the user interacts. By default
+the help message is positioned to the right of the prompt "question".
+A custom help message may be defined on `options.helpMessage`.
+
+**Params**
+
+* `valid` **{boolean|string|undefined}**
+* `returns` **{String}**
+
+### [.renderError](index.js#L475)
+
+Render an error message in the prompt, when `valid` is
+false or a string. This is used when a validation method
+either returns `false`, indicating that the input
+was invalid, or the method returns a string, indicating
+that a custom error message should be rendered. A custom
+error message may also be defined on `options.errorMessage`.
+
+**Params**
+
+* `valid` **{boolean|string|undefined}**
+* `returns` **{String}**
+
+### [.renderOutput](index.js#L494)
+
+Called by [render](#render) to render the readline `line`
+when `prompt.status` is anything besides `answered`, which
+includes everything except for error and help messages.
+
+* `returns` **{String}**
+
+### [.renderMask](index.js#L508)
+
+Mask user input. Called by [renderOutput](#renderOutput),
+this is an identity function that does nothing by default,
+as it's intended to be overwritten in custom prompts, such
+as [prompt-password](https://github.com/enquirer/prompt-password).
+
+* `returns` **{String}**
+
+### [.renderAnswer](index.js#L520)
+
+Render the user's "answer". Called by [render](#render) when
+the `prompt.status` is changed to `answered`.
+
+* `returns` **{String}**
+
+### [.action](index.js#L540)
+
+Get action `name`, or set action `name` with the given `fn`.
+This is useful for overridding actions in custom prompts.
+Actions are used to move the pointer position, toggle checkboxes
+and so on
+
+**Params**
+
+* `name` **{String}**
+* `fn` **{Function}**
+* `returns` **{Object|Function}**: Returns the prompt instance if setting, or the action function if getting.
+
+### [.dispatch](index.js#L557)
+
+Move the cursor in the given `direction` when a `keypress`
+event is emitted.
+
+**Params**
+
+* `direction` **{String}**
+* `event` **{Object}**
+
+### [.onError](index.js#L602)
+
+Default error event handler. If an `error` listener exist, an `error`
+event will be emitted, otherwise the error is logged onto `stderr` and
+the process is exited. This can be overridden in custom prompts.
+
+**Params**
+
+* `err` **{Object}**
+
+### [.submitAnswer](index.js#L618)
+
+Re-render and pass the final answer to the callback.
+This can be replaced by custom prompts.
+
+### [.only](index.js#L642)
+
+Ensures that events for event `name` are only **registered** once and are disabled correctly when specified. This is different from `.once`, which only **emits** once.
+
+**Example**
+
+```js
+prompt.only('keypress', function() {
+  // do keypress stuff
+});
+```
+
+### [.mute](index.js#L671)
+
+Mutes the output stream that was used to create the readline interface, and returns a function for unmuting the stream. This is useful in unit tests.
+
+* `returns` **{Function}**
+
+**Example**
+
+```js
+// mute the stream
+var unmute = prompt.mute();
+
+// unmute the stream
+unmute();
+```
+
+### [.end](index.js#L691)
+
+Pause the readline and unmute the output stream that was
+used to create the readline interface, which is `process.stdout`
+by default.
+
+### [.resume](index.js#L706)
+
+[Resume](https://nodejs.org/api/readline.html#readline_rl_resume) the readline input stream if it has been paused.
+
+* `returns` **{undefined}**
+
+### [.choices](index.js#L759)
+
+Getter for getting the choices array from the question.
+
+* `returns` **{Object}**: Choices object
+
+### [.message](index.js#L776)
+
+Getter that returns `question.message` after passing it to [format](#format).
+
+* `returns` **{String}**: A formatted prompt message.
+
+### [.symbol](index.js#L797)
+
+Getter/setter for getting the checkbox symbol to use.
+
+* `returns` **{String}**: The formatted symbol.
+
+**Example**
+
+```js
+// customize
+prompt.symbol = '[ ]';
+```
+
+### [.prefix](index.js#L823)
+
+Getter/setter that returns the prefix to use before `question.message`. The default value is a green `?`.
+
+* `returns` **{String}**: The formatted prefix.
+
+**Example**
+
+```js
+// customize
+prompt.prefix = ' ❤ ';
+```
+
+### [.ask](index.js#L855)
+
+Static convenience method for running the [.ask](#ask) method. Takes the same arguments as the contructror.
+
+**Params**
+
+* `question` **{Object}**: Plain object or instance of [prompt-question](https://github.com/enquirer/prompt-question).
+* `answers` **{Object}**: Optionally pass an answers object from a prompt manager (like [enquirer](http://enquirer.io)).
+* `ui` **{Object}**: Optionally pass an instance of [readline-ui](https://github.com/enquirer/readline-ui). If not passed, an instance is created for you.
+* `callback` **{Function}**
+* `returns` **{undefined}**
+
+**Example**
+
+```js
+var prompt = require('prompt-base');
+  .ask('What is your favorite color?', function(answer) {
+    console.log({color: answer});
+    //=> { color: 'blue' }
+  });
+```
+
+### [.run](index.js#L881)
+
+Static convenience method for running the [.run](#run) method. Takes the same arguments as the contructror.
+
+**Params**
+
+* `question` **{Object}**: Plain object or instance of [prompt-question](https://github.com/enquirer/prompt-question).
+* `answers` **{Object}**: Optionally pass an answers object from a prompt manager (like [enquirer](http://enquirer.io)).
+* `ui` **{Object}**: Optionally pass an instance of [readline-ui](https://github.com/enquirer/readline-ui). If not passed, an instance is created for you.
+* `returns` **{Promise}**
+
+**Example**
+
+```js
+var prompt = require('prompt-base');
+  .run('What is your favorite color?')
+  .then(function(answer) {
+    console.log({color: answer});
+    //=> { color: 'blue' }
+  });
+```
+
+### [.Question](index.js#L897)
+
+Create a new `Question`. See [prompt-question](https://github.com/enquirer/prompt-question) for more details.
+
+**Params**
+
+* `options` **{Object}**
+* `returns` **{Object}**: Returns an instance of [prompt-question](https://github.com/enquirer/prompt-question)
+
+**Example**
+
+```js
+var question = new Prompt.Question({name: 'foo'});
+```
+
+### [.Choices](index.js#L911)
+
+Create a new `Choices` object. See [prompt-choices](https://github.com/enquirer/prompt-choices) for more details.
+
+**Params**
+
+* `choices` **{Array}**: Array of choices
+* `returns` **{Object}**: Returns an intance of Choices.
+
+**Example**
+
+```js
+var choices = new Prompt.Choices(['foo', 'bar', 'baz']);
+```
+
+### [.Separator](index.js#L924)
+
+Create a new `Separator` object. See [choices-separator](https://github.com/enquirer/choices-separator) for more details.
+
+**Params**
+
+* `separator` **{String}**: Optionally pass a string to use as the separator.
+* `returns` **{Object}**: Returns a separator object.
+
+**Example**
+
+```js
+new Prompt.Separator('---');
+```
+
+## Events
+
+### prompt
+
+Emitted when a prompt (plugin) is instantiated, _after the readline interface is created, but before the actual "question" is asked_.
+
+**Example usage**
+
+```js
+enquirer.on('prompt', function(prompt) {
+  // do stuff with "prompt" instance
+});
+```
+
+### ask
+
+Emitted when the actual "question" is asked.
+
+**Example usage**
+
+Emit `keypress` events to supply the answer (and potentially skip the prompt if the answer is valid):
+
+```js
+enquirer.on('ask', function(prompt) {
+  prompt.rl.input.emit('keypress', 'foo');
+  prompt.rl.input.emit('keypress', '\n');
+});
+```
+
+Change the prompt message:
+
+```js
+enquirer.on('ask', function(prompt) {
+  prompt.message = 'I..\'m Ron Burgundy...?';
+});
+```
+
+### answer
+
+Emitted when the final (valid) answer is submitted, and custom validation function (if defined) returns true.
+
+_(An "answer" is the final input value that's captured when the `readline` emits a `line` event; e.g. when the user hits `enter`)_
+
+**Example usage**
+
+```js
+enquirer.on('answer', function(answer) {
+  // do stuff with answer
+});
+```
+
+## In the wild
+
+The following custom prompts were created using this library:
+
+* [prompt-autocomplete](https://www.npmjs.com/package/prompt-autocomplete): A prompt in the terminal but with autocomplete functionality | [homepage](https://github.com/rickbergfalk/prompt-autocomplete "A prompt in the terminal but with autocomplete functionality")
+* [prompt-checkbox](https://www.npmjs.com/package/prompt-checkbox): Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer](http://enquirer.io). | [homepage](https://github.com/enquirer/prompt-checkbox "Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer].")
+* [prompt-confirm](https://www.npmjs.com/package/prompt-confirm): Confirm (yes/no) prompt. Can be used standalone or with a prompt system like [Enquirer](http://enquirer.io). | [homepage](https://github.com/enquirer/prompt-confirm "Confirm (yes/no) prompt. Can be used standalone or with a prompt system like [Enquirer].")
+* [prompt-editor](https://www.npmjs.com/package/prompt-editor): Editor prompt. Opens your text editor and waits for you to save your input during… [more](https://github.com/enquirer/prompt-editor) | [homepage](https://github.com/enquirer/prompt-editor "Editor prompt. Opens your text editor and waits for you to save your input during a prompt. Can be used standalone or with a prompt system like [Enquirer].")
+* [prompt-expand](https://www.npmjs.com/package/prompt-expand): Expand prompt. Can be used as a standalone prompt, or with a prompt system like… [more](https://github.com/enquirer/prompt-expand) | [homepage](https://github.com/enquirer/prompt-expand "Expand prompt. Can be used as a standalone prompt, or with a prompt system like [Enquirer].")
+* [prompt-list](https://www.npmjs.com/package/prompt-list): List-style prompt. Can be used as a standalone prompt, or with a prompt system like… [more](https://github.com/enquirer/prompt-list) | [homepage](https://github.com/enquirer/prompt-list "List-style prompt. Can be used as a standalone prompt, or with a prompt system like [enquirer].")
+* [prompt-password](https://www.npmjs.com/package/prompt-password): Password prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer](http://enquirer.io). | [homepage](https://github.com/enquirer/prompt-password "Password prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer].")
+* [prompt-radio](https://www.npmjs.com/package/prompt-radio): Radio prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer](http://enquirer.io). | [homepage](https://github.com/enquirer/prompt-radio "Radio prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer].")
+* [prompt-rawlist](https://www.npmjs.com/package/prompt-rawlist): Rawlist prompt. Can be used as a standalone prompt, or with a prompt system like… [more](https://github.com/enquirer/prompt-rawlist) | [homepage](https://github.com/enquirer/prompt-rawlist "Rawlist prompt. Can be used as a standalone prompt, or with a prompt system like [Enquirer].")
+
+## About
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. | [homepage](http://enquirer.io "Intuitive, plugin-based prompt system for node.js.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+* [prompt-question](https://www.npmjs.com/package/prompt-question): Question object, used by Enquirer and prompt plugins. | [homepage](https://github.com/enquirer/prompt-question "Question object, used by Enquirer and prompt plugins.")
+* [readline-utils](https://www.npmjs.com/package/readline-utils): Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more. | [homepage](https://github.com/enquirer/readline-utils "Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 163 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 6 | [doowb](https://github.com/doowb) |
+| 1 | [sbj42](https://github.com/sbj42) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on August 30, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-base/changelog.md b/input_devices/mag/node_modules/prompt-base/changelog.md
new file mode 100644
index 00000000..2b066a10
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-base/changelog.md
@@ -0,0 +1,55 @@
+# Release history
+
+## v4.1.0
+
+**Changed**
+
+- `render` is now emitted before the message is created.
+
+## v4.0.2
+
+**Fixed**
+
+- don't get choices until prompt is called. this ensures that choices defined as a function won't be called early.
+
+## v4.0.0
+
+**Changed**
+
+- no longer throws an error when question name is undefined
+
+**Added**
+
+- adds support for defining `prompt.question.default` as a function
+- adds support for defining `prompt.question.choices` as a function
+
+## v3.0.0
+
+**Added**
+
+- adds initial support for `prompt.context`, an object that can be passed around at runtime to simplify rendering. Future releases will gradually improve context handling until we make a full transition to redux, or redux-like state. Throughout this process, special care will be taken to ensure that the API is the same until the transition to redux, at which time we'll fully document any API changes.
+
+## v2.0.2
+
+**Added**
+
+- `.getDefault` method: to consistently get the `options.default` on any prompt type: input, list, choices etc.
+
+## v2.0.0
+
+**Potentially breaking changes**
+
+- Changes how the `actions` property is initialized. It's unlikely that this will break anyone's code, since it doesn't change any of the behavior or functionality, but a major bump seemed appropriate just in case.
+
+## v1.0.0
+
+**Breaking changes**
+
+- converted hard-coded prototype-methods-as-listeners to [prompt-actions][]. This makes it much easier for custom prompts to change behavior without overriding entire prototype methods.
+
+## v0.8.2 - 2017-05-12
+
+- 100% tests coverage
+- various bugfixes and improvements in event handling
+- ensures nested prompts are working correctly
+- fixes `.getAnswer` to always work with `.ask` or `.run`
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-base/index.js b/input_devices/mag/node_modules/prompt-base/index.js
new file mode 100644
index 00000000..b509c1dd
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-base/index.js
@@ -0,0 +1,938 @@
+'use strict';
+
+var util = require('util');
+var log = require('log-utils');
+var koalas = require('koalas');
+var debug = require('debug')('prompt-base');
+var Emitter = require('component-emitter');
+var Question = require('prompt-question');
+var Actions = require('prompt-actions');
+var extend = require('static-extend');
+var utils = require('readline-utils');
+var UI = require('readline-ui');
+
+/**
+ * Create a new Prompt with the given `question` object, `answers` and optional instance
+ * of [readline-ui][].
+ *
+ * ```js
+ * var prompt = new Prompt({
+ *   name: 'color',
+ *   message: 'What is your favorite color?'
+ * });
+ *
+ * prompt.ask(function(answer) {
+ *   console.log(answer);
+ *   //=> 'blue'
+ * });
+ * ```
+ * @param {Object} `question` Plain object or instance of [prompt-question][].
+ * @param {Object} `answers` Optionally pass an answers object from a prompt manager (like [enquirer][]).
+ * @param {Object} `ui` Optionally pass an instance of [readline-ui][]. If not passed, an instance is created for you.
+ * @api public
+ */
+
+function Prompt(question, answers, ui) {
+  debug('initializing from <%s>', __filename);
+
+  if (!question) {
+    throw new TypeError('expected question to be a string or object');
+  }
+
+  if (!(this instanceof Prompt)) {
+    var proto = Object.create(Prompt.prototype);
+    Prompt.apply(proto, arguments);
+    return proto;
+  }
+
+  Emitter.call(this);
+  if (!(question instanceof Question)) {
+    question = new Question(question);
+  }
+
+  this.question = this.options = question;
+  this.answers = answers || {};
+  this.context = {};
+  this.contextHistory = [];
+  this.actions = new Actions(this);
+
+  if (typeof this.options.limit !== 'number') {
+    this.options.limit = this.options.radio ? 9 : 7;
+  }
+
+  this.ui = ui || UI.create(this.options);
+  this.rl = this.ui.rl;
+  this.errorMessage = log.red('>> invalid input');
+  this.onError = this.onError.bind(this);
+  this.status = 'pending';
+  this.session = false;
+  this.position = 0;
+  this.called = 0;
+  this.state = true;
+  this.ui.rl.pause();
+  this.initListeners();
+}
+
+/**
+ * Inherit `Base`
+ */
+
+util.inherits(Prompt, Emitter);
+
+/**
+ * Modify the answer value before it's returned. Must
+ * return a string or promise.
+ *
+ * ```js
+ * var answers = {};
+ * var Prompt = require('prompt-base');
+ * var prompt = new Prompt({
+ *   name: 'name',
+ *   message: 'What is your name?',
+ *   transform: function(input) {
+ *     return input.toUpperCase();
+ *   }
+ * });
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.transform = function(input) {
+  if (typeof this.options.transform === 'function') {
+    return this.options.transform.call(this, input);
+  }
+  if (typeof this.options.filter === 'function') {
+    return this.options.filter.call(this, input);
+  }
+  return input;
+};
+
+/**
+ * Validate user input on `keypress` events and the answer
+ * value when it's submitted by the `line` event (when the user
+ * hits <kbd>enter</kbd>. This may be overridden in custom prompts.
+ * If the function returns `false`, either `question.errorMessage`
+ * or the default validation error message (`invalid input`) is used.
+ * Must return a boolean, string or promise.
+ *
+ * ```js
+ * var Prompt = require('prompt-base');
+ * var prompt = new Prompt({
+ *   name: 'first',
+ *   message: 'What is your name?',
+ *   errorMessage: 'alphabetical characters only',
+ *   validate: function(input) {
+ *     var str = input ? input.trim() : '';
+ *     var isValid = /^[a-z]+$/i.test(str);
+ *     if (this.state === 'submitted') {
+ *       return str.length > 10 && isValid;
+ *     }
+ *     return isValid;
+ *   }
+ * });
+ * ```
+ * @return {Boolean}
+ * @api public
+ */
+
+Prompt.prototype.validate = function(input, key) {
+  if (typeof this.options.validate === 'function') {
+    this.state = this.options.validate.apply(this, arguments);
+  } else {
+    this.state = true;
+  }
+  return this.state;
+};
+
+/**
+ * A custom `.when` function may be defined to determine
+ * whether or not a question should be asked at all. Must
+ * return a boolean, undefined, or a promise.
+ * ```js
+ * var answers = {};
+ * var Prompt = require('prompt-base');
+ * var prompt = new Prompt({
+ *   name: 'name',
+ *   message: 'What is your name?',
+ *   when: function(answers) {
+ *     return !answers.name;
+ *   }
+ * });
+ * ```
+ * @return {Boolean}
+ * @api public
+ */
+
+Prompt.prototype.when = function(answers) {
+  if (typeof this.options.when === 'function') {
+    return this.options.when.apply(this, arguments);
+  }
+  return true;
+};
+
+/**
+ * Run the prompt with the given `callback` function.
+ *
+ * ```js
+ * var Prompt = require('prompt-base');
+ * var prompt = new Prompt({
+ *   name: 'name',
+ *   message: 'What is your name?'
+ * });
+ *
+ * prompt.ask(function(answer) {
+ *   console.log(answer);
+ * });
+ * ```
+ * @param {Function} `callback`
+ * @return {undefined}
+ * @api public
+ */
+
+Prompt.prototype.ask = function(callback) {
+  if (this.question.on) {
+    this.addListeners(this.question.on);
+  }
+
+  this.callback = callback;
+  this.resume();
+  this.only('error', this.onError);
+  this.only('keypress', this.dispatch.bind(this));
+  this.only('line', this.dispatch.bind(this));
+  this.emit('ask', this);
+
+  if (this.choices && this.choices.length) {
+    this.choices.options.limit = this.options.limit;
+    utils.cursorHide(this.rl);
+  }
+  this.render();
+};
+
+/**
+ * Run the prompt and resolve answers. If [when](#when) is defined
+ * and returns false, the prompt will be skipped.
+ *
+ * ```js
+ * var answers = {};
+ * var Prompt = require('prompt-base');
+ * var prompt = new Prompt({
+ *   name: 'name',
+ *   message: 'What is your name?'
+ * });
+ *
+ * prompt.run(answers)
+ *   .then(function(answer) {
+ *     console.log(answer);
+ *     console.log(answers);
+ *   });
+ * ```
+ * @param {Object} `answers` (optional) When supplied, the answer value will be added to a property where the key is the question name.
+ * @return {Promise}
+ * @api public
+ */
+
+Prompt.prototype.run = function(answers) {
+  answers = answers || {};
+  var self = this;
+
+  return Promise.resolve(this.when(answers))
+    .then(function(when) {
+      if (when === false) {
+        self.end(false);
+        self.emit('answer', self.getAnswer());
+        return Promise.resolve(self.getAnswer());
+      }
+      return new Promise(function(resolve) {
+        self.ask(function(input) {
+          Promise.resolve(self.transform(input))
+            .then(function(answer) {
+              if (typeof answer !== 'undefined') {
+                answers[self.question.name] = answer;
+                self.question.answer = answer;
+              }
+              resolve(answer);
+            })
+            .catch(self.onError);
+        });
+      });
+    })
+    .catch(self.onError);
+};
+
+/**
+ * Get the answer to use. This can be overridden in custom prompts.
+ *
+ * ```js
+ * console.log(prompt.getDefault());
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.getDefault = function() {
+  var val = this.question.default;
+  if (typeof val === 'function') {
+    val = val.call(this);
+  }
+
+  if (this.choices && this.choices.length) {
+    if (val != null) {
+      this.question.default = null;
+      this.choices.check(val);
+      this.choices.default = val;
+      if (Array.isArray(val)) val = val[0];
+      var choice = this.choices.get(val);
+      if (choice) {
+        val = choice.name;
+        this.position = choice.index;
+      }
+    }
+  }
+  this.initialDefault = val;
+  return val;
+};
+
+/**
+ * Get the error message to use. This can be overridden in custom prompts.
+ *
+ * ```js
+ * console.log(prompt.getError());
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.getError = function(input, key) {
+  return koalas(this.options.errorMessage, this.errorMessage, '');
+};
+
+/**
+ * Get the help message to use. This can be overridden in custom prompts.
+ *
+ * ```js
+ * console.log(prompt.getHelp());
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.getHelp = function(input, key) {
+  return koalas(this.options.helpMessage, this.helpMessage, '');
+};
+
+/**
+ * Get the answer to use. This can be overridden in custom prompts.
+ *
+ * ```js
+ * console.log(prompt.getAnswer());
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.getAnswer = function(input, key) {
+  this.answer = this.question.getAnswer(input || this.getDefault(), key);
+  return this.answer;
+};
+
+/**
+ * (Re-)render the prompt message, along with any help or error
+ * messages, user input, choices, list items, and so on. This is
+ * called to render the initial prompt, then it's called again
+ * each time the prompt changes, such as on keypress events (when
+ * the user enters input, or a multiple-choice option is selected).
+ * This method may be overridden in custom prompts, but it's
+ * recommended that you override the more specific render "status"
+ * methods instead.
+ *
+ * ```js
+ * prompt.ui.on('keypress', prompt.render.bind(prompt));
+ * ```
+ * @return {undefined}
+ * @api public
+ */
+
+Prompt.prototype.render = function(state) {
+  if (typeof state === 'undefined') {
+    state = this.state;
+  }
+
+  this.state = state;
+  var context = this.context = {
+    options: this.options,
+    status: this.status,
+    state: this.state,
+    line: this.rl.line,
+    keypress: this.keypress,
+    answer: this.answer,
+    default: this.getDefault(),
+    original: this.renderMessage(this),
+    banner: '',
+    header: '',
+    prefix: this.prefix,
+    message: this.message,
+    input: '',
+    footer: '',
+    append: '',
+    output: '',
+    error: '',
+    hint: '',
+    help: ''
+  };
+
+  context.append = this.renderError(context);
+  context.message = this.renderMessage(context);
+
+  // override message in custom prompts
+  this.emit('render', context);
+
+  // render message with default settings
+  switch (context.status) {
+    case 'help':
+    case 'pending':
+    case 'expanded':
+    case 'initialized':
+      context.message += this.renderHelp(context);
+      context.message += this.renderOutput(context);
+      break;
+    case 'answered':
+      context.message += this.renderAnswer(context);
+      context.answer = this.answer;
+      break;
+    case 'interacted':
+    case 'submitted':
+    default: {
+      context.message += this.renderOutput(context);
+      break;
+    }
+  }
+
+  // push context onto history array, for debugging
+  this.contextHistory.push(context);
+  this.ui.render(context.message, context.append);
+};
+
+/**
+ * Format the prompt message.
+ *
+ * ```js
+ * var answers = {};
+ * var Prompt = require('prompt-base');
+ * var prompt = new Prompt({
+ *   name: 'name',
+ *   message: 'What is your name?',
+ *   transform: function(input) {
+ *     return input.toUpperCase();
+ *   }
+ * });
+ * ```
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.renderMessage = function(context) {
+  return context.prefix + log.bold(context.message) + ' ';
+};
+
+/**
+ * Called by [render](#render) to render a help message when the
+ * `prompt.status` is `initialized` or `help` (usually when the
+ * prompt is first rendered). Calling this method changes the
+ * `prompt.status` to `"interacted"`, and as such, by default, the
+ * message is only displayed until the user interacts. By default
+ * the help message is positioned to the right of the prompt "question".
+ * A custom help message may be defined on `options.helpMessage`.
+ *
+ * @param {boolean|string|undefined} `valid`
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.renderHelp = function(context) {
+  var help = this.getHelp();
+  var val = this.getDefault();
+  if (!help && val != null) {
+    help = log.dim('(' + val + ') ');
+  }
+  return help;
+};
+
+/**
+ * Render an error message in the prompt, when `valid` is
+ * false or a string. This is used when a validation method
+ * either returns `false`, indicating that the input
+ * was invalid, or the method returns a string, indicating
+ * that a custom error message should be rendered. A custom
+ * error message may also be defined on `options.errorMessage`.
+ *
+ * @default `>> invalid input`
+ * @param {boolean|string|undefined} `valid`
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.renderError = function(context) {
+  if (context.state === false) {
+    return this.getError();
+  }
+  if (typeof context.state === 'string') {
+    return log.red('>> ') + context.state;
+  }
+  return '';
+};
+
+/**
+ * Called by [render](#render) to render the readline `line`
+ * when `prompt.status` is anything besides `answered`, which
+ * includes everything except for error and help messages.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.renderOutput = function(context) {
+  return this.renderMask(this.rl.line);
+};
+
+/**
+ * Mask user input. Called by [renderOutput](#renderOutput),
+ * this is an identity function that does nothing by default,
+ * as it's intended to be overwritten in custom prompts, such
+ * as [prompt-password][].
+ *
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.renderMask = function(input) {
+  return input;
+};
+
+/**
+ * Render the user's "answer". Called by [render](#render) when
+ * the `prompt.status` is changed to `answered`.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Prompt.prototype.renderAnswer = function() {
+  var answer = this.renderMask(this.answer);
+  if (answer != null) {
+    return log.cyan(answer);
+  }
+  return '';
+};
+
+/**
+ * Get action `name`, or set action `name` with the given `fn`.
+ * This is useful for overridding actions in custom prompts.
+ * Actions are used to move the pointer position, toggle checkboxes
+ * and so on
+ *
+ * @param {String} `name`
+ * @param {Function} `fn`
+ * @return {Object|Function} Returns the prompt instance if setting, or the action function if getting.
+ * @api public
+ */
+
+Prompt.prototype.action = function(name, fn) {
+  if (typeof fn === 'function') {
+    this.actions[name] = fn;
+    return this;
+  }
+  return this.actions[name];
+};
+
+/**
+ * Move the cursor in the given `direction` when a `keypress`
+ * event is emitted.
+ *
+ * @param {String} `direction`
+ * @param {Object} `event`
+ * @api public
+ */
+
+Prompt.prototype.dispatch = function(input, key) {
+  this.keypress = key;
+  this.choices.position = this.position;
+  var self = this;
+
+  // don't handle "enter" and "return" (handle by "line")
+  if (key.name === 'enter' || key.name === 'return') {
+    return;
+  }
+
+  if (key.name === 'line') {
+    this.status = 'submitted';
+    input = this.answer = this.getAnswer(input, key);
+  }
+
+  // dispatch actions, if one matches a keypress
+  var action = self.action(key.name);
+
+  if (typeof action === 'function') {
+    this.position = action.call(this.actions, this.position, key);
+  }
+
+  return Promise.resolve(this.validate(input, key))
+    .then(function(state) {
+      self.state = state;
+
+      // re-render the prompt in the terminal
+      self.render(state);
+
+      // handle the "enter" keypress event
+      if (key.name === 'line' && state === true) {
+        return self.submitAnswer(input);
+      }
+    })
+    .catch(this.onError);
+};
+
+/**
+ * Default error event handler. If an `error` listener exist, an `error`
+ * event will be emitted, otherwise the error is logged onto `stderr` and
+ * the process is exited. This can be overridden in custom prompts.
+ * @param {Object} `err`
+ * @api public
+ */
+
+Prompt.prototype.onError = function(err) {
+  if (this.hasListeners('error')) {
+    this.emit('error', err);
+  } else {
+    this.end();
+    console.error(err);
+    this.callback();
+  }
+};
+
+/**
+ * Re-render and pass the final answer to the callback.
+ * This can be replaced by custom prompts.
+ * @api public
+ */
+
+Prompt.prototype.submitAnswer = function(answer) {
+  setImmediate(function() {
+    this.status = 'answered';
+    this.answer = answer;
+    this.end();
+    this.emit('answer', this.answer);
+    this.rl.line = '';
+    this.callback(this.answer);
+  }.bind(this));
+};
+
+/**
+ * Ensures that events for event `name` are only **registered**
+ * once and are disabled correctly when specified. This is
+ * different from `.once`, which only **emits** once.
+ *
+ * ```js
+ * prompt.only('keypress', function() {
+ *   // do keypress stuff
+ * });
+ * ```
+ * @api public
+ */
+
+Prompt.prototype.only = function(name, fn) {
+  this._only = this._only || {};
+  if (arguments.length === 0) {
+    for (var key in this._only) {
+      this.ui.off(key, this._only[key]);
+    }
+    return;
+  }
+  this._only[name] = fn;
+  this.ui.on(name, fn);
+  return fn;
+};
+
+/**
+ * Mutes the output stream that was used to create the
+ * readline interface, and returns a function for unmuting the
+ * stream. This is useful in unit tests.
+ *
+ * ```js
+ * // mute the stream
+ * var unmute = prompt.mute();
+ *
+ * // unmute the stream
+ * unmute();
+ * ```
+ * @return {Function}
+ * @api public
+ */
+
+Prompt.prototype.mute = function() {
+  var rl = this.rl;
+  var unmute = rl.output.unmute;
+  rl.output.unmute = function() {};
+  rl.output.mute();
+
+  return function() {
+    rl.output.unmute = unmute;
+    unmute();
+  };
+};
+
+/**
+ * Pause the readline and unmute the output stream that was
+ * used to create the readline interface, which is `process.stdout`
+ * by default.
+ *
+ * @api public
+ */
+
+Prompt.prototype.end = function(state) {
+  this.only();
+  if (state !== false) {
+    this.render();
+  }
+  this.ui.end(state);
+  this.rl.pause();
+};
+
+/**
+ * [Resume][resume] the readline input stream if it has been paused.
+ * @return {undefined}
+ * @api public
+ */
+
+Prompt.prototype.resume = function() {
+  this.status = 'initialized';
+  this.rl.resume();
+};
+
+/**
+ * Initialize event listeners
+ */
+
+Prompt.prototype.initListeners = function() {
+  var prompt = this;
+  var on = {};
+
+  this.action('tab', function(pos, key) {
+    if (key.shift === true && prompt.rl.line.slice(-1) === '\t') {
+      prompt.rl.input.emit('keypress', '', {name: 'backspace'});
+    }
+    return this.position(pos);
+  });
+
+  // allow events to be defined using `question.on`. this is
+  // defined as a setter/getter to allow events to be lazily
+  // added after instantiation
+  Object.defineProperty(this.question, 'on', {
+    set: function(listeners) {
+      prompt.addListeners(listeners);
+      on = listeners;
+    },
+    get: function() {
+      return on;
+    }
+  });
+};
+
+/**
+ * Add an object of event listeners
+ */
+
+Prompt.prototype.addListeners = function(listeners) {
+  var keys = Object.keys(listeners);
+  for (var i = 0; i < keys.length; i++) {
+    this.only(keys[i], listeners[keys[i]].bind(this));
+  }
+};
+
+/**
+ * Getter for getting the choices array from the question.
+ *
+ * @name .choices
+ * @return {Object} Choices object
+ * @api public
+ */
+
+Object.defineProperty(Prompt.prototype, 'choices', {
+  set: function(choices) {
+    this.question.choices = choices;
+  },
+  get: function() {
+    return this.question.choices;
+  }
+});
+
+/**
+ * Getter that returns `question.message` after passing it to [format](#format).
+ *
+ * @name .message
+ * @return {String} A formatted prompt message.
+ * @api public
+ */
+
+Object.defineProperty(Prompt.prototype, 'message', {
+  set: function(message) {
+    this.question.message = message;
+  },
+  get: function() {
+    return this.question.message;
+  }
+});
+
+/**
+ * Getter/setter for getting the checkbox symbol to use.
+ *
+ * ```js
+ * // customize
+ * prompt.symbol = '[ ]';
+ * ```
+ * @name .symbol
+ * @return {String} The formatted symbol.
+ * @api public
+ */
+
+Object.defineProperty(Prompt.prototype, 'symbol', {
+  set: function(symbol) {
+    this.question.symbol = symbol;
+  },
+  get: function() {
+    var val = koalas(this.question.symbol, this.question.options.symbol);
+    if (val != null) {
+      this.question.symbol = val;
+    }
+    return val;
+  }
+});
+
+/**
+ * Getter/setter that returns the prefix to use before `question.message`.
+ * The default value is a green `?`.
+ *
+ * ```js
+ * // customize
+ * prompt.prefix = ' ❤ ';
+ * ```
+ * @name .prefix
+ * @return {String} The formatted prefix.
+ * @api public
+ */
+
+Object.defineProperty(Prompt.prototype, 'prefix', {
+  set: function(prefix) {
+    this.question.prefix = prefix;
+  },
+  get: function() {
+    if (typeof this.question.prefix === 'undefined') {
+      return log.cyan('?') + ' ';
+    } else {
+      return this.question.prefix;
+    }
+  }
+});
+
+/**
+ * Static convenience method for running the [.ask](#ask) method.
+ * Takes the same arguments as the contructror.
+ *
+ * ```js
+ * var prompt = require('prompt-base');
+ *   .ask('What is your favorite color?', function(answer) {
+ *     console.log({color: answer});
+ *     //=> { color: 'blue' }
+ *   });
+ * ```
+ * @param {Object} `question` Plain object or instance of [prompt-question][].
+ * @param {Object} `answers` Optionally pass an answers object from a prompt manager (like [enquirer][]).
+ * @param {Object} `ui` Optionally pass an instance of [readline-ui][]. If not passed, an instance is created for you.
+ * @param {Function} `callback`
+ * @return {undefined}
+ * @api public
+ */
+
+Prompt.ask = function(question, answers, ui) {
+  var args = [].slice.call(arguments);
+  var cb = args.pop();
+  var prompt = new this(...args);
+  prompt.ask(cb);
+};
+
+/**
+ * Static convenience method for running the [.run](#run) method.
+ * Takes the same arguments as the contructror.
+ *
+ * ```js
+ * var prompt = require('prompt-base');
+ *   .run('What is your favorite color?')
+ *   .then(function(answer) {
+ *     console.log({color: answer});
+ *     //=> { color: 'blue' }
+ *   });
+ * ```
+ * @param {Object} `question` Plain object or instance of [prompt-question][].
+ * @param {Object} `answers` Optionally pass an answers object from a prompt manager (like [enquirer][]).
+ * @param {Object} `ui` Optionally pass an instance of [readline-ui][]. If not passed, an instance is created for you.
+ * @return {Promise}
+ * @api public
+ */
+
+Prompt.run = function() {
+  var prompt = new this(...arguments);
+  return prompt.run();
+};
+
+/**
+ * Create a new `Question`. See [prompt-question][] for more details.
+ *
+ * ```js
+ * var question = new Prompt.Question({name: 'foo'});
+ * ```
+ * @param {Object} `options`
+ * @return {Object} Returns an instance of [prompt-question][]
+ * @api public
+ */
+
+Prompt.Question = Question;
+
+/**
+ * Create a new `Choices` object. See [prompt-choices][]
+ * for more details.
+ *
+ * ```js
+ * var choices = new Prompt.Choices(['foo', 'bar', 'baz']);
+ * ```
+ * @param {Array} `choices` Array of choices
+ * @return {Object} Returns an intance of Choices.
+ * @api public
+ */
+
+Prompt.Choices = Question.Choices;
+
+/**
+ * Create a new `Separator` object. See [choices-separator][] for more details.
+ *
+ * ```js
+ * new Prompt.Separator('---');
+ * ```
+ * @param {String} `separator` Optionally pass a string to use as the separator.
+ * @return {Object} Returns a separator object.
+ * @api public
+ */
+
+Prompt.Separator = Question.Separator;
+
+/**
+ * Static method for inheriting `Prompt`. This ensures that all getters/setters,
+ * prototype methods, and static methods are inherited and invoked in the
+ * correct context.
+ */
+
+Prompt.extend = extend(Prompt);
+
+/**
+ * Expose `Prompt`
+ */
+
+module.exports = Prompt;
diff --git a/input_devices/mag/node_modules/prompt-base/package.json b/input_devices/mag/node_modules/prompt-base/package.json
new file mode 100644
index 00000000..4fb2e75f
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-base/package.json
@@ -0,0 +1,192 @@
+{
+  "_args": [
+    [
+      "prompt-base@^4.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-checkbox"
+    ]
+  ],
+  "_from": "prompt-base@>=4.0.2 <5.0.0",
+  "_id": "prompt-base@4.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-base",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prompt-base-4.1.0.tgz_1504140609330_0.7134291110560298"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "prompt-base",
+    "raw": "prompt-base@^4.0.2",
+    "rawSpec": "^4.0.2",
+    "scope": null,
+    "spec": ">=4.0.2 <5.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-checkbox"
+  ],
+  "_resolved": "https://registry.npmjs.org/prompt-base/-/prompt-base-4.1.0.tgz",
+  "_shasum": "7b88e4c01b096c83d2f4e501a7e85f0d369ecd1f",
+  "_shrinkwrap": null,
+  "_spec": "prompt-base@^4.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-checkbox",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/prompt-base/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "James Clark",
+      "url": "http://arbitraryclark.blogspot.com"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "component-emitter": "^1.2.1",
+    "debug": "^3.0.1",
+    "koalas": "^1.0.2",
+    "log-utils": "^0.2.1",
+    "prompt-actions": "^3.0.2",
+    "prompt-question": "^5.0.1",
+    "readline-ui": "^2.2.3",
+    "readline-utils": "^2.2.3",
+    "static-extend": "^0.1.2"
+  },
+  "description": "Base prompt module used for creating custom prompts.",
+  "devDependencies": {
+    "ansi-magenta": "^0.1.1",
+    "capture-stream": "^0.1.2",
+    "gulp": "^3.9.1",
+    "gulp-eslint": "^4.0.0",
+    "gulp-format-md": "^1.0.0",
+    "gulp-istanbul": "^1.1.2",
+    "gulp-mocha": "^3.0.1",
+    "mocha": "^3.5.0",
+    "repeat-string": "^1.6.1",
+    "strip-color": "^0.1.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-svGzgLUKZoqomz9SGMkf1hBG8Wl3K7JGuRCXc/Pv7xw8239hhaTBXrmjt7EXA9P/QZzdyT8uNWt9F/iJTXq75g==",
+    "shasum": "7b88e4c01b096c83d2f4e501a7e85f0d369ecd1f",
+    "tarball": "https://registry.npmjs.org/prompt-base/-/prompt-base-4.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=5.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "5f30952f19f32ece1c436bfd978442d3061d4476",
+  "homepage": "https://github.com/enquirer/prompt-base",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "bar",
+    "base",
+    "bottom",
+    "checkbox",
+    "choice",
+    "cli",
+    "command",
+    "enquirer",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "password",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "prompt-base",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/prompt-base.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "choices-separator",
+      "enquirer",
+      "prompt-choices",
+      "prompt-password",
+      "prompt-question",
+      "readline-ui",
+      "readline-utils"
+    ],
+    "related": {
+      "list": [
+        "enquirer",
+        "prompt-choices",
+        "prompt-question",
+        "readline-utils"
+      ],
+      "prompts": [
+        "prompt-autocomplete",
+        "prompt-checkbox",
+        "prompt-confirm",
+        "prompt-editor",
+        "prompt-expand",
+        "prompt-list",
+        "prompt-password",
+        "prompt-radio",
+        "prompt-rawlist"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "4.1.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/LICENSE b/input_devices/mag/node_modules/prompt-checkbox/LICENSE
new file mode 100644
index 00000000..ece74b5e
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-checkbox/README.md b/input_devices/mag/node_modules/prompt-checkbox/README.md
new file mode 100644
index 00000000..98bd80ad
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/README.md
@@ -0,0 +1,331 @@
+# prompt-checkbox [![NPM version](https://img.shields.io/npm/v/prompt-checkbox.svg?style=flat)](https://www.npmjs.com/package/prompt-checkbox) [![NPM monthly downloads](https://img.shields.io/npm/dm/prompt-checkbox.svg?style=flat)](https://npmjs.org/package/prompt-checkbox) [![NPM total downloads](https://img.shields.io/npm/dt/prompt-checkbox.svg?style=flat)](https://npmjs.org/package/prompt-checkbox) [![Linux Build Status](https://img.shields.io/travis/enquirer/prompt-checkbox.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/prompt-checkbox)
+
+> Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer](http://enquirer.io).
+
+![prompt-checkbox example](https://raw.githubusercontent.com/enquirer/prompt-checkbox/master/docs/example.gif)
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-checkbox
+```
+
+## Usage
+
+```js
+var Prompt = require('prompt-checkbox');
+var prompt = new Prompt({
+  name: 'colors',
+  message: 'What are your favorite colors?',
+  choices: [
+    'red',
+    'blue',
+    'yellow'
+  ]
+});
+
+// promises
+prompt.run()
+  .then(function(answers) {
+    console.log(answers)
+  })
+  .catch(function(err) {
+    console.log(err)
+  })
+
+// async
+prompt.ask(function(answers) {
+  console.log(answers)
+});
+```
+
+## Special features
+
+Features you won't find with other prompts!
+
+### Choices function
+
+Define choices as a function. This allows you to dynamically generate the choices when the question is asked.
+
+```js
+var prompt = new Prompt({
+  name: 'colors',
+  message: 'What are your favorite colors?',
+  choices: function() {
+    // dynamically build choices 
+    return ['red', 'blue', 'green'];
+  }
+});
+```
+
+### Choice groups
+
+![Choices groups](https://raw.githubusercontent.com/enquirer/prompt-checkbox/master/docs/choice-groups.gif)
+
+**Easy to configure!**
+
+Just pass an object of arrays on `choices`, and each key in the object will be used as the group "toggle":
+
+```js
+var Prompt = require('prompt-checkbox');
+var prompt = new Prompt({
+  name: 'install',
+  message: 'Which packages do you want to install?',
+  choices: {
+    dependencies: ['generate', 'micromatch'],
+    devDependencies: ['mocha', 'kind-of']
+  }
+});
+```
+
+### Radio choices
+
+Adds `all` and `none` choices, which select or deselect all choices, respectively. Named "radio choices" since it acts like a hybrid between checkboxes and radio buttons.
+
+<br>
+
+![radio choices](https://raw.githubusercontent.com/enquirer/prompt-checkbox/master/docs/radio-choices.gif)
+
+**Code example**
+
+```js
+var Prompt = require('prompt-checkbox');
+var prompt = new Prompt({
+  name: 'install',
+  message: 'Which packages do you want to install?',
+  radio: true,
+  choices: ['foo', 'bar', 'baz']
+});
+```
+
+### Radio groups
+
+Use "radio" choices with choice groups.
+
+<br>
+
+![radio groups](https://raw.githubusercontent.com/enquirer/prompt-checkbox/master/docs/radio-groups.gif)
+
+```js
+var Prompt = require('prompt-checkbox');
+var prompt = new Prompt({
+  name: 'install',
+  message: 'Which packages do you want to install?',
+  radio: true,
+  choices: {
+    dependencies: ['generate', 'micromatch'],
+    devDependencies: ['mocha', 'kind-of']
+  }
+});
+```
+
+## options
+
+The following options are either specific to prompt-checkbox, or have behavior that differs in some way from the built-in options from [prompt-base](https://github.com/enquirer/prompt-base). _(Any other options from [prompt-base](https://github.com/enquirer/prompt-base) may be used as well.)_
+
+### options.default
+
+**Type**: `string|number|array`
+
+**Default**: `undefined`
+
+Specify the "default" choices to check when the prompt is initialized. Default can be a choice name (string), index (number), or an array of choice names or indices.
+
+**Examples**
+
+Specify default as a string (choice name):
+
+```js
+var prompt = new Prompt({
+  name: 'colors',
+  message: 'Best flavor?',
+  default: 'chocolate',
+  choices: ['chocolate'] // <= hmm, I wonder what they'll choose?
+});
+```
+
+Specify an array of defaults (choice names or indices):
+
+```js
+var prompt = new Prompt({
+  name: 'colors',
+  message: 'Favorite colors?',
+  default: [1, 'blue'],
+  choices: ['red', 'blue', 'yellow']
+});
+```
+
+### options.radio
+
+**Type**: `boolean`
+
+**Default**: `undefined`
+
+Enable hybrid radio-checkbox support, which adds `all` and `none` radio options for toggling all options on and off.
+
+```js
+var Prompt = require('prompt-checkbox');
+var prompt = new Prompt({
+  name: 'colors',
+  message: 'What are your favorite colors?',
+  radio: true,
+  choices: [
+    'red',
+    'blue',
+    'yellow'
+  ]
+});
+```
+
+### options.transform
+
+**Type**: `function`
+
+**Default**: `undefined`
+
+Modify answer values before they're returned.
+
+**Example**
+
+Use `options.transform` and the `prompt.choices.get()` method to convert answers (checked choices) to an array of objects (versus of an array of strings).
+
+```js
+var Prompt = require('prompt-checkbox');
+var prompt = new Prompt({
+  name: 'colors',
+  message: 'What are your favorite colors?',
+  choices: ['red', 'blue', 'yellow'],
+  transform: function(answer) {
+    // - "this" is the prompt instance
+    // - "this.choices.get()" returns the choice object for each choice
+    return answer ? answer.map(this.choices.get.bind(this.choices)) : [];
+  }
+});
+```
+
+## Keypresses
+
+In addition to the keypresses that are supported by [prompt-base](https://github.com/enquirer/prompt-base), the following keypress offer different behavior that is specific to checklists:
+
+* <kbd>down</kbd> - move the pointer (cursor) down one row for each keypress
+* <kbd>up</kbd> - move the pointer (cursor) up one row for each keypress
+* <kbd>i</kbd> - toggle all choices to the opposite of their current state.
+* <kbd>a</kbd> - enable or disable all choices
+* <kbd>space</kbd> - toggle a choice
+* <kbd>number</kbd> - toggle the choice at the given index (starting at 1)
+
+## Usage with [enquirer](http://enquirer.io)
+
+Register the prompt with enquirer:
+
+```js
+var Enquirer = require('enquirer');
+var enquirer = new Enquirer();
+
+enquirer.register('checkbox', require('prompt-checkbox'));
+```
+
+### Enquirer examples
+
+For formatting questions, [enquirer](http://enquirer.io) supports either:
+
+* declarative, inquirer-style question format
+* functional format using the `.question` method.
+
+**Inquirer-style questions**
+
+Declarative questions format, similar to `inquirer`.
+
+```js
+var questions = [
+  {
+    name: 'color',
+    message: 'What is your favorite color?',
+    type: 'checkbox',
+    default: 'blue',
+    choices: ['red', 'yellow', 'blue']
+  }
+];
+
+enquirer.prompt(questions)
+  .then(function(answers) {
+    console.log(answers)
+  });
+```
+
+Or:
+
+```js
+enquirer.prompt({
+    name: 'color',
+    message: 'What is your favorite color?',
+    type: 'checkbox',
+    default: 'blue',
+    choices: ['red', 'yellow', 'blue']
+  })
+  .then(function(answers) {
+    console.log(answers)
+  });
+```
+
+**Functional-style questions**
+
+Use the `.question` method to pre-register questions, so they can be called later. Also, the `message` may be passed as the second argument, or as a property on the question options.
+
+```js
+enquirer.question('letter', 'What are your favorite letters?', {
+  type: 'checkbox', //<= specify the prompt type
+  choices: ['a', 'b', 'c']
+});
+
+enquirer.question('numbers', {
+  type: 'checkbox', //<= specify the prompt type
+  message: 'What are your favorite numbers?',
+  choices: ['1', '2', '3']
+});
+
+// pass the name(s) or questions to ask
+enquirer.prompt(['letters', 'numbers'])
+  .then(function(answers) {
+    console.log(answers)
+  });
+```
+
+## About
+
+### Related projects
+
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. | [homepage](http://enquirer.io "Intuitive, plugin-based prompt system for node.js.")
+* [prompt-base](https://www.npmjs.com/package/prompt-base): Base prompt module used for creating custom prompts. | [homepage](https://github.com/enquirer/prompt-base "Base prompt module used for creating custom prompts.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+* [prompt-question](https://www.npmjs.com/package/prompt-question): Question object, used by Enquirer and prompt plugins. | [homepage](https://github.com/enquirer/prompt-question "Question object, used by Enquirer and prompt plugins.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 08, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-checkbox/index.js b/input_devices/mag/node_modules/prompt-checkbox/index.js
new file mode 100644
index 00000000..86f8a378
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/index.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var debug = require('debug')('prompt-checkbox');
+var Prompt = require('prompt-base');
+var cyan = require('ansi-cyan');
+
+/**
+ * Checkbox prompt
+ */
+
+function Checkbox() {
+  debug('initializing from <%s>', __filename);
+  Prompt.apply(this, arguments);
+  this.errorMessage = null;
+  this.infoMessage = this.options.infoMessage || '(Press '
+    + cyan('<space>')
+    + ' to toggle)';
+}
+
+/**
+ * Inherit prompt-base
+ */
+
+Prompt.extend(Checkbox);
+
+/**
+ * Render all prompt choices to the terminal
+ */
+
+Checkbox.prototype.renderOutput = function() {
+  this.choices.options.filterList = true;
+  return this.choices.render(this.position, this.question.options);
+};
+
+/**
+ * Render only the selected choices to the terminal
+ */
+
+Checkbox.prototype.renderAnswer = function() {
+  var keys = this.choices.checked.map(function(choice) {
+    return typeof choice === 'string' ? choice : choice.value;
+  });
+  return cyan(keys.join(', '));
+};
+
+/**
+ * Module exports
+ */
+
+module.exports = Checkbox;
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.coveralls.yml b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.eslintrc b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+  "rules": {
+    "no-console": 0,
+    "no-empty": [1, { "allowEmptyCatch": true }]
+  },
+  "extends": "eslint:recommended"
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.npmignore b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.travis.yml b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+  - "6"
+  - "5"
+  - "4"
+
+install:
+  - make node_modules
+
+script:
+  - make lint
+  - make test
+  - make coveralls
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/CHANGELOG.md b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+  * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+  * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+  * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+  * Fix: Inline extend function in node implementation (#452, @dougwilson)
+  * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+  
+  * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+  * Misc: clean up browser reference checks (#447, @thebigredgeek)
+  * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+  * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+  * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+  * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+  * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+  * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+  * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+  * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+  * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+  * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+  * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+  * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+  * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+  * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+  * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+  * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+  * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+  * Docs: fixed README typo (#391, @lurch)
+  * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+  * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+  * Fix: wrong reference in bower file (@thebigredgeek)
+  * Fix: webworker compatibility (@thebigredgeek)
+  * Fix: output formatting issue (#388, @kribblo)
+  * Fix: babel-loader compatibility (#383, @escwald)
+  * Misc: removed built asset from repo and publications (@thebigredgeek)
+  * Misc: moved source files to /src (#378, @yamikuronue)
+  * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+  * Test: coveralls integration (#378, @yamikuronue)
+  * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+  * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+  * Fix: custom log function (#379, @hsiliev)
+  * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+  * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+  * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+  * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+  * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+  * Fix: browser colors (#367, @tootallnate)
+  * Misc: travis ci integration (@thebigredgeek)
+  * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+  * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+  * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+  * Fix: revert "handle regex special characters" (@tootallnate)
+  * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+  * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+  * Improvement: allow colors in workers (#335, @botverse)
+  * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+  * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+  * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+  * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+  * Fix: be super-safe in index.js as well (@TooTallNate)
+  * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+  * Fix: Added electron compatibility (#324, @paulcbetts)
+  * Improvement: Added performance optimizations (@tootallnate)
+  * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+  * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+  * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+  * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+  * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+  * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+  * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+  * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+  * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+  * Readme: fix USE_COLORS to DEBUG_COLORS
+  * Readme: Doc fixes for format string sugar (#269, @mlucool)
+  * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+  * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+  * Readme: better docs for browser support (#224, @matthewmueller)
+  * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+  * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+  * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+  * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+  * package: update "ms" to v0.7.1 (#202, @dougwilson)
+  * README: add logging to file example (#193, @DanielOchoa)
+  * README: fixed a typo (#191, @amir-s)
+  * browser: expose `storage` (#190, @stephenmathieson)
+  * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+  * Updated stdout/stderr example (#186)
+  * Updated example/stdout.js to match debug current behaviour
+  * Renamed example/stderr.js to stdout.js
+  * Update Readme.md (#184)
+  * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+  * dist: recompile
+  * update "ms" to v0.7.0
+  * package: update "browserify" to v9.0.3
+  * component: fix "ms.js" repo location
+  * changed bower package name
+  * updated documentation about using debug in a browser
+  * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+  * browser: use `typeof` to check for `console` existence
+  * browser: check for `console.log` truthiness (fix IE 8/9)
+  * browser: add support for Chrome apps
+  * Readme: added Windows usage remarks
+  * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+  * node: implement `DEBUG_FD` env variable support
+  * package: update "browserify" to v6.1.0
+  * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+  * package: update "browserify" to v5.11.0
+  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+  * dist: recompile
+  * example: remove `console.info()` log usage
+  * example: add "Content-Type" UTF-8 header to browser example
+  * browser: place %c marker after the space character
+  * browser: reset the "content" color via `color: inherit`
+  * browser: add colors support for Firefox >= v31
+  * debug: prefer an instance `log()` function over the global one (#119)
+  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+  * Add support for multiple wildcards in namespaces (#122, @seegno)
+  * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+  * browser: update color palette (#113, @gscottolson)
+  * common: make console logging function configurable (#108, @timoxley)
+  * node: fix %o colors on old node <= 0.8.x
+  * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+  * browser: use `removeItem()` to clear localStorage
+  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+  * package: add "contributors" section
+  * node: fix comment typo
+  * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+  * make ms diff be global, not be scope
+  * debug: ignore empty strings in enable()
+  * node: make DEBUG_COLORS able to disable coloring
+  * *: export the `colors` array
+  * npmignore: don't publish the `dist` dir
+  * Makefile: refactor to use browserify
+  * package: add "browserify" as a dev dependency
+  * Readme: add Web Inspector Colors section
+  * node: reset terminal color for the debug content
+  * node: map "%o" to `util.inspect()`
+  * browser: map "%j" to `JSON.stringify()`
+  * debug: add custom "formatters"
+  * debug: use "ms" module for humanizing the diff
+  * Readme: add "bash" syntax highlighting
+  * browser: add Firebug color support
+  * browser: add colors for WebKit browsers
+  * node: apply log to `console`
+  * rewrite: abstract common logic for Node & browsers
+  * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+  * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+  * add `enable()` method for nodejs. Closes #27
+  * change from stderr to stdout
+  * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+  * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+  * fix: catch localStorage security error when cookies are blocked (Chrome)
+  * add debug(err) support. Closes #46
+  * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/LICENSE b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/Makefile b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+	@NODE_ENV= $(PKG) install
+	@touch node_modules
+
+lint: .FORCE
+	eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+	istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+	mkdir -p dist
+
+	@$(BROWSERIFY) \
+		--standalone debug \
+		. > dist/debug.js
+
+	karma start --single-run
+	rimraf dist
+
+test: .FORCE
+	concurrently \
+		"make test-node" \
+		"make test-browser"
+
+coveralls:
+	cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/README.md b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) 
+[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+  ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+
+## Conventions
+
+  If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+  When running through Node.js, you can set a few environment variables that will
+  change the behavior of the debug logging:
+
+| Name      | Purpose                                         |
+|-----------|-------------------------------------------------|
+| `DEBUG`   | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+  __Note:__ The environment variables beginning with `DEBUG_` end up being
+  converted into an Options object that gets used with `%o`/`%O` formatters.
+  See the Node.js documentation for
+  [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+  for the complete list.
+
+## Formatters
+
+
+  Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O`      | Pretty-print an Object on multiple lines. |
+| `%o`      | Pretty-print an Object all on a single line. |
+| `%s`      | String. |
+| `%d`      | Number (both integer and float). |
+| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%`      | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+  You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+  return v.toString('hex')
+}
+
+// …elsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+//   foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+  You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+  or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+  if you don't want to build it yourself.
+
+  Debug's enable state is currently persisted by `localStorage`.
+  Consider the situation shown below where you have `worker:a` and `worker:b`,
+  and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+  Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+  option. These are WebKit web inspectors, Firefox ([since version
+  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+  and the Firebug plugin for Firefox (any version).
+
+  Colored output looks something like:
+
+  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
+
+
+## Output streams
+
+  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+ 
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/component.json b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+  "name": "debug",
+  "repo": "visionmedia/debug",
+  "description": "small debugging utility",
+  "version": "2.6.9",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "main": "src/browser.js",
+  "scripts": [
+    "src/browser.js",
+    "src/debug.js"
+  ],
+  "dependencies": {
+    "rauchg/ms.js": "0.7.1"
+  }
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/karma.conf.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['mocha', 'chai', 'sinon'],
+
+
+    // list of files / patterns to load in the browser
+    files: [
+      'dist/debug.js',
+      'test/*spec.js'
+    ],
+
+
+    // list of files to exclude
+    exclude: [
+      'src/node.js'
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['progress'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false,
+
+    // Concurrency level
+    // how many browser should be started simultaneous
+    concurrency: Infinity
+  })
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/node.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/package.json b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/package.json
new file mode 100644
index 00000000..54e5d858
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/package.json
@@ -0,0 +1,128 @@
+{
+  "_args": [
+    [
+      "debug@^2.6.8",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-checkbox"
+    ]
+  ],
+  "_from": "debug@>=2.6.8 <3.0.0",
+  "_id": "debug@2.6.9",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-checkbox/debug",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196"
+  },
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "debug",
+    "raw": "debug@^2.6.8",
+    "rawSpec": "^2.6.8",
+    "scope": null,
+    "spec": ">=2.6.8 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-checkbox"
+  ],
+  "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+  "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+  "_shrinkwrap": null,
+  "_spec": "debug@^2.6.8",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-checkbox",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "browser": "./src/browser.js",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "component": {
+    "scripts": {
+      "debug/debug.js": "debug.js",
+      "debug/index.js": "browser.js"
+    }
+  },
+  "contributors": [
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "http://n8.io"
+    },
+    {
+      "name": "Andrew Rhyne",
+      "email": "rhyneandrew@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "ms": "2.0.0"
+  },
+  "description": "small debugging utility",
+  "devDependencies": {
+    "browserify": "9.0.3",
+    "chai": "^3.5.0",
+    "concurrently": "^3.1.0",
+    "coveralls": "^2.11.15",
+    "eslint": "^3.12.1",
+    "istanbul": "^0.4.5",
+    "karma": "^1.3.0",
+    "karma-chai": "^0.1.0",
+    "karma-mocha": "^1.3.0",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "karma-sinon": "^1.0.5",
+    "mocha": "^3.2.0",
+    "mocha-lcov-reporter": "^1.2.0",
+    "rimraf": "^2.5.4",
+    "sinon": "^1.17.6",
+    "sinon-chai": "^2.8.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+    "shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+    "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
+  },
+  "gitHead": "13abeae468fea297d0dccc50bc55590809241083",
+  "homepage": "https://github.com/visionmedia/debug#readme",
+  "keywords": [
+    "debug",
+    "debugger",
+    "log"
+  ],
+  "license": "MIT",
+  "main": "./src/index.js",
+  "maintainers": [
+    {
+      "name": "thebigredgeek",
+      "email": "rhyneandrew@gmail.com"
+    },
+    {
+      "name": "kolban",
+      "email": "kolban1@kolban.com"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    }
+  ],
+  "name": "debug",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "version": "2.6.9"
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/browser.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+               && 'undefined' != typeof chrome.storage
+                  ? chrome.storage.local
+                  : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+  'lightseagreen',
+  'forestgreen',
+  'goldenrod',
+  'dodgerblue',
+  'darkorchid',
+  'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+  // NB: In an Electron preload script, document will be defined but not fully
+  // initialized. Since we know we're in Chrome, we'll just detect this case
+  // explicitly
+  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+    return true;
+  }
+
+  // is webkit? http://stackoverflow.com/a/16459606/376773
+  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+    // is firebug? http://stackoverflow.com/a/398120/376773
+    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+    // is firefox >= v31?
+    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+    // double check webkit in userAgent just in case we are in a worker
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+  try {
+    return JSON.stringify(v);
+  } catch (err) {
+    return '[UnexpectedJSONParseError]: ' + err.message;
+  }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var useColors = this.useColors;
+
+  args[0] = (useColors ? '%c' : '')
+    + this.namespace
+    + (useColors ? ' %c' : ' ')
+    + args[0]
+    + (useColors ? '%c ' : ' ')
+    + '+' + exports.humanize(this.diff);
+
+  if (!useColors) return;
+
+  var c = 'color: ' + this.color;
+  args.splice(1, 0, c, 'color: inherit')
+
+  // the final "%c" is somewhat tricky, because there could be other
+  // arguments passed either before or after the %c, so we need to
+  // figure out the correct index to insert the CSS into
+  var index = 0;
+  var lastC = 0;
+  args[0].replace(/%[a-zA-Z%]/g, function(match) {
+    if ('%%' === match) return;
+    index++;
+    if ('%c' === match) {
+      // we only are interested in the *last* %c
+      // (the user may have provided their own)
+      lastC = index;
+    }
+  });
+
+  args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+  // this hackery is required for IE8/9, where
+  // the `console.log` function doesn't have 'apply'
+  return 'object' === typeof console
+    && console.log
+    && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  try {
+    if (null == namespaces) {
+      exports.storage.removeItem('debug');
+    } else {
+      exports.storage.debug = namespaces;
+    }
+  } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  var r;
+  try {
+    r = exports.storage.debug;
+  } catch(e) {}
+
+  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+  if (!r && typeof process !== 'undefined' && 'env' in process) {
+    r = process.env.DEBUG;
+  }
+
+  return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+  try {
+    return window.localStorage;
+  } catch (e) {}
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/debug.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+  var hash = 0, i;
+
+  for (i in namespace) {
+    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
+    hash |= 0; // Convert to 32bit integer
+  }
+
+  return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+  function debug() {
+    // disabled?
+    if (!debug.enabled) return;
+
+    var self = debug;
+
+    // set `diff` timestamp
+    var curr = +new Date();
+    var ms = curr - (prevTime || curr);
+    self.diff = ms;
+    self.prev = prevTime;
+    self.curr = curr;
+    prevTime = curr;
+
+    // turn the `arguments` into a proper Array
+    var args = new Array(arguments.length);
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i];
+    }
+
+    args[0] = exports.coerce(args[0]);
+
+    if ('string' !== typeof args[0]) {
+      // anything else let's inspect with %O
+      args.unshift('%O');
+    }
+
+    // apply any `formatters` transformations
+    var index = 0;
+    args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+      // if we encounter an escaped % then don't increase the array index
+      if (match === '%%') return match;
+      index++;
+      var formatter = exports.formatters[format];
+      if ('function' === typeof formatter) {
+        var val = args[index];
+        match = formatter.call(self, val);
+
+        // now we need to remove `args[index]` since it's inlined in the `format`
+        args.splice(index, 1);
+        index--;
+      }
+      return match;
+    });
+
+    // apply env-specific formatting (colors, etc.)
+    exports.formatArgs.call(self, args);
+
+    var logFn = debug.log || exports.log || console.log.bind(console);
+    logFn.apply(self, args);
+  }
+
+  debug.namespace = namespace;
+  debug.enabled = exports.enabled(namespace);
+  debug.useColors = exports.useColors();
+  debug.color = selectColor(namespace);
+
+  // env-specific initialization logic for debug instances
+  if ('function' === typeof exports.init) {
+    exports.init(debug);
+  }
+
+  return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+  exports.save(namespaces);
+
+  exports.names = [];
+  exports.skips = [];
+
+  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+  var len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    if (!split[i]) continue; // ignore empty strings
+    namespaces = split[i].replace(/\*/g, '.*?');
+    if (namespaces[0] === '-') {
+      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+    } else {
+      exports.names.push(new RegExp('^' + namespaces + '$'));
+    }
+  }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+  exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+  var i, len;
+  for (i = 0, len = exports.skips.length; i < len; i++) {
+    if (exports.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (i = 0, len = exports.names.length; i < len; i++) {
+    if (exports.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/index.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+  module.exports = require('./browser.js');
+} else {
+  module.exports = require('./node.js');
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/inspector-log.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+  const stdout = console._stdout;
+  console._stdout = nullStream;
+  console.log.apply(console, arguments);
+  console._stdout = stdout;
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/node.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+  return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+  // camel-case
+  var prop = key
+    .substring(6)
+    .toLowerCase()
+    .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+  // coerce string value into JS value
+  var val = process.env[key];
+  if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+  else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+  else if (val === 'null') val = null;
+  else val = Number(val);
+
+  obj[prop] = val;
+  return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ *   $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+  util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+             2 === fd ? process.stderr :
+             createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+  return 'colors' in exports.inspectOpts
+    ? Boolean(exports.inspectOpts.colors)
+    : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts)
+    .split('\n').map(function(str) {
+      return str.trim()
+    }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var name = this.namespace;
+  var useColors = this.useColors;
+
+  if (useColors) {
+    var c = this.color;
+    var prefix = '  \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+    args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+    args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+  } else {
+    args[0] = new Date().toUTCString()
+      + ' ' + name + ' ' + args[0];
+  }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+  return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  if (null == namespaces) {
+    // If you set a process.env field to null or undefined, it gets cast to the
+    // string 'null' or 'undefined'. Just delete instead.
+    delete process.env.DEBUG;
+  } else {
+    process.env.DEBUG = namespaces;
+  }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+  var stream;
+  var tty_wrap = process.binding('tty_wrap');
+
+  // Note stream._type is used for test-module-load-list.js
+
+  switch (tty_wrap.guessHandleType(fd)) {
+    case 'TTY':
+      stream = new tty.WriteStream(fd);
+      stream._type = 'tty';
+
+      // Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    case 'FILE':
+      var fs = require('fs');
+      stream = new fs.SyncWriteStream(fd, { autoClose: false });
+      stream._type = 'fs';
+      break;
+
+    case 'PIPE':
+    case 'TCP':
+      var net = require('net');
+      stream = new net.Socket({
+        fd: fd,
+        readable: false,
+        writable: true
+      });
+
+      // FIXME Should probably have an option in net.Socket to create a
+      // stream from an existing fd which is writable only. But for now
+      // we'll just add this hack and set the `readable` member to false.
+      // Test: ./node test/fixtures/echo.js < /etc/passwd
+      stream.readable = false;
+      stream.read = null;
+      stream._type = 'pipe';
+
+      // FIXME Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    default:
+      // Probably an error on in uv_guess_handle()
+      throw new Error('Implement me. Unknown stream file type!');
+  }
+
+  // For supporting legacy API we put the FD here.
+  stream.fd = fd;
+
+  stream._isStdio = true;
+
+  return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+  debug.inspectOpts = {};
+
+  var keys = Object.keys(exports.inspectOpts);
+  for (var i = 0; i < keys.length; i++) {
+    debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+  }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/index.js b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+  options = options || {};
+  var type = typeof val;
+  if (type === 'string' && val.length > 0) {
+    return parse(val);
+  } else if (type === 'number' && isNaN(val) === false) {
+    return options.long ? fmtLong(val) : fmtShort(val);
+  }
+  throw new Error(
+    'val is not a non-empty string or a valid number. val=' +
+      JSON.stringify(val)
+  );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  str = String(str);
+  if (str.length > 100) {
+    return;
+  }
+  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+    str
+  );
+  if (!match) {
+    return;
+  }
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'yrs':
+    case 'yr':
+    case 'y':
+      return n * y;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'hrs':
+    case 'hr':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'mins':
+    case 'min':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 'secs':
+    case 'sec':
+    case 's':
+      return n * s;
+    case 'milliseconds':
+    case 'millisecond':
+    case 'msecs':
+    case 'msec':
+    case 'ms':
+      return n;
+    default:
+      return undefined;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+  if (ms >= d) {
+    return Math.round(ms / d) + 'd';
+  }
+  if (ms >= h) {
+    return Math.round(ms / h) + 'h';
+  }
+  if (ms >= m) {
+    return Math.round(ms / m) + 'm';
+  }
+  if (ms >= s) {
+    return Math.round(ms / s) + 's';
+  }
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+  return plural(ms, d, 'day') ||
+    plural(ms, h, 'hour') ||
+    plural(ms, m, 'minute') ||
+    plural(ms, s, 'second') ||
+    ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+  if (ms < n) {
+    return;
+  }
+  if (ms < n * 1.5) {
+    return Math.floor(ms / n) + ' ' + name;
+  }
+  return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/license.md b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/package.json b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/package.json
new file mode 100644
index 00000000..5b35fa02
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "ms@2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug"
+    ]
+  ],
+  "_from": "ms@2.0.0",
+  "_id": "ms@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-checkbox/ms",
+  "_nodeVersion": "7.8.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945"
+  },
+  "_npmUser": {
+    "email": "leo@zeit.co",
+    "name": "leo"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ms",
+    "raw": "ms@2.0.0",
+    "rawSpec": "2.0.0",
+    "scope": null,
+    "spec": "2.0.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/prompt-checkbox/debug"
+  ],
+  "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+  "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+  "_shrinkwrap": null,
+  "_spec": "ms@2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-checkbox/node_modules/debug",
+  "bugs": {
+    "url": "https://github.com/zeit/ms/issues"
+  },
+  "dependencies": {},
+  "description": "Tiny milisecond conversion utility",
+  "devDependencies": {
+    "eslint": "3.19.0",
+    "expect.js": "0.3.1",
+    "husky": "0.13.3",
+    "lint-staged": "3.4.1",
+    "mocha": "3.4.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+    "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
+  },
+  "eslintConfig": {
+    "env": {
+      "es6": true,
+      "node": true
+    },
+    "extends": "eslint:recommended"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4",
+  "homepage": "https://github.com/zeit/ms#readme",
+  "license": "MIT",
+  "lint-staged": {
+    "*.js": [
+      "git add",
+      "npm run lint",
+      "prettier --single-quote --write"
+    ]
+  },
+  "main": "./index",
+  "maintainers": [
+    {
+      "name": "leo",
+      "email": "leo@zeit.co"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "name": "ms",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zeit/ms.git"
+  },
+  "scripts": {
+    "lint": "eslint lib/* bin/*",
+    "precommit": "lint-staged",
+    "test": "mocha tests.js"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/readme.md b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days')  // 172800000
+ms('1d')      // 86400000
+ms('10h')     // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h')      // 7200000
+ms('1m')      // 60000
+ms('5s')      // 5000
+ms('1y')      // 31557600000
+ms('100')     // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000)             // "1m"
+ms(2 * 60000)         // "2m"
+ms(ms('10 hours'))    // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true })             // "1 minute"
+ms(2 * 60000, { long: true })         // "2 minutes"
+ms(ms('10 hours'), { long: true })    // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/input_devices/mag/node_modules/prompt-checkbox/package.json b/input_devices/mag/node_modules/prompt-checkbox/package.json
new file mode 100644
index 00000000..79b63e76
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-checkbox/package.json
@@ -0,0 +1,168 @@
+{
+  "_args": [
+    [
+      "prompt-checkbox@^2.2.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-radio"
+    ]
+  ],
+  "_from": "prompt-checkbox@>=2.2.0 <3.0.0",
+  "_id": "prompt-checkbox@2.2.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-checkbox",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prompt-checkbox-2.2.0.tgz_1499500001247_0.7523783801589161"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.1.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "prompt-checkbox",
+    "raw": "prompt-checkbox@^2.2.0",
+    "rawSpec": "^2.2.0",
+    "scope": null,
+    "spec": ">=2.2.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-radio"
+  ],
+  "_resolved": "https://registry.npmjs.org/prompt-checkbox/-/prompt-checkbox-2.2.0.tgz",
+  "_shasum": "a1b086bac7e3422a3f1c34f66d6da52486472690",
+  "_shrinkwrap": null,
+  "_spec": "prompt-checkbox@^2.2.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-radio",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/prompt-checkbox/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "ansi-cyan": "^0.1.1",
+    "debug": "^2.6.8",
+    "prompt-base": "^4.0.2"
+  },
+  "description": "Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer].",
+  "devDependencies": {
+    "ansi-colors": "^0.2.0",
+    "ansi-magenta": "^0.1.1",
+    "clone-deep": "^0.3.0",
+    "enquirer": "^1.0.2",
+    "gulp": "^3.9.1",
+    "gulp-eslint": "^4.0.0",
+    "gulp-format-md": "^1.0.0",
+    "gulp-istanbul": "^1.1.2",
+    "gulp-mocha": "^3.0.1",
+    "mocha": "^3.4.2",
+    "prompt-question": "^5.0.0",
+    "prompt-text": "^1.1.0",
+    "radio-symbol": "^2.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-T/QWgkdUmKjRSr0FQlV8O+LfgmBk8PwDbWhzllm7mwWNAjs3qOVuru5Y1gV4/14L73zCncqcuwGwvnDyVcVgvA==",
+    "shasum": "a1b086bac7e3422a3f1c34f66d6da52486472690",
+    "tarball": "https://registry.npmjs.org/prompt-checkbox/-/prompt-checkbox-2.2.0.tgz"
+  },
+  "engines": {
+    "node": ">=5.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e40e9e05c7bdd72595a63691d84dfe365ba2e57e",
+  "homepage": "https://github.com/enquirer/prompt-checkbox",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "checkbox",
+    "choice",
+    "choices",
+    "cli",
+    "command",
+    "enquirer",
+    "enquirerprompt",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "multiple-choice",
+    "password",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "prompt-checkbox",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/prompt-checkbox.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "data": {
+      "alias": "checkbox"
+    },
+    "layout": "common-minimal",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "enquirer",
+      "prompt-base"
+    ],
+    "related": {
+      "list": [
+        "enquirer",
+        "prompt-base",
+        "prompt-choices",
+        "prompt-question"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.2.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-choices/LICENSE b/input_devices/mag/node_modules/prompt-choices/LICENSE
new file mode 100644
index 00000000..7c9987bc
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2018, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/prompt-choices/README.md b/input_devices/mag/node_modules/prompt-choices/README.md
new file mode 100644
index 00000000..cf23802c
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/README.md
@@ -0,0 +1,523 @@
+# prompt-choices [![NPM version](https://img.shields.io/npm/v/prompt-choices.svg?style=flat)](https://www.npmjs.com/package/prompt-choices) [![NPM monthly downloads](https://img.shields.io/npm/dm/prompt-choices.svg?style=flat)](https://npmjs.org/package/prompt-choices) [![NPM total downloads](https://img.shields.io/npm/dt/prompt-choices.svg?style=flat)](https://npmjs.org/package/prompt-choices) [![Linux Build Status](https://img.shields.io/travis/enquirer/prompt-choices.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/prompt-choices)
+
+> Create an array of multiple choice objects for use in prompts.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-choices
+```
+
+## Usage
+
+```js
+var Choices = require('prompt-choices');
+var choices = new Choices(['foo', 'bar', 'baz']);
+```
+
+## API
+
+### [Choices](index.js#L21)
+
+Create a new `Choices` collection.
+
+**Params**
+
+* `choices` **{Array}**: One or more `choice` strings or objects.
+
+**Example**
+
+```js
+const choices = new Choices(['foo', 'bar', 'baz']);
+const choices = new Choices([{name: 'foo'}, {name: 'bar'}, {name: 'baz'}]);
+```
+
+### [.render](index.js#L52)
+
+Render choices.
+
+**Params**
+
+* `position` **{Number}**: Cursor position
+* `options` **{Object}**
+* `returns` **{String}**
+
+### [.renderChoice](index.js#L90)
+
+Render a specific choice. This can be overridden in prompts.
+
+**Params**
+
+* `choice` **{Object}**
+* `position` **{Number}**
+* `options` **{Object}**
+* `returns` **{String}**: Returns the line to render.
+
+**Example**
+
+```js
+choices.render = function(choice, position, options) {
+  // do custom logic
+  return '';
+};
+```
+
+### [.choice](index.js#L105)
+
+Create a new `Choice` object.
+
+**Params**
+
+* `val` **{String|Object}**
+* `returns` **{Object}**: Returns a choice object.
+
+**Example**
+
+```js
+choices.choice('blue');
+```
+
+### [.toChoice](index.js#L123)
+
+Returns a normalized `choice` object.
+
+**Params**
+
+* `choice` **{Object|String}**
+* `returns` **{Object}**
+
+**Example**
+
+```js
+choices.toChoice('foo');
+choices.toChoice({name: 'foo'});
+```
+
+### [.addChoice](index.js#L143)
+
+Add a normalized `choice` object to the `choices` array.
+
+**Params**
+
+* `choice` **{string|Object}**: One or more choices to add.
+
+**Example**
+
+```js
+choices.addChoice(['foo', 'bar', 'baz']);
+```
+
+### [.addChoices](index.js#L173)
+
+Add an array of normalized `choice` objects to the `choices` array. This method is called in the constructor, but it can also be used to add choices after instantiation.
+
+**Params**
+
+* `choices` **{Array|Object}**: One or more choices to add.
+
+**Example**
+
+```js
+choices.addChoices(['foo', 'bar', 'baz']);
+```
+
+### [.toGroups](index.js#L206)
+
+Create choice "groups" from the given choices object. ![choice groups](docs/prompt-groups.gif).
+
+**Params**
+
+* `choices` **{Object}**: (required) The value of each object must be an array of choices (strings or objects).
+* `returns` **{Array}**: Returns an array of normalized choice objects.
+
+**Example**
+
+```js
+choices.toGroups({
+  foo: ['a', 'b', 'c'],
+  bar: ['d', 'e', 'f']
+});
+```
+
+### [.separator](index.js#L282)
+
+Create a new `Separator` object. See [choices-separator](https://github.com/enquirer/choices-separator) for more details.
+
+**Params**
+
+* `separator` **{String}**: Optionally pass a string to use as the separator.
+* `returns` **{Object}**: Returns a separator object.
+
+**Example**
+
+```js
+choices.separator();
+```
+
+### [.hasChoice](index.js#L298)
+
+Returns true if a choice exists.
+
+**Params**
+
+* `val` **{Number}**: The index or key of the choice to check for.
+* `returns` **{Boolean}**
+
+**Example**
+
+```js
+choices.hasChoice(1);
+choices.hasChoice('foo');
+```
+
+### [.getChoice](index.js#L314)
+
+Get a non-separator choice from the collection.
+
+**Params**
+
+* `idx` **{Number}**: The selected choice index
+* `returns` **{Object|undefined}**: Return the matched choice object or undefined
+
+**Example**
+
+```js
+choices.getChoice(1);
+choices.getChoice('foo');
+```
+
+### [.getIndex](index.js#L341)
+
+Get the index of a non-separator choice from the collection.
+
+**Params**
+
+* `key` **{String}**: The key of the choice to get
+* `returns` **{Number}**: Index of the choice or `-1`;
+
+**Example**
+
+```js
+const choices = new Choices(['foo', 'bar', 'baz']);
+console.log(choices.getIndex('foo')); //=> 0
+console.log(choices.getIndex('baz')); //=> 2
+console.log(choices.getIndex('bar')); //=> 1
+console.log(choices.getIndex('qux')); //=> -1
+```
+
+### [.get](index.js#L365)
+
+Get the choice at the specified index.
+
+**Params**
+
+* `key` **{Number|String}**: The name or index of the object to get
+* `returns` **{Object}**: Returns the specified choice
+
+**Example**
+
+```js
+const choice = choices.get(1);
+//=> {name: 'foo'}
+const choice = choices.get(1, 'name');
+//=> 'foo'
+```
+
+### [.clear](index.js#L389)
+
+Clear all choices from the instance. This is useful when you need to update the indices of choices without re-instantiating.
+
+**Example**
+
+```js
+choices.clear();
+```
+
+### [.key](index.js#L403)
+
+Return the `.key` property from the choice at the given index.
+
+**Params**
+
+* `key` **{String}**: Property name to use for plucking objects.
+* `returns` **{Array}**: Plucked objects
+
+### [.check](index.js#L417)
+
+Check the choice at the given `idx`.
+
+**Params**
+
+* `val` **{Number|Array}**: The key(s) or index(s) of the choice(s) to check.
+
+**Example**
+
+```js
+choices.check(1);
+```
+
+### [.uncheck](index.js#L442)
+
+Disable the choice at the given `idx`.
+
+**Params**
+
+* `idx` **{Number}**: The index of the choice to enable.
+
+**Example**
+
+```js
+choices.uncheck(1);
+```
+
+### [.isChecked](index.js#L473)
+
+Returns true if a choice is checked.
+
+**Params**
+
+* `name` **{String|Number}**: Name or index of the choice.
+* `returns` **{Boolean}**
+
+**Example**
+
+```js
+const choices = new Choices(['foo', 'bar', 'baz']);
+console.log(choices.isChecked('foo'));
+//=> false
+choices.check('foo');
+console.log(choices.isChecked('foo'));
+//=> true
+```
+
+### [.toggle](index.js#L501)
+
+Toggle the choice at the given `idx`.
+
+**Params**
+
+* `idx` **{Number}**: The index of the choice to toggle.
+
+**Example**
+
+```js
+choices.toggle(1);
+// radio mode
+choices.toggle(1, true);
+```
+
+### [.swap](index.js#L609)
+
+Swap two choices in the choices array.
+
+**Params**
+
+* `a` **{String|Number}**
+* `b` **{String|Number}**
+* `returns` **{Object}**: Returns the `Choices` instance
+
+### [.where](index.js#L625)
+
+Return choice values for choices that return truthy based
+on the given `val`.
+
+**Params**
+
+* `val` **{Array|Object|Function|String|RegExp}**
+* `returns` **{Array}**: Matching choices or empty array
+
+### [.isItem](index.js#L673)
+
+Returns true if the given `choice` is a valid choice item, and
+not a "group" or "radio" choice.
+
+**Params**
+
+* `key` **{String}**: Property name to use for plucking objects.
+* `returns` **{Array}**: Plucked objects
+
+### [.isValidIndex](index.js#L688)
+
+Returns true if the given `index` is a valid choice index.
+
+**Params**
+
+* `key` **{String}**: Property name to use for plucking objects.
+* `returns` **{Array}**: Plucked objects
+
+### [.pluck](index.js#L699)
+
+Pluck an object with the specified key from the choices collection.
+
+**Params**
+
+* `key` **{String}**: Property name to use for plucking objects.
+* `returns` **{Array}**: Plucked objects
+
+### [.default](index.js#L735)
+
+Getter for getting the default choice.
+
+### [.checked](index.js#L762)
+
+Getter for getting the checked choices from the collection.
+
+### [.length](index.js#L804)
+
+Getter for getting the length of the collection.
+
+### [.Separator](index.js#L824)
+
+Create a new `Separator` object. See [choices-separator](https://github.com/enquirer/choices-separator) for more details.
+
+**Params**
+
+* `separator` **{String}**: Optionally pass a string to use as the separator.
+* `returns` **{Object}**: Returns a separator object.
+
+**Example**
+
+```js
+new Choices.Separator();
+```
+
+### [.isChoices](index.js#L840)
+
+Create a new `Separator` object. See [choices-separator](https://github.com/enquirer/choices-separator) for more details.
+
+**Params**
+
+* `choices` **{String}**: The value to test.
+* `returns` **{Boolean}**: Returns true if the given value is an instance of `Choices`.
+
+**Example**
+
+```js
+const Choices = require('prompt-choices');
+const choices = new Choices(['foo']);
+console.log(Choices.isChoices(choices)); //=> true
+console.log(Choices.isChoices({})); //=> false
+```
+
+### [.isChoice](index.js#L859)
+
+Create a new `Separator` object. See [choices-separator](https://github.com/enquirer/choices-separator) for more details.
+
+**Params**
+
+* `choice` **{String}**: The value to test.
+* `returns` **{Boolean}**: Returns true if the given value is an instance of `Choice`.
+
+**Example**
+
+```js
+const Choices = require('prompt-choices');
+const choices = new Choices(['foo']);
+const foo = choices.getChoice('foo');
+console.log(Choices.isChoice(foo)); //=> true
+console.log(Choices.isChoice({})); //=> false
+```
+
+## Release history
+
+### v3.0.2
+
+**Added**
+
+* adds array support to `.isChecked`
+
+**Fixed**
+
+* ensures that choice groups are checked/unchecked based on group items
+
+### v3.0.0
+
+**Added**
+
+* adds support for choice "groups"! This allows you to define an object of choice arrays, where each key in the object creates a choice group.
+
+### v2.0.0
+
+**Changed**
+
+* renamed `Move` class to `Actions`
+* renamed `choices.move` property to `choices.actions`
+
+**Removed**
+
+* removed `.enable` and `.disable` prototype methods from both `Choice` and `Choices`. These methods were ambiguous as they blurred the distinction between "enabling" a choice (meaning that it's "checked") versus enabling a property on a choice. If this is confusing, that's why they were removed.
+
+**Added**
+
+* adds `Actions` class (previously named `Move`) for managing actions on choices
+* adds `.addChoice` prototype method, for adding a single choice after instantiation
+* adds `.action` prototype method to `Choices`, which calls a method on the `Actions` class
+* adds `.check` and `.uncheck` prototype methods (previously ambiguously named `.enable` and `.disable`)
+
+## Attribution
+
+Some of the code in this library was initially based on the `Choices` class in Inquirer.
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. | [homepage](http://enquirer.io "Intuitive, plugin-based prompt system for node.js.")
+* [prompt-base](https://www.npmjs.com/package/prompt-base): Base prompt module used for creating custom prompts. | [homepage](https://github.com/enquirer/prompt-base "Base prompt module used for creating custom prompts.")
+* [prompt-checkbox](https://www.npmjs.com/package/prompt-checkbox): Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer]. | [homepage](https://github.com/enquirer/prompt-checkbox "Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer].")
+* [prompt-question](https://www.npmjs.com/package/prompt-question): Question object, used by Enquirer and prompt plugins. | [homepage](https://github.com/enquirer/prompt-question "Question object, used by Enquirer and prompt plugins.")
+* [prompt-radio](https://www.npmjs.com/package/prompt-radio): Radio prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer]. | [homepage](https://github.com/enquirer/prompt-radio "Radio prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer].")
+
+### Author
+
+**Jon Schlinkert**
+
+* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
+* [GitHub Profile](https://github.com/jonschlinkert)
+* [Twitter Profile](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 28, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-choices/index.js b/input_devices/mag/node_modules/prompt-choices/index.js
new file mode 100644
index 00000000..b718755f
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/index.js
@@ -0,0 +1,867 @@
+'use strict';
+
+const swap = require('arr-swap');
+const Paginator = require('terminal-paginator');
+const define = require('define-property');
+const visit = require('collection-visit');
+const Choice = require('./lib/choice');
+const utils = require('./lib/utils');
+
+/**
+ * Create a new `Choices` collection.
+ *
+ * ```js
+ * const choices = new Choices(['foo', 'bar', 'baz']);
+ * const choices = new Choices([{name: 'foo'}, {name: 'bar'}, {name: 'baz'}]);
+ * ```
+ * @param {Array} `choices` One or more `choice` strings or objects.
+ * @api public
+ */
+
+function Choices(choices, options) {
+  if (utils.isObject(choices) && choices.isChoices) {
+    return choices;
+  }
+
+  define(this, 'isChoices', true);
+  this.options = options || {};
+  this.answers = this.options.answers || {};
+  this.paginator = new Paginator(this.options);
+  this.choices = [];
+  this.items = [];
+  this.keymap = {};
+  this.keys = [];
+  this.original = [];
+  this.position = 0;
+
+  if (choices) {
+    this.original = utils.clone(choices);
+    this.addChoices(choices);
+  }
+}
+
+/**
+ * Render choices.
+ *
+ * @param {Number} `position` Cursor position
+ * @param {Object} `options`
+ * @return {String}
+ * @api public
+ */
+
+Choices.prototype.render = function(position, options) {
+  const opts = Object.assign({limit: 7}, this.options, options);
+  let buf = '';
+
+  if (opts.radio === true) {
+    opts.limit += 2;
+  }
+
+  this.position = position || 0;
+  for (let i = 0; i < this.choices.length; i++) {
+    let choice = this.choices[i];
+    if (opts && typeof opts.renderChoice === 'function') {
+      buf += opts.renderChoice.call(this, this.position, choice, opts);
+    } else {
+      buf += this.renderChoice(choice, this.position, opts);
+    }
+  }
+
+  const str = '\n' + buf.replace(/\s+$/, '');
+  return this.paginator.paginate(str, this.position, opts);
+};
+
+/**
+ * Render a specific choice. This can be overridden in prompts.
+ *
+ * ```js
+ * choices.render = function(choice, position, options) {
+ *   // do custom logic
+ *   return '';
+ * };
+ * ```
+ * @param {Object} `choice`
+ * @param {Number} `position`
+ * @param {Object} `options`
+ * @return {String} Returns the line to render.
+ * @api public
+ */
+
+Choices.prototype.renderChoice = function(choice, position, options) {
+  return choice.render.call(choice, position, options);
+};
+
+/**
+ * Create a new `Choice` object.
+ *
+ * ```js
+ * choices.choice('blue');
+ * ```
+ * @param {String|Object} `val`
+ * @return {Object} Returns a choice object.
+ * @api public
+ */
+
+Choices.prototype.choice = function(val) {
+  const choice = new Choice(val, this.options);
+  define(choice, 'parent', this);
+  return choice;
+};
+
+/**
+ * Returns a normalized `choice` object.
+ *
+ * ```js
+ * choices.toChoice('foo');
+ * choices.toChoice({name: 'foo'});
+ * ```
+ * @param {Object|String} `choice`
+ * @return {Object}
+ * @api public
+ */
+
+Choices.prototype.toChoice = function(choice) {
+  if (choice.type === 'separator') {
+    if (!choice.isSeparator) {
+      choice = this.separator(choice.line, this.options);
+    }
+    return choice;
+  }
+  return this.choice(choice);
+};
+
+/**
+ * Add a normalized `choice` object to the `choices` array.
+ *
+ * ```js
+ * choices.addChoice(['foo', 'bar', 'baz']);
+ * ```
+ * @param {string|Object} `choice` One or more choices to add.
+ * @api public
+ */
+
+Choices.prototype.addChoice = function(choice) {
+  choice = this.toChoice(choice);
+  if (!choice.disabled && choice.type !== 'separator') {
+    choice.index = this.items.length;
+    this.keymap[choice.key] = choice;
+    this.keys.push(choice.key);
+    this.items.push(choice);
+  }
+
+  if (this.default == null && choice.default === true) {
+    this.default = choice.name;
+    choice.default = false;
+  }
+
+  this.choices.push(choice);
+  return this;
+};
+
+/**
+ * Add an array of normalized `choice` objects to the `choices` array. This
+ * method is called in the constructor, but it can also be used to add
+ * choices after instantiation.
+ *
+ * ```js
+ * choices.addChoices(['foo', 'bar', 'baz']);
+ * ```
+ * @param {Array|Object} `choices` One or more choices to add.
+ * @api public
+ */
+
+Choices.prototype.addChoices = function(choices) {
+  if (this.options.radio === true && Array.isArray(choices) && choices.length > 1) {
+    choices = { all: choices };
+  }
+
+  if (utils.isObject(choices)) {
+    choices = this.toGroups(choices);
+  }
+
+  if (!Array.isArray(choices)) {
+    return;
+  }
+
+  for (const choice of choices) {
+    this.addChoice(choice);
+  }
+};
+
+/**
+ * Create choice "groups" from the given choices object.
+ * ![choice groups](docs/prompt-groups.gif).
+ *
+ * ```js
+ * choices.toGroups({
+ *   foo: ['a', 'b', 'c'],
+ *   bar: ['d', 'e', 'f']
+ * });
+ * ```
+ * @param {Object} `choices` (required) The value of each object must be an array of choices (strings or objects).
+ * @return {Array} Returns an array of normalized choice objects.
+ * @api public
+ */
+
+Choices.prototype.toGroups = function(choices) {
+  if (!utils.isObject(choices)) {
+    throw new TypeError('expected choices to be an object');
+  }
+
+  let line = this.separator(this.options);
+  let keys = Object.keys(choices);
+  let head = [];
+  let tail = this.options.radio ? [line] : [];
+  let items = [];
+
+  for (let i = 0; i < keys.length; i++) {
+    let key = keys[i];
+    let val = choices[key];
+    let arr = (utils.isObject(val) && val.choices) ? val.choices : val;
+
+    if (!Array.isArray(arr)) {
+      throw new TypeError('expected group choices to be an array');
+    }
+
+    let select = this.choice({
+      name: key,
+      type: 'group',
+      choices: [],
+      keys: []
+    });
+
+    if (key !== 'all') {
+      tail.push(select);
+    }
+
+    for (let j = 0; j < arr.length; j++) {
+      let choice = this.choice(arr[j]);
+      choice.type = 'option';
+      choice.group = select;
+      choice.groupName = key;
+      select.choices.push(choice);
+      select.keys.push(choice.name);
+      tail.push(choice);
+      items.push(choice);
+    }
+  }
+
+  let none = {name: 'none', type: 'radio', choices: items};
+  let all = {name: 'all', type: 'radio', choices: items};
+  if (keys.length === 1 && items.length <= 2) {
+    return tail.filter(function(choice) {
+      let isOption = choice.type === 'option';
+      delete choice.type;
+      return isOption;
+    });
+  }
+
+  if (this.options.radio === true) {
+    head.unshift(none);
+    head.unshift(all);
+
+  } else if (keys.length === 1 && keys[0] === 'all') {
+    head.push(none);
+  }
+
+  return head.concat(tail);
+};
+
+/**
+ * Create a new `Separator` object. See [choices-separator][]
+ * for more details.
+ *
+ * ```js
+ * choices.separator();
+ * ```
+ * @param {String} `separator` Optionally pass a string to use as the separator.
+ * @return {Object} Returns a separator object.
+ * @api public
+ */
+
+Choices.prototype.separator = function(separator, options) {
+  return new utils.Separator(separator, options);
+};
+
+/**
+ * Returns true if a choice exists.
+ *
+ * ```js
+ * choices.hasChoice(1);
+ * choices.hasChoice('foo');
+ * ```
+ * @param {Number} `val` The index or key of the choice to check for.
+ * @return {Boolean}
+ * @api public
+ */
+
+Choices.prototype.hasChoice = function(val) {
+  return typeof this.get(val) !== 'undefined';
+};
+
+/**
+ * Get a non-separator choice from the collection.
+ *
+ * ```js
+ * choices.getChoice(1);
+ * choices.getChoice('foo');
+ * ```
+ * @param {Number} `idx` The selected choice index
+ * @return {Object|undefined} Return the matched choice object or undefined
+ * @api public
+ */
+
+Choices.prototype.getChoice = function(idx) {
+  if (typeof idx === 'string') {
+    idx = this.getIndex(idx);
+  }
+
+  const choice = this.items[idx];
+  if (choice) {
+    choice.index = idx;
+    return choice;
+  }
+};
+
+/**
+ * Get the index of a non-separator choice from the collection.
+ *
+ * ```js
+ * const choices = new Choices(['foo', 'bar', 'baz']);
+ * console.log(choices.getIndex('foo')); //=> 0
+ * console.log(choices.getIndex('baz')); //=> 2
+ * console.log(choices.getIndex('bar')); //=> 1
+ * console.log(choices.getIndex('qux')); //=> -1
+ * ```
+ * @param {String} `key` The key of the choice to get
+ * @return {Number} Index of the choice or `-1`;
+ * @api public
+ */
+
+Choices.prototype.getIndex = function(key) {
+  if (Choices.isChoice(key)) {
+    return this.items.indexOf(key);
+  }
+  if (typeof key === 'string') {
+    return this.items.indexOf(this.keymap[key]);
+  }
+  return this.isValidIndex(key) ? key : -1;
+};
+
+/**
+ * Get the choice at the specified index.
+ *
+ * ```js
+ * const choice = choices.get(1);
+ * //=> {name: 'foo'}
+ * const choice = choices.get(1, 'name');
+ * //=> 'foo'
+ * ```
+ * @param {Number|String} `key` The name or index of the object to get
+ * @return {Object} Returns the specified choice
+ * @api public
+ */
+
+Choices.prototype.get = function(key, prop) {
+  if (typeof key === 'string') {
+    key = this.getIndex(key);
+  }
+  if (!utils.isNumber(key)) {
+    return null;
+  }
+  const choice = this.getChoice(key);
+  if (choice && typeof prop === 'string') {
+    return choice[prop];
+  }
+  return choice;
+};
+
+/**
+ * Clear all choices from the instance. This is useful when you
+ * need to update the indices of choices without re-instantiating.
+ *
+ * ```js
+ * choices.clear();
+ * ```
+ * @api public
+ */
+
+Choices.prototype.clear = function() {
+  this.choices = [];
+  this.items = [];
+  this.keymap = {};
+  this.keys = [];
+};
+
+/**
+ * Return the `.key` property from the choice at the given index.
+ * @param {String} `key` Property name to use for plucking objects.
+ * @return {Array} Plucked objects
+ * @api public
+ */
+
+Choices.prototype.key = function(val) {
+  return this.get(val, 'key');
+};
+
+/**
+ * Check the choice at the given `idx`.
+ *
+ * ```js
+ * choices.check(1);
+ * ```
+ * @param {Number|Array} `val` The key(s) or index(s) of the choice(s) to check.
+ * @api public
+ */
+
+Choices.prototype.check = function(val) {
+  if (typeof val === 'undefined') {
+    val = this.keys;
+  }
+  if (Array.isArray(val)) {
+    visit(this, 'check', val);
+    return this;
+  }
+  const choice = this.get(val);
+  if (choice != null) {
+    choice.checked = true;
+  }
+  return this;
+};
+
+/**
+ * Disable the choice at the given `idx`.
+ *
+ * ```js
+ * choices.uncheck(1);
+ * ```
+ * @param {Number} `idx` The index of the choice to enable.
+ * @api public
+ */
+
+Choices.prototype.uncheck = function(val) {
+  if (typeof val === 'undefined') {
+    val = this.keys;
+  }
+  if (Array.isArray(val)) {
+    visit(this, 'uncheck', val);
+    return this;
+  }
+  const choice = this.get(val);
+  if (choice) {
+    choice.checked = false;
+  }
+  return this;
+};
+
+/**
+ * Returns true if a choice is checked.
+ *
+ * ```js
+ * const choices = new Choices(['foo', 'bar', 'baz']);
+ * console.log(choices.isChecked('foo'));
+ * //=> false
+ * choices.check('foo');
+ * console.log(choices.isChecked('foo'));
+ * //=> true
+ * ```
+ * @param {String|Number} `name` Name or index of the choice.
+ * @return {Boolean}
+ * @api public
+ */
+
+Choices.prototype.isChecked = function(name) {
+  if (Array.isArray(name)) {
+    for (const ele of name) {
+      if (!this.isChecked(ele)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  const choice = this.get(name);
+  if (choice) {
+    return choice.checked === true;
+  }
+};
+
+/**
+ * Toggle the choice at the given `idx`.
+ *
+ * ```js
+ * choices.toggle(1);
+ * // radio mode
+ * choices.toggle(1, true);
+ * ```
+ * @param {Number} `idx` The index of the choice to toggle.
+ * @api public
+ */
+
+Choices.prototype.toggle = function(val, radio) {
+  if (typeof val === 'undefined') {
+    val = this.keys;
+  }
+
+  if (Array.isArray(val)) {
+    visit(this, 'toggle', val, radio);
+    return this;
+  }
+
+  const choice = this.get(val);
+  if (!choice) {
+    return this;
+  }
+
+  if (radio) {
+    utils.toggle(this.items, 'checked', this.getIndex(choice));
+  } else {
+    choice.toggle();
+  }
+
+  if (choice.type === 'group') {
+    choice.checked = this.isChecked(choice.keys);
+  }
+  if (choice.type === 'option') {
+    choice.group.checked = this.isChecked(choice.group.keys);
+  }
+
+  this.update();
+  return this;
+};
+
+/**
+ * When user press `enter` key
+ */
+
+Choices.prototype.radio = function() {
+  const choice = this.get(this.position);
+  if (!choice) return;
+
+  if (choice.type === 'group') {
+    if (choice.checked === true) {
+      this.uncheck(choice.keys);
+    } else {
+      this.check(choice.keys);
+    }
+    choice.toggle();
+    this.update();
+    return;
+  }
+
+  if (choice.type === 'option') {
+    choice.toggle();
+    choice.group.checked = this.isChecked(choice.group.keys);
+    this.update();
+    return;
+  }
+
+  if (this.length > 1) {
+    if (choice.name === 'all') {
+      this[choice.checked ? 'uncheck' : 'check']();
+      this.toggle('none');
+      this.update();
+      return;
+    }
+
+    if (choice.name === 'none') {
+      this.uncheck();
+      this.check(this.position);
+      this.update();
+      return;
+    }
+  }
+
+  choice.toggle();
+  this.update();
+};
+
+/**
+ * Update "radio" choices to ensure that `all` and `none` are
+ * correct based on other choices.
+ */
+
+Choices.prototype.update = function() {
+  if (this.all) {
+    this.check('all');
+    this.uncheck('none');
+    return;
+  }
+  if (this.none) {
+    this.uncheck('all');
+    this.check('none');
+    return;
+  }
+  if (this.checked.length) {
+    this.uncheck(['all', 'none']);
+  }
+};
+
+/**
+ * Swap two choices in the choices array.
+ *
+ * @param {String|Number} `a`
+ * @param {String|Number} `b`
+ * @return {Object} Returns the `Choices` instance
+ * @api public
+ */
+
+Choices.prototype.swap = function(a, b) {
+  const choices = swap(this.choices.slice(), a, b);
+  this.clear();
+  this.addChoices(choices);
+  return this;
+};
+
+/**
+ * Return choice values for choices that return truthy based
+ * on the given `val`.
+ *
+ * @param {Array|Object|Function|String|RegExp} `val`
+ * @return {Array} Matching choices or empty array
+ * @api public
+ */
+
+Choices.prototype.where = function(val) {
+  if (typeof val === 'function') {
+    return this.filter(val);
+  }
+
+  if (typeof val === 'string') {
+    return this.filter(function(choice) {
+      return choice.name === val || choice.key === val;
+    });
+  }
+
+  if (utils.typeOf(val) === 'regexp') {
+    return this.filter(function(choice) {
+      return val.test(choice.name) || val.test(choice.key);
+    });
+  }
+
+  if (utils.isObject(val)) {
+    return this.filter(function(choice) {
+      for (const key in val) {
+        if (!choice.hasOwnProperty(key)) {
+          return false;
+        }
+        return val[key] === choice[key];
+      }
+    });
+  }
+
+  if (Array.isArray(val)) {
+    let acc = [];
+    for (const ele of val) {
+      acc = acc.concat(this.where.call(this, ele));
+    }
+    return acc;
+  }
+
+  return [];
+};
+
+/**
+ * Returns true if the given `choice` is a valid choice item, and
+ * not a "group" or "radio" choice.
+ *
+ * @param {String} `key` Property name to use for plucking objects.
+ * @return {Array} Plucked objects
+ * @api public
+ */
+
+Choices.prototype.isItem = function(choice) {
+  return choice.type !== 'separator'
+    && choice.type !== 'group'
+    && choice.type !== 'radio'
+    && choice.name !== 'none'
+    && choice.name !== 'all';
+};
+
+/**
+ * Returns true if the given `index` is a valid choice index.
+ * @param {String} `key` Property name to use for plucking objects.
+ * @return {Array} Plucked objects
+ * @api public
+ */
+
+Choices.prototype.isValidIndex = function(idx) {
+  return utils.isNumber(idx) && idx !== -1 && idx < this.items.length;
+};
+
+/**
+ * Pluck an object with the specified key from the choices collection.
+ * @param {String} `key` Property name to use for plucking objects.
+ * @return {Array} Plucked objects
+ * @api public
+ */
+
+Choices.prototype.pluck = function(key) {
+  return this.items.map(function(choice) {
+    return choice[key];
+  });
+};
+
+/**
+ * Convenience array methods
+ */
+
+Choices.prototype.indexOf = function() {
+  return this.getChoice(this.keys.indexOf.apply(this.keys, arguments));
+};
+
+Choices.prototype.forEach = function() {
+  return this.items.forEach.apply(this.items, arguments);
+};
+
+Choices.prototype.filter = function() {
+  return this.items.filter.apply(this.items, arguments);
+};
+
+Choices.prototype.some = function() {
+  return this.items.some.apply(this.items, arguments);
+};
+
+Choices.prototype.every = function() {
+  return this.items.every.apply(this.items, arguments);
+};
+
+/**
+ * Getter for getting the default choice.
+ * @name .default
+ * @api public
+ */
+
+Object.defineProperty(Choices.prototype, 'default', {
+  configurable: true,
+  set: function(val) {
+    this._default = this.getIndex(val);
+  },
+  get: function() {
+    if (this._default == null) {
+      for (const choice of this.items) {
+        if (choice.default === true) {
+          define(this, '_default', choice.index);
+          break;
+        }
+      }
+    }
+    if (this._default != null) {
+      this.check(this.getIndex(this._default));
+    }
+    return this._default;
+  }
+});
+
+/**
+ * Getter for getting the checked choices from the collection.
+ * @name .checked
+ * @api public
+ */
+
+Object.defineProperty(Choices.prototype, 'checked', {
+  set: function() {
+    throw new Error('.checked is a getter and cannot be defined');
+  },
+  get: function() {
+    return this.items.reduce(function(acc, choice) {
+      if (this.options.radio === true && !this.isItem(choice)) {
+        return acc;
+      }
+      if (choice.checked === true) {
+        acc.push(choice.value);
+      }
+      return acc;
+    }.bind(this), []);
+  }
+});
+
+Object.defineProperty(Choices.prototype, 'all', {
+  set: function() {
+    throw new Error('.all is a getter and cannot be defined');
+  },
+  get: function() {
+    const items = this.filter(this.isItem);
+    return items.length === this.checked.length;
+  }
+});
+
+Object.defineProperty(Choices.prototype, 'none', {
+  set: function() {
+    throw new Error('.none is a getter and may not be defined');
+  },
+  get: function() {
+    return this.checked.length === 0;
+  }
+});
+
+/**
+ * Getter for getting the length of the collection.
+ * @name .length
+ * @api public
+ */
+
+Object.defineProperty(Choices.prototype, 'length', {
+  set: function() {
+    throw new Error('.length is a getter and cannot be defined');
+  },
+  get: function() {
+    return this.items.length;
+  }
+});
+
+/**
+ * Create a new `Separator` object. See [choices-separator][] for more details.
+ *
+ * ```js
+ * new Choices.Separator();
+ * ```
+ * @param {String} `separator` Optionally pass a string to use as the separator.
+ * @return {Object} Returns a separator object.
+ * @api public
+ */
+
+Choices.Separator = utils.Separator;
+
+/**
+ * Create a new `Separator` object. See [choices-separator][] for more details.
+ *
+ * ```js
+ * const Choices = require('prompt-choices');
+ * const choices = new Choices(['foo']);
+ * console.log(Choices.isChoices(choices)); //=> true
+ * console.log(Choices.isChoices({})); //=> false
+ * ```
+ * @param {String} `choices` The value to test.
+ * @return {Boolean} Returns true if the given value is an instance of `Choices`.
+ * @api public
+ */
+
+Choices.isChoices = function(choices) {
+  return utils.isObject(choices) && choices.isChoices;
+};
+
+/**
+ * Create a new `Separator` object. See [choices-separator][] for more details.
+ *
+ * ```js
+ * const Choices = require('prompt-choices');
+ * const choices = new Choices(['foo']);
+ * const foo = choices.getChoice('foo');
+ * console.log(Choices.isChoice(foo)); //=> true
+ * console.log(Choices.isChoice({})); //=> false
+ * ```
+ * @param {String} `choice` The value to test.
+ * @return {Boolean} Returns true if the given value is an instance of `Choice`.
+ * @api public
+ */
+
+Choices.isChoice = function(choice) {
+  return utils.isObject(choice) && choice.isChoice;
+};
+
+/**
+ * Expose `Choices`
+ */
+
+module.exports = Choices;
diff --git a/input_devices/mag/node_modules/prompt-choices/lib/choice.js b/input_devices/mag/node_modules/prompt-choices/lib/choice.js
new file mode 100644
index 00000000..6bb1c9eb
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/lib/choice.js
@@ -0,0 +1,258 @@
+'use strict';
+
+const log = require('log-utils');
+const koalas = require('koalas');
+const define = require('define-property');
+const pointer = require('pointer-symbol');
+const radio = require('radio-symbol');
+const strip = require('strip-color');
+const utils = require('./utils');
+
+/**
+ * Create a new `Choice` to create a normalized choice object from the given input.
+ * @param {String|Object} `val` Choice value. If an object is passed, it should contains at least one of `value` or `name` property.
+ * @api public
+ */
+
+function Choice(choice, options) {
+  if (typeof choice === 'string') {
+    choice = { name: choice };
+  }
+  if (!utils.isObject(choice)) {
+    throw new TypeError('expected choice to be a string or object');
+  }
+  if (choice.type === 'separator' || choice.isSeparator) {
+    choice.isSeparator = true;
+  }
+  if (choice.isChoice || choice instanceof Choice) {
+    return choice;
+  }
+  define(this, 'cache', {});
+  this.initChoice(choice, options);
+}
+
+/**
+ * Initialize choice.
+ * @param {Object} `choice`
+ * @param {Object} `options`
+ */
+
+Choice.prototype.initChoice = function(choice, options) {
+  define(this, 'isChoice', true);
+
+  this.name = null;
+  this.short = null;
+  this.value = null;
+  this.disabled = false;
+  this.checked = false;
+  this.index = 0;
+
+  define(this, 'position', 0);
+  define(this, 'options', options || {});
+  Object.assign(this, choice);
+
+  this.name = choice.name || choice.value;
+  if (typeof choice.hint === 'string') {
+    this.hint = choice.hint;
+  }
+
+  this.value = choice.hasOwnProperty('value') ? choice.value : choice.name;
+  this.short = choice.short || choice.name;
+  define(this, 'key', this.key || this.short);
+
+  this.pointer = pointer(this.options);
+  if (!this.options.pointer) {
+    this.pointer = log.cyan(this.pointer);
+  }
+
+  define(this, 'prefix', this.padding(this.pointer));
+};
+
+Choice.prototype.render = function(idx, options) {
+  options = options || {};
+  if (typeof options.pointer === 'string') {
+    this.pointer = options.pointer;
+  }
+  if (typeof options.checkbox === 'string') {
+    this.symbol = options.checkbox;
+  }
+  if (this.type === 'separator') {
+    return this.value;
+  }
+  this.position = idx;
+  return this.line;
+};
+
+Choice.prototype.toggle = function() {
+  this.checked = !this.checked;
+  return this;
+};
+
+Choice.prototype.format = function(str) {
+  if (typeof this.options.format === 'function') {
+    str = this.options.format.call(this, str);
+  }
+  return this.disabled ? log.dim(str) : str;
+};
+
+Choice.prototype.padding = function(val) {
+  return Array(strip(val).length + 1).join(' ');
+};
+
+/**
+ * Getter for getting the pointer to use before each line in the prompt
+ * @name .pointer
+ * @api public
+ */
+
+Object.defineProperty(Choice.prototype, 'siblings', {
+  get: function() {
+    return this.parent ? this.parent.items : null;
+  }
+});
+
+/**
+ * Getter for getting the choice.index
+ * @name .index
+ * @api public
+ */
+
+Object.defineProperty(Choice.prototype, 'index', {
+  set: function(index) {
+    define(this, 'idx', index);
+  },
+  get: function() {
+    if (!Array.isArray(this.siblings)) {
+      return this.idx;
+    }
+    var choice = this.siblings[this.idx];
+    if (choice !== this) {
+      this.idx = this.siblings.indexOf(this);
+    }
+    return this.idx;
+  }
+});
+
+/**
+ * Getter for getting the pointer to use before each line in the prompt
+ * @name .pointer
+ * @api public
+ */
+
+Object.defineProperty(Choice.prototype, 'pointer', {
+  set: function(val) {
+    define(this.cache, 'pointer', val);
+  },
+  get: function() {
+    var pointer = this.cache.pointer || this.options.pointer;
+    if (this.position !== this.index) {
+      return (this.prefix = this.padding(pointer));
+    }
+    return pointer;
+  }
+});
+
+/**
+ * Getter for getting the current state of the choice. States
+ * are `on`, `off` and `disabled`.
+ * @name .state
+ * @api public
+ */
+
+Object.defineProperty(Choice.prototype, 'state', {
+  set: function() {
+    throw new Error('.state is a getter and cannot be defined');
+  },
+  get: function() {
+    if (this.disabled) {
+      return 'disabled';
+    }
+    return this.checked ? 'on' : 'off';
+  }
+});
+
+/**
+ * Getter for getting the checkbox or radio symbol to use.
+ * @name .symbol
+ * @api public
+ */
+
+Object.defineProperty(Choice.prototype, 'symbol', {
+  set: function(val) {
+    if (typeof val === 'string') {
+      throw new TypeError('expected checkbox symbol to be an object');
+    }
+    this.options.symbol = val;
+  },
+  get: function() {
+    var opts = this.options;
+    var symbol = koalas(opts.checkbox, opts.symbol, radio);
+    if (symbol === false) {
+      return '';
+    }
+    return symbol[this.state];
+  }
+});
+
+/**
+ * Getter for getting the line to render for a choice
+ * @name .line
+ * @api public
+ */
+
+Object.defineProperty(Choice.prototype, 'line', {
+  configurable: true,
+  set: function(line) {
+    if (typeof line === 'string') this.value = line;
+  },
+  get: function() {
+    var line = this.value;
+    if (line.trim() === 'all' || line.trim() === 'none') {
+      line = log.bold(line);
+    }
+
+    if (typeof this.disabled === 'string') {
+      this.pointer = this.prefix;
+      line += ' (' + this.disabled + ')';
+    } else if (this.disabled === true) {
+      this.pointer = this.prefix;
+      line += ' (Disabled)';
+    } else if (typeof this.hint === 'string') {
+      line += this.hint;
+    }
+
+    var symbol = this.symbol;
+    if (this.type === 'option') {
+      symbol = '  ' + radio.check[this.state];
+    }
+
+    return this.pointer + symbol + ' '
+      + this.format(line).replace(/\s+$/, '')
+      + '\n';
+  }
+});
+
+/**
+ * Getter for getting the line to render for a choice
+ * @name .line
+ * @api public
+ */
+
+Object.defineProperty(Choice.prototype, 'disabled', {
+  enumerable: true,
+  set: function(disabled) {
+    define(this.cache, 'disabled', disabled);
+  },
+  get: function() {
+    if (typeof this.cache.disabled === 'function') {
+      return this.cache.disabled.call(this, this.options.answers);
+    }
+    return this.cache.disabled;
+  }
+});
+
+/**
+ * Expose Choice
+ */
+
+module.exports = Choice;
diff --git a/input_devices/mag/node_modules/prompt-choices/lib/utils.js b/input_devices/mag/node_modules/prompt-choices/lib/utils.js
new file mode 100644
index 00000000..1c7361cd
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/lib/utils.js
@@ -0,0 +1,46 @@
+'use strict';
+
+const isNumber = require('is-number');
+
+/**
+ * Lazily require module dependencies in a way that is both
+ * friendly to node.js and webpack/browserify.
+ */
+
+define(exports, 'flatten', () => require('arr-flatten'));
+define(exports, 'clone', () => require('clone-deep'));
+define(exports, 'Separator', () => require('choices-separator'));
+define(exports, 'define', () => require('define-property'));
+define(exports, 'typeOf', () => require('kind-of'));
+define(exports, 'toggle', () => require('toggle-array'));
+define(exports, 'set', () => require('set-value'));
+
+function define(obj, key, value) {
+  Reflect.defineProperty(obj, key, { get: value });
+}
+
+/**
+ * Returns true if `val` is a number (also ensures that val
+ * is not whitespace, which is cast to `0`)
+ */
+
+exports.isNumber = function(val) {
+  return isNumber(val) && String(val).trim() !== '';
+};
+
+/**
+ * Returns true if `val` is a number (also ensures that val
+ * is not whitespace, which is cast to `0`)
+ */
+
+exports.isObject = function(val) {
+  return exports.typeOf(val) === 'object';
+};
+
+/**
+ * Cast `val` to an array.
+ */
+
+exports.arrayify = function(val) {
+  return val ? (Array.isArray(val) ? val : [val]) : [];
+};
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/LICENSE b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/LICENSE
new file mode 100644
index 00000000..d32ab442
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2018, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/README.md b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/README.md
new file mode 100644
index 00000000..6f1a3ab8
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/README.md
@@ -0,0 +1,98 @@
+# clone-deep [![NPM version](https://img.shields.io/npm/v/clone-deep.svg?style=flat)](https://www.npmjs.com/package/clone-deep) [![NPM monthly downloads](https://img.shields.io/npm/dm/clone-deep.svg?style=flat)](https://npmjs.org/package/clone-deep) [![NPM total downloads](https://img.shields.io/npm/dt/clone-deep.svg?style=flat)](https://npmjs.org/package/clone-deep) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/clone-deep.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/clone-deep)
+
+> Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save clone-deep
+```
+
+## Usage
+
+```js
+var cloneDeep = require('clone-deep');
+
+var obj = {a: 'b'};
+var arr = [obj];
+
+var copy = cloneDeep(arr);
+obj.c = 'd';
+
+console.log(copy);
+//=> [{a: 'b'}]
+
+console.log(arr);
+//=> [{a: 'b', c: 'd'}]
+```
+
+## Heads up!
+
+The `instanceClone` function is invoked to clone objects that are not "plain" objects (as defined by [isPlainObject](#isPlainObject)`isPlainObject`) if it is provided. If `instanceClone` is not specified, it will not attempt to clone non-plain objects, and will copy the object reference.
+
+## Attribution
+
+Based on [mout's](https://github.com/mout/mout) implementation of deepClone.
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+* [shallow-clone](https://www.npmjs.com/package/shallow-clone): Creates a shallow clone of any JavaScript value. | [homepage](https://github.com/jonschlinkert/shallow-clone "Creates a shallow clone of any JavaScript value.")
+
+### Author
+
+**Jon Schlinkert**
+
+* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
+* [GitHub Profile](https://github.com/jonschlinkert)
+* [Twitter Profile](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on April 10, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/index.js b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/index.js
new file mode 100644
index 00000000..7741f3b0
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/index.js
@@ -0,0 +1,48 @@
+'use strict';
+
+/**
+ * Module dependenices
+ */
+
+const clone = require('shallow-clone');
+const typeOf = require('kind-of');
+
+function cloneDeep(val, instanceClone) {
+  switch (typeOf(val)) {
+    case 'object':
+      return cloneObjectDeep(val, instanceClone);
+    case 'array':
+      return cloneArrayDeep(val, instanceClone);
+    default: {
+      return clone(val);
+    }
+  }
+}
+
+function cloneObjectDeep(val, instanceClone) {
+  if (typeof instanceClone === 'function') {
+    return instanceClone(val);
+  }
+  if (typeOf(val) === 'object') {
+    const res = new val.constructor();
+    for (const key in val) {
+      res[key] = cloneDeep(val[key], instanceClone);
+    }
+    return res;
+  }
+  return val;
+}
+
+function cloneArrayDeep(val, instanceClone) {
+  const res = new val.constructor(val.length);
+  for (let i = 0; i < val.length; i++) {
+    res[i] = cloneDeep(val[i], instanceClone);
+  }
+  return res;
+}
+
+/**
+ * Expose `cloneDeep`
+ */
+
+module.exports = cloneDeep;
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/package.json b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/package.json
new file mode 100644
index 00000000..9f8d04d0
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep/package.json
@@ -0,0 +1,141 @@
+{
+  "_args": [
+    [
+      "clone-deep@^4.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "clone-deep@>=4.0.0 <5.0.0",
+  "_id": "clone-deep@4.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-choices/clone-deep",
+  "_nodeVersion": "9.9.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/clone-deep_4.0.0_1523343881408_0.8365443462498223"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.8.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "clone-deep",
+    "raw": "clone-deep@^4.0.0",
+    "rawSpec": "^4.0.0",
+    "scope": null,
+    "spec": ">=4.0.0 <5.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.0.tgz",
+  "_shasum": "a41ae54db9048b407d9c73e703297a12e1dfd932",
+  "_shrinkwrap": null,
+  "_spec": "clone-deep@^4.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/clone-deep/issues"
+  },
+  "dependencies": {
+    "kind-of": "^6.0.2",
+    "shallow-clone": "^3.0.0"
+  },
+  "description": "Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-aNJ5/7Bz2IYBb7nIj34TLGk78lBXpXUgV9qsLngtTvJ9+scsZNnlU0OX2S2N4ax/sUQt7sDBkXiGjGJEmNbXOQ==",
+    "shasum": "a41ae54db9048b407d9c73e703297a12e1dfd932",
+    "tarball": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.0.tgz",
+    "unpackedSize": 7393
+  },
+  "engines": {
+    "node": ">=8"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e5735371900714e976a369a27cfeab7a1991c887",
+  "homepage": "https://github.com/jonschlinkert/clone-deep",
+  "keywords": [
+    "array",
+    "assign",
+    "buffer",
+    "clamped",
+    "clone",
+    "clone-array",
+    "clone-array-deep",
+    "clone-buffer",
+    "clone-date",
+    "clone-deep",
+    "clone-object",
+    "clone-object-deep",
+    "clone-reg-exp",
+    "clone-regex",
+    "clone-regexp",
+    "date",
+    "deep",
+    "extend",
+    "mixin",
+    "mixin-object",
+    "object",
+    "shallow",
+    "symbol"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "clone-deep",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/clone-deep.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-plain-object",
+        "isobject",
+        "kind-of",
+        "shallow-clone"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "4.0.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/CHANGELOG.md b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/CHANGELOG.md
new file mode 100644
index 00000000..901c8aae
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/CHANGELOG.md
@@ -0,0 +1,82 @@
+# Release history
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<details>
+  <summary><strong>Guiding Principles</strong></summary>
+
+- Changelogs are for humans, not machines.
+- There should be an entry for every single version.
+- The same types of changes should be grouped.
+- Versions and sections should be linkable.
+- The latest version comes first.
+- The release date of each versions is displayed.
+- Mention whether you follow Semantic Versioning.
+
+</details>
+
+<details>
+  <summary><strong>Types of changes</strong></summary>
+
+Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_):
+
+- `Added` for new features.
+- `Changed` for changes in existing functionality.
+- `Deprecated` for soon-to-be removed features.
+- `Removed` for now removed features.
+- `Fixed` for any bug fixes.
+- `Security` in case of vulnerabilities.
+
+</details>
+
+## [2.0.0] - 2017-04-20
+
+### Changed
+
+- Now supports data descriptors in addition to accessor descriptors.
+- Now uses [Reflect.defineProperty][reflect] when available, otherwise falls back to [Object.defineProperty][object]. 
+
+## [1.0.0] - 2017-04-20
+
+- stable release
+
+## [0.2.5] - 2015-08-31
+
+- use is-descriptor
+
+## [0.2.3] - 2015-08-29
+
+- check keys length
+
+## [0.2.2] - 2015-08-27
+
+- ensure val is an object
+
+## [0.2.1] - 2015-08-27
+
+- support functions
+
+## [0.2.0] - 2015-08-27
+
+- support get/set
+- update docs
+
+## [0.1.0] - 2015-08-12
+
+- first commit
+
+[2.0.0]: https://github.com/jonschlinkert/define-property/compare/1.0.0...2.0.0
+[1.0.0]: https://github.com/jonschlinkert/define-property/compare/0.2.5...1.0.0
+[0.2.5]: https://github.com/jonschlinkert/define-property/compare/0.2.3...0.2.5
+[0.2.3]: https://github.com/jonschlinkert/define-property/compare/0.2.2...0.2.3
+[0.2.2]: https://github.com/jonschlinkert/define-property/compare/0.2.1...0.2.2
+[0.2.1]: https://github.com/jonschlinkert/define-property/compare/0.2.0...0.2.1
+[0.2.0]: https://github.com/jonschlinkert/define-property/compare/0.1.3...0.2.0
+
+[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog
+
+[object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
+[reflect]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/LICENSE b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/LICENSE
new file mode 100644
index 00000000..f8de0630
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2018, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/README.md b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/README.md
new file mode 100644
index 00000000..f1ee8f92
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/README.md
@@ -0,0 +1,117 @@
+# define-property [![NPM version](https://img.shields.io/npm/v/define-property.svg?style=flat)](https://www.npmjs.com/package/define-property) [![NPM monthly downloads](https://img.shields.io/npm/dm/define-property.svg?style=flat)](https://npmjs.org/package/define-property) [![NPM total downloads](https://img.shields.io/npm/dt/define-property.svg?style=flat)](https://npmjs.org/package/define-property) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/define-property.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/define-property)
+
+> Define a non-enumerable property on an object. Uses Reflect.defineProperty when available, otherwise Object.defineProperty.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save define-property
+```
+
+## Release history
+
+See [the CHANGELOG](changelog.md) for updates.
+
+## Usage
+
+**Params**
+
+* `object`: The object on which to define the property.
+* `key`: The name of the property to be defined or modified.
+* `value`: The value or descriptor of the property being defined or modified.
+
+```js
+var define = require('define-property');
+var obj = {};
+define(obj, 'foo', function(val) {
+  return val.toUpperCase();
+});
+
+// by default, defined properties are non-enumberable
+console.log(obj);
+//=> {}
+
+console.log(obj.foo('bar'));
+//=> 'BAR'
+```
+
+**defining setters/getters**
+
+Pass the same properties you would if using [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) or [Reflect.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty).
+
+```js
+define(obj, 'foo', {
+  set: function() {},
+  get: function() {}
+});
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [assign-deep](https://www.npmjs.com/package/assign-deep): Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target… [more](https://github.com/jonschlinkert/assign-deep) | [homepage](https://github.com/jonschlinkert/assign-deep "Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target (first) object.")
+* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow "Extend an object with the properties of additional objects. node.js/javascript util.")
+* [merge-deep](https://www.npmjs.com/package/merge-deep): Recursively merge values in a javascript object. | [homepage](https://github.com/jonschlinkert/merge-deep "Recursively merge values in a javascript object.")
+* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep "Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone.")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 28 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [doowb](https://github.com/doowb) |
+
+### Author
+
+**Jon Schlinkert**
+
+* Connect with me on [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
+* Follow me on [github/jonschlinkert](https://github.com/jonschlinkert)
+* Follow me on [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on January 25, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/index.js b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/index.js
new file mode 100644
index 00000000..0efa0a9e
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/index.js
@@ -0,0 +1,38 @@
+/*!
+ * define-property <https://github.com/jonschlinkert/define-property>
+ *
+ * Copyright (c) 2015-2018, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var isobject = require('isobject');
+var isDescriptor = require('is-descriptor');
+var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty)
+  ? Reflect.defineProperty
+  : Object.defineProperty;
+
+module.exports = function defineProperty(obj, key, val) {
+  if (!isobject(obj) && typeof obj !== 'function' && !Array.isArray(obj)) {
+    throw new TypeError('expected an object, function, or array');
+  }
+
+  if (typeof key !== 'string') {
+    throw new TypeError('expected "key" to be a string');
+  }
+
+  if (isDescriptor(val)) {
+    define(obj, key, val);
+    return obj;
+  }
+
+  define(obj, key, {
+    configurable: true,
+    enumerable: false,
+    writable: true,
+    value: val
+  });
+
+  return obj;
+};
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/package.json b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/package.json
new file mode 100644
index 00000000..5289fd56
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/define-property/package.json
@@ -0,0 +1,136 @@
+{
+  "_args": [
+    [
+      "define-property@^2.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "define-property@>=2.0.2 <3.0.0",
+  "_id": "define-property@2.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-choices/define-property",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/define-property-2.0.2.tgz_1516998261413_0.9784700081218034"
+  },
+  "_npmUser": {
+    "email": "brian.woodward@gmail.com",
+    "name": "doowb"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "define-property",
+    "raw": "define-property@^2.0.2",
+    "rawSpec": "^2.0.2",
+    "scope": null,
+    "spec": ">=2.0.2 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+  "_shasum": "d459689e8d654ba77e02a817f8710d702cb16e9d",
+  "_shrinkwrap": null,
+  "_spec": "define-property@^2.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/define-property/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "is-descriptor": "^1.0.2",
+    "isobject": "^3.0.1"
+  },
+  "description": "Define a non-enumerable property on an object. Uses Reflect.defineProperty when available, otherwise Object.defineProperty.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+    "shasum": "d459689e8d654ba77e02a817f8710d702cb16e9d",
+    "tarball": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "04717307be822f2ca2544778b92e5d2cbe300c55",
+  "homepage": "https://github.com/jonschlinkert/define-property",
+  "keywords": [
+    "define",
+    "define-property",
+    "enumerable",
+    "key",
+    "non",
+    "non-enumerable",
+    "object",
+    "prop",
+    "property",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "define-property",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/define-property.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "assign-deep",
+        "extend-shallow",
+        "merge-deep",
+        "mixin-deep"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.0.2"
+}
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/CHANGELOG.md b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/CHANGELOG.md
new file mode 100644
index 00000000..fb30b06d
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/CHANGELOG.md
@@ -0,0 +1,157 @@
+# Release history
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<details>
+  <summary><strong>Guiding Principles</strong></summary>
+
+- Changelogs are for humans, not machines.
+- There should be an entry for every single version.
+- The same types of changes should be grouped.
+- Versions and sections should be linkable.
+- The latest version comes first.
+- The release date of each versions is displayed.
+- Mention whether you follow Semantic Versioning.
+
+</details>
+
+<details>
+  <summary><strong>Types of changes</strong></summary>
+
+Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_):
+
+- `Added` for new features.
+- `Changed` for changes in existing functionality.
+- `Deprecated` for soon-to-be removed features.
+- `Removed` for now removed features.
+- `Fixed` for any bug fixes.
+- `Security` in case of vulnerabilities.
+
+</details>
+
+## [6.0.0] - 2017-10-13
+
+- refactor code to be more performant
+- refactor benchmarks
+
+## [5.1.0] - 2017-10-13
+
+**Added**
+
+- Merge pull request #15 from aretecode/patch-1
+- adds support and tests for string & array iterators
+
+**Changed**
+
+- updates benchmarks
+
+## [5.0.2] - 2017-08-02
+
+- Merge pull request #14 from struct78/master
+- Added `undefined` check
+
+## [5.0.0] - 2017-06-21
+
+- Merge pull request #12 from aretecode/iterator
+- Set Iterator + Map Iterator
+- streamline `isbuffer`, minor edits
+
+## [4.0.0] - 2017-05-19
+
+- Merge pull request #8 from tunnckoCore/master
+- update deps
+
+## [3.2.2] - 2017-05-16
+
+- fix version
+
+## [3.2.1] - 2017-05-16
+
+- add browserify
+
+## [3.2.0] - 2017-04-25
+
+- Merge pull request #10 from ksheedlo/unrequire-buffer
+- add `promise` support and tests
+- Remove unnecessary `Buffer` check
+
+## [3.1.0] - 2016-12-07
+
+- Merge pull request #7 from laggingreflex/err
+- add support for `error` and tests
+- run update
+
+## [3.0.4] - 2016-07-29
+
+- move tests
+- run update
+
+## [3.0.3] - 2016-05-03
+
+- fix prepublish script
+- remove unused dep
+
+## [3.0.0] - 2015-11-17
+
+- add typed array support
+- Merge pull request #5 from miguelmota/typed-arrays
+- adds new tests
+
+## [2.0.1] - 2015-08-21
+
+- use `is-buffer` module
+
+## [2.0.0] - 2015-05-31
+
+- Create fallback for `Array.isArray` if used as a browser package
+- Merge pull request #2 from dtothefp/patch-1
+- Merge pull request #3 from pdehaan/patch-1
+- Merge branch 'master' of https://github.com/chorks/kind-of into chorks-master
+- optimizations, mostly date and regex
+
+## [1.1.0] - 2015-02-09
+
+- adds `buffer` support
+- adds tests for `buffer`
+
+## [1.0.0] - 2015-01-19
+
+- update benchmarks
+- optimizations based on benchmarks
+
+## [0.1.2] - 2014-10-26
+
+- return `typeof` value if it's not an object. very slight speed improvement
+- use `.slice`
+- adds benchmarks
+
+## [0.1.0] - 2014-9-26
+
+- first commit
+
+[6.0.0]: https://github.com/jonschlinkert/kind-of/compare/5.1.0...6.0.0
+[5.1.0]: https://github.com/jonschlinkert/kind-of/compare/5.0.2...5.1.0
+[5.0.2]: https://github.com/jonschlinkert/kind-of/compare/5.0.1...5.0.2
+[5.0.1]: https://github.com/jonschlinkert/kind-of/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/jonschlinkert/kind-of/compare/4.0.0...5.0.0
+[4.0.0]: https://github.com/jonschlinkert/kind-of/compare/3.2.2...4.0.0
+[3.2.2]: https://github.com/jonschlinkert/kind-of/compare/3.2.1...3.2.2
+[3.2.1]: https://github.com/jonschlinkert/kind-of/compare/3.2.0...3.2.1
+[3.2.0]: https://github.com/jonschlinkert/kind-of/compare/3.1.0...3.2.0
+[3.1.0]: https://github.com/jonschlinkert/kind-of/compare/3.0.4...3.1.0
+[3.0.4]: https://github.com/jonschlinkert/kind-of/compare/3.0.3...3.0.4
+[3.0.3]: https://github.com/jonschlinkert/kind-of/compare/3.0.0...3.0.3
+[3.0.0]: https://github.com/jonschlinkert/kind-of/compare/2.0.1...3.0.0
+[2.0.1]: https://github.com/jonschlinkert/kind-of/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/jonschlinkert/kind-of/compare/1.1.0...2.0.0
+[1.1.0]: https://github.com/jonschlinkert/kind-of/compare/1.0.0...1.1.0
+[1.0.0]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...1.0.0
+[0.1.2]: https://github.com/jonschlinkert/kind-of/compare/0.1.0...0.1.2
+[0.1.0]: https://github.com/jonschlinkert/kind-of/commit/2fae09b0b19b1aadb558e9be39f0c3ef6034eb87
+
+[Unreleased]: https://github.com/jonschlinkert/kind-of/compare/0.1.2...HEAD
+[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog
+
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/README.md b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/README.md
new file mode 100644
index 00000000..4b0d4a81
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/README.md
@@ -0,0 +1,365 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, es6, and browser ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(new Error('error'));
+//=> 'error'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'generatorfunction'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+
+```bash
+# arguments (32 bytes)
+  kind-of x 17,024,098 ops/sec ±1.90% (86 runs sampled)
+  lib-type-of x 11,926,235 ops/sec ±1.34% (83 runs sampled)
+  lib-typeof x 9,245,257 ops/sec ±1.22% (87 runs sampled)
+
+  fastest is kind-of (by 161% avg)
+
+# array (22 bytes)
+  kind-of x 17,196,492 ops/sec ±1.07% (88 runs sampled)
+  lib-type-of x 8,838,283 ops/sec ±1.02% (87 runs sampled)
+  lib-typeof x 8,677,848 ops/sec ±0.87% (87 runs sampled)
+
+  fastest is kind-of (by 196% avg)
+
+# boolean (24 bytes)
+  kind-of x 16,841,600 ops/sec ±1.10% (86 runs sampled)
+  lib-type-of x 8,096,787 ops/sec ±0.95% (87 runs sampled)
+  lib-typeof x 8,423,345 ops/sec ±1.15% (86 runs sampled)
+
+  fastest is kind-of (by 204% avg)
+
+# buffer (38 bytes)
+  kind-of x 14,848,060 ops/sec ±1.05% (86 runs sampled)
+  lib-type-of x 3,671,577 ops/sec ±1.49% (87 runs sampled)
+  lib-typeof x 8,360,236 ops/sec ±1.24% (86 runs sampled)
+
+  fastest is kind-of (by 247% avg)
+
+# date (30 bytes)
+  kind-of x 16,067,761 ops/sec ±1.58% (86 runs sampled)
+  lib-type-of x 8,954,436 ops/sec ±1.40% (87 runs sampled)
+  lib-typeof x 8,488,307 ops/sec ±1.51% (84 runs sampled)
+
+  fastest is kind-of (by 184% avg)
+
+# error (36 bytes)
+  kind-of x 9,634,090 ops/sec ±1.12% (89 runs sampled)
+  lib-type-of x 7,735,624 ops/sec ±1.32% (86 runs sampled)
+  lib-typeof x 7,442,160 ops/sec ±1.11% (90 runs sampled)
+
+  fastest is kind-of (by 127% avg)
+
+# function (34 bytes)
+  kind-of x 10,031,494 ops/sec ±1.27% (86 runs sampled)
+  lib-type-of x 9,502,757 ops/sec ±1.17% (89 runs sampled)
+  lib-typeof x 8,278,985 ops/sec ±1.08% (88 runs sampled)
+
+  fastest is kind-of (by 113% avg)
+
+# null (24 bytes)
+  kind-of x 18,159,808 ops/sec ±1.92% (86 runs sampled)
+  lib-type-of x 12,927,635 ops/sec ±1.01% (88 runs sampled)
+  lib-typeof x 7,958,234 ops/sec ±1.21% (89 runs sampled)
+
+  fastest is kind-of (by 174% avg)
+
+# number (22 bytes)
+  kind-of x 17,846,779 ops/sec ±0.91% (85 runs sampled)
+  lib-type-of x 3,316,636 ops/sec ±1.19% (86 runs sampled)
+  lib-typeof x 2,329,477 ops/sec ±2.21% (85 runs sampled)
+
+  fastest is kind-of (by 632% avg)
+
+# object-plain (47 bytes)
+  kind-of x 7,085,155 ops/sec ±1.05% (88 runs sampled)
+  lib-type-of x 8,870,930 ops/sec ±1.06% (83 runs sampled)
+  lib-typeof x 8,716,024 ops/sec ±1.05% (87 runs sampled)
+
+  fastest is lib-type-of (by 112% avg)
+
+# regex (25 bytes)
+  kind-of x 14,196,052 ops/sec ±1.65% (84 runs sampled)
+  lib-type-of x 9,554,164 ops/sec ±1.25% (88 runs sampled)
+  lib-typeof x 8,359,691 ops/sec ±1.07% (87 runs sampled)
+
+  fastest is kind-of (by 158% avg)
+
+# string (33 bytes)
+  kind-of x 16,131,428 ops/sec ±1.41% (85 runs sampled)
+  lib-type-of x 7,273,172 ops/sec ±1.05% (87 runs sampled)
+  lib-typeof x 7,382,635 ops/sec ±1.17% (85 runs sampled)
+
+  fastest is kind-of (by 220% avg)
+
+# symbol (34 bytes)
+  kind-of x 17,011,537 ops/sec ±1.24% (86 runs sampled)
+  lib-type-of x 3,492,454 ops/sec ±1.23% (89 runs sampled)
+  lib-typeof x 7,471,235 ops/sec ±2.48% (87 runs sampled)
+
+  fastest is kind-of (by 310% avg)
+
+# template-strings (36 bytes)
+  kind-of x 15,434,250 ops/sec ±1.46% (83 runs sampled)
+  lib-type-of x 7,157,907 ops/sec ±0.97% (87 runs sampled)
+  lib-typeof x 7,517,986 ops/sec ±0.92% (86 runs sampled)
+
+  fastest is kind-of (by 210% avg)
+
+# undefined (29 bytes)
+  kind-of x 19,167,115 ops/sec ±1.71% (87 runs sampled)
+  lib-type-of x 15,477,740 ops/sec ±1.63% (85 runs sampled)
+  lib-typeof x 19,075,495 ops/sec ±1.17% (83 runs sampled)
+
+  fastest is lib-typeof,kind-of
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of seems to be more consistently "correct" than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly identifies instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 98 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ianstormtaylor](https://github.com/ianstormtaylor) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike-old](https://github.com/charlike-old) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on December 01, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/index.js b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/index.js
new file mode 100644
index 00000000..aa2bb394
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/index.js
@@ -0,0 +1,129 @@
+var toString = Object.prototype.toString;
+
+module.exports = function kindOf(val) {
+  if (val === void 0) return 'undefined';
+  if (val === null) return 'null';
+
+  var type = typeof val;
+  if (type === 'boolean') return 'boolean';
+  if (type === 'string') return 'string';
+  if (type === 'number') return 'number';
+  if (type === 'symbol') return 'symbol';
+  if (type === 'function') {
+    return isGeneratorFn(val) ? 'generatorfunction' : 'function';
+  }
+
+  if (isArray(val)) return 'array';
+  if (isBuffer(val)) return 'buffer';
+  if (isArguments(val)) return 'arguments';
+  if (isDate(val)) return 'date';
+  if (isError(val)) return 'error';
+  if (isRegexp(val)) return 'regexp';
+
+  switch (ctorName(val)) {
+    case 'Symbol': return 'symbol';
+    case 'Promise': return 'promise';
+
+    // Set, Map, WeakSet, WeakMap
+    case 'WeakMap': return 'weakmap';
+    case 'WeakSet': return 'weakset';
+    case 'Map': return 'map';
+    case 'Set': return 'set';
+
+    // 8-bit typed arrays
+    case 'Int8Array': return 'int8array';
+    case 'Uint8Array': return 'uint8array';
+    case 'Uint8ClampedArray': return 'uint8clampedarray';
+
+    // 16-bit typed arrays
+    case 'Int16Array': return 'int16array';
+    case 'Uint16Array': return 'uint16array';
+
+    // 32-bit typed arrays
+    case 'Int32Array': return 'int32array';
+    case 'Uint32Array': return 'uint32array';
+    case 'Float32Array': return 'float32array';
+    case 'Float64Array': return 'float64array';
+  }
+
+  if (isGeneratorObj(val)) {
+    return 'generator';
+  }
+
+  // Non-plain objects
+  type = toString.call(val);
+  switch (type) {
+    case '[object Object]': return 'object';
+    // iterators
+    case '[object Map Iterator]': return 'mapiterator';
+    case '[object Set Iterator]': return 'setiterator';
+    case '[object String Iterator]': return 'stringiterator';
+    case '[object Array Iterator]': return 'arrayiterator';
+  }
+
+  // other
+  return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
+};
+
+function ctorName(val) {
+  return val.constructor ? val.constructor.name : null;
+}
+
+function isArray(val) {
+  if (Array.isArray) return Array.isArray(val);
+  return val instanceof Array;
+}
+
+function isError(val) {
+  return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number');
+}
+
+function isDate(val) {
+  if (val instanceof Date) return true;
+  return typeof val.toDateString === 'function'
+    && typeof val.getDate === 'function'
+    && typeof val.setDate === 'function';
+}
+
+function isRegexp(val) {
+  if (val instanceof RegExp) return true;
+  return typeof val.flags === 'string'
+    && typeof val.ignoreCase === 'boolean'
+    && typeof val.multiline === 'boolean'
+    && typeof val.global === 'boolean';
+}
+
+function isGeneratorFn(name, val) {
+  return ctorName(name) === 'GeneratorFunction';
+}
+
+function isGeneratorObj(val) {
+  return typeof val.throw === 'function'
+    && typeof val.return === 'function'
+    && typeof val.next === 'function';
+}
+
+function isArguments(val) {
+  try {
+    if (typeof val.length === 'number' && typeof val.callee === 'function') {
+      return true;
+    }
+  } catch (err) {
+    if (err.message.indexOf('callee') !== -1) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  if (val.constructor && typeof val.constructor.isBuffer === 'function') {
+    return val.constructor.isBuffer(val);
+  }
+  return false;
+}
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/package.json b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/package.json
new file mode 100644
index 00000000..3d5c8d0f
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/kind-of/package.json
@@ -0,0 +1,178 @@
+{
+  "_args": [
+    [
+      "kind-of@^6.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "kind-of@>=6.0.2 <7.0.0",
+  "_id": "kind-of@6.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-choices/kind-of",
+  "_nodeVersion": "9.1.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-6.0.2.tgz_1512153086430_0.774781379615888"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^6.0.2",
+    "rawSpec": "^6.0.2",
+    "scope": null,
+    "spec": ">=6.0.2 <7.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices",
+    "/prompt-choices/clone-deep",
+    "/prompt-choices/shallow-clone"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+  "_shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^6.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "benchmarked": "^2.0.0",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^4.0.1",
+    "write": "^1.0.3"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+    "shasum": "01146b36a6218e64e58f3a8d66de5d7fc6f6d051",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "1491da72e8d276479f5f6198a9e79c1379c5d0c7",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "6.0.2"
+}
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/LICENSE b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/LICENSE
new file mode 100644
index 00000000..f8de0630
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2018, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/README.md b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/README.md
new file mode 100644
index 00000000..7dea70e6
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/README.md
@@ -0,0 +1,152 @@
+# shallow-clone [![NPM version](https://img.shields.io/npm/v/shallow-clone.svg?style=flat)](https://www.npmjs.com/package/shallow-clone) [![NPM monthly downloads](https://img.shields.io/npm/dm/shallow-clone.svg?style=flat)](https://npmjs.org/package/shallow-clone) [![NPM total downloads](https://img.shields.io/npm/dt/shallow-clone.svg?style=flat)](https://npmjs.org/package/shallow-clone) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/shallow-clone.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/shallow-clone)
+
+> Creates a shallow clone of any JavaScript value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save shallow-clone
+```
+
+## Usage
+
+```js
+const clone = require('shallow-clone');
+```
+
+**Supports**
+
+* arrays
+* objects
+* dates
+* maps
+* sets
+* buffers
+* symbols
+* array buffers
+* float32 arrays
+* float64 arrays
+* int16 arrays
+* int32 arrays
+* int8 arrays
+* uint16 arrays
+* uint32 arrays
+* uint8clamped arrays
+* uint8 arrays
+* regular expressions
+* errors
+* primitives
+
+## Arrays
+
+By default, only the array itself is cloned, use [clone-deep](https://github.com/jonschlinkert/clone-deep) if you also need the elements in the array to be cloned.
+
+```js
+const arr = [{ a: 0 }, { b: 1 }];
+const foo = clone(arr);
+// foo =>  [{ 'a': 0 }, { 'b': 1 }]
+
+// array is cloned
+assert(actual === expected); // false
+
+// array elements are not
+assert.deepEqual(actual[0], expected[0]); // true
+```
+
+## Objects
+
+Only the object is shallow cloned, use [clone-deep](https://github.com/jonschlinkert/clone-deep) if you also need the values in the object to be cloned.
+
+```js
+clone({a: 1, b: 2, c: 3 });
+//=> {a: 1, b: 2, c: 3 }
+```
+
+## RegExp
+
+Clones regular expressions and flags, and preserves the `.lastIndex`.
+
+```js
+const re = clone(/foo/g); //=> /foo/g
+// you can manually reset lastIndex if necessary
+re.lastIndex = 0;
+```
+
+## Primitives
+
+Simply returns primitives unchanged.
+
+```js
+clone(0); //=> 0
+clone('foo'); //=> 'foo'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [assign-deep](https://www.npmjs.com/package/assign-deep): Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target… [more](https://github.com/jonschlinkert/assign-deep) | [homepage](https://github.com/jonschlinkert/assign-deep "Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target (first) object.")
+* [clone-deep](https://www.npmjs.com/package/clone-deep): Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives. | [homepage](https://github.com/jonschlinkert/clone-deep "Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives.")
+* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 15 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 2 | [doowb](https://github.com/doowb) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
+* [GitHub Profile](https://github.com/jonschlinkert)
+* [Twitter Profile](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on April 10, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/index.js b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/index.js
new file mode 100644
index 00000000..09dc08a3
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/index.js
@@ -0,0 +1,82 @@
+/*!
+ * shallow-clone <https://github.com/jonschlinkert/shallow-clone>
+ *
+ * Copyright (c) 2015-2018, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+const valueOf = Symbol.prototype.valueOf;
+const typeOf = require('kind-of');
+
+function clone(val, deep) {
+  switch (typeOf(val)) {
+    case 'array':
+      return val.slice();
+    case 'object':
+      return Object.assign({}, val);
+    case 'date':
+      return new val.constructor(+val);
+    case 'map':
+      return new Map(val);
+    case 'set':
+      return new Set(val);
+    case 'buffer':
+      return cloneBuffer(val);
+    case 'symbol':
+      return cloneSymbol(val);
+    case 'arraybuffer':
+      return cloneArrayBuffer(val);
+    case 'float32array':
+    case 'float64array':
+    case 'int16array':
+    case 'int32array':
+    case 'int8array':
+    case 'uint16array':
+    case 'uint32array':
+    case 'uint8clampedarray':
+    case 'uint8array':
+      return cloneTypedArray(val);
+    case 'regexp':
+      return cloneRegExp(val);
+    case 'error':
+      return Object.create(val);
+    default: {
+      return val;
+    }
+  }
+}
+
+function cloneRegExp(val) {
+  const re = new val.constructor(val.source, /\w+$/.exec(val));
+  re.lastIndex = val.lastIndex;
+  return re;
+}
+
+function cloneArrayBuffer(val) {
+  const res = new val.constructor(val.byteLength);
+  new Uint8Array(res).set(new Uint8Array(val));
+  return res;
+}
+
+function cloneTypedArray(val, deep) {
+  return new val.constructor(val.buffer, val.byteOffset, val.length);
+}
+
+function cloneBuffer(val) {
+  const len = val.length;
+  const buf = Buffer.allocUnsafe ? Buffer.allocUnsafe(len) : new Buffer(len);
+  val.copy(buf);
+  return buf;
+}
+
+function cloneSymbol(val) {
+  return valueOf ? Object(valueOf.call(val)) : {};
+}
+
+/**
+ * Expose `clone`
+ */
+
+module.exports = clone;
diff --git a/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/package.json b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/package.json
new file mode 100644
index 00000000..4e3220f2
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/node_modules/shallow-clone/package.json
@@ -0,0 +1,135 @@
+{
+  "_args": [
+    [
+      "shallow-clone@^3.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep"
+    ]
+  ],
+  "_from": "shallow-clone@>=3.0.0 <4.0.0",
+  "_id": "shallow-clone@3.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-choices/shallow-clone",
+  "_nodeVersion": "9.9.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/shallow-clone_3.0.0_1523342926123_0.141181021651261"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.8.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "shallow-clone",
+    "raw": "shallow-clone@^3.0.0",
+    "rawSpec": "^3.0.0",
+    "scope": null,
+    "spec": ">=3.0.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices/clone-deep"
+  ],
+  "_resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.0.tgz",
+  "_shasum": "317b701facce5e742d4c04c64e1d52f957e22b28",
+  "_shrinkwrap": null,
+  "_spec": "shallow-clone@^3.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices/node_modules/clone-deep",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/shallow-clone/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "kind-of": "^6.0.2"
+  },
+  "description": "Creates a shallow clone of any JavaScript value.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-Drg+nOI+ofeuslBf0nulyWLZhK1BZprqNvPJaiB4VvES+9gC6GG+qOVAfuO12zVSgxq9SKevcme7S3uDT6Be8w==",
+    "shasum": "317b701facce5e742d4c04c64e1d52f957e22b28",
+    "tarball": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.0.tgz",
+    "unpackedSize": 9090
+  },
+  "engines": {
+    "node": ">=8"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "fa62f9dfa131ba79bab0fe2b09d1e9a53121c48e",
+  "homepage": "https://github.com/jonschlinkert/shallow-clone",
+  "keywords": [
+    "array",
+    "clone",
+    "copy",
+    "extend",
+    "mixin",
+    "object",
+    "primitive",
+    "shallow"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "shallow-clone",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/shallow-clone.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "assign-deep",
+        "clone-deep",
+        "is-plain-object",
+        "kind-of"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.0.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-choices/package.json b/input_devices/mag/node_modules/prompt-choices/package.json
new file mode 100644
index 00000000..4aa3f10f
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-choices/package.json
@@ -0,0 +1,165 @@
+{
+  "_args": [
+    [
+      "prompt-choices@^4.0.5",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question"
+    ]
+  ],
+  "_from": "prompt-choices@>=4.0.5 <5.0.0",
+  "_id": "prompt-choices@4.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-choices",
+  "_nodeVersion": "10.0.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prompt-choices_4.1.0_1527539149423_0.4620227023819321"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "6.0.1",
+  "_phantomChildren": {
+    "is-descriptor": "1.0.2",
+    "isobject": "3.0.1"
+  },
+  "_requested": {
+    "name": "prompt-choices",
+    "raw": "prompt-choices@^4.0.5",
+    "rawSpec": "^4.0.5",
+    "scope": null,
+    "spec": ">=4.0.5 <5.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-question"
+  ],
+  "_resolved": "https://registry.npmjs.org/prompt-choices/-/prompt-choices-4.1.0.tgz",
+  "_shasum": "6094202c4e55d0762e49c1e53735727e53fd484f",
+  "_shrinkwrap": null,
+  "_spec": "prompt-choices@^4.0.5",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/prompt-choices/issues"
+  },
+  "dependencies": {
+    "arr-flatten": "^1.1.0",
+    "arr-swap": "^1.0.1",
+    "choices-separator": "^2.0.0",
+    "clone-deep": "^4.0.0",
+    "collection-visit": "^1.0.0",
+    "define-property": "^2.0.2",
+    "is-number": "^6.0.0",
+    "kind-of": "^6.0.2",
+    "koalas": "^1.0.2",
+    "log-utils": "^0.2.1",
+    "pointer-symbol": "^1.0.0",
+    "radio-symbol": "^2.0.0",
+    "set-value": "^3.0.0",
+    "strip-color": "^0.1.0",
+    "terminal-paginator": "^2.0.2",
+    "toggle-array": "^1.0.1"
+  },
+  "description": "Create an array of multiple choice objects for use in prompts.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "is-windows": "^1.0.2",
+    "mocha": "^5.2.0",
+    "prompt-actions": "^3.0.2"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 6,
+    "integrity": "sha512-ZNYLv6rW9z9n0WdwCkEuS+w5nUAGzRgtRt6GQ5aFNFz6MIcU7nHFlHOwZtzy7RQBk80KzUGPSRQphvMiQzB8pg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDGXOCRA9TVsSAnZWagAARL8P/2CjUwNmRj4jQb1SPJJv\nmyaWdMjnTdIIUW8b3JR6ynq8Rtgi7FKO0ylq8wl25XVwGM5jPdfFMeLvfCUB\ne1je89/8RQGGE/phWcTFpdbSakJLdSZarIGtTvXQBsM8ga5J5Mk3WPh/oPva\nvqQyln9FfaFAWDmVFUBSbB3zzJKID84ISbqJYz3MSCudkMvesD83xEnCV7UV\njwl4BQ8NQe4BiqHn21hzirCcXyviyGKw8NGqLCxQYhyMow8f0UVt5m+XSozn\nMsWFhHbQ6PjOwvqTjD0UKvGsmTBVCMAMNdxv5MrfV6wq7WgrA2c5XXnEl1ax\n6dhmUcZ1/+jfW1rGO6q7J+qSwW7zcMmmQ1Tnos3zLiCjrRUJP87o1Q+EZRsf\nEAzlis5UJexbo7ukC2hwQkOESGOoBdE/IidWd1r/Khms4yruyPL68epEj5iO\nMnTQl39GMcM4vSGua1XPR9xNMA4keWhvcgvkcfrDZJWvkRSn5r8iJr8mHJM4\n3fxbvW3uf6ZgOcOSd1YN8sYm1468xPju4b61iXprhFf8rTQGG6OfI2JuE1AZ\ng6lqZ/HRaAjlv1SbvWD8cTq+lm2+FM5esObr/yv77MlCiaXramDfYrtkw7Wc\nQUkjVGNrvm+OduBDIQcSAa/3behRV+yVNLWmX4J1DNaHI7tkYi0W5XzBemk/\nAIJ7\r\n=s+bN\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "6094202c4e55d0762e49c1e53735727e53fd484f",
+    "tarball": "https://registry.npmjs.org/prompt-choices/-/prompt-choices-4.1.0.tgz",
+    "unpackedSize": 42800
+  },
+  "engines": {
+    "node": ">=4.0.0"
+  },
+  "files": [
+    "index.js",
+    "lib"
+  ],
+  "gitHead": "f36752e8b950d8d86ba816f9321ecca61c987f68",
+  "homepage": "https://github.com/enquirer/prompt-choices",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "checkbox",
+    "choice",
+    "choices",
+    "cli",
+    "command",
+    "enquirer",
+    "enquirerprompt",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "password",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "prompt-choices",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/prompt-choices.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "choices-separator"
+    ],
+    "related": {
+      "list": [
+        "enquirer",
+        "prompt-base",
+        "prompt-checkbox",
+        "prompt-question",
+        "prompt-radio"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "4.1.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-list/LICENSE b/input_devices/mag/node_modules/prompt-list/LICENSE
new file mode 100644
index 00000000..681d1bf7
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-list/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-present, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/prompt-list/README.md b/input_devices/mag/node_modules/prompt-list/README.md
new file mode 100644
index 00000000..fc32f1d5
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-list/README.md
@@ -0,0 +1,173 @@
+# prompt-list [![NPM version](https://img.shields.io/npm/v/prompt-list.svg?style=flat)](https://www.npmjs.com/package/prompt-list) [![NPM monthly downloads](https://img.shields.io/npm/dm/prompt-list.svg?style=flat)](https://npmjs.org/package/prompt-list)  [![NPM total downloads](https://img.shields.io/npm/dt/prompt-list.svg?style=flat)](https://npmjs.org/package/prompt-list) [![Linux Build Status](https://img.shields.io/travis/enquirer/prompt-list.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/prompt-list) [![Windows Build Status](https://img.shields.io/appveyor/ci/enquirer/prompt-list.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/enquirer/prompt-list)
+
+> List-style prompt. Can be used as a standalone prompt, or with a prompt system like [enquirer](http://enquirer.io).
+
+Follow this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), for updates on this project and others.
+
+![prompt-list example](https://raw.githubusercontent.com/enquirer/prompt-list/master/docs/example.gif)
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-list
+```
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-list
+```
+
+## Example usage
+
+```js
+var List = require('prompt-list');
+var list = new List({
+  name: 'order',
+  message: 'What would you like to order?',
+  // choices may be defined as an array or a function that returns an array
+  choices: [
+    'Coke',
+    'Diet Coke',
+    'Cherry Coke',
+    {name: 'Sprite', disabled: 'Temporarily unavailable'},
+    'Water'
+  ]
+});
+
+// async
+list.ask(function(answer) {
+  console.log(answer);
+});
+
+// promise
+list.run()
+  .then(function(answer) {
+    console.log(answer);
+  });
+```
+
+## Enquirer usage
+
+Register the prompt as an [enquirer](http://enquirer.io) plugin:
+
+```js
+var Enquirer = require('enquirer');
+var enquirer = new Enquirer();
+
+enquirer.register('list', require('prompt-list'));
+```
+
+### Enquirer examples
+
+Enquirer supports both declarative, inquirer-style questions, and an expressive format, using the `.question` method:
+
+**Declarative**
+
+```js
+var questions = [
+  {
+    type: 'list',
+    name: 'order',
+    message: 'What would you like to order?',
+    choices: [
+      'Coke',
+      'Diet Coke',
+      'Cherry Coke',
+      {name: 'Sprite', disabled: 'Temporarily unavailable'},
+      'Water'
+    ]
+  }
+];
+
+enquirer.ask(questions)
+  .then(function(answers) {
+    console.log(answers);
+  })
+  .catch(function(err) {
+    console.log(err);
+  });
+```
+
+**Expressive**
+
+```js
+enquirer.question('order', 'What would you like to order?', {
+  type: 'list',
+  choices: [
+    'Coke',
+    'Diet Coke',
+    'Cherry Coke',
+    {name: 'Sprite', disabled: 'Temporarily unavailable'},
+    'Water'
+  ]
+});
+
+enquirer.ask(['order'])
+  .then(function(answers) {
+    console.log(answers);
+  })
+  .catch(function(err) {
+    console.log(err);
+  });
+```
+
+## About
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [enquirer-prompt](https://www.npmjs.com/package/enquirer-prompt): Base prompt module used for creating custom prompt types for Enquirer. | [homepage](https://github.com/jonschlinkert/enquirer-prompt "Base prompt module used for creating custom prompt types for Enquirer.")
+* [enquirer-question](https://www.npmjs.com/package/enquirer-question): Question object, used by Enquirer and prompt plugins. | [homepage](https://github.com/enquirer/enquirer-question "Question object, used by Enquirer and prompt plugins.")
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. | [homepage](http://enquirer.io "Intuitive, plugin-based prompt system for node.js.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** |  
+| --- | --- |  
+| 45 | [jonschlinkert](https://github.com/jonschlinkert) |  
+| 6  | [doowb](https://github.com/doowb) |  
+| 3  | [albizures](https://github.com/albizures) |  
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on December 28, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-list/index.js b/input_devices/mag/node_modules/prompt-list/index.js
new file mode 100644
index 00000000..f607733b
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-list/index.js
@@ -0,0 +1,84 @@
+'use strict';
+
+const Radio = require('prompt-radio');
+const cyan = require('ansi-cyan');
+const dim = require('ansi-dim');
+
+/**
+ * List prompt
+ */
+
+function List(question, answers, ui) {
+  Radio.apply(this, arguments);
+  this.listInitialized = false;
+  this.question.type = 'list';
+  this.on('ask', this.onAsk.bind(this));
+  this.on('render', () => {
+    if (this.contextHistory.length > 0) this.helpMessage = '';
+  });
+}
+
+/**
+ * Inherit Radio
+ */
+
+Radio.extend(List);
+
+/**
+ * Render a choice.
+ */
+
+List.prototype.onAsk = function() {
+  if (this.listInitialized) return;
+  this.listInitialized = true;
+  this.helpMessage = this.options.helpMessage || dim('(Use arrow keys)');
+  this.choices.options.checkbox = false;
+  this.choices.options.format = this.renderChoice(this.choices);
+};
+
+/**
+ * Render a choice.
+ */
+
+List.prototype.renderChoice = function(choices) {
+  return function(line) {
+    return choices.position === choices.index ? cyan(line) : line;
+  };
+};
+
+/**
+ * Render final selected answer when "line" ("enter" keypress)
+ * is emitted
+ */
+
+List.prototype.renderAnswer = function() {
+  return cyan(this.choices.get(this.position, 'value'));
+};
+
+/**
+ * Get selected list item
+ */
+
+List.prototype.getAnswer = function() {
+  return this.choices.key(this.position);
+};
+
+/**
+ * overriding "when" function to avoid setting a value when there
+ * is not a default value and the question was not asked
+ */
+
+List.prototype.when = function() {
+  var that = this;
+  return Promise.resolve(Radio.prototype.when.apply(this, arguments))
+    .then(function(when) {
+      that.position = that.choices.getIndex(that.options.default);
+      return when;
+    });
+};
+
+/**
+ * Module exports
+ */
+
+module.exports = List;
diff --git a/input_devices/mag/node_modules/prompt-list/package.json b/input_devices/mag/node_modules/prompt-list/package.json
new file mode 100644
index 00000000..76335976
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-list/package.json
@@ -0,0 +1,164 @@
+{
+  "_args": [
+    [
+      "prompt-list@^3.2.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport"
+    ]
+  ],
+  "_from": "prompt-list@>=3.2.0 <4.0.0",
+  "_id": "prompt-list@3.2.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-list",
+  "_nodeVersion": "10.0.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prompt-list_3.2.0_1527538263174_0.5338071041083554"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "6.0.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "prompt-list",
+    "raw": "prompt-list@^3.2.0",
+    "rawSpec": "^3.2.0",
+    "scope": null,
+    "spec": ">=3.2.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/serialport"
+  ],
+  "_resolved": "https://registry.npmjs.org/prompt-list/-/prompt-list-3.2.0.tgz",
+  "_shasum": "b33472e01677a5751f59094fa7fe20b09da9db94",
+  "_shrinkwrap": null,
+  "_spec": "prompt-list@^3.2.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/serialport",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/prompt-list/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Jose Albizures",
+      "url": "https://twitter.com/albizures36"
+    }
+  ],
+  "dependencies": {
+    "ansi-cyan": "^0.1.1",
+    "ansi-dim": "^0.1.1",
+    "prompt-radio": "^1.2.1"
+  },
+  "description": "List-style prompt. Can be used as a standalone prompt, or with a prompt system like [enquirer].",
+  "devDependencies": {
+    "choices-separator": "^2.0.0",
+    "enquirer": "^1.0.3",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^5.2.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-PDao47cmC9+m2zEUghH+WIIascd8SuyyWO+akuUubd0XxOQyUH96HMdIcL3YnNS8kJUHwddH1rHVgL9vZA1QsQ==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbDGJXCRA9TVsSAnZWagAAF6QP/RFnnivVMRC6rXVi1Rgl\nBMiTOFqHwt4b3hj8C0aUwD7pO/v8bufItRg1pS+Z2BJYmNbBwiY/QJzPHSv5\n1zwYHgLrkM3AwJswWe7/cAM67I+75efLnfG0BcvVvKVAQSxl8bi4XZtsprSa\nBXorsbh63inVwVmYyiZE3LYapPIx3hNi1WvWpftIF8+lpC4Pzx+Lyx2sWduk\nhvPMU7uP0nm6qtoIZqdAMCKd0Fa1/ET0SzyR8jIvbk7/viv2C/fEUevX+OdO\nmr8nwheTF5qqXSKBs/VXwM1PEWZso4oKbN8N+ctBE3bGh6TueFgeDUpi4hCV\nt6WM+l7RyLhiWAkgV+uFfoGcis/ZhCQyoam+OLOikprrkskxzi/VNFnhoPWI\nF7wGKYtlKnlyQQ4vy8SqvAJLpNF3MCepZj25uaxtJolT2Glgf8fz7uSY7lhj\n5p1XMS9lZslxbj5rWek0waRduB8camCAiiIjZEgjoP3rbgKtTfbbOOpvhQ0e\n57fpaPdEAYfDDNzyimyYWAsVv631HA/M/fpQKmGhoEYMuSDK3ITqd7XkFvyk\nWyImkOjcdclbHRv0yVYZ3v8af74fXqstiSMOKlbZcrTcwRSUp+tSDRM1pk/v\nTboJ8RXyc17cElAZLQe4hx7uM5asXwY0aWnYtbWeroHd7FkozbFiSLOc/Zxn\n/gfg\r\n=q1YS\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "b33472e01677a5751f59094fa7fe20b09da9db94",
+    "tarball": "https://registry.npmjs.org/prompt-list/-/prompt-list-3.2.0.tgz",
+    "unpackedSize": 9646
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "4c18a263ac3d461f5e246f3da999236f72dddb5a",
+  "homepage": "https://github.com/enquirer/prompt-list",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "checkbox",
+    "choice",
+    "cli",
+    "command",
+    "enquirer-prompt",
+    "enquirerprompt",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "password",
+    "plugin",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "prompt-list",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/prompt-list.git"
+  },
+  "scripts": {
+    "test": "eslint . && mocha"
+  },
+  "verb": {
+    "data": {
+      "alias": "list"
+    },
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "enquirer",
+        "enquirer-prompt",
+        "enquirer-question"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.2.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-question/LICENSE b/input_devices/mag/node_modules/prompt-question/LICENSE
new file mode 100644
index 00000000..ece74b5e
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-question/README.md b/input_devices/mag/node_modules/prompt-question/README.md
new file mode 100644
index 00000000..f5a7826a
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/README.md
@@ -0,0 +1,301 @@
+# prompt-question [![NPM version](https://img.shields.io/npm/v/prompt-question.svg?style=flat)](https://www.npmjs.com/package/prompt-question) [![NPM monthly downloads](https://img.shields.io/npm/dm/prompt-question.svg?style=flat)](https://npmjs.org/package/prompt-question) [![NPM total downloads](https://img.shields.io/npm/dt/prompt-question.svg?style=flat)](https://npmjs.org/package/prompt-question) [![Linux Build Status](https://img.shields.io/travis/enquirer/prompt-question.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/prompt-question)
+
+> Question object, used by Enquirer and prompt plugins.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-question
+```
+
+## Usage
+
+The main export is a constructor function that is used to create new `Question` objects, which are used in prompts by [base-prompt][].
+
+```js
+var Question = require('prompt-question');
+var question = new Question('color', 'What is favorite color?');
+```
+
+**Examples**
+
+Any of the following signatures may be used:
+
+```js
+var question = new Question('color'); // sets message as the same value as `name`
+var question = new Question('color', 'What is favorite color?');
+var question = new Question('color', {message: 'What is favorite color?'});
+var question = new Question({name: 'color', message: 'What is favorite color?'});
+var question = new Question({name: 'color'});
+```
+
+## API
+
+### [Question](index.js#L29)
+
+Create a new question with the given `name`, `message` and `options`.
+
+**Params**
+
+* `name` **{String|Object}**: Question name or options.
+* `message` **{String|Object}**: Question message or options.
+* `options` **{String|Object}**: Question options.
+
+**Example**
+
+```js
+var question = new Question('first', 'What is your first name?');
+console.log(question);
+// {
+//   type: 'input',
+//   name: 'color',
+//   message: 'What is your favorite color?'
+// }
+```
+
+### [.clone](index.js#L71)
+
+Clone the question instance.
+
+* `returns` **{Object}**: Returns the cloned question
+
+**Example**
+
+```js
+var clonedQuestion = question.clone();
+```
+
+### [.addChoices](index.js#L95)
+
+Add formatted choice objects to the `question.choices` array. See [prompt-choices](https://github.com/enquirer/prompt-choices) for more details.
+
+**Params**
+
+* `choices` **{String|Array}**: One or more choices to add.
+* `returns` **{Object}**: Returns the question instance for chaining
+
+**Example**
+
+```js
+question.addChoices(['foo', 'bar', 'baz']);
+```
+
+### [.addChoice](index.js#L112)
+
+Add a choice to `question.choices` array. See [prompt-choices](https://github.com/enquirer/prompt-choices) for more details.
+
+**Params**
+
+* `choice` **{String|Object}**
+* `returns` **{Object}**: Returns the question instance for chaining
+
+**Example**
+
+```js
+question.addChoice('foo');
+```
+
+### [.getDefault](index.js#L142)
+
+Returns the given `val` or `question.default` if `val` is undefined or null.
+
+**Params**
+
+* `val` **{any}**
+* `returns` **{any}**
+
+**Example**
+
+```js
+var question = new Question({
+  name: 'first',
+  message: 'First name'?,
+  default: 'Bob'
+});
+
+console.log(question.getAnswer());
+//=> 'Bob'
+console.log(question.getAnswer('Joe'));
+//=> 'Joe'
+console.log(question.getAnswer(false));
+//=> false
+console.log(question.getAnswer(0));
+//=> 0
+```
+
+### [.getChoice](index.js#L186)
+
+Get the given choice from `questions.choices`.
+
+**Params**
+
+* `val` **{any}**
+* `returns` **{any}**
+
+**Example**
+
+```js
+var Question = require('prompt-question');
+var question = new Question('color', 'What is your favorite color?', {
+  choices: ['red', 'blue', 'yellow']
+});
+console.log(question.getChoice('red'));
+//=> Choice { name: 'red', short: 'red', value: 'red', checked: false }
+```
+
+### [.separator](index.js#L195)
+
+Create a separator using [choices-separator](https://github.com/enquirer/choices-separator).
+
+### [.hasDefault](index.js#L207)
+
+Getter that returns true if a `default` value has been defined.
+
+* `returns` **{Boolean}**: True if a default value is defined.
+
+### [.checkbox](index.js#L229)
+
+Getter/setter for the checkbox symbols to use.
+
+* `returns` **{Object}**: Checkbox object with `.on`, `.off` and `.disabled` properties.
+
+**Example**
+
+```js
+var question = new Question({
+  name: 'foo',
+  checkbox: {off: '[ ]', on: '[x]', disabled: 'X'}
+});
+// or
+question.checkbox = {off: '[ ]', on: '[x]', disabled: 'X'};
+```
+
+### [.choices](index.js#L253)
+
+Getter/setter for getting and setting choices (if applicable).
+
+* `returns` **{Object}**: Returns an instance of [prompt-choices](https://github.com/enquirer/prompt-choices)
+
+**Example**
+
+```js
+var question = new Question();
+question.choices = ['a', 'b', 'c'];
+```
+
+### [.Question.isQuestion](index.js#L288)
+
+Static method that returns true if `question` is a valid question object.
+
+**Params**
+
+* `question` **{Object}**
+* `returns` **{Boolean}**
+
+**Example**
+
+```js
+console.log(Question.isQuestion('foo'));
+//=> false
+console.log(Question.isQuestion(new Question('What is your name?')));
+//=> true
+```
+
+### [.Question.choices](index.js#L305)
+
+Static method for creating a new `Choices` object. See [prompt-choices](https://github.com/enquirer/prompt-choices) for more details.
+
+**Params**
+
+* `choices` **{Array}**: Array of choices
+* `returns` **{Object}**: Returns an intance of Choices.
+
+**Example**
+
+```js
+var choices = new Question.Choices(['foo', 'bar', 'baz']);
+```
+
+### [.Question.Separator](index.js#L320)
+
+Static method for creating a new `Separator` object. See [choices-separator](https://github.com/enquirer/choices-separator) for more details.
+
+**Params**
+
+* `separator` **{String}**: Optionally pass a string to use as the separator.
+* `returns` **{Object}**: Returns a separator object.
+
+**Example**
+
+```js
+new Question.Separator();
+```
+
+## Release history
+
+### v5.0.0
+
+* Support `.choices` as a function
+
+### v4.0.0
+
+* bumps [prompt-choices](https://github.com/enquirer/prompt-choices)
+
+### v3.0.0
+
+* bumps [prompt-choices](https://github.com/enquirer/prompt-choices)
+
+### v2.0.0
+
+* bumps [prompt-choices](https://github.com/enquirer/prompt-choices). A major bump was warranted due to potentially breaking changes in prompt-choices. Please see that library for more details.
+
+## About
+
+### Related projects
+
+* [choices-separator](https://www.npmjs.com/package/choices-separator): Separator for choices arrays in prompts. Based on the Separator from inquirer. | [homepage](https://github.com/enquirer/choices-separator "Separator for choices arrays in prompts. Based on the Separator from inquirer.")
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. | [homepage](http://enquirer.io "Intuitive, plugin-based prompt system for node.js.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+* [readline-utils](https://www.npmjs.com/package/readline-utils): Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more. | [homepage](https://github.com/enquirer/readline-utils "Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 08, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-question/index.js b/input_devices/mag/node_modules/prompt-question/index.js
new file mode 100644
index 00000000..6bcd2a03
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/index.js
@@ -0,0 +1,326 @@
+'use strict';
+
+var debug = require('debug')('prompt-question');
+var Choices = require('prompt-choices');
+var define = require('define-property');
+var isObject = require('isobject');
+var clone = require('clone-deep');
+var koalas = require('koalas');
+var utils = require('./lib/utils');
+
+/**
+ * Create a new question with the given `name`, `message` and `options`.
+ *
+ * ```js
+ * var question = new Question('first', 'What is your first name?');
+ * console.log(question);
+ * // {
+ * //   type: 'input',
+ * //   name: 'color',
+ * //   message: 'What is your favorite color?'
+ * // }
+ * ```
+ * @param {String|Object} `name` Question name or options.
+ * @param {String|Object} `message` Question message or options.
+ * @param {String|Object} `options` Question options.
+ * @api public
+ */
+
+function Question(name, message, options) {
+  debug('initializing from <%s>', __filename);
+  if (arguments.length === 0) {
+    throw new TypeError('expected a string or object');
+  }
+
+  if (Question.isQuestion(name)) {
+    return name;
+  }
+
+  this.type = 'input';
+  this.options = {};
+  this.getDefault();
+
+  if (Array.isArray(message)) {
+    options = { choices: message };
+    message = name;
+  }
+
+  if (Array.isArray(options)) {
+    options = { choices: options };
+  }
+
+  define(this, 'Choices', Choices);
+  define(this, 'isQuestion', true);
+  utils.assign(this, {
+    name: name,
+    message: message,
+    options: options
+  });
+}
+
+/**
+ * Clone the question instance.
+ *
+ * ```js
+ * var clonedQuestion = question.clone();
+ * ```
+ * @return {Object} Returns the cloned question
+ * @api public
+ */
+
+Question.prototype.clone = function() {
+  var keys = Object.keys(this);
+  var cloned = new this.constructor(clone(this.cache));
+  for (var i = 0; i < keys.length; i++) {
+    var key = keys[i];
+    if (!(key in cloned)) {
+      cloned[key] = this[key];
+    }
+  }
+  return cloned;
+};
+
+/**
+ * Add formatted choice objects to the `question.choices` array.
+ * See [prompt-choices][] for more details.
+ *
+ * ```js
+ * question.addChoices(['foo', 'bar', 'baz']);
+ * ```
+ * @param {String|Array} `choices` One or more choices to add.
+ * @return {Object} Returns the question instance for chaining
+ * @api public
+ */
+
+Question.prototype.addChoices = function() {
+  this.choices.addChoices.apply(this.choices, arguments);
+  return this;
+};
+
+/**
+ * Add a choice to `question.choices` array.
+ * See [prompt-choices][] for more details.
+ *
+ * ```js
+ * question.addChoice('foo');
+ * ```
+ * @param {String|Object} `choice`
+ * @return {Object} Returns the question instance for chaining
+ * @api public
+ */
+
+Question.prototype.addChoice = function() {
+  this.choices.addChoice.apply(this.choices, arguments);
+  return this;
+};
+
+/**
+ * Returns the given `val` or `question.default` if `val` is undefined or null.
+ *
+ * ```js
+ * var question = new Question({
+ *   name: 'first',
+ *   message: 'First name'?,
+ *   default: 'Bob'
+ * });
+ *
+ * console.log(question.getAnswer());
+ * //=> 'Bob'
+ * console.log(question.getAnswer('Joe'));
+ * //=> 'Joe'
+ * console.log(question.getAnswer(false));
+ * //=> false
+ * console.log(question.getAnswer(0));
+ * //=> 0
+ * ```
+ *
+ * @param {any} `val`
+ * @return {any}
+ * @api public
+ */
+
+Question.prototype.getDefault = function(val) {
+  var def = koalas(this.default, this.options.default, this.choices.default);
+  if (def == null) {
+    return def;
+  }
+  if (this.choices.length) {
+    var idx = this.choices.getIndex(def);
+    if (typeof idx === 'number') {
+      this.choices.default = idx;
+      this.choices.check(idx);
+      def = idx;
+    }
+  }
+  this.default = def;
+  return def;
+};
+
+Question.prototype.getAnswer = function(val) {
+  if (this._choices && !this.choices.checked.length && this.default != null) {
+    this.choices.check(utils.decrement(this.default));
+  }
+  if (this._choices && this.choices.length) {
+    return this.choices.checked;
+  }
+  return koalas(val, this.default);
+};
+
+/**
+ * Get the given choice from `questions.choices`.
+ *
+ * ```js
+ * var Question = require('prompt-question');
+ * var question = new Question('color', 'What is your favorite color?', {
+ *   choices: ['red', 'blue', 'yellow']
+ * });
+ * console.log(question.getChoice('red'));
+ * //=> Choice { name: 'red', short: 'red', value: 'red', checked: false }
+ * ```
+ *
+ * @param {any} `val`
+ * @return {any}
+ * @api public
+ */
+
+Question.prototype.getChoice = function() {
+  return this.choices.get.apply(this.choices, arguments);
+};
+
+/**
+ * Create a separator using [choices-separator][].
+ * @api public
+ */
+
+Question.prototype.separator = function() {
+  return this.choices.separator.apply(this.choices, arguments);
+};
+
+/**
+ * Getter that returns true if a `default` value has been defined.
+ *
+ * @name .hasDefault
+ * @return {Boolean} True if a default value is defined.
+ * @api public
+ */
+
+Object.defineProperty(Question.prototype, 'hasDefault', {
+  get: function() {
+    return this.default != null;
+  }
+});
+
+/**
+ * Getter/setter for the checkbox symbols to use.
+ *
+ * ```js
+ * var question = new Question({
+ *   name: 'foo',
+ *   checkbox: {off: '[ ]', on: '[x]', disabled: 'X'}
+ * });
+ * // or
+ * question.checkbox = {off: '[ ]', on: '[x]', disabled: 'X'};
+ * ```
+ * @name .checkbox
+ * @return {Object} Checkbox object with `.on`, `.off` and `.disabled` properties.
+ * @api public
+ */
+
+Object.defineProperty(Question.prototype, 'checkbox', {
+  set: function(checkbox) {
+    if (utils.isObject(checkbox)) {
+      throw new TypeError('expected checkbox symbols to be an object');
+    }
+    this.choices.checkbox = checkbox;
+  },
+  get: function() {
+    return this.choices.checkbox;
+  }
+});
+
+/**
+ * Getter/setter for getting and setting choices (if applicable).
+ *
+ * ```js
+ * var question = new Question();
+ * question.choices = ['a', 'b', 'c'];
+ * ```
+ * @name .choices
+ * @return {Object} Returns an instance of [prompt-choices]
+ * @api public
+ */
+
+Object.defineProperty(Question.prototype, 'choices', {
+  configurable: true,
+  enumerable: true,
+  set: function(choices) {
+    define(this, '_choices', choices);
+  },
+  get: function() {
+    if (typeof this._choices === 'function') {
+      this._choices = this._choices.call(this);
+    }
+    if (this._choices == null) {
+      define(this, '_choices', this.options.choices);
+    }
+    if (!(this._choices instanceof Choices)) {
+      this._choices = new Choices(this._choices, this);
+    }
+    return this._choices;
+  }
+});
+
+/**
+ * Static method that returns true if `question` is a valid question object.
+ *
+ * ```js
+ * console.log(Question.isQuestion('foo'));
+ * //=> false
+ * console.log(Question.isQuestion(new Question('What is your name?')));
+ * //=> true
+ * ```
+ * @name Question.isQuestion
+ * @param {Object} `question`
+ * @return {Boolean}
+ * @api public
+ */
+
+Question.isQuestion = function(question) {
+  return utils.isObject(question) && question.isQuestion === true;
+};
+
+/**
+ * Static method for creating a new `Choices` object. See [prompt-choices][]
+ * for more details.
+ *
+ * ```js
+ * var choices = new Question.Choices(['foo', 'bar', 'baz']);
+ * ```
+ * @name Question.choices
+ * @param {Array} `choices` Array of choices
+ * @return {Object} Returns an intance of Choices.
+ * @api public
+ */
+
+Question.Choices = Choices;
+
+/**
+ * Static method for creating a new `Separator` object.
+ * See [choices-separator][] for more details.
+ *
+ * ```js
+ * new Question.Separator();
+ * ```
+ * @name Question.Separator
+ * @param {String} `separator` Optionally pass a string to use as the separator.
+ * @return {Object} Returns a separator object.
+ * @api public
+ */
+
+Question.Separator = Choices.Separator;
+
+/**
+ * Expose `Question`
+ */
+
+module.exports = Question;
diff --git a/input_devices/mag/node_modules/prompt-question/lib/utils.js b/input_devices/mag/node_modules/prompt-question/lib/utils.js
new file mode 100644
index 00000000..3e5d5e4b
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/lib/utils.js
@@ -0,0 +1,72 @@
+'use strict';
+
+var define = require('define-property');
+var typeOf = require('kind-of');
+var utils = module.exports;
+
+/**
+ * Extend the given `obj` with `options`. Assigned values
+ * are also on "question.cache" so that we can easily use
+ * those when question.clone() is called
+ */
+
+utils.assign = function(question, options) {
+  var keys = Object.keys(options);
+  var cache = {options: {}};
+
+  for (var i = 0; i < keys.length; i++) {
+    var key = keys[i];
+    var val = options[key];
+
+    if (utils.isObject(val)) {
+      Object.assign(cache, val);
+
+    }  else if (val != null) {
+      cache[key] = val;
+    }
+  }
+
+  if (!cache.message) {
+    cache.message = cache.name;
+  }
+  define(question, 'cache', cache);
+  var opts = question.options;
+  Object.assign(question, cache);
+  question.options = Object.assign({}, opts, cache.options);
+};
+
+/**
+ * Decrement the number on each value in the given array.
+ */
+
+utils.decrement = function(val) {
+  val = Array.isArray(val) ? val : [val];
+  for (var i = 0; i < val.length; i++) {
+    if (typeof val[i] === 'number') {
+      val[i] = val[i] - 1;
+    }
+  }
+  return val;
+};
+
+/**
+ * Return true if `val` is an object
+ */
+
+utils.isObject = function(val) {
+  return typeOf(val) === 'object';
+};
+
+/**
+ * Return true if `str` is a non-empty string
+ */
+
+utils.isString = function(str) {
+  return str && typeof str === 'string';
+};
+
+/**
+ * Expose `utils` modules
+ */
+
+module.exports = utils;
diff --git a/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/README.md b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/README.md
new file mode 100644
index 00000000..170bf304
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/README.md
@@ -0,0 +1,342 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Release history
+
+### v4.0.0
+
+**Added**
+
+* `promise` support
+
+### v5.0.0
+
+**Added**
+
+* `Set Iterator` and `Map Iterator` support
+
+**Fixed**
+
+* Now returns `generatorfunction` for generator functions
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of is more correct than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly tests instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+<details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+<details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+<details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 82 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike](https://github.com/charlike) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on October 13, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/index.js b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/index.js
new file mode 100644
index 00000000..fc5cde96
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/index.js
@@ -0,0 +1,147 @@
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  var type = typeof val;
+
+  // primitivies
+  if (type === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (type === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (type === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (type === 'function' || val instanceof Function) {
+    if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') {
+      return 'generatorfunction';
+    }
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+  if (type === '[object Promise]') {
+    return 'promise';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+  
+  if (type === '[object Map Iterator]') {
+    return 'mapiterator';
+  }
+  if (type === '[object Set Iterator]') {
+    return 'setiterator';
+  }
+  if (type === '[object String Iterator]') {
+    return 'stringiterator';
+  }
+  if (type === '[object Array Iterator]') {
+    return 'arrayiterator';
+  }
+  
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  return val.constructor
+    && typeof val.constructor.isBuffer === 'function'
+    && val.constructor.isBuffer(val);
+}
diff --git a/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/package.json b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/package.json
new file mode 100644
index 00000000..2f739225
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/node_modules/kind-of/package.json
@@ -0,0 +1,179 @@
+{
+  "_args": [
+    [
+      "kind-of@^5.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question"
+    ]
+  ],
+  "_from": "kind-of@>=5.0.2 <6.0.0",
+  "_id": "kind-of@5.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-question/kind-of",
+  "_nodeVersion": "8.7.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-5.1.0.tgz_1507878225264_0.114781056297943"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.4.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^5.0.2",
+    "rawSpec": "^5.0.2",
+    "scope": null,
+    "spec": ">=5.0.2 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-question"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+  "_shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^5.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-question",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.1.1",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^0.1.12",
+    "matched": "^0.4.4",
+    "mocha": "^3.4.2",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+    "shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ed479b6ee194dc1edff852f17095ae1de40bafbc",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "5.1.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-question/package.json b/input_devices/mag/node_modules/prompt-question/package.json
new file mode 100644
index 00000000..a773e228
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-question/package.json
@@ -0,0 +1,153 @@
+{
+  "_args": [
+    [
+      "prompt-question@^5.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "prompt-question@>=5.0.1 <6.0.0",
+  "_id": "prompt-question@5.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-question",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prompt-question-5.0.2.tgz_1504203320180_0.42657720809802413"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "prompt-question",
+    "raw": "prompt-question@^5.0.1",
+    "rawSpec": "^5.0.1",
+    "scope": null,
+    "spec": ">=5.0.1 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base"
+  ],
+  "_resolved": "https://registry.npmjs.org/prompt-question/-/prompt-question-5.0.2.tgz",
+  "_shasum": "81a479f38f0bafecc758e5d6f7bc586e599610b3",
+  "_shrinkwrap": null,
+  "_spec": "prompt-question@^5.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/prompt-question/issues"
+  },
+  "dependencies": {
+    "clone-deep": "^1.0.0",
+    "debug": "^3.0.1",
+    "define-property": "^1.0.0",
+    "isobject": "^3.0.1",
+    "kind-of": "^5.0.2",
+    "koalas": "^1.0.2",
+    "prompt-choices": "^4.0.5"
+  },
+  "description": "Question object, used by Enquirer and prompt plugins.",
+  "devDependencies": {
+    "gulp": "^3.9.1",
+    "gulp-eslint": "^4.0.0",
+    "gulp-format-md": "^1.0.0",
+    "gulp-istanbul": "^1.1.2",
+    "gulp-mocha": "^3.0.1",
+    "gulp-unused": "^0.2.1",
+    "mocha": "^3.5.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-wreaLbbu8f5+7zXds199uiT11Ojp59Z4iBi6hONlSLtsKGTvL2UY8VglcxQ3t/X4qWIxsNCg6aT4O8keO65v6Q==",
+    "shasum": "81a479f38f0bafecc758e5d6f7bc586e599610b3",
+    "tarball": "https://registry.npmjs.org/prompt-question/-/prompt-question-5.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=4.0.0"
+  },
+  "files": [
+    "index.js",
+    "lib"
+  ],
+  "gitHead": "7c13d50538d52eaae5178488d213ee30639318ba",
+  "homepage": "https://github.com/enquirer/prompt-question",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "bar",
+    "bottom",
+    "checkbox",
+    "choice",
+    "cli",
+    "command",
+    "enquirer",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "password",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "prompt-question",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/prompt-question.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "base-prompt",
+      "prompt-choices"
+    ],
+    "related": {
+      "list": [
+        "choices-separator",
+        "enquirer",
+        "prompt-choices",
+        "readline-utils"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "5.0.2"
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/LICENSE b/input_devices/mag/node_modules/prompt-radio/LICENSE
new file mode 100644
index 00000000..ece74b5e
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-radio/README.md b/input_devices/mag/node_modules/prompt-radio/README.md
new file mode 100644
index 00000000..e0cb7324
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/README.md
@@ -0,0 +1,152 @@
+# prompt-radio [![NPM version](https://img.shields.io/npm/v/prompt-radio.svg?style=flat)](https://www.npmjs.com/package/prompt-radio) [![NPM monthly downloads](https://img.shields.io/npm/dm/prompt-radio.svg?style=flat)](https://npmjs.org/package/prompt-radio) [![NPM total downloads](https://img.shields.io/npm/dt/prompt-radio.svg?style=flat)](https://npmjs.org/package/prompt-radio) [![Linux Build Status](https://img.shields.io/travis/enquirer/prompt-radio.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/prompt-radio)
+
+> Radio prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer](http://enquirer.io).
+
+![prompt-radio example](https://raw.githubusercontent.com/enquirer/prompt-radio/master/docs/example.gif)
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save prompt-radio
+```
+
+## Usage
+
+```js
+var Radio = require('prompt-radio');
+var prompt = new Radio({
+  name: 'colors',
+  message: 'Favorite flavor?',
+  choices: [
+    'chocolate',
+    'strawberry',
+    'vanilla'
+  ]
+});
+
+// async
+prompt.ask(function(answer) {
+  console.log(answer);
+  // chocolate
+});
+
+// promise
+prompt.run()
+  .then(function(answer) {
+    console.log(answer);
+    // chocolate
+  });
+```
+
+## Enquirer plugin
+
+Register as a plugin with [enquirer](http://enquirer.io):
+
+```js
+var Enquirer = require('enquirer');
+var enquirer = new Enquirer();
+
+enquirer.register('radio', require('prompt-radio'));
+```
+
+### Enquirer examples
+
+[Enquirer](http://enquirer.io) supports both the declarative inquirer-style question format and a functional format using the `.question` method:
+
+**Declarative format**
+
+Questions can be defined as an array of objects, or a single question object:
+
+```js
+var questions = [
+  {
+    name: 'color',
+    message: 'What is your favorite color?',
+    type: 'radio',
+    default: 'blue',
+    choices: ['red', 'yellow', 'blue']
+  }
+];
+
+enquirer.ask(questions)
+  .then(function(answers) {
+    console.log(answers)
+  });
+```
+
+**Expressive format**
+
+Functional style questions.
+
+```js
+enquirer.question('color', 'Favorite color?', {
+  type: 'radio',
+  choices: ['red', 'yellow', 'blue']
+});
+
+enquirer.question('flavor', 'Favorite flavor?', {
+  type: 'radio',
+  default: 'chocolate',
+  choices: ['chocolate'] //<= no need for other choices ;)
+});
+
+enquirer.ask(['color', 'flavor'])
+  .then(function(answers) {
+    console.log(answers)
+  });
+```
+
+## Options
+
+### options.pointer
+
+Customize the pointer to use.
+
+TODO
+
+### options.checkbox
+
+**Type**: `Object`
+
+**Default**: (TODO)
+
+Customize the checkbox symbols to use.
+
+## About
+
+### Related projects
+
+* [prompt-base](https://www.npmjs.com/package/prompt-base): Base prompt module used for creating custom prompts. | [homepage](https://github.com/enquirer/prompt-base "Base prompt module used for creating custom prompts.")
+* [prompt-checkbox](https://www.npmjs.com/package/prompt-checkbox): Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer](http://enquirer.io). | [homepage](https://github.com/enquirer/prompt-checkbox "Multiple-choice/checkbox prompt. Can be used standalone or with a prompt system like [Enquirer].")
+* [prompt-confirm](https://www.npmjs.com/package/prompt-confirm): Confirm (yes/no) prompt. Can be used standalone or with a prompt system like [Enquirer](http://enquirer.io). | [homepage](https://github.com/enquirer/prompt-confirm "Confirm (yes/no) prompt. Can be used standalone or with a prompt system like [Enquirer].")
+* [prompt-question](https://www.npmjs.com/package/prompt-question): Question object, used by Enquirer and prompt plugins. | [homepage](https://github.com/enquirer/prompt-question "Question object, used by Enquirer and prompt plugins.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 08, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/prompt-radio/index.js b/input_devices/mag/node_modules/prompt-radio/index.js
new file mode 100644
index 00000000..22731aef
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/index.js
@@ -0,0 +1,60 @@
+'use strict';
+
+var debug = require('debug')('prompt-radio');
+var Checkbox = require('prompt-checkbox');
+
+/**
+ * Radio prompt
+ */
+
+function Radio(/*question, answers, rl*/) {
+  debug('initializing from <%s>', __filename);
+  Checkbox.apply(this, arguments);
+  this.question.type = 'radio';
+
+  this.action('i', function(pos) {
+    return pos;
+  });
+
+  this.action('a', function(pos) {
+    return pos;
+  });
+
+  this.action('number', function(pos, key) {
+    return enable(this, pos, key);
+  });
+
+  this.action('space', function(pos) {
+    return enable(this, pos);
+  });
+
+  function enable(actions, pos, key) {
+    pos = actions.position(pos, key) + (key ? -1 : 0);
+    actions.choices.uncheck();
+    actions.choices.check(pos);
+    return pos;
+  }
+}
+
+/**
+ * Inherit Checkbox prompt
+ */
+
+Checkbox.extend(Radio);
+
+/**
+ * Get selected choice
+ */
+
+Radio.prototype.getAnswer = function(input) {
+  if (Array.isArray(this.options.default)) {
+    throw new TypeError('expected options.default to be a string or number');
+  }
+  return Checkbox.prototype.getAnswer.call(this, arguments)[0];
+};
+
+/**
+ * Module exports
+ */
+
+module.exports = Radio;
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.coveralls.yml b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.eslintrc b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+  "rules": {
+    "no-console": 0,
+    "no-empty": [1, { "allowEmptyCatch": true }]
+  },
+  "extends": "eslint:recommended"
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.npmignore b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.travis.yml b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+  - "6"
+  - "5"
+  - "4"
+
+install:
+  - make node_modules
+
+script:
+  - make lint
+  - make test
+  - make coveralls
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/CHANGELOG.md b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+  * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+  * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+  * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+  * Fix: Inline extend function in node implementation (#452, @dougwilson)
+  * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+  
+  * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+  * Misc: clean up browser reference checks (#447, @thebigredgeek)
+  * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+  * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+  * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+  * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+  * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+  * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+  * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+  * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+  * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+  * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+  * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+  * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+  * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+  * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+  * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+  * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+  * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+  * Docs: fixed README typo (#391, @lurch)
+  * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+  * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+  * Fix: wrong reference in bower file (@thebigredgeek)
+  * Fix: webworker compatibility (@thebigredgeek)
+  * Fix: output formatting issue (#388, @kribblo)
+  * Fix: babel-loader compatibility (#383, @escwald)
+  * Misc: removed built asset from repo and publications (@thebigredgeek)
+  * Misc: moved source files to /src (#378, @yamikuronue)
+  * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+  * Test: coveralls integration (#378, @yamikuronue)
+  * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+  * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+  * Fix: custom log function (#379, @hsiliev)
+  * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+  * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+  * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+  * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+  * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+  * Fix: browser colors (#367, @tootallnate)
+  * Misc: travis ci integration (@thebigredgeek)
+  * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+  * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+  * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+  * Fix: revert "handle regex special characters" (@tootallnate)
+  * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+  * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+  * Improvement: allow colors in workers (#335, @botverse)
+  * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+  * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+  * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+  * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+  * Fix: be super-safe in index.js as well (@TooTallNate)
+  * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+  * Fix: Added electron compatibility (#324, @paulcbetts)
+  * Improvement: Added performance optimizations (@tootallnate)
+  * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+  * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+  * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+  * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+  * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+  * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+  * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+  * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+  * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+  * Readme: fix USE_COLORS to DEBUG_COLORS
+  * Readme: Doc fixes for format string sugar (#269, @mlucool)
+  * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+  * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+  * Readme: better docs for browser support (#224, @matthewmueller)
+  * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+  * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+  * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+  * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+  * package: update "ms" to v0.7.1 (#202, @dougwilson)
+  * README: add logging to file example (#193, @DanielOchoa)
+  * README: fixed a typo (#191, @amir-s)
+  * browser: expose `storage` (#190, @stephenmathieson)
+  * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+  * Updated stdout/stderr example (#186)
+  * Updated example/stdout.js to match debug current behaviour
+  * Renamed example/stderr.js to stdout.js
+  * Update Readme.md (#184)
+  * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+  * dist: recompile
+  * update "ms" to v0.7.0
+  * package: update "browserify" to v9.0.3
+  * component: fix "ms.js" repo location
+  * changed bower package name
+  * updated documentation about using debug in a browser
+  * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+  * browser: use `typeof` to check for `console` existence
+  * browser: check for `console.log` truthiness (fix IE 8/9)
+  * browser: add support for Chrome apps
+  * Readme: added Windows usage remarks
+  * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+  * node: implement `DEBUG_FD` env variable support
+  * package: update "browserify" to v6.1.0
+  * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+  * package: update "browserify" to v5.11.0
+  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+  * dist: recompile
+  * example: remove `console.info()` log usage
+  * example: add "Content-Type" UTF-8 header to browser example
+  * browser: place %c marker after the space character
+  * browser: reset the "content" color via `color: inherit`
+  * browser: add colors support for Firefox >= v31
+  * debug: prefer an instance `log()` function over the global one (#119)
+  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+  * Add support for multiple wildcards in namespaces (#122, @seegno)
+  * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+  * browser: update color palette (#113, @gscottolson)
+  * common: make console logging function configurable (#108, @timoxley)
+  * node: fix %o colors on old node <= 0.8.x
+  * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+  * browser: use `removeItem()` to clear localStorage
+  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+  * package: add "contributors" section
+  * node: fix comment typo
+  * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+  * make ms diff be global, not be scope
+  * debug: ignore empty strings in enable()
+  * node: make DEBUG_COLORS able to disable coloring
+  * *: export the `colors` array
+  * npmignore: don't publish the `dist` dir
+  * Makefile: refactor to use browserify
+  * package: add "browserify" as a dev dependency
+  * Readme: add Web Inspector Colors section
+  * node: reset terminal color for the debug content
+  * node: map "%o" to `util.inspect()`
+  * browser: map "%j" to `JSON.stringify()`
+  * debug: add custom "formatters"
+  * debug: use "ms" module for humanizing the diff
+  * Readme: add "bash" syntax highlighting
+  * browser: add Firebug color support
+  * browser: add colors for WebKit browsers
+  * node: apply log to `console`
+  * rewrite: abstract common logic for Node & browsers
+  * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+  * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+  * add `enable()` method for nodejs. Closes #27
+  * change from stderr to stdout
+  * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+  * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+  * fix: catch localStorage security error when cookies are blocked (Chrome)
+  * add debug(err) support. Closes #46
+  * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/LICENSE b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/prompt-radio/node_modules/debug/Makefile b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+	@NODE_ENV= $(PKG) install
+	@touch node_modules
+
+lint: .FORCE
+	eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+	istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+	mkdir -p dist
+
+	@$(BROWSERIFY) \
+		--standalone debug \
+		. > dist/debug.js
+
+	karma start --single-run
+	rimraf dist
+
+test: .FORCE
+	concurrently \
+		"make test-node" \
+		"make test-browser"
+
+coveralls:
+	cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/README.md b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) 
+[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+  ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+
+## Conventions
+
+  If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+  When running through Node.js, you can set a few environment variables that will
+  change the behavior of the debug logging:
+
+| Name      | Purpose                                         |
+|-----------|-------------------------------------------------|
+| `DEBUG`   | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+  __Note:__ The environment variables beginning with `DEBUG_` end up being
+  converted into an Options object that gets used with `%o`/`%O` formatters.
+  See the Node.js documentation for
+  [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+  for the complete list.
+
+## Formatters
+
+
+  Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O`      | Pretty-print an Object on multiple lines. |
+| `%o`      | Pretty-print an Object all on a single line. |
+| `%s`      | String. |
+| `%d`      | Number (both integer and float). |
+| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%`      | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+  You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+  return v.toString('hex')
+}
+
+// …elsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+//   foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+  You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+  or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+  if you don't want to build it yourself.
+
+  Debug's enable state is currently persisted by `localStorage`.
+  Consider the situation shown below where you have `worker:a` and `worker:b`,
+  and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+  Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+  option. These are WebKit web inspectors, Firefox ([since version
+  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+  and the Firebug plugin for Firefox (any version).
+
+  Colored output looks something like:
+
+  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
+
+
+## Output streams
+
+  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+ 
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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/input_devices/mag/node_modules/prompt-radio/node_modules/debug/component.json b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+  "name": "debug",
+  "repo": "visionmedia/debug",
+  "description": "small debugging utility",
+  "version": "2.6.9",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "main": "src/browser.js",
+  "scripts": [
+    "src/browser.js",
+    "src/debug.js"
+  ],
+  "dependencies": {
+    "rauchg/ms.js": "0.7.1"
+  }
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/karma.conf.js b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['mocha', 'chai', 'sinon'],
+
+
+    // list of files / patterns to load in the browser
+    files: [
+      'dist/debug.js',
+      'test/*spec.js'
+    ],
+
+
+    // list of files to exclude
+    exclude: [
+      'src/node.js'
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['progress'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false,
+
+    // Concurrency level
+    // how many browser should be started simultaneous
+    concurrency: Infinity
+  })
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/node.js b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/package.json b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/package.json
new file mode 100644
index 00000000..e647be1a
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/package.json
@@ -0,0 +1,128 @@
+{
+  "_args": [
+    [
+      "debug@^2.6.8",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-radio"
+    ]
+  ],
+  "_from": "debug@>=2.6.8 <3.0.0",
+  "_id": "debug@2.6.9",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-radio/debug",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196"
+  },
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "debug",
+    "raw": "debug@^2.6.8",
+    "rawSpec": "^2.6.8",
+    "scope": null,
+    "spec": ">=2.6.8 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-radio"
+  ],
+  "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+  "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+  "_shrinkwrap": null,
+  "_spec": "debug@^2.6.8",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-radio",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "browser": "./src/browser.js",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "component": {
+    "scripts": {
+      "debug/debug.js": "debug.js",
+      "debug/index.js": "browser.js"
+    }
+  },
+  "contributors": [
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "http://n8.io"
+    },
+    {
+      "name": "Andrew Rhyne",
+      "email": "rhyneandrew@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "ms": "2.0.0"
+  },
+  "description": "small debugging utility",
+  "devDependencies": {
+    "browserify": "9.0.3",
+    "chai": "^3.5.0",
+    "concurrently": "^3.1.0",
+    "coveralls": "^2.11.15",
+    "eslint": "^3.12.1",
+    "istanbul": "^0.4.5",
+    "karma": "^1.3.0",
+    "karma-chai": "^0.1.0",
+    "karma-mocha": "^1.3.0",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "karma-sinon": "^1.0.5",
+    "mocha": "^3.2.0",
+    "mocha-lcov-reporter": "^1.2.0",
+    "rimraf": "^2.5.4",
+    "sinon": "^1.17.6",
+    "sinon-chai": "^2.8.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+    "shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+    "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
+  },
+  "gitHead": "13abeae468fea297d0dccc50bc55590809241083",
+  "homepage": "https://github.com/visionmedia/debug#readme",
+  "keywords": [
+    "debug",
+    "debugger",
+    "log"
+  ],
+  "license": "MIT",
+  "main": "./src/index.js",
+  "maintainers": [
+    {
+      "name": "thebigredgeek",
+      "email": "rhyneandrew@gmail.com"
+    },
+    {
+      "name": "kolban",
+      "email": "kolban1@kolban.com"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    }
+  ],
+  "name": "debug",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "version": "2.6.9"
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/browser.js b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+               && 'undefined' != typeof chrome.storage
+                  ? chrome.storage.local
+                  : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+  'lightseagreen',
+  'forestgreen',
+  'goldenrod',
+  'dodgerblue',
+  'darkorchid',
+  'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+  // NB: In an Electron preload script, document will be defined but not fully
+  // initialized. Since we know we're in Chrome, we'll just detect this case
+  // explicitly
+  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+    return true;
+  }
+
+  // is webkit? http://stackoverflow.com/a/16459606/376773
+  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+    // is firebug? http://stackoverflow.com/a/398120/376773
+    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+    // is firefox >= v31?
+    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+    // double check webkit in userAgent just in case we are in a worker
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+  try {
+    return JSON.stringify(v);
+  } catch (err) {
+    return '[UnexpectedJSONParseError]: ' + err.message;
+  }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var useColors = this.useColors;
+
+  args[0] = (useColors ? '%c' : '')
+    + this.namespace
+    + (useColors ? ' %c' : ' ')
+    + args[0]
+    + (useColors ? '%c ' : ' ')
+    + '+' + exports.humanize(this.diff);
+
+  if (!useColors) return;
+
+  var c = 'color: ' + this.color;
+  args.splice(1, 0, c, 'color: inherit')
+
+  // the final "%c" is somewhat tricky, because there could be other
+  // arguments passed either before or after the %c, so we need to
+  // figure out the correct index to insert the CSS into
+  var index = 0;
+  var lastC = 0;
+  args[0].replace(/%[a-zA-Z%]/g, function(match) {
+    if ('%%' === match) return;
+    index++;
+    if ('%c' === match) {
+      // we only are interested in the *last* %c
+      // (the user may have provided their own)
+      lastC = index;
+    }
+  });
+
+  args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+  // this hackery is required for IE8/9, where
+  // the `console.log` function doesn't have 'apply'
+  return 'object' === typeof console
+    && console.log
+    && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  try {
+    if (null == namespaces) {
+      exports.storage.removeItem('debug');
+    } else {
+      exports.storage.debug = namespaces;
+    }
+  } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  var r;
+  try {
+    r = exports.storage.debug;
+  } catch(e) {}
+
+  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+  if (!r && typeof process !== 'undefined' && 'env' in process) {
+    r = process.env.DEBUG;
+  }
+
+  return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+  try {
+    return window.localStorage;
+  } catch (e) {}
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/debug.js b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+  var hash = 0, i;
+
+  for (i in namespace) {
+    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
+    hash |= 0; // Convert to 32bit integer
+  }
+
+  return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+  function debug() {
+    // disabled?
+    if (!debug.enabled) return;
+
+    var self = debug;
+
+    // set `diff` timestamp
+    var curr = +new Date();
+    var ms = curr - (prevTime || curr);
+    self.diff = ms;
+    self.prev = prevTime;
+    self.curr = curr;
+    prevTime = curr;
+
+    // turn the `arguments` into a proper Array
+    var args = new Array(arguments.length);
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i];
+    }
+
+    args[0] = exports.coerce(args[0]);
+
+    if ('string' !== typeof args[0]) {
+      // anything else let's inspect with %O
+      args.unshift('%O');
+    }
+
+    // apply any `formatters` transformations
+    var index = 0;
+    args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+      // if we encounter an escaped % then don't increase the array index
+      if (match === '%%') return match;
+      index++;
+      var formatter = exports.formatters[format];
+      if ('function' === typeof formatter) {
+        var val = args[index];
+        match = formatter.call(self, val);
+
+        // now we need to remove `args[index]` since it's inlined in the `format`
+        args.splice(index, 1);
+        index--;
+      }
+      return match;
+    });
+
+    // apply env-specific formatting (colors, etc.)
+    exports.formatArgs.call(self, args);
+
+    var logFn = debug.log || exports.log || console.log.bind(console);
+    logFn.apply(self, args);
+  }
+
+  debug.namespace = namespace;
+  debug.enabled = exports.enabled(namespace);
+  debug.useColors = exports.useColors();
+  debug.color = selectColor(namespace);
+
+  // env-specific initialization logic for debug instances
+  if ('function' === typeof exports.init) {
+    exports.init(debug);
+  }
+
+  return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+  exports.save(namespaces);
+
+  exports.names = [];
+  exports.skips = [];
+
+  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+  var len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    if (!split[i]) continue; // ignore empty strings
+    namespaces = split[i].replace(/\*/g, '.*?');
+    if (namespaces[0] === '-') {
+      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+    } else {
+      exports.names.push(new RegExp('^' + namespaces + '$'));
+    }
+  }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+  exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+  var i, len;
+  for (i = 0, len = exports.skips.length; i < len; i++) {
+    if (exports.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (i = 0, len = exports.names.length; i < len; i++) {
+    if (exports.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/index.js b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+  module.exports = require('./browser.js');
+} else {
+  module.exports = require('./node.js');
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/inspector-log.js b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+  const stdout = console._stdout;
+  console._stdout = nullStream;
+  console.log.apply(console, arguments);
+  console._stdout = stdout;
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/node.js b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+  return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+  // camel-case
+  var prop = key
+    .substring(6)
+    .toLowerCase()
+    .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+  // coerce string value into JS value
+  var val = process.env[key];
+  if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+  else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+  else if (val === 'null') val = null;
+  else val = Number(val);
+
+  obj[prop] = val;
+  return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ *   $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+  util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+             2 === fd ? process.stderr :
+             createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+  return 'colors' in exports.inspectOpts
+    ? Boolean(exports.inspectOpts.colors)
+    : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts)
+    .split('\n').map(function(str) {
+      return str.trim()
+    }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var name = this.namespace;
+  var useColors = this.useColors;
+
+  if (useColors) {
+    var c = this.color;
+    var prefix = '  \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+    args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+    args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+  } else {
+    args[0] = new Date().toUTCString()
+      + ' ' + name + ' ' + args[0];
+  }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+  return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  if (null == namespaces) {
+    // If you set a process.env field to null or undefined, it gets cast to the
+    // string 'null' or 'undefined'. Just delete instead.
+    delete process.env.DEBUG;
+  } else {
+    process.env.DEBUG = namespaces;
+  }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+  var stream;
+  var tty_wrap = process.binding('tty_wrap');
+
+  // Note stream._type is used for test-module-load-list.js
+
+  switch (tty_wrap.guessHandleType(fd)) {
+    case 'TTY':
+      stream = new tty.WriteStream(fd);
+      stream._type = 'tty';
+
+      // Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    case 'FILE':
+      var fs = require('fs');
+      stream = new fs.SyncWriteStream(fd, { autoClose: false });
+      stream._type = 'fs';
+      break;
+
+    case 'PIPE':
+    case 'TCP':
+      var net = require('net');
+      stream = new net.Socket({
+        fd: fd,
+        readable: false,
+        writable: true
+      });
+
+      // FIXME Should probably have an option in net.Socket to create a
+      // stream from an existing fd which is writable only. But for now
+      // we'll just add this hack and set the `readable` member to false.
+      // Test: ./node test/fixtures/echo.js < /etc/passwd
+      stream.readable = false;
+      stream.read = null;
+      stream._type = 'pipe';
+
+      // FIXME Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    default:
+      // Probably an error on in uv_guess_handle()
+      throw new Error('Implement me. Unknown stream file type!');
+  }
+
+  // For supporting legacy API we put the FD here.
+  stream.fd = fd;
+
+  stream._isStdio = true;
+
+  return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+  debug.inspectOpts = {};
+
+  var keys = Object.keys(exports.inspectOpts);
+  for (var i = 0; i < keys.length; i++) {
+    debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+  }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/ms/index.js b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+  options = options || {};
+  var type = typeof val;
+  if (type === 'string' && val.length > 0) {
+    return parse(val);
+  } else if (type === 'number' && isNaN(val) === false) {
+    return options.long ? fmtLong(val) : fmtShort(val);
+  }
+  throw new Error(
+    'val is not a non-empty string or a valid number. val=' +
+      JSON.stringify(val)
+  );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  str = String(str);
+  if (str.length > 100) {
+    return;
+  }
+  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+    str
+  );
+  if (!match) {
+    return;
+  }
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'yrs':
+    case 'yr':
+    case 'y':
+      return n * y;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'hrs':
+    case 'hr':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'mins':
+    case 'min':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 'secs':
+    case 'sec':
+    case 's':
+      return n * s;
+    case 'milliseconds':
+    case 'millisecond':
+    case 'msecs':
+    case 'msec':
+    case 'ms':
+      return n;
+    default:
+      return undefined;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+  if (ms >= d) {
+    return Math.round(ms / d) + 'd';
+  }
+  if (ms >= h) {
+    return Math.round(ms / h) + 'h';
+  }
+  if (ms >= m) {
+    return Math.round(ms / m) + 'm';
+  }
+  if (ms >= s) {
+    return Math.round(ms / s) + 's';
+  }
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+  return plural(ms, d, 'day') ||
+    plural(ms, h, 'hour') ||
+    plural(ms, m, 'minute') ||
+    plural(ms, s, 'second') ||
+    ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+  if (ms < n) {
+    return;
+  }
+  if (ms < n * 1.5) {
+    return Math.floor(ms / n) + ' ' + name;
+  }
+  return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/ms/license.md b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/input_devices/mag/node_modules/prompt-radio/node_modules/ms/package.json b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/package.json
new file mode 100644
index 00000000..986e90ba
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "ms@2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-radio/node_modules/debug"
+    ]
+  ],
+  "_from": "ms@2.0.0",
+  "_id": "ms@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-radio/ms",
+  "_nodeVersion": "7.8.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945"
+  },
+  "_npmUser": {
+    "email": "leo@zeit.co",
+    "name": "leo"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ms",
+    "raw": "ms@2.0.0",
+    "rawSpec": "2.0.0",
+    "scope": null,
+    "spec": "2.0.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/prompt-radio/debug"
+  ],
+  "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+  "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+  "_shrinkwrap": null,
+  "_spec": "ms@2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-radio/node_modules/debug",
+  "bugs": {
+    "url": "https://github.com/zeit/ms/issues"
+  },
+  "dependencies": {},
+  "description": "Tiny milisecond conversion utility",
+  "devDependencies": {
+    "eslint": "3.19.0",
+    "expect.js": "0.3.1",
+    "husky": "0.13.3",
+    "lint-staged": "3.4.1",
+    "mocha": "3.4.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+    "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
+  },
+  "eslintConfig": {
+    "env": {
+      "es6": true,
+      "node": true
+    },
+    "extends": "eslint:recommended"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4",
+  "homepage": "https://github.com/zeit/ms#readme",
+  "license": "MIT",
+  "lint-staged": {
+    "*.js": [
+      "git add",
+      "npm run lint",
+      "prettier --single-quote --write"
+    ]
+  },
+  "main": "./index",
+  "maintainers": [
+    {
+      "name": "leo",
+      "email": "leo@zeit.co"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "name": "ms",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zeit/ms.git"
+  },
+  "scripts": {
+    "lint": "eslint lib/* bin/*",
+    "precommit": "lint-staged",
+    "test": "mocha tests.js"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/prompt-radio/node_modules/ms/readme.md b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days')  // 172800000
+ms('1d')      // 86400000
+ms('10h')     // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h')      // 7200000
+ms('1m')      // 60000
+ms('5s')      // 5000
+ms('1y')      // 31557600000
+ms('100')     // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000)             // "1m"
+ms(2 * 60000)         // "2m"
+ms(ms('10 hours'))    // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true })             // "1 minute"
+ms(2 * 60000, { long: true })         // "2 minutes"
+ms(ms('10 hours'), { long: true })    // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/input_devices/mag/node_modules/prompt-radio/package.json b/input_devices/mag/node_modules/prompt-radio/package.json
new file mode 100644
index 00000000..420971c5
--- /dev/null
+++ b/input_devices/mag/node_modules/prompt-radio/package.json
@@ -0,0 +1,146 @@
+{
+  "_args": [
+    [
+      "prompt-radio@^1.2.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-list"
+    ]
+  ],
+  "_from": "prompt-radio@>=1.2.1 <2.0.0",
+  "_id": "prompt-radio@1.2.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/prompt-radio",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/prompt-radio-1.2.1.tgz_1499500707406_0.09980320744216442"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.1.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "prompt-radio",
+    "raw": "prompt-radio@^1.2.1",
+    "rawSpec": "^1.2.1",
+    "scope": null,
+    "spec": ">=1.2.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-list"
+  ],
+  "_resolved": "https://registry.npmjs.org/prompt-radio/-/prompt-radio-1.2.1.tgz",
+  "_shasum": "66a4cb2b189d3373e7f9ddbbc10700186c8959ff",
+  "_shrinkwrap": null,
+  "_spec": "prompt-radio@^1.2.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-list",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/prompt-radio/issues"
+  },
+  "dependencies": {
+    "debug": "^2.6.8",
+    "prompt-checkbox": "^2.2.0"
+  },
+  "description": "Radio prompt. Can be used as a standalone prompt, or as a plugin for [Enquirer].",
+  "devDependencies": {
+    "ansi-colors": "^0.2.0",
+    "enquirer": "^1.0.2",
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.4.2",
+    "strip-color": "^0.1.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-vH1iAkgbWyvZBC1BTajydiHmwJP4F1b684gq0fm2wOjPVW1zaDo01OXWr/Dske0XdoHhtZFNMOXNj/ZUSRBywg==",
+    "shasum": "66a4cb2b189d3373e7f9ddbbc10700186c8959ff",
+    "tarball": "https://registry.npmjs.org/prompt-radio/-/prompt-radio-1.2.1.tgz"
+  },
+  "engines": {
+    "node": ">=5.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "7f88f1d61c6b7e3c5aa0d07908d287b121a57894",
+  "homepage": "https://github.com/enquirer/prompt-radio",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "checkbox",
+    "choice",
+    "cli",
+    "command",
+    "enquirer",
+    "enquirer-prompt",
+    "enquirerprompt",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "password",
+    "plugin",
+    "prompt",
+    "prompts",
+    "question",
+    "radio",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "prompt-radio",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/prompt-radio.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "data": {
+      "alias": "radio"
+    },
+    "layout": "common-minimal",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "prompt-base",
+        "prompt-checkbox",
+        "prompt-confirm",
+        "prompt-question"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.2.1"
+}
diff --git a/input_devices/mag/node_modules/pump/.travis.yml b/input_devices/mag/node_modules/pump/.travis.yml
new file mode 100644
index 00000000..17f94330
--- /dev/null
+++ b/input_devices/mag/node_modules/pump/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - "0.10"
+
+script: "npm test"
diff --git a/input_devices/mag/node_modules/pump/LICENSE b/input_devices/mag/node_modules/pump/LICENSE
new file mode 100644
index 00000000..757562ec
--- /dev/null
+++ b/input_devices/mag/node_modules/pump/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mathias Buus
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/pump/README.md b/input_devices/mag/node_modules/pump/README.md
new file mode 100644
index 00000000..5029b27d
--- /dev/null
+++ b/input_devices/mag/node_modules/pump/README.md
@@ -0,0 +1,56 @@
+# pump
+
+pump is a small node module that pipes streams together and destroys all of them if one of them closes.
+
+```
+npm install pump
+```
+
+[![build status](http://img.shields.io/travis/mafintosh/pump.svg?style=flat)](http://travis-ci.org/mafintosh/pump)
+
+## What problem does it solve?
+
+When using standard `source.pipe(dest)` source will _not_ be destroyed if dest emits close or an error.
+You are also not able to provide a callback to tell when then pipe has finished.
+
+pump does these two things for you
+
+## Usage
+
+Simply pass the streams you want to pipe together to pump and add an optional callback
+
+``` js
+var pump = require('pump')
+var fs = require('fs')
+
+var source = fs.createReadStream('/dev/random')
+var dest = fs.createWriteStream('/dev/null')
+
+pump(source, dest, function(err) {
+  console.log('pipe finished', err)
+})
+
+setTimeout(function() {
+  dest.destroy() // when dest is closed pump will destroy source
+}, 1000)
+```
+
+You can use pump to pipe more than two streams together as well
+
+``` js
+var transform = someTransformStream()
+
+pump(source, transform, anotherTransform, dest, function(err) {
+  console.log('pipe finished', err)
+})
+```
+
+If `source`, `transform`, `anotherTransform` or `dest` closes all of them will be destroyed.
+
+## License
+
+MIT
+
+## Related
+
+`pump` is part of the [mississippi stream utility collection](https://github.com/maxogden/mississippi) which includes more useful stream modules similar to this one.
diff --git a/input_devices/mag/node_modules/pump/index.js b/input_devices/mag/node_modules/pump/index.js
new file mode 100644
index 00000000..d9ca0335
--- /dev/null
+++ b/input_devices/mag/node_modules/pump/index.js
@@ -0,0 +1,82 @@
+var once = require('once')
+var eos = require('end-of-stream')
+var fs = require('fs') // we only need fs to get the ReadStream and WriteStream prototypes
+
+var noop = function () {}
+var ancient = /^v?\.0/.test(process.version)
+
+var isFn = function (fn) {
+  return typeof fn === 'function'
+}
+
+var isFS = function (stream) {
+  if (!ancient) return false // newer node version do not need to care about fs is a special way
+  if (!fs) return false // browser
+  return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close)
+}
+
+var isRequest = function (stream) {
+  return stream.setHeader && isFn(stream.abort)
+}
+
+var destroyer = function (stream, reading, writing, callback) {
+  callback = once(callback)
+
+  var closed = false
+  stream.on('close', function () {
+    closed = true
+  })
+
+  eos(stream, {readable: reading, writable: writing}, function (err) {
+    if (err) return callback(err)
+    closed = true
+    callback()
+  })
+
+  var destroyed = false
+  return function (err) {
+    if (closed) return
+    if (destroyed) return
+    destroyed = true
+
+    if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks
+    if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want
+
+    if (isFn(stream.destroy)) return stream.destroy()
+
+    callback(err || new Error('stream was destroyed'))
+  }
+}
+
+var call = function (fn) {
+  fn()
+}
+
+var pipe = function (from, to) {
+  return from.pipe(to)
+}
+
+var pump = function () {
+  var streams = Array.prototype.slice.call(arguments)
+  var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop
+
+  if (Array.isArray(streams[0])) streams = streams[0]
+  if (streams.length < 2) throw new Error('pump requires two streams per minimum')
+
+  var error
+  var destroys = streams.map(function (stream, i) {
+    var reading = i < streams.length - 1
+    var writing = i > 0
+    return destroyer(stream, reading, writing, function (err) {
+      if (!error) error = err
+      if (err) destroys.forEach(call)
+      if (reading) return
+      destroys.forEach(call)
+      callback(error)
+    })
+  })
+
+  streams.reduce(pipe)
+}
+
+module.exports = pump
diff --git a/input_devices/mag/node_modules/pump/package.json b/input_devices/mag/node_modules/pump/package.json
new file mode 100644
index 00000000..799bfc07
--- /dev/null
+++ b/input_devices/mag/node_modules/pump/package.json
@@ -0,0 +1,88 @@
+{
+  "_args": [
+    [
+      "pump@^2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "pump@>=2.0.1 <3.0.0",
+  "_id": "pump@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/pump",
+  "_nodeVersion": "8.9.4",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/pump-2.0.1.tgz_1516638146695_0.7931882732082158"
+  },
+  "_npmUser": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "mafintosh"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "pump",
+    "raw": "pump@^2.0.1",
+    "rawSpec": "^2.0.1",
+    "scope": null,
+    "spec": ">=2.0.1 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+  "_shasum": "12399add6e4cf7526d973cbc8b5ce2e2908b3909",
+  "_shrinkwrap": null,
+  "_spec": "pump@^2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "Mathias Buus Madsen"
+  },
+  "browser": {
+    "fs": false
+  },
+  "bugs": {
+    "url": "https://github.com/mafintosh/pump/issues"
+  },
+  "dependencies": {
+    "end-of-stream": "^1.1.0",
+    "once": "^1.3.1"
+  },
+  "description": "pipe streams together and close all of them if one of them closes",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+    "shasum": "12399add6e4cf7526d973cbc8b5ce2e2908b3909",
+    "tarball": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz"
+  },
+  "gitHead": "4c93a460459fd970dd963fd9600c75b0e90404c2",
+  "homepage": "https://github.com/mafintosh/pump#readme",
+  "keywords": [
+    "callback",
+    "destroy",
+    "pipe",
+    "streams"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    }
+  ],
+  "name": "pump",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mafintosh/pump.git"
+  },
+  "scripts": {
+    "test": "node test-browser.js && node test-node.js"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/pump/test-browser.js b/input_devices/mag/node_modules/pump/test-browser.js
new file mode 100644
index 00000000..75ea4a29
--- /dev/null
+++ b/input_devices/mag/node_modules/pump/test-browser.js
@@ -0,0 +1,62 @@
+var stream = require('stream')
+var pump = require('./index')
+
+var rs = new stream.Readable()
+var ws = new stream.Writable()
+
+rs._read = function (size) {
+  this.push(Buffer(size).fill('abc'))
+}
+
+ws._write = function (chunk, encoding, cb) {
+  setTimeout(function () {
+    cb()
+  }, 100)
+}
+
+var toHex = function () {
+  var reverse = new (require('stream').Transform)()
+
+  reverse._transform = function (chunk, enc, callback) {
+    reverse.push(chunk.toString('hex'))
+    callback()
+  }
+
+  return reverse
+}
+
+var wsClosed = false
+var rsClosed = false
+var callbackCalled = false
+
+var check = function () {
+  if (wsClosed && rsClosed && callbackCalled) {
+    console.log('test-browser.js passes')
+    clearTimeout(timeout)
+  }
+}
+
+ws.on('finish', function () {
+  wsClosed = true
+  check()
+})
+
+rs.on('end', function () {
+  rsClosed = true
+  check()
+})
+
+pump(rs, toHex(), toHex(), toHex(), ws, function () {
+  callbackCalled = true
+  check()
+})
+
+setTimeout(function () {
+  rs.push(null)
+  rs.emit('close')
+}, 1000)
+
+var timeout = setTimeout(function () {
+  check()
+  throw new Error('timeout')
+}, 5000)
diff --git a/input_devices/mag/node_modules/pump/test-node.js b/input_devices/mag/node_modules/pump/test-node.js
new file mode 100644
index 00000000..034a6541
--- /dev/null
+++ b/input_devices/mag/node_modules/pump/test-node.js
@@ -0,0 +1,53 @@
+var pump = require('./index')
+
+var rs = require('fs').createReadStream('/dev/random')
+var ws = require('fs').createWriteStream('/dev/null')
+
+var toHex = function () {
+  var reverse = new (require('stream').Transform)()
+
+  reverse._transform = function (chunk, enc, callback) {
+    reverse.push(chunk.toString('hex'))
+    callback()
+  }
+
+  return reverse
+}
+
+var wsClosed = false
+var rsClosed = false
+var callbackCalled = false
+
+var check = function () {
+  if (wsClosed && rsClosed && callbackCalled) {
+    console.log('test-node.js passes')
+    clearTimeout(timeout)
+  }
+}
+
+ws.on('close', function () {
+  wsClosed = true
+  check()
+})
+
+rs.on('close', function () {
+  rsClosed = true
+  check()
+})
+
+var res = pump(rs, toHex(), toHex(), toHex(), ws, function () {
+  callbackCalled = true
+  check()
+})
+
+if (res) {
+  process.exit(1)
+}
+
+setTimeout(function () {
+  rs.destroy()
+}, 1000)
+
+var timeout = setTimeout(function () {
+  throw new Error('timeout')
+}, 5000)
diff --git a/input_devices/mag/node_modules/radio-symbol/LICENSE b/input_devices/mag/node_modules/radio-symbol/LICENSE
new file mode 100644
index 00000000..b11cb796
--- /dev/null
+++ b/input_devices/mag/node_modules/radio-symbol/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/radio-symbol/README.md b/input_devices/mag/node_modules/radio-symbol/README.md
new file mode 100644
index 00000000..4aead752
--- /dev/null
+++ b/input_devices/mag/node_modules/radio-symbol/README.md
@@ -0,0 +1,147 @@
+# radio-symbol [![NPM version](https://img.shields.io/npm/v/radio-symbol.svg?style=flat)](https://www.npmjs.com/package/radio-symbol) [![NPM monthly downloads](https://img.shields.io/npm/dm/radio-symbol.svg?style=flat)](https://npmjs.org/package/radio-symbol) [![NPM total downloads](https://img.shields.io/npm/dt/radio-symbol.svg?style=flat)](https://npmjs.org/package/radio-symbol) [![Linux Build Status](https://img.shields.io/travis/enquirer/radio-symbol.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/radio-symbol) [![Windows Build Status](https://img.shields.io/appveyor/ci/enquirer/radio-symbol.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/enquirer/radio-symbol)
+
+> Unicode radio button symbol, for toggling on/off in prompts.
+
+## Table of Contents
+
+- [Install](#install)
+- [Styles](#styles)
+- [Usage](#usage)
+  * [Circle symbol](#circle-symbol)
+  * [Ballot symbol](#ballot-symbol)
+  * [Star symbol](#star-symbol)
+- [About](#about)
+
+_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save radio-symbol
+```
+
+## Styles
+
+Have an idea for another radio-symbol style? [Pull requests](../../issues) greatly appreciated!
+
+## Usage
+
+* All of the `off` states are unstyled.
+* All of the `on` states are styled using [ansi green](https://github.com/jonschlinkert/ansi-green).
+* All of the `disabled` states are styled using [ansi gray](ansi-gray).
+
+**Unstyled**
+
+A `.nocolor` property is exposed with all states unstyled:
+
+```js
+var radio = require('radio-symbol').nocolor;
+```
+
+### Circle symbol
+
+The main export is a circle. This is the only symbol that has a windows-specific alternative.
+
+_(I haven't tested the star or ballot symbols on windows, if you try them [let us know](../../issues/new) if they have issues!)._
+
+```js
+var radio = require('radio-symbol');
+console.log(radio.on);
+//=> '◉'
+
+console.log(radio.off);
+//=> '◯'
+
+console.log(radio.disabled);
+//=> 'ⓧ'
+```
+
+**Windows**
+
+```js
+console.log(radio.on);
+//=> '(*)'
+
+console.log(radio.off);
+//=> '( )'
+
+console.log(radio.disabled);
+//=> '(x)'
+```
+
+### Ballot symbol
+
+```js
+var radio = require('radio-symbol');
+console.log(radio.ballot.on);
+//=> '☑'
+
+console.log(radio.ballot.off);
+//=> '☐
+
+console.log(radio.ballot.disabled);
+//=> '☒' 
+```
+
+### Star symbol
+
+```js
+var radio = require('radio-symbol');
+console.log(radio.star.on);
+//=> '★'
+
+console.log(radio.star.off);
+//=> '☆'
+
+console.log(radio.star.disabled);
+//=> '☆' // same as "off"
+```
+
+## About
+
+### Related projects
+
+* [error-symbol](https://www.npmjs.com/package/error-symbol): Cross-platform error symbol. | [homepage](https://github.com/jonschlinkert/error-symbol "Cross-platform error symbol.")
+* [info-symbol](https://www.npmjs.com/package/info-symbol): Cross-platform info symbol. | [homepage](https://github.com/jonschlinkert/info-symbol "Cross-platform info symbol.")
+* [success-symbol](https://www.npmjs.com/package/success-symbol): Cross-platform success symbol. | [homepage](https://github.com/jonschlinkert/success-symbol "Cross-platform success symbol.")
+* [warning-symbol](https://www.npmjs.com/package/warning-symbol): Cross-platform warning symbol. | [homepage](https://github.com/jonschlinkert/warning-symbol "Cross-platform warning symbol.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 21, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/radio-symbol/index.js b/input_devices/mag/node_modules/radio-symbol/index.js
new file mode 100644
index 00000000..3693adb6
--- /dev/null
+++ b/input_devices/mag/node_modules/radio-symbol/index.js
@@ -0,0 +1,53 @@
+'use strict';
+
+var win = require('is-windows')();
+var green = require('ansi-green');
+var gray = require('ansi-gray');
+
+module.exports = {
+  on: green(win ? '(*)' : '◉'),
+  off: win ? '( )' : '◯',
+  disabled: gray(win ? '(|)' : 'Ⓘ')
+};
+
+module.exports.star = {
+  on: green('★'),
+  off: '☆',
+  disabled: gray('☆')
+};
+
+module.exports.check = {
+  on: green(win ? '\u221A' : '✓'),
+  off: win ? '[ ]' : '☐',
+  disabled: gray(win ? '\u00D7' : '☒')
+};
+
+module.exports.ballot = {
+  on: green(win ? '[×]' : '☑'),
+  off: win ? '[ ]' : '☐',
+  disabled: gray(win ? '\u00D7' : '☒')
+};
+
+module.exports.nocolor = {
+  on: win ? '(*)' : '◉',
+  off: win ? '( )' : '◯',
+  disabled: win ? '(|)' : 'Ⓘ',
+
+  star: {
+    on: win ? '*' : '★',
+    off: '☆',
+    disabled: '☆'
+  },
+
+  ballot: {
+    on: '☑',
+    off: '☐',
+    disabled: '☒'
+  },
+
+  check: {
+    on: win ? '\u221A' : '✓',
+    off: win ? '[ ]' : '☐',
+    disabled: win ? '\u00D7' : '☒'
+  }
+};
diff --git a/input_devices/mag/node_modules/radio-symbol/package.json b/input_devices/mag/node_modules/radio-symbol/package.json
new file mode 100644
index 00000000..7b451834
--- /dev/null
+++ b/input_devices/mag/node_modules/radio-symbol/package.json
@@ -0,0 +1,119 @@
+{
+  "_args": [
+    [
+      "radio-symbol@^2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "radio-symbol@>=2.0.0 <3.0.0",
+  "_id": "radio-symbol@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/radio-symbol",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/radio-symbol-2.0.0.tgz_1495372809447_0.24921682686544955"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.6.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "radio-symbol",
+    "raw": "radio-symbol@^2.0.0",
+    "rawSpec": "^2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/radio-symbol/-/radio-symbol-2.0.0.tgz",
+  "_shasum": "7aa9bfc50485636d52dd76d6a8e631b290799ae1",
+  "_shrinkwrap": null,
+  "_spec": "radio-symbol@^2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/radio-symbol/issues"
+  },
+  "dependencies": {
+    "ansi-gray": "^0.1.1",
+    "ansi-green": "^0.1.1",
+    "is-windows": "^1.0.1"
+  },
+  "description": "Unicode radio button symbol, for toggling on/off in prompts.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.3.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "7aa9bfc50485636d52dd76d6a8e631b290799ae1",
+    "tarball": "https://registry.npmjs.org/radio-symbol/-/radio-symbol-2.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "470288958e83edb2169a8082761edd75caf93e81",
+  "homepage": "https://github.com/enquirer/radio-symbol",
+  "keywords": [
+    "cli",
+    "console",
+    "prompt",
+    "radio",
+    "symbol",
+    "terminal",
+    "unicode"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "radio-symbol",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/radio-symbol.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "error-symbol",
+        "info-symbol",
+        "success-symbol",
+        "warning-symbol"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": true
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/LICENSE.APACHE2 b/input_devices/mag/node_modules/rc/LICENSE.APACHE2
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/LICENSE.APACHE2
rename to input_devices/mag/node_modules/rc/LICENSE.APACHE2
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/LICENSE.BSD b/input_devices/mag/node_modules/rc/LICENSE.BSD
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/LICENSE.BSD
rename to input_devices/mag/node_modules/rc/LICENSE.BSD
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/LICENSE.MIT b/input_devices/mag/node_modules/rc/LICENSE.MIT
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/LICENSE.MIT
rename to input_devices/mag/node_modules/rc/LICENSE.MIT
diff --git a/input_devices/mag/node_modules/rc/README.md b/input_devices/mag/node_modules/rc/README.md
new file mode 100644
index 00000000..e6522e26
--- /dev/null
+++ b/input_devices/mag/node_modules/rc/README.md
@@ -0,0 +1,227 @@
+# rc
+
+The non-configurable configuration loader for lazy people.
+
+## Usage
+
+The only option is to pass rc the name of your app, and your default configuration.
+
+```javascript
+var conf = require('rc')(appname, {
+  //defaults go here.
+  port: 2468,
+
+  //defaults which are objects will be merged, not replaced
+  views: {
+    engine: 'jade'
+  }
+});
+```
+
+`rc` will return your configuration options merged with the defaults you specify.
+If you pass in a predefined defaults object, it will be mutated:
+
+```javascript
+var conf = {};
+require('rc')(appname, conf);
+```
+
+If `rc` finds any config files for your app, the returned config object will have
+a `configs` array containing their paths:
+
+```javascript
+var appCfg = require('rc')(appname, conf);
+appCfg.configs[0] // /etc/appnamerc
+appCfg.configs[1] // /home/dominictarr/.config/appname
+appCfg.config // same as appCfg.configs[appCfg.configs.length - 1]
+```
+
+## Standards
+
+Given your application name (`appname`), rc will look in all the obvious places for configuration.
+
+  * command line arguments, parsed by minimist _(e.g. `--foo baz`, also nested: `--foo.bar=baz`)_
+  * environment variables prefixed with `${appname}_`
+    * or use "\_\_" to indicate nested properties <br/> _(e.g. `appname_foo__bar__baz` => `foo.bar.baz`)_
+  * if you passed an option `--config file` then from that file
+  * a local `.${appname}rc` or the first found looking in `./ ../ ../../ ../../../` etc.
+  * `$HOME/.${appname}rc`
+  * `$HOME/.${appname}/config`
+  * `$HOME/.config/${appname}`
+  * `$HOME/.config/${appname}/config`
+  * `/etc/${appname}rc`
+  * `/etc/${appname}/config`
+  * the defaults object you passed in.
+
+All configuration sources that were found will be flattened into one object,
+so that sources **earlier** in this list override later ones.
+
+
+## Configuration File Formats
+
+Configuration files (e.g. `.appnamerc`) may be in either [json](http://json.org/example) or [ini](http://en.wikipedia.org/wiki/INI_file) format. **No** file extension (`.json` or `.ini`) should be used. The example configurations below are equivalent:
+
+
+#### Formatted as `ini`
+
+```
+; You can include comments in `ini` format if you want.
+
+dependsOn=0.10.0
+
+
+; `rc` has built-in support for ini sections, see?
+
+[commands]
+  www     = ./commands/www
+  console = ./commands/repl
+
+
+; You can even do nested sections
+
+[generators.options]
+  engine  = ejs
+
+[generators.modules]
+  new     = generate-new
+  engine  = generate-backend
+
+```
+
+#### Formatted as `json`
+
+```javascript
+{
+  // You can even comment your JSON, if you want
+  "dependsOn": "0.10.0",
+  "commands": {
+    "www": "./commands/www",
+    "console": "./commands/repl"
+  },
+  "generators": {
+    "options": {
+      "engine": "ejs"
+    },
+    "modules": {
+      "new": "generate-new",
+      "backend": "generate-backend"
+    }
+  }
+}
+```
+
+Comments are stripped from JSON config via [strip-json-comments](https://github.com/sindresorhus/strip-json-comments).
+
+> Since ini, and env variables do not have a standard for types, your application needs be prepared for strings.
+
+To ensure that string representations of booleans and numbers are always converted into their proper types (especially useful if you intend to do strict `===` comparisons), consider using a module such as [parse-strings-in-object](https://github.com/anselanza/parse-strings-in-object) to wrap the config object returned from rc.
+
+
+## Simple example demonstrating precedence
+Assume you have an application like this (notice the hard-coded defaults passed to rc):
+```
+const conf = require('rc')('myapp', {
+    port: 12345,
+    mode: 'test'
+});
+
+console.log(JSON.stringify(conf, null, 2));
+```
+You also have a file `config.json`, with these contents:
+```
+{
+  "port": 9000,
+  "foo": "from config json",
+  "something": "else"
+}
+```
+And a file `.myapprc` in the same folder, with these contents:
+```
+{
+  "port": "3001",
+  "foo": "bar"
+}
+```
+Here is the expected output from various commands:
+
+`node .`
+```
+{
+  "port": "3001",
+  "mode": "test",
+  "foo": "bar",
+  "_": [],
+  "configs": [
+    "/Users/stephen/repos/conftest/.myapprc"
+  ],
+  "config": "/Users/stephen/repos/conftest/.myapprc"
+}
+```
+*Default `mode` from hard-coded object is retained, but port is overridden by `.myapprc` file (automatically found based on appname match), and `foo` is added.*
+
+
+`node . --foo baz`
+```
+{
+  "port": "3001",
+  "mode": "test",
+  "foo": "baz",
+  "_": [],
+  "configs": [
+    "/Users/stephen/repos/conftest/.myapprc"
+  ],
+  "config": "/Users/stephen/repos/conftest/.myapprc"
+}
+```
+*Same result as above but `foo` is overridden because command-line arguments take precedence over `.myapprc` file.*
+
+`node . --foo barbar --config config.json`
+```
+{
+  "port": 9000,
+  "mode": "test",
+  "foo": "barbar",
+  "something": "else",
+  "_": [],
+  "config": "config.json",
+  "configs": [
+    "/Users/stephen/repos/conftest/.myapprc",
+    "config.json"
+  ]
+}
+```
+*Now the `port` comes from the `config.json` file specified (overriding the value from `.myapprc`), and `foo` value is overriden by command-line despite also being specified in the `config.json` file.*
+ 
+
+
+## Advanced Usage
+
+#### Pass in your own `argv`
+
+You may pass in your own `argv` as the third argument to `rc`.  This is in case you want to [use your own command-line opts parser](https://github.com/dominictarr/rc/pull/12).
+
+```javascript
+require('rc')(appname, defaults, customArgvParser);
+```
+
+## Pass in your own parser
+
+If you have a special need to use a non-standard parser,
+you can do so by passing in the parser as the 4th argument.
+(leave the 3rd as null to get the default args parser)
+
+```javascript
+require('rc')(appname, defaults, null, parser);
+```
+
+This may also be used to force a more strict format,
+such as strict, valid JSON only.
+
+## Note on Performance
+
+`rc` is running `fs.statSync`-- so make sure you don't use it in a hot code path (e.g. a request handler) 
+
+
+## License
+
+Multi-licensed under the two-clause BSD License, MIT License, or Apache License, version 2.0
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/browser.js b/input_devices/mag/node_modules/rc/browser.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/browser.js
rename to input_devices/mag/node_modules/rc/browser.js
diff --git a/input_devices/mag/node_modules/rc/cli.js b/input_devices/mag/node_modules/rc/cli.js
new file mode 100755
index 00000000..ab05b607
--- /dev/null
+++ b/input_devices/mag/node_modules/rc/cli.js
@@ -0,0 +1,4 @@
+#! /usr/bin/env node
+var rc = require('./index')
+
+console.log(JSON.stringify(rc(process.argv[2]), false, 2))
diff --git a/input_devices/mag/node_modules/rc/index.js b/input_devices/mag/node_modules/rc/index.js
new file mode 100755
index 00000000..65eb47af
--- /dev/null
+++ b/input_devices/mag/node_modules/rc/index.js
@@ -0,0 +1,53 @@
+var cc   = require('./lib/utils')
+var join = require('path').join
+var deepExtend = require('deep-extend')
+var etc = '/etc'
+var win = process.platform === "win32"
+var home = win
+           ? process.env.USERPROFILE
+           : process.env.HOME
+
+module.exports = function (name, defaults, argv, parse) {
+  if('string' !== typeof name)
+    throw new Error('rc(name): name *must* be string')
+  if(!argv)
+    argv = require('minimist')(process.argv.slice(2))
+  defaults = (
+      'string' === typeof defaults
+    ? cc.json(defaults) : defaults
+    ) || {}
+
+  parse = parse || cc.parse
+
+  var env = cc.env(name + '_')
+
+  var configs = [defaults]
+  var configFiles = []
+  function addConfigFile (file) {
+    if (configFiles.indexOf(file) >= 0) return
+    var fileConfig = cc.file(file)
+    if (fileConfig) {
+      configs.push(parse(fileConfig))
+      configFiles.push(file)
+    }
+  }
+
+  // which files do we look at?
+  if (!win)
+   [join(etc, name, 'config'),
+    join(etc, name + 'rc')].forEach(addConfigFile)
+  if (home)
+   [join(home, '.config', name, 'config'),
+    join(home, '.config', name),
+    join(home, '.' + name, 'config'),
+    join(home, '.' + name + 'rc')].forEach(addConfigFile)
+  addConfigFile(cc.find('.'+name+'rc'))
+  if (env.config) addConfigFile(env.config)
+  if (argv.config) addConfigFile(argv.config)
+
+  return deepExtend.apply(null, configs.concat([
+    env,
+    argv,
+    configFiles.length ? {configs: configFiles, config: configFiles[configFiles.length - 1]} : undefined,
+  ]))
+}
diff --git a/input_devices/mag/node_modules/rc/lib/utils.js b/input_devices/mag/node_modules/rc/lib/utils.js
new file mode 100644
index 00000000..8b3beffa
--- /dev/null
+++ b/input_devices/mag/node_modules/rc/lib/utils.js
@@ -0,0 +1,104 @@
+'use strict';
+var fs   = require('fs')
+var ini  = require('ini')
+var path = require('path')
+var stripJsonComments = require('strip-json-comments')
+
+var parse = exports.parse = function (content) {
+
+  //if it ends in .json or starts with { then it must be json.
+  //must be done this way, because ini accepts everything.
+  //can't just try and parse it and let it throw if it's not ini.
+  //everything is ini. even json with a syntax error.
+
+  if(/^\s*{/.test(content))
+    return JSON.parse(stripJsonComments(content))
+  return ini.parse(content)
+
+}
+
+var file = exports.file = function () {
+  var args = [].slice.call(arguments).filter(function (arg) { return arg != null })
+
+  //path.join breaks if it's a not a string, so just skip this.
+  for(var i in args)
+    if('string' !== typeof args[i])
+      return
+
+  var file = path.join.apply(null, args)
+  var content
+  try {
+    return fs.readFileSync(file,'utf-8')
+  } catch (err) {
+    return
+  }
+}
+
+var json = exports.json = function () {
+  var content = file.apply(null, arguments)
+  return content ? parse(content) : null
+}
+
+var env = exports.env = function (prefix, env) {
+  env = env || process.env
+  var obj = {}
+  var l = prefix.length
+  for(var k in env) {
+    if(k.toLowerCase().indexOf(prefix.toLowerCase()) === 0) {
+
+      var keypath = k.substring(l).split('__')
+
+      // Trim empty strings from keypath array
+      var _emptyStringIndex
+      while ((_emptyStringIndex=keypath.indexOf('')) > -1) {
+        keypath.splice(_emptyStringIndex, 1)
+      }
+
+      var cursor = obj
+      keypath.forEach(function _buildSubObj(_subkey,i){
+
+        // (check for _subkey first so we ignore empty strings)
+        // (check for cursor to avoid assignment to primitive objects)
+        if (!_subkey || typeof cursor !== 'object')
+          return
+
+        // If this is the last key, just stuff the value in there
+        // Assigns actual value from env variable to final key
+        // (unless it's just an empty string- in that case use the last valid key)
+        if (i === keypath.length-1)
+          cursor[_subkey] = env[k]
+
+
+        // Build sub-object if nothing already exists at the keypath
+        if (cursor[_subkey] === undefined)
+          cursor[_subkey] = {}
+
+        // Increment cursor used to track the object at the current depth
+        cursor = cursor[_subkey]
+
+      })
+
+    }
+
+  }
+
+  return obj
+}
+
+var find = exports.find = function () {
+  var rel = path.join.apply(null, [].slice.call(arguments))
+
+  function find(start, rel) {
+    var file = path.join(start, rel)
+    try {
+      fs.statSync(file)
+      return file
+    } catch (err) {
+      if(path.dirname(start) !== start) // root
+        return find(path.dirname(start), rel)
+    }
+  }
+  return find(process.cwd(), rel)
+}
+
+
diff --git a/input_devices/mag/node_modules/rc/package.json b/input_devices/mag/node_modules/rc/package.json
new file mode 100644
index 00000000..d05f5524
--- /dev/null
+++ b/input_devices/mag/node_modules/rc/package.json
@@ -0,0 +1,96 @@
+{
+  "_args": [
+    [
+      "rc@^1.2.7",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "rc@>=1.2.7 <2.0.0",
+  "_id": "rc@1.2.8",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/rc",
+  "_nodeVersion": "8.11.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/rc_1.2.8_1527378233915_0.6821654736416851"
+  },
+  "_npmUser": {
+    "email": "dominic.tarr@gmail.com",
+    "name": "dominictarr"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "rc",
+    "raw": "rc@^1.2.7",
+    "rawSpec": "^1.2.7",
+    "scope": null,
+    "spec": ">=1.2.7 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+  "_shasum": "cd924bf5200a075b83c188cd6b9e211b7fc0d3ed",
+  "_shrinkwrap": null,
+  "_spec": "rc@^1.2.7",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "dominic.tarr@gmail.com",
+    "name": "Dominic Tarr",
+    "url": "dominictarr.com"
+  },
+  "bin": {
+    "rc": "./cli.js"
+  },
+  "browser": "browser.js",
+  "bugs": {
+    "url": "https://github.com/dominictarr/rc/issues"
+  },
+  "dependencies": {
+    "deep-extend": "^0.6.0",
+    "ini": "~1.3.0",
+    "minimist": "^1.2.0",
+    "strip-json-comments": "~2.0.1"
+  },
+  "description": "hardwired configuration loader",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 12,
+    "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbCfE7CRA9TVsSAnZWagAAYbwQAICZiX5zsBQ0j8NLD+Kp\n1BuZLlHANAd292mKHzfTgaukUXwfHN1x66tmuMaZtLZUWLemGDHsBybaZ9NK\na0bRpM8olD7JxvN2Fuh2zn93RZd7HBu7RY8IVel01Bp33uMrzVY6JtwUbkKc\n21iIB8FLjYyKvebSdG8IlPbHgcrrDtms7sn8WGnINnQCBIl7CjcqgUmqueZi\n8pUmTMfAAhTCbC9+oKVmAFzwv0SAslzORoCuMW+V0czRPh98s0KGg25yiNN8\nqeO76miy59yF8NsOr3woO1+Reu9yfirtNeImJUTR9ByLvQi41wnyswqjn7nC\nFX2M5HwywwS/S/Ku3PF7JmqCcNyjTzRI2h74GT6WQ6QVVKHf3ctOrCL8Iq68\nfVLT/flyOq86jxFp4D6TWATJLrnMfA2sNEFHR+mqRI0xPxOMbz5CZLXa7wDW\nLvR41cWoY8BR+jMl2dh96LQ7SMOel8WYw2Kmf9RQbGBB0oHcU1fG9GDXWdsU\nqdShHMHX7I+mLIHyp2eFIUT4OhNXqP2XWkepg+M7gOSMktHhkAf1skUlcBxP\nyaGSSCYQ29IB9RsCZDTqYfwxVdYT69nkaQkMp8qW9cPoI06dYinhyb4WfGQI\nai0HxFBuNZUSSdHykNEUC+e6cs7OmLx4Z5/7O9Xqv6z/+ZbibTCGyxcdMp7h\nd3Ki\r\n=VTiJ\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "cd924bf5200a075b83c188cd6b9e211b7fc0d3ed",
+    "tarball": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+    "unpackedSize": 17255
+  },
+  "gitHead": "a97f6adcc37ee1cad06ab7dc9b0bd842bbc5c664",
+  "homepage": "https://github.com/dominictarr/rc#readme",
+  "keywords": [
+    "config",
+    "defaults",
+    "rc",
+    "unix"
+  ],
+  "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "dominictarr",
+      "email": "dominic.tarr@gmail.com"
+    }
+  ],
+  "name": "rc",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/dominictarr/rc.git"
+  },
+  "scripts": {
+    "test": "set -e; node test/test.js; node test/ini.js; node test/nested-env-vars.js"
+  },
+  "version": "1.2.8"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/test/ini.js b/input_devices/mag/node_modules/rc/test/ini.js
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/test/ini.js
rename to input_devices/mag/node_modules/rc/test/ini.js
diff --git a/input_devices/mag/node_modules/rc/test/nested-env-vars.js b/input_devices/mag/node_modules/rc/test/nested-env-vars.js
new file mode 100644
index 00000000..0ecd1763
--- /dev/null
+++ b/input_devices/mag/node_modules/rc/test/nested-env-vars.js
@@ -0,0 +1,50 @@
+
+var seed = Math.random();
+var n = 'rc'+ seed;
+var N = 'RC'+ seed;
+var assert = require('assert')
+
+
+// Basic usage
+process.env[n+'_someOpt__a'] = 42
+process.env[n+'_someOpt__x__'] = 99
+process.env[n+'_someOpt__a__b'] = 186
+process.env[n+'_someOpt__a__b__c'] = 243
+process.env[n+'_someOpt__x__y'] = 1862
+process.env[n+'_someOpt__z'] = 186577
+
+// Should ignore empty strings from orphaned '__'
+process.env[n+'_someOpt__z__x__'] = 18629
+process.env[n+'_someOpt__w__w__'] = 18629
+
+// Leading '__' should ignore everything up to 'z'
+process.env[n+'___z__i__'] = 9999
+
+// should ignore case for config name section.
+process.env[N+'_test_upperCase'] = 187
+
+function testPrefix(prefix) {
+	var config = require('../')(prefix, {
+	  option: true
+	})
+
+	console.log('\n\n------ nested-env-vars ------\n',{prefix: prefix}, '\n', config);
+
+	assert.equal(config.option, true)
+	assert.equal(config.someOpt.a, 42)
+	assert.equal(config.someOpt.x, 99)
+	// Should not override `a` once it's been set
+	assert.equal(config.someOpt.a/*.b*/, 42)
+	// Should not override `x` once it's been set
+	assert.equal(config.someOpt.x/*.y*/, 99)
+	assert.equal(config.someOpt.z, 186577)
+	// Should not override `z` once it's been set
+	assert.equal(config.someOpt.z/*.x*/, 186577)
+	assert.equal(config.someOpt.w.w, 18629)
+	assert.equal(config.z.i, 9999)
+
+	assert.equal(config.test_upperCase, 187)
+}
+
+testPrefix(n);
+testPrefix(N);
diff --git a/input_devices/mag/node_modules/rc/test/test.js b/input_devices/mag/node_modules/rc/test/test.js
new file mode 100644
index 00000000..4f633518
--- /dev/null
+++ b/input_devices/mag/node_modules/rc/test/test.js
@@ -0,0 +1,59 @@
+
+var n = 'rc'+Math.random()
+var assert = require('assert')
+
+process.env[n+'_envOption'] = 42
+
+var config = require('../')(n, {
+  option: true
+})
+
+console.log(config)
+
+assert.equal(config.option, true)
+assert.equal(config.envOption, 42)
+
+var customArgv = require('../')(n, {
+  option: true
+}, { // nopt-like argv
+  option: false,
+  envOption: 24,
+  argv: {
+    remain: [],
+    cooked: ['--no-option', '--envOption', '24'],
+    original: ['--no-option', '--envOption=24']
+  }
+})
+
+console.log(customArgv)
+
+assert.equal(customArgv.option, false)
+assert.equal(customArgv.envOption, 24)
+
+var fs = require('fs')
+var path = require('path')
+var jsonrc = path.resolve('.' + n + 'rc');
+
+fs.writeFileSync(jsonrc, [
+  '{',
+    '// json overrides default',
+    '"option": false,',
+    '/* env overrides json */',
+    '"envOption": 24',
+  '}'
+].join('\n'));
+
+var commentedJSON = require('../')(n, {
+  option: true
+})
+
+fs.unlinkSync(jsonrc);
+
+console.log(commentedJSON)
+
+assert.equal(commentedJSON.option, false)
+assert.equal(commentedJSON.envOption, 42)
+
+assert.equal(commentedJSON.config, jsonrc)
+assert.equal(commentedJSON.configs.length, 1)
+assert.equal(commentedJSON.configs[0], jsonrc)
diff --git a/input_devices/mag/node_modules/readable-stream/.travis.yml b/input_devices/mag/node_modules/readable-stream/.travis.yml
new file mode 100644
index 00000000..40992555
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/.travis.yml
@@ -0,0 +1,55 @@
+sudo: false
+language: node_js
+before_install:
+  - npm install -g npm@2
+  - test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g
+notifications:
+  email: false
+matrix:
+  fast_finish: true
+  include:
+  - node_js: '0.8'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: '0.10'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: '0.11'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: '0.12'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 1
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 2
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 3
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 4
+    env: TASK=test
+  - node_js: 5
+    env: TASK=test
+  - node_js: 6
+    env: TASK=test
+  - node_js: 7
+    env: TASK=test
+  - node_js: 8
+    env: TASK=test
+  - node_js: 9
+    env: TASK=test
+script: "npm run $TASK"
+env:
+  global:
+  - secure: rE2Vvo7vnjabYNULNyLFxOyt98BoJexDqsiOnfiD6kLYYsiQGfr/sbZkPMOFm9qfQG7pjqx+zZWZjGSswhTt+626C0t/njXqug7Yps4c3dFblzGfreQHp7wNX5TFsvrxd6dAowVasMp61sJcRnB2w8cUzoe3RAYUDHyiHktwqMc=
+  - secure: g9YINaKAdMatsJ28G9jCGbSaguXCyxSTy+pBO6Ch0Cf57ZLOTka3HqDj8p3nV28LUIHZ3ut5WO43CeYKwt4AUtLpBS3a0dndHdY6D83uY6b2qh5hXlrcbeQTq2cvw2y95F7hm4D1kwrgZ7ViqaKggRcEupAL69YbJnxeUDKWEdI=
diff --git a/input_devices/mag/node_modules/readable-stream/CONTRIBUTING.md b/input_devices/mag/node_modules/readable-stream/CONTRIBUTING.md
new file mode 100644
index 00000000..f478d58d
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/CONTRIBUTING.md
@@ -0,0 +1,38 @@
+# Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+* (a) The contribution was created in whole or in part by me and I
+  have the right to submit it under the open source license
+  indicated in the file; or
+
+* (b) The contribution is based upon previous work that, to the best
+  of my knowledge, is covered under an appropriate open source
+  license and I have the right under that license to submit that
+  work with modifications, whether created in whole or in part
+  by me, under the same open source license (unless I am
+  permitted to submit under a different license), as indicated
+  in the file; or
+
+* (c) The contribution was provided directly to me by some other
+  person who certified (a), (b) or (c) and I have not modified
+  it.
+
+* (d) I understand and agree that this project and the contribution
+  are public and that a record of the contribution (including all
+  personal information I submit with it, including my sign-off) is
+  maintained indefinitely and may be redistributed consistent with
+  this project or the open source license(s) involved.
+
+## Moderation Policy
+
+The [Node.js Moderation Policy] applies to this WG.
+
+## Code of Conduct
+
+The [Node.js Code of Conduct][] applies to this WG.
+
+[Node.js Code of Conduct]:
+https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md
+[Node.js Moderation Policy]:
+https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md
diff --git a/input_devices/mag/node_modules/readable-stream/GOVERNANCE.md b/input_devices/mag/node_modules/readable-stream/GOVERNANCE.md
new file mode 100644
index 00000000..16ffb93f
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/GOVERNANCE.md
@@ -0,0 +1,136 @@
+### Streams Working Group
+
+The Node.js Streams is jointly governed by a Working Group
+(WG)
+that is responsible for high-level guidance of the project.
+
+The WG has final authority over this project including:
+
+* Technical direction
+* Project governance and process (including this policy)
+* Contribution policy
+* GitHub repository hosting
+* Conduct guidelines
+* Maintaining the list of additional Collaborators
+
+For the current list of WG members, see the project
+[README.md](./README.md#current-project-team-members).
+
+### Collaborators
+
+The readable-stream GitHub repository is
+maintained by the WG and additional Collaborators who are added by the
+WG on an ongoing basis.
+
+Individuals making significant and valuable contributions are made
+Collaborators and given commit-access to the project. These
+individuals are identified by the WG and their addition as
+Collaborators is discussed during the WG meeting.
+
+_Note:_ If you make a significant contribution and are not considered
+for commit-access log an issue or contact a WG member directly and it
+will be brought up in the next WG meeting.
+
+Modifications of the contents of the readable-stream repository are
+made on
+a collaborative basis. Anybody with a GitHub account may propose a
+modification via pull request and it will be considered by the project
+Collaborators. All pull requests must be reviewed and accepted by a
+Collaborator with sufficient expertise who is able to take full
+responsibility for the change. In the case of pull requests proposed
+by an existing Collaborator, an additional Collaborator is required
+for sign-off. Consensus should be sought if additional Collaborators
+participate and there is disagreement around a particular
+modification. See _Consensus Seeking Process_ below for further detail
+on the consensus model used for governance.
+
+Collaborators may opt to elevate significant or controversial
+modifications, or modifications that have not found consensus to the
+WG for discussion by assigning the ***WG-agenda*** tag to a pull
+request or issue. The WG should serve as the final arbiter where
+required.
+
+For the current list of Collaborators, see the project
+[README.md](./README.md#members).
+
+### WG Membership
+
+WG seats are not time-limited.  There is no fixed size of the WG.
+However, the expected target is between 6 and 12, to ensure adequate
+coverage of important areas of expertise, balanced with the ability to
+make decisions efficiently.
+
+There is no specific set of requirements or qualifications for WG
+membership beyond these rules.
+
+The WG may add additional members to the WG by unanimous consensus.
+
+A WG member may be removed from the WG by voluntary resignation, or by
+unanimous consensus of all other WG members.
+
+Changes to WG membership should be posted in the agenda, and may be
+suggested as any other agenda item (see "WG Meetings" below).
+
+If an addition or removal is proposed during a meeting, and the full
+WG is not in attendance to participate, then the addition or removal
+is added to the agenda for the subsequent meeting.  This is to ensure
+that all members are given the opportunity to participate in all
+membership decisions.  If a WG member is unable to attend a meeting
+where a planned membership decision is being made, then their consent
+is assumed.
+
+No more than 1/3 of the WG members may be affiliated with the same
+employer.  If removal or resignation of a WG member, or a change of
+employment by a WG member, creates a situation where more than 1/3 of
+the WG membership shares an employer, then the situation must be
+immediately remedied by the resignation or removal of one or more WG
+members affiliated with the over-represented employer(s).
+
+### WG Meetings
+
+The WG meets occasionally on a Google Hangout On Air. A designated moderator
+approved by the WG runs the meeting. Each meeting should be
+published to YouTube.
+
+Items are added to the WG agenda that are considered contentious or
+are modifications of governance, contribution policy, WG membership,
+or release process.
+
+The intention of the agenda is not to approve or review all patches;
+that should happen continuously on GitHub and be handled by the larger
+group of Collaborators.
+
+Any community member or contributor can ask that something be added to
+the next meeting's agenda by logging a GitHub Issue. Any Collaborator,
+WG member or the moderator can add the item to the agenda by adding
+the ***WG-agenda*** tag to the issue.
+
+Prior to each WG meeting the moderator will share the Agenda with
+members of the WG. WG members can add any items they like to the
+agenda at the beginning of each meeting. The moderator and the WG
+cannot veto or remove items.
+
+The WG may invite persons or representatives from certain projects to
+participate in a non-voting capacity.
+
+The moderator is responsible for summarizing the discussion of each
+agenda item and sends it as a pull request after the meeting.
+
+### Consensus Seeking Process
+
+The WG follows a
+[Consensus
+Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making)
+decision-making model.
+
+When an agenda item has appeared to reach a consensus the moderator
+will ask "Does anyone object?" as a final call for dissent from the
+consensus.
+
+If an agenda item cannot reach a consensus a WG member can call for
+either a closing vote or a vote to table the issue to the next
+meeting. The call for a vote must be seconded by a majority of the WG
+or else the discussion will continue. Simple majority wins.
+
+Note that changes to WG membership require a majority consensus.  See
+"WG Membership" above.
diff --git a/input_devices/mag/node_modules/readable-stream/LICENSE b/input_devices/mag/node_modules/readable-stream/LICENSE
new file mode 100644
index 00000000..2873b3b2
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/LICENSE
@@ -0,0 +1,47 @@
+Node.js is licensed for use as follows:
+
+"""
+Copyright Node.js contributors. All rights reserved.
+
+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.
+"""
+
+This license applies to parts of Node.js originating from the
+https://github.com/joyent/node repository:
+
+"""
+Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+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/input_devices/mag/node_modules/readable-stream/README.md b/input_devices/mag/node_modules/readable-stream/README.md
new file mode 100644
index 00000000..23fe3f3e
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/README.md
@@ -0,0 +1,58 @@
+# readable-stream
+
+***Node-core v8.11.1 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream)
+
+
+[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/)
+[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/)
+
+
+[![Sauce Test Status](https://saucelabs.com/browser-matrix/readable-stream.svg)](https://saucelabs.com/u/readable-stream)
+
+```bash
+npm install --save readable-stream
+```
+
+***Node-core streams for userland***
+
+This package is a mirror of the Streams2 and Streams3 implementations in
+Node-core.
+
+Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.11.1/docs/api/stream.html).
+
+If you want to guarantee a stable streams base, regardless of what version of
+Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html).
+
+As of version 2.0.0 **readable-stream** uses semantic versioning.
+
+# Streams Working Group
+
+`readable-stream` is maintained by the Streams Working Group, which
+oversees the development and maintenance of the Streams API within
+Node.js. The responsibilities of the Streams Working Group include:
+
+* Addressing stream issues on the Node.js issue tracker.
+* Authoring and editing stream documentation within the Node.js project.
+* Reviewing changes to stream subclasses within the Node.js project.
+* Redirecting changes to streams from the Node.js project to this
+  project.
+* Assisting in the implementation of stream providers within Node.js.
+* Recommending versions of `readable-stream` to be included in Node.js.
+* Messaging about the future of streams to give the community advance
+  notice of changes.
+
+<a name="members"></a>
+## Team Members
+
+* **Chris Dickinson** ([@chrisdickinson](https://github.com/chrisdickinson)) &lt;christopher.s.dickinson@gmail.com&gt;
+  - Release GPG key: 9554F04D7259F04124DE6B476D5A82AC7E37093B
+* **Calvin Metcalf** ([@calvinmetcalf](https://github.com/calvinmetcalf)) &lt;calvin.metcalf@gmail.com&gt;
+  - Release GPG key: F3EF5F62A87FC27A22E643F714CE4FF5015AA242
+* **Rod Vagg** ([@rvagg](https://github.com/rvagg)) &lt;rod@vagg.org&gt;
+  - Release GPG key: DD8F2338BAE7501E3DD5AC78C273792F7D83545D
+* **Sam Newman** ([@sonewman](https://github.com/sonewman)) &lt;newmansam@outlook.com&gt;
+* **Mathias Buus** ([@mafintosh](https://github.com/mafintosh)) &lt;mathiasbuus@gmail.com&gt;
+* **Domenic Denicola** ([@domenic](https://github.com/domenic)) &lt;d@domenic.me&gt;
+* **Matteo Collina** ([@mcollina](https://github.com/mcollina)) &lt;matteo.collina@gmail.com&gt;
+  - Release GPG key: 3ABC01543F22DD2239285CDD818674489FBC127E
+* **Irina Shestak** ([@lrlna](https://github.com/lrlna)) &lt;shestak.irina@gmail.com&gt;
diff --git a/input_devices/mag/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md b/input_devices/mag/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md
new file mode 100644
index 00000000..83275f19
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md
@@ -0,0 +1,60 @@
+# streams WG Meeting 2015-01-30
+
+## Links
+
+* **Google Hangouts Video**: http://www.youtube.com/watch?v=I9nDOSGfwZg
+* **GitHub Issue**: https://github.com/iojs/readable-stream/issues/106
+* **Original Minutes Google Doc**: https://docs.google.com/document/d/17aTgLnjMXIrfjgNaTUnHQO7m3xgzHR2VXBTmi03Qii4/
+
+## Agenda
+
+Extracted from https://github.com/iojs/readable-stream/labels/wg-agenda prior to meeting.
+
+* adopt a charter [#105](https://github.com/iojs/readable-stream/issues/105)
+* release and versioning strategy [#101](https://github.com/iojs/readable-stream/issues/101)
+* simpler stream creation [#102](https://github.com/iojs/readable-stream/issues/102)
+* proposal: deprecate implicit flowing of streams [#99](https://github.com/iojs/readable-stream/issues/99)
+
+## Minutes
+
+### adopt a charter
+
+* group: +1's all around
+
+### What versioning scheme should be adopted?
+* group: +1’s 3.0.0
+* domenic+group: pulling in patches from other sources where appropriate
+* mikeal: version independently, suggesting versions for io.js
+* mikeal+domenic: work with TC to notify in advance of changes
+simpler stream creation
+
+### streamline creation of streams
+* sam: streamline creation of streams
+* domenic: nice simple solution posted
+  but, we lose the opportunity to change the model
+  may not be backwards incompatible (double check keys)
+
+  **action item:** domenic will check
+
+### remove implicit flowing of streams on(‘data’)
+* add isFlowing / isPaused
+* mikeal: worrying that we’re documenting polyfill methods – confuses users
+* domenic: more reflective API is probably good, with warning labels for users
+* new section for mad scientists (reflective stream access)
+* calvin: name the “third state”
+* mikeal: maybe borrow the name from whatwg?
+* domenic: we’re missing the “third state”
+* consensus: kind of difficult to name the third state
+* mikeal: figure out differences in states / compat
+* mathias: always flow on data – eliminates third state
+  * explore what it breaks
+
+**action items:**
+* ask isaac for ability to list packages by what public io.js APIs they use (esp. Stream)
+* ask rod/build for infrastructure
+* **chris**: explore the “flow on data” approach
+* add isPaused/isFlowing
+* add new docs section
+* move isPaused to that section
+
+
diff --git a/input_devices/mag/node_modules/readable-stream/duplex-browser.js b/input_devices/mag/node_modules/readable-stream/duplex-browser.js
new file mode 100644
index 00000000..f8b2db83
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/duplex-browser.js
@@ -0,0 +1 @@
+module.exports = require('./lib/_stream_duplex.js');
diff --git a/input_devices/mag/node_modules/readable-stream/duplex.js b/input_devices/mag/node_modules/readable-stream/duplex.js
new file mode 100644
index 00000000..46924cbf
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/duplex.js
@@ -0,0 +1 @@
+module.exports = require('./readable').Duplex
diff --git a/input_devices/mag/node_modules/readable-stream/lib/_stream_duplex.js b/input_devices/mag/node_modules/readable-stream/lib/_stream_duplex.js
new file mode 100644
index 00000000..a1ca813e
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/_stream_duplex.js
@@ -0,0 +1,131 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+// a duplex stream is just a stream that is both readable and writable.
+// Since JS doesn't have multiple prototypal inheritance, this class
+// prototypally inherits from Readable, and then parasitically from
+// Writable.
+
+'use strict';
+
+/*<replacement>*/
+
+var pna = require('process-nextick-args');
+/*</replacement>*/
+
+/*<replacement>*/
+var objectKeys = Object.keys || function (obj) {
+  var keys = [];
+  for (var key in obj) {
+    keys.push(key);
+  }return keys;
+};
+/*</replacement>*/
+
+module.exports = Duplex;
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+var Readable = require('./_stream_readable');
+var Writable = require('./_stream_writable');
+
+util.inherits(Duplex, Readable);
+
+{
+  // avoid scope creep, the keys array can then be collected
+  var keys = objectKeys(Writable.prototype);
+  for (var v = 0; v < keys.length; v++) {
+    var method = keys[v];
+    if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
+  }
+}
+
+function Duplex(options) {
+  if (!(this instanceof Duplex)) return new Duplex(options);
+
+  Readable.call(this, options);
+  Writable.call(this, options);
+
+  if (options && options.readable === false) this.readable = false;
+
+  if (options && options.writable === false) this.writable = false;
+
+  this.allowHalfOpen = true;
+  if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
+
+  this.once('end', onend);
+}
+
+Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
+  // making it explicit this property is not enumerable
+  // because otherwise some prototype manipulation in
+  // userland will fail
+  enumerable: false,
+  get: function () {
+    return this._writableState.highWaterMark;
+  }
+});
+
+// the no-half-open enforcer
+function onend() {
+  // if we allow half-open state, or if the writable side ended,
+  // then we're ok.
+  if (this.allowHalfOpen || this._writableState.ended) return;
+
+  // no more data can be written.
+  // But allow more writes to happen in this tick.
+  pna.nextTick(onEndNT, this);
+}
+
+function onEndNT(self) {
+  self.end();
+}
+
+Object.defineProperty(Duplex.prototype, 'destroyed', {
+  get: function () {
+    if (this._readableState === undefined || this._writableState === undefined) {
+      return false;
+    }
+    return this._readableState.destroyed && this._writableState.destroyed;
+  },
+  set: function (value) {
+    // we ignore the value if the stream
+    // has not been initialized yet
+    if (this._readableState === undefined || this._writableState === undefined) {
+      return;
+    }
+
+    // backward compatibility, the user is explicitly
+    // managing destroyed
+    this._readableState.destroyed = value;
+    this._writableState.destroyed = value;
+  }
+});
+
+Duplex.prototype._destroy = function (err, cb) {
+  this.push(null);
+  this.end();
+
+  pna.nextTick(cb, err);
+};
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_passthrough.js b/input_devices/mag/node_modules/readable-stream/lib/_stream_passthrough.js
similarity index 91%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_passthrough.js
rename to input_devices/mag/node_modules/readable-stream/lib/_stream_passthrough.js
index 895ca50a..a9c83588 100644
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_passthrough.js
+++ b/input_devices/mag/node_modules/readable-stream/lib/_stream_passthrough.js
@@ -23,6 +23,8 @@
 // basically just the most minimal sort of Transform stream.
 // Every written chunk gets output as-is.
 
+'use strict';
+
 module.exports = PassThrough;
 
 var Transform = require('./_stream_transform');
@@ -35,12 +37,11 @@ util.inherits = require('inherits');
 util.inherits(PassThrough, Transform);
 
 function PassThrough(options) {
-  if (!(this instanceof PassThrough))
-    return new PassThrough(options);
+  if (!(this instanceof PassThrough)) return new PassThrough(options);
 
   Transform.call(this, options);
 }
 
-PassThrough.prototype._transform = function(chunk, encoding, cb) {
+PassThrough.prototype._transform = function (chunk, encoding, cb) {
   cb(null, chunk);
-};
+};
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readable-stream/lib/_stream_readable.js b/input_devices/mag/node_modules/readable-stream/lib/_stream_readable.js
new file mode 100644
index 00000000..bf34ac65
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/_stream_readable.js
@@ -0,0 +1,1019 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+'use strict';
+
+/*<replacement>*/
+
+var pna = require('process-nextick-args');
+/*</replacement>*/
+
+module.exports = Readable;
+
+/*<replacement>*/
+var isArray = require('isarray');
+/*</replacement>*/
+
+/*<replacement>*/
+var Duplex;
+/*</replacement>*/
+
+Readable.ReadableState = ReadableState;
+
+/*<replacement>*/
+var EE = require('events').EventEmitter;
+
+var EElistenerCount = function (emitter, type) {
+  return emitter.listeners(type).length;
+};
+/*</replacement>*/
+
+/*<replacement>*/
+var Stream = require('./internal/streams/stream');
+/*</replacement>*/
+
+/*<replacement>*/
+
+var Buffer = require('safe-buffer').Buffer;
+var OurUint8Array = global.Uint8Array || function () {};
+function _uint8ArrayToBuffer(chunk) {
+  return Buffer.from(chunk);
+}
+function _isUint8Array(obj) {
+  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
+}
+
+/*</replacement>*/
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+/*<replacement>*/
+var debugUtil = require('util');
+var debug = void 0;
+if (debugUtil && debugUtil.debuglog) {
+  debug = debugUtil.debuglog('stream');
+} else {
+  debug = function () {};
+}
+/*</replacement>*/
+
+var BufferList = require('./internal/streams/BufferList');
+var destroyImpl = require('./internal/streams/destroy');
+var StringDecoder;
+
+util.inherits(Readable, Stream);
+
+var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume'];
+
+function prependListener(emitter, event, fn) {
+  // Sadly this is not cacheable as some libraries bundle their own
+  // event emitter implementation with them.
+  if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn);
+
+  // This is a hack to make sure that our error handler is attached before any
+  // userland ones.  NEVER DO THIS. This is here only because this code needs
+  // to continue to work with older versions of Node.js that do not include
+  // the prependListener() method. The goal is to eventually remove this hack.
+  if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
+}
+
+function ReadableState(options, stream) {
+  Duplex = Duplex || require('./_stream_duplex');
+
+  options = options || {};
+
+  // Duplex streams are both readable and writable, but share
+  // the same options object.
+  // However, some cases require setting options to different
+  // values for the readable and the writable sides of the duplex stream.
+  // These options can be provided separately as readableXXX and writableXXX.
+  var isDuplex = stream instanceof Duplex;
+
+  // object stream flag. Used to make read(n) ignore n and to
+  // make all the buffer merging and length checks go away
+  this.objectMode = !!options.objectMode;
+
+  if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
+
+  // the point at which it stops calling _read() to fill the buffer
+  // Note: 0 is a valid value, means "don't call _read preemptively ever"
+  var hwm = options.highWaterMark;
+  var readableHwm = options.readableHighWaterMark;
+  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
+
+  if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm;
+
+  // cast to ints.
+  this.highWaterMark = Math.floor(this.highWaterMark);
+
+  // A linked list is used to store data chunks instead of an array because the
+  // linked list can remove elements from the beginning faster than
+  // array.shift()
+  this.buffer = new BufferList();
+  this.length = 0;
+  this.pipes = null;
+  this.pipesCount = 0;
+  this.flowing = null;
+  this.ended = false;
+  this.endEmitted = false;
+  this.reading = false;
+
+  // a flag to be able to tell if the event 'readable'/'data' is emitted
+  // immediately, or on a later tick.  We set this to true at first, because
+  // any actions that shouldn't happen until "later" should generally also
+  // not happen before the first read call.
+  this.sync = true;
+
+  // whenever we return null, then we set a flag to say
+  // that we're awaiting a 'readable' event emission.
+  this.needReadable = false;
+  this.emittedReadable = false;
+  this.readableListening = false;
+  this.resumeScheduled = false;
+
+  // has it been destroyed
+  this.destroyed = false;
+
+  // Crypto is kind of old and crusty.  Historically, its default string
+  // encoding is 'binary' so we have to make this configurable.
+  // Everything else in the universe uses 'utf8', though.
+  this.defaultEncoding = options.defaultEncoding || 'utf8';
+
+  // the number of writers that are awaiting a drain event in .pipe()s
+  this.awaitDrain = 0;
+
+  // if true, a maybeReadMore has been scheduled
+  this.readingMore = false;
+
+  this.decoder = null;
+  this.encoding = null;
+  if (options.encoding) {
+    if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
+    this.decoder = new StringDecoder(options.encoding);
+    this.encoding = options.encoding;
+  }
+}
+
+function Readable(options) {
+  Duplex = Duplex || require('./_stream_duplex');
+
+  if (!(this instanceof Readable)) return new Readable(options);
+
+  this._readableState = new ReadableState(options, this);
+
+  // legacy
+  this.readable = true;
+
+  if (options) {
+    if (typeof options.read === 'function') this._read = options.read;
+
+    if (typeof options.destroy === 'function') this._destroy = options.destroy;
+  }
+
+  Stream.call(this);
+}
+
+Object.defineProperty(Readable.prototype, 'destroyed', {
+  get: function () {
+    if (this._readableState === undefined) {
+      return false;
+    }
+    return this._readableState.destroyed;
+  },
+  set: function (value) {
+    // we ignore the value if the stream
+    // has not been initialized yet
+    if (!this._readableState) {
+      return;
+    }
+
+    // backward compatibility, the user is explicitly
+    // managing destroyed
+    this._readableState.destroyed = value;
+  }
+});
+
+Readable.prototype.destroy = destroyImpl.destroy;
+Readable.prototype._undestroy = destroyImpl.undestroy;
+Readable.prototype._destroy = function (err, cb) {
+  this.push(null);
+  cb(err);
+};
+
+// Manually shove something into the read() buffer.
+// This returns true if the highWaterMark has not been hit yet,
+// similar to how Writable.write() returns true if you should
+// write() some more.
+Readable.prototype.push = function (chunk, encoding) {
+  var state = this._readableState;
+  var skipChunkCheck;
+
+  if (!state.objectMode) {
+    if (typeof chunk === 'string') {
+      encoding = encoding || state.defaultEncoding;
+      if (encoding !== state.encoding) {
+        chunk = Buffer.from(chunk, encoding);
+        encoding = '';
+      }
+      skipChunkCheck = true;
+    }
+  } else {
+    skipChunkCheck = true;
+  }
+
+  return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
+};
+
+// Unshift should *always* be something directly out of read()
+Readable.prototype.unshift = function (chunk) {
+  return readableAddChunk(this, chunk, null, true, false);
+};
+
+function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
+  var state = stream._readableState;
+  if (chunk === null) {
+    state.reading = false;
+    onEofChunk(stream, state);
+  } else {
+    var er;
+    if (!skipChunkCheck) er = chunkInvalid(state, chunk);
+    if (er) {
+      stream.emit('error', er);
+    } else if (state.objectMode || chunk && chunk.length > 0) {
+      if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) {
+        chunk = _uint8ArrayToBuffer(chunk);
+      }
+
+      if (addToFront) {
+        if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true);
+      } else if (state.ended) {
+        stream.emit('error', new Error('stream.push() after EOF'));
+      } else {
+        state.reading = false;
+        if (state.decoder && !encoding) {
+          chunk = state.decoder.write(chunk);
+          if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state);
+        } else {
+          addChunk(stream, state, chunk, false);
+        }
+      }
+    } else if (!addToFront) {
+      state.reading = false;
+    }
+  }
+
+  return needMoreData(state);
+}
+
+function addChunk(stream, state, chunk, addToFront) {
+  if (state.flowing && state.length === 0 && !state.sync) {
+    stream.emit('data', chunk);
+    stream.read(0);
+  } else {
+    // update the buffer info.
+    state.length += state.objectMode ? 1 : chunk.length;
+    if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
+
+    if (state.needReadable) emitReadable(stream);
+  }
+  maybeReadMore(stream, state);
+}
+
+function chunkInvalid(state, chunk) {
+  var er;
+  if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
+    er = new TypeError('Invalid non-string/buffer chunk');
+  }
+  return er;
+}
+
+// if it's past the high water mark, we can push in some more.
+// Also, if we have no data yet, we can stand some
+// more bytes.  This is to work around cases where hwm=0,
+// such as the repl.  Also, if the push() triggered a
+// readable event, and the user called read(largeNumber) such that
+// needReadable was set, then we ought to push more, so that another
+// 'readable' event will be triggered.
+function needMoreData(state) {
+  return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
+}
+
+Readable.prototype.isPaused = function () {
+  return this._readableState.flowing === false;
+};
+
+// backwards compatibility.
+Readable.prototype.setEncoding = function (enc) {
+  if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
+  this._readableState.decoder = new StringDecoder(enc);
+  this._readableState.encoding = enc;
+  return this;
+};
+
+// Don't raise the hwm > 8MB
+var MAX_HWM = 0x800000;
+function computeNewHighWaterMark(n) {
+  if (n >= MAX_HWM) {
+    n = MAX_HWM;
+  } else {
+    // Get the next highest power of 2 to prevent increasing hwm excessively in
+    // tiny amounts
+    n--;
+    n |= n >>> 1;
+    n |= n >>> 2;
+    n |= n >>> 4;
+    n |= n >>> 8;
+    n |= n >>> 16;
+    n++;
+  }
+  return n;
+}
+
+// This function is designed to be inlinable, so please take care when making
+// changes to the function body.
+function howMuchToRead(n, state) {
+  if (n <= 0 || state.length === 0 && state.ended) return 0;
+  if (state.objectMode) return 1;
+  if (n !== n) {
+    // Only flow one buffer at a time
+    if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
+  }
+  // If we're asking for more than the current hwm, then raise the hwm.
+  if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
+  if (n <= state.length) return n;
+  // Don't have enough
+  if (!state.ended) {
+    state.needReadable = true;
+    return 0;
+  }
+  return state.length;
+}
+
+// you can override either this method, or the async _read(n) below.
+Readable.prototype.read = function (n) {
+  debug('read', n);
+  n = parseInt(n, 10);
+  var state = this._readableState;
+  var nOrig = n;
+
+  if (n !== 0) state.emittedReadable = false;
+
+  // if we're doing read(0) to trigger a readable event, but we
+  // already have a bunch of data in the buffer, then just trigger
+  // the 'readable' event and move on.
+  if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
+    debug('read: emitReadable', state.length, state.ended);
+    if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
+    return null;
+  }
+
+  n = howMuchToRead(n, state);
+
+  // if we've ended, and we're now clear, then finish it up.
+  if (n === 0 && state.ended) {
+    if (state.length === 0) endReadable(this);
+    return null;
+  }
+
+  // All the actual chunk generation logic needs to be
+  // *below* the call to _read.  The reason is that in certain
+  // synthetic stream cases, such as passthrough streams, _read
+  // may be a completely synchronous operation which may change
+  // the state of the read buffer, providing enough data when
+  // before there was *not* enough.
+  //
+  // So, the steps are:
+  // 1. Figure out what the state of things will be after we do
+  // a read from the buffer.
+  //
+  // 2. If that resulting state will trigger a _read, then call _read.
+  // Note that this may be asynchronous, or synchronous.  Yes, it is
+  // deeply ugly to write APIs this way, but that still doesn't mean
+  // that the Readable class should behave improperly, as streams are
+  // designed to be sync/async agnostic.
+  // Take note if the _read call is sync or async (ie, if the read call
+  // has returned yet), so that we know whether or not it's safe to emit
+  // 'readable' etc.
+  //
+  // 3. Actually pull the requested chunks out of the buffer and return.
+
+  // if we need a readable event, then we need to do some reading.
+  var doRead = state.needReadable;
+  debug('need readable', doRead);
+
+  // if we currently have less than the highWaterMark, then also read some
+  if (state.length === 0 || state.length - n < state.highWaterMark) {
+    doRead = true;
+    debug('length less than watermark', doRead);
+  }
+
+  // however, if we've ended, then there's no point, and if we're already
+  // reading, then it's unnecessary.
+  if (state.ended || state.reading) {
+    doRead = false;
+    debug('reading or ended', doRead);
+  } else if (doRead) {
+    debug('do read');
+    state.reading = true;
+    state.sync = true;
+    // if the length is currently zero, then we *need* a readable event.
+    if (state.length === 0) state.needReadable = true;
+    // call internal read method
+    this._read(state.highWaterMark);
+    state.sync = false;
+    // If _read pushed data synchronously, then `reading` will be false,
+    // and we need to re-evaluate how much data we can return to the user.
+    if (!state.reading) n = howMuchToRead(nOrig, state);
+  }
+
+  var ret;
+  if (n > 0) ret = fromList(n, state);else ret = null;
+
+  if (ret === null) {
+    state.needReadable = true;
+    n = 0;
+  } else {
+    state.length -= n;
+  }
+
+  if (state.length === 0) {
+    // If we have nothing in the buffer, then we want to know
+    // as soon as we *do* get something into the buffer.
+    if (!state.ended) state.needReadable = true;
+
+    // If we tried to read() past the EOF, then emit end on the next tick.
+    if (nOrig !== n && state.ended) endReadable(this);
+  }
+
+  if (ret !== null) this.emit('data', ret);
+
+  return ret;
+};
+
+function onEofChunk(stream, state) {
+  if (state.ended) return;
+  if (state.decoder) {
+    var chunk = state.decoder.end();
+    if (chunk && chunk.length) {
+      state.buffer.push(chunk);
+      state.length += state.objectMode ? 1 : chunk.length;
+    }
+  }
+  state.ended = true;
+
+  // emit 'readable' now to make sure it gets picked up.
+  emitReadable(stream);
+}
+
+// Don't emit readable right away in sync mode, because this can trigger
+// another read() call => stack overflow.  This way, it might trigger
+// a nextTick recursion warning, but that's not so bad.
+function emitReadable(stream) {
+  var state = stream._readableState;
+  state.needReadable = false;
+  if (!state.emittedReadable) {
+    debug('emitReadable', state.flowing);
+    state.emittedReadable = true;
+    if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream);
+  }
+}
+
+function emitReadable_(stream) {
+  debug('emit readable');
+  stream.emit('readable');
+  flow(stream);
+}
+
+// at this point, the user has presumably seen the 'readable' event,
+// and called read() to consume some data.  that may have triggered
+// in turn another _read(n) call, in which case reading = true if
+// it's in progress.
+// However, if we're not ended, or reading, and the length < hwm,
+// then go ahead and try to read some more preemptively.
+function maybeReadMore(stream, state) {
+  if (!state.readingMore) {
+    state.readingMore = true;
+    pna.nextTick(maybeReadMore_, stream, state);
+  }
+}
+
+function maybeReadMore_(stream, state) {
+  var len = state.length;
+  while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
+    debug('maybeReadMore read 0');
+    stream.read(0);
+    if (len === state.length)
+      // didn't get any data, stop spinning.
+      break;else len = state.length;
+  }
+  state.readingMore = false;
+}
+
+// abstract method.  to be overridden in specific implementation classes.
+// call cb(er, data) where data is <= n in length.
+// for virtual (non-string, non-buffer) streams, "length" is somewhat
+// arbitrary, and perhaps not very meaningful.
+Readable.prototype._read = function (n) {
+  this.emit('error', new Error('_read() is not implemented'));
+};
+
+Readable.prototype.pipe = function (dest, pipeOpts) {
+  var src = this;
+  var state = this._readableState;
+
+  switch (state.pipesCount) {
+    case 0:
+      state.pipes = dest;
+      break;
+    case 1:
+      state.pipes = [state.pipes, dest];
+      break;
+    default:
+      state.pipes.push(dest);
+      break;
+  }
+  state.pipesCount += 1;
+  debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
+
+  var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
+
+  var endFn = doEnd ? onend : unpipe;
+  if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn);
+
+  dest.on('unpipe', onunpipe);
+  function onunpipe(readable, unpipeInfo) {
+    debug('onunpipe');
+    if (readable === src) {
+      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
+        unpipeInfo.hasUnpiped = true;
+        cleanup();
+      }
+    }
+  }
+
+  function onend() {
+    debug('onend');
+    dest.end();
+  }
+
+  // when the dest drains, it reduces the awaitDrain counter
+  // on the source.  This would be more elegant with a .once()
+  // handler in flow(), but adding and removing repeatedly is
+  // too slow.
+  var ondrain = pipeOnDrain(src);
+  dest.on('drain', ondrain);
+
+  var cleanedUp = false;
+  function cleanup() {
+    debug('cleanup');
+    // cleanup event handlers once the pipe is broken
+    dest.removeListener('close', onclose);
+    dest.removeListener('finish', onfinish);
+    dest.removeListener('drain', ondrain);
+    dest.removeListener('error', onerror);
+    dest.removeListener('unpipe', onunpipe);
+    src.removeListener('end', onend);
+    src.removeListener('end', unpipe);
+    src.removeListener('data', ondata);
+
+    cleanedUp = true;
+
+    // if the reader is waiting for a drain event from this
+    // specific writer, then it would cause it to never start
+    // flowing again.
+    // So, if this is awaiting a drain, then we just call it now.
+    // If we don't know, then assume that we are waiting for one.
+    if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
+  }
+
+  // If the user pushes more data while we're writing to dest then we'll end up
+  // in ondata again. However, we only want to increase awaitDrain once because
+  // dest will only emit one 'drain' event for the multiple writes.
+  // => Introduce a guard on increasing awaitDrain.
+  var increasedAwaitDrain = false;
+  src.on('data', ondata);
+  function ondata(chunk) {
+    debug('ondata');
+    increasedAwaitDrain = false;
+    var ret = dest.write(chunk);
+    if (false === ret && !increasedAwaitDrain) {
+      // If the user unpiped during `dest.write()`, it is possible
+      // to get stuck in a permanently paused state if that write
+      // also returned false.
+      // => Check whether `dest` is still a piping destination.
+      if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
+        debug('false write response, pause', src._readableState.awaitDrain);
+        src._readableState.awaitDrain++;
+        increasedAwaitDrain = true;
+      }
+      src.pause();
+    }
+  }
+
+  // if the dest has an error, then stop piping into it.
+  // however, don't suppress the throwing behavior for this.
+  function onerror(er) {
+    debug('onerror', er);
+    unpipe();
+    dest.removeListener('error', onerror);
+    if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
+  }
+
+  // Make sure our error handler is attached before userland ones.
+  prependListener(dest, 'error', onerror);
+
+  // Both close and finish should trigger unpipe, but only once.
+  function onclose() {
+    dest.removeListener('finish', onfinish);
+    unpipe();
+  }
+  dest.once('close', onclose);
+  function onfinish() {
+    debug('onfinish');
+    dest.removeListener('close', onclose);
+    unpipe();
+  }
+  dest.once('finish', onfinish);
+
+  function unpipe() {
+    debug('unpipe');
+    src.unpipe(dest);
+  }
+
+  // tell the dest that it's being piped to
+  dest.emit('pipe', src);
+
+  // start the flow if it hasn't been started already.
+  if (!state.flowing) {
+    debug('pipe resume');
+    src.resume();
+  }
+
+  return dest;
+};
+
+function pipeOnDrain(src) {
+  return function () {
+    var state = src._readableState;
+    debug('pipeOnDrain', state.awaitDrain);
+    if (state.awaitDrain) state.awaitDrain--;
+    if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
+      state.flowing = true;
+      flow(src);
+    }
+  };
+}
+
+Readable.prototype.unpipe = function (dest) {
+  var state = this._readableState;
+  var unpipeInfo = { hasUnpiped: false };
+
+  // if we're not piping anywhere, then do nothing.
+  if (state.pipesCount === 0) return this;
+
+  // just one destination.  most common case.
+  if (state.pipesCount === 1) {
+    // passed in one, but it's not the right one.
+    if (dest && dest !== state.pipes) return this;
+
+    if (!dest) dest = state.pipes;
+
+    // got a match.
+    state.pipes = null;
+    state.pipesCount = 0;
+    state.flowing = false;
+    if (dest) dest.emit('unpipe', this, unpipeInfo);
+    return this;
+  }
+
+  // slow case. multiple pipe destinations.
+
+  if (!dest) {
+    // remove all.
+    var dests = state.pipes;
+    var len = state.pipesCount;
+    state.pipes = null;
+    state.pipesCount = 0;
+    state.flowing = false;
+
+    for (var i = 0; i < len; i++) {
+      dests[i].emit('unpipe', this, unpipeInfo);
+    }return this;
+  }
+
+  // try to find the right one.
+  var index = indexOf(state.pipes, dest);
+  if (index === -1) return this;
+
+  state.pipes.splice(index, 1);
+  state.pipesCount -= 1;
+  if (state.pipesCount === 1) state.pipes = state.pipes[0];
+
+  dest.emit('unpipe', this, unpipeInfo);
+
+  return this;
+};
+
+// set up data events if they are asked for
+// Ensure readable listeners eventually get something
+Readable.prototype.on = function (ev, fn) {
+  var res = Stream.prototype.on.call(this, ev, fn);
+
+  if (ev === 'data') {
+    // Start flowing on next tick if stream isn't explicitly paused
+    if (this._readableState.flowing !== false) this.resume();
+  } else if (ev === 'readable') {
+    var state = this._readableState;
+    if (!state.endEmitted && !state.readableListening) {
+      state.readableListening = state.needReadable = true;
+      state.emittedReadable = false;
+      if (!state.reading) {
+        pna.nextTick(nReadingNextTick, this);
+      } else if (state.length) {
+        emitReadable(this);
+      }
+    }
+  }
+
+  return res;
+};
+Readable.prototype.addListener = Readable.prototype.on;
+
+function nReadingNextTick(self) {
+  debug('readable nexttick read 0');
+  self.read(0);
+}
+
+// pause() and resume() are remnants of the legacy readable stream API
+// If the user uses them, then switch into old mode.
+Readable.prototype.resume = function () {
+  var state = this._readableState;
+  if (!state.flowing) {
+    debug('resume');
+    state.flowing = true;
+    resume(this, state);
+  }
+  return this;
+};
+
+function resume(stream, state) {
+  if (!state.resumeScheduled) {
+    state.resumeScheduled = true;
+    pna.nextTick(resume_, stream, state);
+  }
+}
+
+function resume_(stream, state) {
+  if (!state.reading) {
+    debug('resume read 0');
+    stream.read(0);
+  }
+
+  state.resumeScheduled = false;
+  state.awaitDrain = 0;
+  stream.emit('resume');
+  flow(stream);
+  if (state.flowing && !state.reading) stream.read(0);
+}
+
+Readable.prototype.pause = function () {
+  debug('call pause flowing=%j', this._readableState.flowing);
+  if (false !== this._readableState.flowing) {
+    debug('pause');
+    this._readableState.flowing = false;
+    this.emit('pause');
+  }
+  return this;
+};
+
+function flow(stream) {
+  var state = stream._readableState;
+  debug('flow', state.flowing);
+  while (state.flowing && stream.read() !== null) {}
+}
+
+// wrap an old-style stream as the async data source.
+// This is *not* part of the readable stream interface.
+// It is an ugly unfortunate mess of history.
+Readable.prototype.wrap = function (stream) {
+  var _this = this;
+
+  var state = this._readableState;
+  var paused = false;
+
+  stream.on('end', function () {
+    debug('wrapped end');
+    if (state.decoder && !state.ended) {
+      var chunk = state.decoder.end();
+      if (chunk && chunk.length) _this.push(chunk);
+    }
+
+    _this.push(null);
+  });
+
+  stream.on('data', function (chunk) {
+    debug('wrapped data');
+    if (state.decoder) chunk = state.decoder.write(chunk);
+
+    // don't skip over falsy values in objectMode
+    if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
+
+    var ret = _this.push(chunk);
+    if (!ret) {
+      paused = true;
+      stream.pause();
+    }
+  });
+
+  // proxy all the other methods.
+  // important when wrapping filters and duplexes.
+  for (var i in stream) {
+    if (this[i] === undefined && typeof stream[i] === 'function') {
+      this[i] = function (method) {
+        return function () {
+          return stream[method].apply(stream, arguments);
+        };
+      }(i);
+    }
+  }
+
+  // proxy certain important events.
+  for (var n = 0; n < kProxyEvents.length; n++) {
+    stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n]));
+  }
+
+  // when we try to consume some more bytes, simply unpause the
+  // underlying stream.
+  this._read = function (n) {
+    debug('wrapped _read', n);
+    if (paused) {
+      paused = false;
+      stream.resume();
+    }
+  };
+
+  return this;
+};
+
+Object.defineProperty(Readable.prototype, 'readableHighWaterMark', {
+  // making it explicit this property is not enumerable
+  // because otherwise some prototype manipulation in
+  // userland will fail
+  enumerable: false,
+  get: function () {
+    return this._readableState.highWaterMark;
+  }
+});
+
+// exposed for testing purposes only.
+Readable._fromList = fromList;
+
+// Pluck off n bytes from an array of buffers.
+// Length is the combined lengths of all the buffers in the list.
+// This function is designed to be inlinable, so please take care when making
+// changes to the function body.
+function fromList(n, state) {
+  // nothing buffered
+  if (state.length === 0) return null;
+
+  var ret;
+  if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
+    // read it all, truncate the list
+    if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length);
+    state.buffer.clear();
+  } else {
+    // read part of list
+    ret = fromListPartial(n, state.buffer, state.decoder);
+  }
+
+  return ret;
+}
+
+// Extracts only enough buffered data to satisfy the amount requested.
+// This function is designed to be inlinable, so please take care when making
+// changes to the function body.
+function fromListPartial(n, list, hasStrings) {
+  var ret;
+  if (n < list.head.data.length) {
+    // slice is the same for buffers and strings
+    ret = list.head.data.slice(0, n);
+    list.head.data = list.head.data.slice(n);
+  } else if (n === list.head.data.length) {
+    // first chunk is a perfect match
+    ret = list.shift();
+  } else {
+    // result spans more than one buffer
+    ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
+  }
+  return ret;
+}
+
+// Copies a specified amount of characters from the list of buffered data
+// chunks.
+// This function is designed to be inlinable, so please take care when making
+// changes to the function body.
+function copyFromBufferString(n, list) {
+  var p = list.head;
+  var c = 1;
+  var ret = p.data;
+  n -= ret.length;
+  while (p = p.next) {
+    var str = p.data;
+    var nb = n > str.length ? str.length : n;
+    if (nb === str.length) ret += str;else ret += str.slice(0, n);
+    n -= nb;
+    if (n === 0) {
+      if (nb === str.length) {
+        ++c;
+        if (p.next) list.head = p.next;else list.head = list.tail = null;
+      } else {
+        list.head = p;
+        p.data = str.slice(nb);
+      }
+      break;
+    }
+    ++c;
+  }
+  list.length -= c;
+  return ret;
+}
+
+// Copies a specified amount of bytes from the list of buffered data chunks.
+// This function is designed to be inlinable, so please take care when making
+// changes to the function body.
+function copyFromBuffer(n, list) {
+  var ret = Buffer.allocUnsafe(n);
+  var p = list.head;
+  var c = 1;
+  p.data.copy(ret);
+  n -= p.data.length;
+  while (p = p.next) {
+    var buf = p.data;
+    var nb = n > buf.length ? buf.length : n;
+    buf.copy(ret, ret.length - n, 0, nb);
+    n -= nb;
+    if (n === 0) {
+      if (nb === buf.length) {
+        ++c;
+        if (p.next) list.head = p.next;else list.head = list.tail = null;
+      } else {
+        list.head = p;
+        p.data = buf.slice(nb);
+      }
+      break;
+    }
+    ++c;
+  }
+  list.length -= c;
+  return ret;
+}
+
+function endReadable(stream) {
+  var state = stream._readableState;
+
+  // If we get here before consuming all the bytes, then that is a
+  // bug in node.  Should never happen.
+  if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');
+
+  if (!state.endEmitted) {
+    state.ended = true;
+    pna.nextTick(endReadableNT, state, stream);
+  }
+}
+
+function endReadableNT(state, stream) {
+  // Check that we didn't get one last unshift.
+  if (!state.endEmitted && state.length === 0) {
+    state.endEmitted = true;
+    stream.readable = false;
+    stream.emit('end');
+  }
+}
+
+function indexOf(xs, x) {
+  for (var i = 0, l = xs.length; i < l; i++) {
+    if (xs[i] === x) return i;
+  }
+  return -1;
+}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readable-stream/lib/_stream_transform.js b/input_devices/mag/node_modules/readable-stream/lib/_stream_transform.js
new file mode 100644
index 00000000..5d1f8b87
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/_stream_transform.js
@@ -0,0 +1,214 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+// a transform stream is a readable/writable stream where you do
+// something with the data.  Sometimes it's called a "filter",
+// but that's not a great name for it, since that implies a thing where
+// some bits pass through, and others are simply ignored.  (That would
+// be a valid example of a transform, of course.)
+//
+// While the output is causally related to the input, it's not a
+// necessarily symmetric or synchronous transformation.  For example,
+// a zlib stream might take multiple plain-text writes(), and then
+// emit a single compressed chunk some time in the future.
+//
+// Here's how this works:
+//
+// The Transform stream has all the aspects of the readable and writable
+// stream classes.  When you write(chunk), that calls _write(chunk,cb)
+// internally, and returns false if there's a lot of pending writes
+// buffered up.  When you call read(), that calls _read(n) until
+// there's enough pending readable data buffered up.
+//
+// In a transform stream, the written data is placed in a buffer.  When
+// _read(n) is called, it transforms the queued up data, calling the
+// buffered _write cb's as it consumes chunks.  If consuming a single
+// written chunk would result in multiple output chunks, then the first
+// outputted bit calls the readcb, and subsequent chunks just go into
+// the read buffer, and will cause it to emit 'readable' if necessary.
+//
+// This way, back-pressure is actually determined by the reading side,
+// since _read has to be called to start processing a new chunk.  However,
+// a pathological inflate type of transform can cause excessive buffering
+// here.  For example, imagine a stream where every byte of input is
+// interpreted as an integer from 0-255, and then results in that many
+// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
+// 1kb of data being output.  In this case, you could write a very small
+// amount of input, and end up with a very large amount of output.  In
+// such a pathological inflating mechanism, there'd be no way to tell
+// the system to stop doing the transform.  A single 4MB write could
+// cause the system to run out of memory.
+//
+// However, even in such a pathological case, only a single written chunk
+// would be consumed, and then the rest would wait (un-transformed) until
+// the results of the previous transformed chunk were consumed.
+
+'use strict';
+
+module.exports = Transform;
+
+var Duplex = require('./_stream_duplex');
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+util.inherits(Transform, Duplex);
+
+function afterTransform(er, data) {
+  var ts = this._transformState;
+  ts.transforming = false;
+
+  var cb = ts.writecb;
+
+  if (!cb) {
+    return this.emit('error', new Error('write callback called multiple times'));
+  }
+
+  ts.writechunk = null;
+  ts.writecb = null;
+
+  if (data != null) // single equals check for both `null` and `undefined`
+    this.push(data);
+
+  cb(er);
+
+  var rs = this._readableState;
+  rs.reading = false;
+  if (rs.needReadable || rs.length < rs.highWaterMark) {
+    this._read(rs.highWaterMark);
+  }
+}
+
+function Transform(options) {
+  if (!(this instanceof Transform)) return new Transform(options);
+
+  Duplex.call(this, options);
+
+  this._transformState = {
+    afterTransform: afterTransform.bind(this),
+    needTransform: false,
+    transforming: false,
+    writecb: null,
+    writechunk: null,
+    writeencoding: null
+  };
+
+  // start out asking for a readable event once data is transformed.
+  this._readableState.needReadable = true;
+
+  // we have implemented the _read method, and done the other things
+  // that Readable wants before the first _read call, so unset the
+  // sync guard flag.
+  this._readableState.sync = false;
+
+  if (options) {
+    if (typeof options.transform === 'function') this._transform = options.transform;
+
+    if (typeof options.flush === 'function') this._flush = options.flush;
+  }
+
+  // When the writable side finishes, then flush out anything remaining.
+  this.on('prefinish', prefinish);
+}
+
+function prefinish() {
+  var _this = this;
+
+  if (typeof this._flush === 'function') {
+    this._flush(function (er, data) {
+      done(_this, er, data);
+    });
+  } else {
+    done(this, null, null);
+  }
+}
+
+Transform.prototype.push = function (chunk, encoding) {
+  this._transformState.needTransform = false;
+  return Duplex.prototype.push.call(this, chunk, encoding);
+};
+
+// This is the part where you do stuff!
+// override this function in implementation classes.
+// 'chunk' is an input chunk.
+//
+// Call `push(newChunk)` to pass along transformed output
+// to the readable side.  You may call 'push' zero or more times.
+//
+// Call `cb(err)` when you are done with this chunk.  If you pass
+// an error, then that'll put the hurt on the whole operation.  If you
+// never call cb(), then you'll never get another chunk.
+Transform.prototype._transform = function (chunk, encoding, cb) {
+  throw new Error('_transform() is not implemented');
+};
+
+Transform.prototype._write = function (chunk, encoding, cb) {
+  var ts = this._transformState;
+  ts.writecb = cb;
+  ts.writechunk = chunk;
+  ts.writeencoding = encoding;
+  if (!ts.transforming) {
+    var rs = this._readableState;
+    if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
+  }
+};
+
+// Doesn't matter what the args are here.
+// _transform does all the work.
+// That we got here means that the readable side wants more data.
+Transform.prototype._read = function (n) {
+  var ts = this._transformState;
+
+  if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
+    ts.transforming = true;
+    this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
+  } else {
+    // mark that we need a transform, so that any data that comes in
+    // will get processed, now that we've asked for it.
+    ts.needTransform = true;
+  }
+};
+
+Transform.prototype._destroy = function (err, cb) {
+  var _this2 = this;
+
+  Duplex.prototype._destroy.call(this, err, function (err2) {
+    cb(err2);
+    _this2.emit('close');
+  });
+};
+
+function done(stream, er, data) {
+  if (er) return stream.emit('error', er);
+
+  if (data != null) // single equals check for both `null` and `undefined`
+    stream.push(data);
+
+  // if there's nothing in the write buffer, then that means
+  // that nothing more will ever be provided
+  if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0');
+
+  if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming');
+
+  return stream.push(null);
+}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readable-stream/lib/_stream_writable.js b/input_devices/mag/node_modules/readable-stream/lib/_stream_writable.js
new file mode 100644
index 00000000..b3f4e85a
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/_stream_writable.js
@@ -0,0 +1,687 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+// A bit simpler than readable streams.
+// Implement an async ._write(chunk, encoding, cb), and it'll handle all
+// the drain event emission and buffering.
+
+'use strict';
+
+/*<replacement>*/
+
+var pna = require('process-nextick-args');
+/*</replacement>*/
+
+module.exports = Writable;
+
+/* <replacement> */
+function WriteReq(chunk, encoding, cb) {
+  this.chunk = chunk;
+  this.encoding = encoding;
+  this.callback = cb;
+  this.next = null;
+}
+
+// It seems a linked list but it is not
+// there will be only 2 of these for each stream
+function CorkedRequest(state) {
+  var _this = this;
+
+  this.next = null;
+  this.entry = null;
+  this.finish = function () {
+    onCorkedFinish(_this, state);
+  };
+}
+/* </replacement> */
+
+/*<replacement>*/
+var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
+/*</replacement>*/
+
+/*<replacement>*/
+var Duplex;
+/*</replacement>*/
+
+Writable.WritableState = WritableState;
+
+/*<replacement>*/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/*</replacement>*/
+
+/*<replacement>*/
+var internalUtil = {
+  deprecate: require('util-deprecate')
+};
+/*</replacement>*/
+
+/*<replacement>*/
+var Stream = require('./internal/streams/stream');
+/*</replacement>*/
+
+/*<replacement>*/
+
+var Buffer = require('safe-buffer').Buffer;
+var OurUint8Array = global.Uint8Array || function () {};
+function _uint8ArrayToBuffer(chunk) {
+  return Buffer.from(chunk);
+}
+function _isUint8Array(obj) {
+  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
+}
+
+/*</replacement>*/
+
+var destroyImpl = require('./internal/streams/destroy');
+
+util.inherits(Writable, Stream);
+
+function nop() {}
+
+function WritableState(options, stream) {
+  Duplex = Duplex || require('./_stream_duplex');
+
+  options = options || {};
+
+  // Duplex streams are both readable and writable, but share
+  // the same options object.
+  // However, some cases require setting options to different
+  // values for the readable and the writable sides of the duplex stream.
+  // These options can be provided separately as readableXXX and writableXXX.
+  var isDuplex = stream instanceof Duplex;
+
+  // object stream flag to indicate whether or not this stream
+  // contains buffers or objects.
+  this.objectMode = !!options.objectMode;
+
+  if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
+
+  // the point at which write() starts returning false
+  // Note: 0 is a valid value, means that we always return false if
+  // the entire buffer is not flushed immediately on write()
+  var hwm = options.highWaterMark;
+  var writableHwm = options.writableHighWaterMark;
+  var defaultHwm = this.objectMode ? 16 : 16 * 1024;
+
+  if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm;
+
+  // cast to ints.
+  this.highWaterMark = Math.floor(this.highWaterMark);
+
+  // if _final has been called
+  this.finalCalled = false;
+
+  // drain event flag.
+  this.needDrain = false;
+  // at the start of calling end()
+  this.ending = false;
+  // when end() has been called, and returned
+  this.ended = false;
+  // when 'finish' is emitted
+  this.finished = false;
+
+  // has it been destroyed
+  this.destroyed = false;
+
+  // should we decode strings into buffers before passing to _write?
+  // this is here so that some node-core streams can optimize string
+  // handling at a lower level.
+  var noDecode = options.decodeStrings === false;
+  this.decodeStrings = !noDecode;
+
+  // Crypto is kind of old and crusty.  Historically, its default string
+  // encoding is 'binary' so we have to make this configurable.
+  // Everything else in the universe uses 'utf8', though.
+  this.defaultEncoding = options.defaultEncoding || 'utf8';
+
+  // not an actual buffer we keep track of, but a measurement
+  // of how much we're waiting to get pushed to some underlying
+  // socket or file.
+  this.length = 0;
+
+  // a flag to see when we're in the middle of a write.
+  this.writing = false;
+
+  // when true all writes will be buffered until .uncork() call
+  this.corked = 0;
+
+  // a flag to be able to tell if the onwrite cb is called immediately,
+  // or on a later tick.  We set this to true at first, because any
+  // actions that shouldn't happen until "later" should generally also
+  // not happen before the first write call.
+  this.sync = true;
+
+  // a flag to know if we're processing previously buffered items, which
+  // may call the _write() callback in the same tick, so that we don't
+  // end up in an overlapped onwrite situation.
+  this.bufferProcessing = false;
+
+  // the callback that's passed to _write(chunk,cb)
+  this.onwrite = function (er) {
+    onwrite(stream, er);
+  };
+
+  // the callback that the user supplies to write(chunk,encoding,cb)
+  this.writecb = null;
+
+  // the amount that is being written when _write is called.
+  this.writelen = 0;
+
+  this.bufferedRequest = null;
+  this.lastBufferedRequest = null;
+
+  // number of pending user-supplied write callbacks
+  // this must be 0 before 'finish' can be emitted
+  this.pendingcb = 0;
+
+  // emit prefinish if the only thing we're waiting for is _write cbs
+  // This is relevant for synchronous Transform streams
+  this.prefinished = false;
+
+  // True if the error was already emitted and should not be thrown again
+  this.errorEmitted = false;
+
+  // count buffered requests
+  this.bufferedRequestCount = 0;
+
+  // allocate the first CorkedRequest, there is always
+  // one allocated and free to use, and we maintain at most two
+  this.corkedRequestsFree = new CorkedRequest(this);
+}
+
+WritableState.prototype.getBuffer = function getBuffer() {
+  var current = this.bufferedRequest;
+  var out = [];
+  while (current) {
+    out.push(current);
+    current = current.next;
+  }
+  return out;
+};
+
+(function () {
+  try {
+    Object.defineProperty(WritableState.prototype, 'buffer', {
+      get: internalUtil.deprecate(function () {
+        return this.getBuffer();
+      }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
+    });
+  } catch (_) {}
+})();
+
+// Test _writableState for inheritance to account for Duplex streams,
+// whose prototype chain only points to Readable.
+var realHasInstance;
+if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
+  realHasInstance = Function.prototype[Symbol.hasInstance];
+  Object.defineProperty(Writable, Symbol.hasInstance, {
+    value: function (object) {
+      if (realHasInstance.call(this, object)) return true;
+      if (this !== Writable) return false;
+
+      return object && object._writableState instanceof WritableState;
+    }
+  });
+} else {
+  realHasInstance = function (object) {
+    return object instanceof this;
+  };
+}
+
+function Writable(options) {
+  Duplex = Duplex || require('./_stream_duplex');
+
+  // Writable ctor is applied to Duplexes, too.
+  // `realHasInstance` is necessary because using plain `instanceof`
+  // would return false, as no `_writableState` property is attached.
+
+  // Trying to use the custom `instanceof` for Writable here will also break the
+  // Node.js LazyTransform implementation, which has a non-trivial getter for
+  // `_writableState` that would lead to infinite recursion.
+  if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
+    return new Writable(options);
+  }
+
+  this._writableState = new WritableState(options, this);
+
+  // legacy.
+  this.writable = true;
+
+  if (options) {
+    if (typeof options.write === 'function') this._write = options.write;
+
+    if (typeof options.writev === 'function') this._writev = options.writev;
+
+    if (typeof options.destroy === 'function') this._destroy = options.destroy;
+
+    if (typeof options.final === 'function') this._final = options.final;
+  }
+
+  Stream.call(this);
+}
+
+// Otherwise people can pipe Writable streams, which is just wrong.
+Writable.prototype.pipe = function () {
+  this.emit('error', new Error('Cannot pipe, not readable'));
+};
+
+function writeAfterEnd(stream, cb) {
+  var er = new Error('write after end');
+  // TODO: defer error events consistently everywhere, not just the cb
+  stream.emit('error', er);
+  pna.nextTick(cb, er);
+}
+
+// Checks that a user-supplied chunk is valid, especially for the particular
+// mode the stream is in. Currently this means that `null` is never accepted
+// and undefined/non-string values are only allowed in object mode.
+function validChunk(stream, state, chunk, cb) {
+  var valid = true;
+  var er = false;
+
+  if (chunk === null) {
+    er = new TypeError('May not write null values to stream');
+  } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
+    er = new TypeError('Invalid non-string/buffer chunk');
+  }
+  if (er) {
+    stream.emit('error', er);
+    pna.nextTick(cb, er);
+    valid = false;
+  }
+  return valid;
+}
+
+Writable.prototype.write = function (chunk, encoding, cb) {
+  var state = this._writableState;
+  var ret = false;
+  var isBuf = !state.objectMode && _isUint8Array(chunk);
+
+  if (isBuf && !Buffer.isBuffer(chunk)) {
+    chunk = _uint8ArrayToBuffer(chunk);
+  }
+
+  if (typeof encoding === 'function') {
+    cb = encoding;
+    encoding = null;
+  }
+
+  if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
+
+  if (typeof cb !== 'function') cb = nop;
+
+  if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
+    state.pendingcb++;
+    ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
+  }
+
+  return ret;
+};
+
+Writable.prototype.cork = function () {
+  var state = this._writableState;
+
+  state.corked++;
+};
+
+Writable.prototype.uncork = function () {
+  var state = this._writableState;
+
+  if (state.corked) {
+    state.corked--;
+
+    if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
+  }
+};
+
+Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
+  // node::ParseEncoding() requires lower case.
+  if (typeof encoding === 'string') encoding = encoding.toLowerCase();
+  if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
+  this._writableState.defaultEncoding = encoding;
+  return this;
+};
+
+function decodeChunk(state, chunk, encoding) {
+  if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
+    chunk = Buffer.from(chunk, encoding);
+  }
+  return chunk;
+}
+
+Object.defineProperty(Writable.prototype, 'writableHighWaterMark', {
+  // making it explicit this property is not enumerable
+  // because otherwise some prototype manipulation in
+  // userland will fail
+  enumerable: false,
+  get: function () {
+    return this._writableState.highWaterMark;
+  }
+});
+
+// if we're already writing something, then just put this
+// in the queue, and wait our turn.  Otherwise, call _write
+// If we return false, then we need a drain event, so set that flag.
+function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
+  if (!isBuf) {
+    var newChunk = decodeChunk(state, chunk, encoding);
+    if (chunk !== newChunk) {
+      isBuf = true;
+      encoding = 'buffer';
+      chunk = newChunk;
+    }
+  }
+  var len = state.objectMode ? 1 : chunk.length;
+
+  state.length += len;
+
+  var ret = state.length < state.highWaterMark;
+  // we must ensure that previous needDrain will not be reset to false.
+  if (!ret) state.needDrain = true;
+
+  if (state.writing || state.corked) {
+    var last = state.lastBufferedRequest;
+    state.lastBufferedRequest = {
+      chunk: chunk,
+      encoding: encoding,
+      isBuf: isBuf,
+      callback: cb,
+      next: null
+    };
+    if (last) {
+      last.next = state.lastBufferedRequest;
+    } else {
+      state.bufferedRequest = state.lastBufferedRequest;
+    }
+    state.bufferedRequestCount += 1;
+  } else {
+    doWrite(stream, state, false, len, chunk, encoding, cb);
+  }
+
+  return ret;
+}
+
+function doWrite(stream, state, writev, len, chunk, encoding, cb) {
+  state.writelen = len;
+  state.writecb = cb;
+  state.writing = true;
+  state.sync = true;
+  if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
+  state.sync = false;
+}
+
+function onwriteError(stream, state, sync, er, cb) {
+  --state.pendingcb;
+
+  if (sync) {
+    // defer the callback if we are being called synchronously
+    // to avoid piling up things on the stack
+    pna.nextTick(cb, er);
+    // this can emit finish, and it will always happen
+    // after error
+    pna.nextTick(finishMaybe, stream, state);
+    stream._writableState.errorEmitted = true;
+    stream.emit('error', er);
+  } else {
+    // the caller expect this to happen before if
+    // it is async
+    cb(er);
+    stream._writableState.errorEmitted = true;
+    stream.emit('error', er);
+    // this can emit finish, but finish must
+    // always follow error
+    finishMaybe(stream, state);
+  }
+}
+
+function onwriteStateUpdate(state) {
+  state.writing = false;
+  state.writecb = null;
+  state.length -= state.writelen;
+  state.writelen = 0;
+}
+
+function onwrite(stream, er) {
+  var state = stream._writableState;
+  var sync = state.sync;
+  var cb = state.writecb;
+
+  onwriteStateUpdate(state);
+
+  if (er) onwriteError(stream, state, sync, er, cb);else {
+    // Check if we're actually ready to finish, but don't emit yet
+    var finished = needFinish(state);
+
+    if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
+      clearBuffer(stream, state);
+    }
+
+    if (sync) {
+      /*<replacement>*/
+      asyncWrite(afterWrite, stream, state, finished, cb);
+      /*</replacement>*/
+    } else {
+      afterWrite(stream, state, finished, cb);
+    }
+  }
+}
+
+function afterWrite(stream, state, finished, cb) {
+  if (!finished) onwriteDrain(stream, state);
+  state.pendingcb--;
+  cb();
+  finishMaybe(stream, state);
+}
+
+// Must force callback to be called on nextTick, so that we don't
+// emit 'drain' before the write() consumer gets the 'false' return
+// value, and has a chance to attach a 'drain' listener.
+function onwriteDrain(stream, state) {
+  if (state.length === 0 && state.needDrain) {
+    state.needDrain = false;
+    stream.emit('drain');
+  }
+}
+
+// if there's something in the buffer waiting, then process it
+function clearBuffer(stream, state) {
+  state.bufferProcessing = true;
+  var entry = state.bufferedRequest;
+
+  if (stream._writev && entry && entry.next) {
+    // Fast case, write everything using _writev()
+    var l = state.bufferedRequestCount;
+    var buffer = new Array(l);
+    var holder = state.corkedRequestsFree;
+    holder.entry = entry;
+
+    var count = 0;
+    var allBuffers = true;
+    while (entry) {
+      buffer[count] = entry;
+      if (!entry.isBuf) allBuffers = false;
+      entry = entry.next;
+      count += 1;
+    }
+    buffer.allBuffers = allBuffers;
+
+    doWrite(stream, state, true, state.length, buffer, '', holder.finish);
+
+    // doWrite is almost always async, defer these to save a bit of time
+    // as the hot path ends with doWrite
+    state.pendingcb++;
+    state.lastBufferedRequest = null;
+    if (holder.next) {
+      state.corkedRequestsFree = holder.next;
+      holder.next = null;
+    } else {
+      state.corkedRequestsFree = new CorkedRequest(state);
+    }
+    state.bufferedRequestCount = 0;
+  } else {
+    // Slow case, write chunks one-by-one
+    while (entry) {
+      var chunk = entry.chunk;
+      var encoding = entry.encoding;
+      var cb = entry.callback;
+      var len = state.objectMode ? 1 : chunk.length;
+
+      doWrite(stream, state, false, len, chunk, encoding, cb);
+      entry = entry.next;
+      state.bufferedRequestCount--;
+      // if we didn't call the onwrite immediately, then
+      // it means that we need to wait until it does.
+      // also, that means that the chunk and cb are currently
+      // being processed, so move the buffer counter past them.
+      if (state.writing) {
+        break;
+      }
+    }
+
+    if (entry === null) state.lastBufferedRequest = null;
+  }
+
+  state.bufferedRequest = entry;
+  state.bufferProcessing = false;
+}
+
+Writable.prototype._write = function (chunk, encoding, cb) {
+  cb(new Error('_write() is not implemented'));
+};
+
+Writable.prototype._writev = null;
+
+Writable.prototype.end = function (chunk, encoding, cb) {
+  var state = this._writableState;
+
+  if (typeof chunk === 'function') {
+    cb = chunk;
+    chunk = null;
+    encoding = null;
+  } else if (typeof encoding === 'function') {
+    cb = encoding;
+    encoding = null;
+  }
+
+  if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
+
+  // .end() fully uncorks
+  if (state.corked) {
+    state.corked = 1;
+    this.uncork();
+  }
+
+  // ignore unnecessary end() calls.
+  if (!state.ending && !state.finished) endWritable(this, state, cb);
+};
+
+function needFinish(state) {
+  return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
+}
+function callFinal(stream, state) {
+  stream._final(function (err) {
+    state.pendingcb--;
+    if (err) {
+      stream.emit('error', err);
+    }
+    state.prefinished = true;
+    stream.emit('prefinish');
+    finishMaybe(stream, state);
+  });
+}
+function prefinish(stream, state) {
+  if (!state.prefinished && !state.finalCalled) {
+    if (typeof stream._final === 'function') {
+      state.pendingcb++;
+      state.finalCalled = true;
+      pna.nextTick(callFinal, stream, state);
+    } else {
+      state.prefinished = true;
+      stream.emit('prefinish');
+    }
+  }
+}
+
+function finishMaybe(stream, state) {
+  var need = needFinish(state);
+  if (need) {
+    prefinish(stream, state);
+    if (state.pendingcb === 0) {
+      state.finished = true;
+      stream.emit('finish');
+    }
+  }
+  return need;
+}
+
+function endWritable(stream, state, cb) {
+  state.ending = true;
+  finishMaybe(stream, state);
+  if (cb) {
+    if (state.finished) pna.nextTick(cb);else stream.once('finish', cb);
+  }
+  state.ended = true;
+  stream.writable = false;
+}
+
+function onCorkedFinish(corkReq, state, err) {
+  var entry = corkReq.entry;
+  corkReq.entry = null;
+  while (entry) {
+    var cb = entry.callback;
+    state.pendingcb--;
+    cb(err);
+    entry = entry.next;
+  }
+  if (state.corkedRequestsFree) {
+    state.corkedRequestsFree.next = corkReq;
+  } else {
+    state.corkedRequestsFree = corkReq;
+  }
+}
+
+Object.defineProperty(Writable.prototype, 'destroyed', {
+  get: function () {
+    if (this._writableState === undefined) {
+      return false;
+    }
+    return this._writableState.destroyed;
+  },
+  set: function (value) {
+    // we ignore the value if the stream
+    // has not been initialized yet
+    if (!this._writableState) {
+      return;
+    }
+
+    // backward compatibility, the user is explicitly
+    // managing destroyed
+    this._writableState.destroyed = value;
+  }
+});
+
+Writable.prototype.destroy = destroyImpl.destroy;
+Writable.prototype._undestroy = destroyImpl.undestroy;
+Writable.prototype._destroy = function (err, cb) {
+  this.end();
+  cb(err);
+};
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readable-stream/lib/internal/streams/BufferList.js b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/BufferList.js
new file mode 100644
index 00000000..aefc68bd
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/BufferList.js
@@ -0,0 +1,79 @@
+'use strict';
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Buffer = require('safe-buffer').Buffer;
+var util = require('util');
+
+function copyBuffer(src, target, offset) {
+  src.copy(target, offset);
+}
+
+module.exports = function () {
+  function BufferList() {
+    _classCallCheck(this, BufferList);
+
+    this.head = null;
+    this.tail = null;
+    this.length = 0;
+  }
+
+  BufferList.prototype.push = function push(v) {
+    var entry = { data: v, next: null };
+    if (this.length > 0) this.tail.next = entry;else this.head = entry;
+    this.tail = entry;
+    ++this.length;
+  };
+
+  BufferList.prototype.unshift = function unshift(v) {
+    var entry = { data: v, next: this.head };
+    if (this.length === 0) this.tail = entry;
+    this.head = entry;
+    ++this.length;
+  };
+
+  BufferList.prototype.shift = function shift() {
+    if (this.length === 0) return;
+    var ret = this.head.data;
+    if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
+    --this.length;
+    return ret;
+  };
+
+  BufferList.prototype.clear = function clear() {
+    this.head = this.tail = null;
+    this.length = 0;
+  };
+
+  BufferList.prototype.join = function join(s) {
+    if (this.length === 0) return '';
+    var p = this.head;
+    var ret = '' + p.data;
+    while (p = p.next) {
+      ret += s + p.data;
+    }return ret;
+  };
+
+  BufferList.prototype.concat = function concat(n) {
+    if (this.length === 0) return Buffer.alloc(0);
+    if (this.length === 1) return this.head.data;
+    var ret = Buffer.allocUnsafe(n >>> 0);
+    var p = this.head;
+    var i = 0;
+    while (p) {
+      copyBuffer(p.data, ret, i);
+      i += p.data.length;
+      p = p.next;
+    }
+    return ret;
+  };
+
+  return BufferList;
+}();
+
+if (util && util.inspect && util.inspect.custom) {
+  module.exports.prototype[util.inspect.custom] = function () {
+    var obj = util.inspect({ length: this.length });
+    return this.constructor.name + ' ' + obj;
+  };
+}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readable-stream/lib/internal/streams/destroy.js b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/destroy.js
new file mode 100644
index 00000000..5a0a0d88
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/destroy.js
@@ -0,0 +1,74 @@
+'use strict';
+
+/*<replacement>*/
+
+var pna = require('process-nextick-args');
+/*</replacement>*/
+
+// undocumented cb() API, needed for core, not for public API
+function destroy(err, cb) {
+  var _this = this;
+
+  var readableDestroyed = this._readableState && this._readableState.destroyed;
+  var writableDestroyed = this._writableState && this._writableState.destroyed;
+
+  if (readableDestroyed || writableDestroyed) {
+    if (cb) {
+      cb(err);
+    } else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
+      pna.nextTick(emitErrorNT, this, err);
+    }
+    return this;
+  }
+
+  // we set destroyed to true before firing error callbacks in order
+  // to make it re-entrance safe in case destroy() is called within callbacks
+
+  if (this._readableState) {
+    this._readableState.destroyed = true;
+  }
+
+  // if this is a duplex stream mark the writable part as destroyed as well
+  if (this._writableState) {
+    this._writableState.destroyed = true;
+  }
+
+  this._destroy(err || null, function (err) {
+    if (!cb && err) {
+      pna.nextTick(emitErrorNT, _this, err);
+      if (_this._writableState) {
+        _this._writableState.errorEmitted = true;
+      }
+    } else if (cb) {
+      cb(err);
+    }
+  });
+
+  return this;
+}
+
+function undestroy() {
+  if (this._readableState) {
+    this._readableState.destroyed = false;
+    this._readableState.reading = false;
+    this._readableState.ended = false;
+    this._readableState.endEmitted = false;
+  }
+
+  if (this._writableState) {
+    this._writableState.destroyed = false;
+    this._writableState.ended = false;
+    this._writableState.ending = false;
+    this._writableState.finished = false;
+    this._writableState.errorEmitted = false;
+  }
+}
+
+function emitErrorNT(self, err) {
+  self.emit('error', err);
+}
+
+module.exports = {
+  destroy: destroy,
+  undestroy: undestroy
+};
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream-browser.js b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream-browser.js
new file mode 100644
index 00000000..9332a3fd
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream-browser.js
@@ -0,0 +1 @@
+module.exports = require('events').EventEmitter;
diff --git a/input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream.js b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream.js
new file mode 100644
index 00000000..ce2ad5b6
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/lib/internal/streams/stream.js
@@ -0,0 +1 @@
+module.exports = require('stream');
diff --git a/input_devices/mag/node_modules/readable-stream/package.json b/input_devices/mag/node_modules/readable-stream/package.json
new file mode 100644
index 00000000..06c0f711
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/package.json
@@ -0,0 +1,134 @@
+{
+  "_args": [
+    [
+      "readable-stream@^2.0.6",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/are-we-there-yet"
+    ]
+  ],
+  "_from": "readable-stream@>=2.0.6 <3.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "readable-stream@2.3.6",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readable-stream",
+  "_nodeVersion": "8.10.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/readable-stream_2.3.6_1522856414086_0.18438932255173968"
+  },
+  "_npmUser": {
+    "email": "hello@matteocollina.com",
+    "name": "matteo.collina"
+  },
+  "_npmVersion": "5.8.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "readable-stream",
+    "raw": "readable-stream@^2.0.6",
+    "rawSpec": "^2.0.6",
+    "scope": null,
+    "spec": ">=2.0.6 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/are-we-there-yet",
+    "/bl",
+    "/tar-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+  "_shasum": "b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf",
+  "_shrinkwrap": null,
+  "_spec": "readable-stream@^2.0.6",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/are-we-there-yet",
+  "browser": {
+    "./duplex.js": "./duplex-browser.js",
+    "./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js",
+    "./readable.js": "./readable-browser.js",
+    "./writable.js": "./writable-browser.js",
+    "util": false
+  },
+  "bugs": {
+    "url": "https://github.com/nodejs/readable-stream/issues"
+  },
+  "dependencies": {
+    "core-util-is": "~1.0.0",
+    "inherits": "~2.0.3",
+    "isarray": "~1.0.0",
+    "process-nextick-args": "~2.0.0",
+    "safe-buffer": "~5.1.1",
+    "string_decoder": "~1.1.1",
+    "util-deprecate": "~1.0.1"
+  },
+  "description": "Streams3, a user-land copy of the stream library from Node.js",
+  "devDependencies": {
+    "assert": "^1.4.0",
+    "babel-polyfill": "^6.9.1",
+    "buffer": "^4.9.0",
+    "lolex": "^2.3.2",
+    "nyc": "^6.4.0",
+    "tap": "^0.7.0",
+    "tape": "^4.8.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 24,
+    "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+    "shasum": "b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf",
+    "tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+    "unpackedSize": 87961
+  },
+  "gitHead": "b3cf9b1f46eaa1865930ae03b96d7a4a570746f0",
+  "homepage": "https://github.com/nodejs/readable-stream#readme",
+  "keywords": [
+    "pipe",
+    "readable",
+    "stream"
+  ],
+  "license": "MIT",
+  "main": "readable.js",
+  "maintainers": [
+    {
+      "name": "cwmma",
+      "email": "calvin.metcalf@gmail.com"
+    },
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    },
+    {
+      "name": "matteo.collina",
+      "email": "hello@matteocollina.com"
+    },
+    {
+      "name": "nodejs-foundation",
+      "email": "build@iojs.org"
+    },
+    {
+      "name": "rvagg",
+      "email": "r@va.gg"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    }
+  ],
+  "name": "readable-stream",
+  "nyc": {
+    "include": [
+      "lib/**.js"
+    ]
+  },
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/nodejs/readable-stream.git"
+  },
+  "scripts": {
+    "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js",
+    "cover": "nyc npm test",
+    "report": "nyc report --reporter=lcov",
+    "test": "tap test/parallel/*.js test/ours/*.js && node test/verify-dependencies.js"
+  },
+  "version": "2.3.6"
+}
diff --git a/input_devices/mag/node_modules/readable-stream/passthrough.js b/input_devices/mag/node_modules/readable-stream/passthrough.js
new file mode 100644
index 00000000..ffd791d7
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/passthrough.js
@@ -0,0 +1 @@
+module.exports = require('./readable').PassThrough
diff --git a/input_devices/mag/node_modules/readable-stream/readable-browser.js b/input_devices/mag/node_modules/readable-stream/readable-browser.js
new file mode 100644
index 00000000..e5037259
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/readable-browser.js
@@ -0,0 +1,7 @@
+exports = module.exports = require('./lib/_stream_readable.js');
+exports.Stream = exports;
+exports.Readable = exports;
+exports.Writable = require('./lib/_stream_writable.js');
+exports.Duplex = require('./lib/_stream_duplex.js');
+exports.Transform = require('./lib/_stream_transform.js');
+exports.PassThrough = require('./lib/_stream_passthrough.js');
diff --git a/input_devices/mag/node_modules/readable-stream/readable.js b/input_devices/mag/node_modules/readable-stream/readable.js
new file mode 100644
index 00000000..ec89ec53
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/readable.js
@@ -0,0 +1,19 @@
+var Stream = require('stream');
+if (process.env.READABLE_STREAM === 'disable' && Stream) {
+  module.exports = Stream;
+  exports = module.exports = Stream.Readable;
+  exports.Readable = Stream.Readable;
+  exports.Writable = Stream.Writable;
+  exports.Duplex = Stream.Duplex;
+  exports.Transform = Stream.Transform;
+  exports.PassThrough = Stream.PassThrough;
+  exports.Stream = Stream;
+} else {
+  exports = module.exports = require('./lib/_stream_readable.js');
+  exports.Stream = Stream || exports;
+  exports.Readable = exports;
+  exports.Writable = require('./lib/_stream_writable.js');
+  exports.Duplex = require('./lib/_stream_duplex.js');
+  exports.Transform = require('./lib/_stream_transform.js');
+  exports.PassThrough = require('./lib/_stream_passthrough.js');
+}
diff --git a/input_devices/mag/node_modules/readable-stream/transform.js b/input_devices/mag/node_modules/readable-stream/transform.js
new file mode 100644
index 00000000..b1baba26
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/transform.js
@@ -0,0 +1 @@
+module.exports = require('./readable').Transform
diff --git a/input_devices/mag/node_modules/readable-stream/writable-browser.js b/input_devices/mag/node_modules/readable-stream/writable-browser.js
new file mode 100644
index 00000000..ebdde6a8
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/writable-browser.js
@@ -0,0 +1 @@
+module.exports = require('./lib/_stream_writable.js');
diff --git a/input_devices/mag/node_modules/readable-stream/writable.js b/input_devices/mag/node_modules/readable-stream/writable.js
new file mode 100644
index 00000000..3211a6f8
--- /dev/null
+++ b/input_devices/mag/node_modules/readable-stream/writable.js
@@ -0,0 +1,8 @@
+var Stream = require("stream")
+var Writable = require("./lib/_stream_writable.js")
+
+if (process.env.READABLE_STREAM === 'disable') {
+  module.exports = Stream && Stream.Writable || Writable
+} else {
+  module.exports = Writable
+}
diff --git a/input_devices/mag/node_modules/readline-ui/LICENSE b/input_devices/mag/node_modules/readline-ui/LICENSE
new file mode 100644
index 00000000..b11cb796
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/readline-ui/README.md b/input_devices/mag/node_modules/readline-ui/README.md
new file mode 100644
index 00000000..ad1addd1
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/README.md
@@ -0,0 +1,198 @@
+# readline-ui [![NPM version](https://img.shields.io/npm/v/readline-ui.svg?style=flat)](https://www.npmjs.com/package/readline-ui) [![NPM monthly downloads](https://img.shields.io/npm/dm/readline-ui.svg?style=flat)](https://npmjs.org/package/readline-ui) [![NPM total downloads](https://img.shields.io/npm/dt/readline-ui.svg?style=flat)](https://npmjs.org/package/readline-ui) [![Linux Build Status](https://img.shields.io/travis/enquirer/readline-ui.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/readline-ui)
+
+> Create a readline interface with default settings to use in prompts.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save readline-ui
+```
+
+## Usage
+
+```js
+var UI = require('readline-ui');
+var ui = new UI();
+```
+
+## Example
+
+![example](example.gif)
+
+The following example shows how to create a basic input prompt. This example is a greatly simplified version of [prompt-base](https://github.com/enquirer/prompt-base).
+
+_(This code is also in [example.js](example.js) if you want to run it yourself.)_
+
+```js
+var cyan = require('ansi-cyan');
+var UI = require('readline-ui');
+var ui = new UI();
+
+// first, we need to render the "question" 
+// to display in the terminal
+var prompt = '? foo ';
+ui.render(prompt);
+
+// on keypress events, re-render the prompt 
+// along with user input
+ui.on('keypress', function() {
+  ui.render(prompt + ui.rl.line);
+});
+
+// when the "line" event is emitted (from the "enter" keypress)
+// we `.end()` to unmute the output stream then pause the readline. 
+ui.on('line', function(answer) {
+  ui.render(prompt + cyan(answer));
+  ui.end();
+  ui.rl.pause();
+  console.log({color: answer});
+});
+```
+
+## API
+
+### [.onKeypress](index.js#L70)
+
+Handle `keypress` events.
+
+**Params**
+
+* `str` **{String}**
+* `key` **{Object}**
+* `returns` **{undefined}**
+
+### [.render](index.js#L82)
+
+Render the prompt with the given `input` and optional `footer`.
+
+**Params**
+
+* `input` **{String}**
+* `footer` **{String}**: (optional)
+* `returns` **{undefined}**
+
+### [.clearLines](index.js#L148)
+
+Remove `n` lines from the bottom of the terminal
+
+**Params**
+
+* `lines` **{Number}**: Number of lines to remove
+
+### [.cacheCursorPos](index.js#L159)
+
+Cache the current cursor's column and line position.
+
+* `returns` **{Object}**: UI instance.
+
+### [.restoreCursorPos](index.js#L170)
+
+Restore the cursor position to the cached column and line.
+
+* `returns` **{Object}**: UI instance.
+
+### [.resume](index.js#L180)
+
+Resume the input stream.
+
+### [.pause](index.js#L189)
+
+Pause the input stream, allowing it to be resumed later if necessary.
+
+### [.close](index.js#L201)
+
+Close the `readline.Interface` instance and relinquish
+control over the input and output streams. Also removes
+event listeners, and restores/unmutes prompt functionality.
+
+### [.forceClose](index.js#L211)
+
+Close the interface when the keypress is `^C`
+
+### [.finish](index.js#L222)
+
+Returns an "indentity" function that calls `.close()`,
+which can be used as the final `.then()` function with
+promises.
+
+### [.end](index.js#L237)
+
+Default method for writing a prompt to the terminal.
+This can be overridden.
+
+### [.mute](index.js#L260)
+
+Mutes the output stream that was used to create the readline interface, and returns a function for unmuting the stream. This is useful in unit tests.
+
+* `returns` **{Function}**
+
+**Example**
+
+```js
+// mute the stream
+var unmute = ui.mute();
+
+// unmute the stream
+unmute();
+```
+
+### [.log](index.js#L280)
+
+Unmute then write to the output stream that was used
+to create the readline interface, then re-mute the stream.
+Useful for debugging prompts.
+
+## Attribution
+
+Inspired by the "screen manager" code in Inquirer.
+
+## About
+
+### Related projects
+
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. | [homepage](http://enquirer.io "Intuitive, plugin-based prompt system for node.js.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+* [prompt-question](https://www.npmjs.com/package/prompt-question): Question object, used by Enquirer and prompt plugins. | [homepage](https://github.com/enquirer/prompt-question "Question object, used by Enquirer and prompt plugins.")
+* [readline-utils](https://www.npmjs.com/package/readline-utils): Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more. | [homepage](https://github.com/enquirer/readline-utils "Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on June 04, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readline-ui/index.js b/input_devices/mag/node_modules/readline-ui/index.js
new file mode 100644
index 00000000..ad09ab07
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/index.js
@@ -0,0 +1,301 @@
+'use strict';
+
+var util = require('util');
+var debug = require('debug')('readline-ui');
+var Emitter = require('component-emitter');
+var stringWidth = require('string-width');
+var utils = require('readline-utils');
+var cached;
+
+/**
+ * Create a readline interface to use in prompts
+ */
+
+function UI(options) {
+  if (!(this instanceof UI)) {
+    var ui = Object.create(UI.prototype);
+    UI.apply(ui, arguments);
+    return ui;
+  }
+  debug('initializing from <%s>', __filename);
+  this.options = utils.createOptions(options);
+  this.appendedLines = 0;
+  this.height = 0;
+  this.initInterface();
+}
+
+/**
+ * Decorate emitter methods
+ */
+
+Emitter(UI.prototype);
+
+/**
+ * Initialize settings and events.
+ */
+
+UI.prototype.initInterface = function() {
+  if (this.initialized) return;
+  this.initialized = true;
+  var self = this;
+  if (typeof this.rl === 'undefined') {
+    this.rl = utils.createInterface(this.options);
+  }
+
+  this.forceClose = this.forceClose.bind(this);
+  this.onKeypress = this.onKeypress.bind(this);
+
+  this.rl.input.on('keypress', self.onKeypress);
+  this.resume();
+
+  this.rl.on('line', function(line) {
+    setImmediate(function() {
+      self.emit('line', line, {name: 'line', value: line});
+    })
+  });
+
+  this.rl.on('SIGINT', this.forceClose);
+  process.on('exit', this.forceClose);
+};
+
+/**
+ * Handle `keypress` events.
+ *
+ * @param {String} `str`
+ * @param {Object} `key`
+ * @return {undefined}
+ * @api public
+ */
+
+UI.prototype.onKeypress = function(input, key) {
+  utils.emitKeypress(this, input, key);
+};
+
+/**
+ * Render the prompt with the given `input` and optional `footer`.
+ * @param {String} `input`
+ * @param {String} `footer` (optional)
+ * @return {undefined}
+ * @api public
+ */
+
+UI.prototype.render = function(input, footer) {
+  this.rl.output.unmute();
+  this.clearLines(this.appendedLines);
+
+  // Write message to screen and setPrompt to control backspace
+  var line = utils.lastLine(input);
+  var rawLine = utils.unstyle(line);
+
+  // Remove the last line from our prompt. We can't rely
+  // on the input of rl.line (mainly because of the password
+  // prompt), so just rely on it's length.
+  var prompt = line;
+  if (this.rl.line.length) {
+    prompt = prompt.slice(0, -this.rl.line.length);
+  }
+
+  this.rl.setPrompt(prompt);
+
+  // setPrompt will change cursor position, now we can get correct value
+  var cursorPos = this.cacheCursorPos();
+  var width = utils.cliWidth(this.rl);
+
+  input = utils.forceLineReturn(input, width);
+  if (footer) {
+    footer = utils.forceLineReturn(footer, width);
+  }
+
+  // Manually insert an extra line if we're at the end of
+  // the line. This prevents the cursor from appearing at
+  // the beginning of the current line.
+  if (rawLine.length % width === 0) {
+    input += '\n';
+  }
+
+  var fullContent = input + (footer ? '\n' + String(footer) : '');
+  this.rl.output.write(fullContent);
+
+  // We need to consider parts of the prompt under the
+  // cursor as part of the bottom string in order to
+  // correctly cleanup and re-render.
+  var promptLineUpDiff = Math.floor(rawLine.length / width) - cursorPos.rows;
+  var footerHeight = promptLineUpDiff + (footer ? utils.height(footer) : 0);
+  if (footerHeight > 0) {
+    utils.up(this.rl, footerHeight);
+  }
+
+  // Reset cursor at the beginning of the line
+  var lastLine = utils.lastLine(fullContent);
+  utils.left(this.rl, stringWidth(lastLine));
+
+  // Adjust cursor on the right
+  var newPos = utils.unstyle(input).length;
+  utils.right(this.rl, newPos);
+
+  // Set up state for next re-rendering
+  this.appendedLines = footerHeight;
+  this.height = utils.height(fullContent);
+  this.rl.output.mute();
+};
+
+/**
+ * Remove `n` lines from the bottom of the terminal
+ * @param {Number} `lines` Number of lines to remove
+ * @api public
+ */
+
+UI.prototype.clearLines = function(n) {
+  if (n) utils.down(this.rl, n);
+  utils.clearLine(this.rl, this.height);
+};
+
+/**
+ * Cache the current cursor's column and line position.
+ * @returns {Object} UI instance.
+ * @api public
+ */
+
+UI.prototype.cacheCursorPos = function() {
+  this.cursorPos = utils.cursorPosition(this.rl);
+  return this.cursorPos;
+};
+
+/**
+ * Restore the cursor position to the cached column and line.
+ * @return {Object} UI instance.
+ * @api public
+ */
+
+UI.prototype.restoreCursorPos = function() {
+  utils.restoreCursorPos(this.rl, this.cursorPos);
+  return this;
+};
+
+/**
+ * Resume the input stream.
+ * @api public
+ */
+
+UI.prototype.resume = function() {
+  this.rl.resume();
+};
+
+/**
+ * Pause the input stream, allowing it to be resumed later if necessary.
+ * @api public
+ */
+
+UI.prototype.pause = function() {
+  this.rl.pause();
+  this.emit('pause');
+};
+
+/**
+ * Close the `readline.Interface` instance and relinquish
+ * control over the input and output streams. Also removes
+ * event listeners, and restores/unmutes prompt functionality.
+ * @api public
+ */
+
+UI.prototype.close = function() {
+  utils.close(this.rl);
+  this.emit('close');
+};
+
+/**
+ * Close the interface when the keypress is `^C`
+ * @api public
+ */
+
+UI.prototype.forceClose = function() {
+  utils.forceClose(this.rl);
+};
+
+/**
+ * Returns an "indentity" function that calls `.close()`,
+ * which can be used as the final `.then()` function with
+ * promises.
+ * @api public
+ */
+
+UI.prototype.finish = function() {
+  var ui = this;
+  return function(val) {
+    ui.close();
+    ui.emit('finish');
+    return val;
+  };
+};
+
+/**
+ * Default method for writing a prompt to the terminal.
+ * This can be overridden.
+ * @api public
+ */
+
+UI.prototype.end = function(newline) {
+  this.rl.setPrompt('');
+  this.rl.output.unmute();
+  this.rl.output.write(newline !== false ? '\n' : '');
+  utils.cursorShow(this.rl);
+};
+
+/**
+ * Mutes the output stream that was used to create the
+ * readline interface, and returns a function for unmuting the
+ * stream. This is useful in unit tests.
+ *
+ * ```js
+ * // mute the stream
+ * var unmute = ui.mute();
+ *
+ * // unmute the stream
+ * unmute();
+ * ```
+ * @return {Function}
+ * @api public
+ */
+
+UI.prototype.mute = function() {
+  var rl = this.rl;
+  var unmute = rl.output.unmute;
+  rl.output.unmute = function() {};
+  rl.output.mute();
+
+  return function() {
+    rl.output.unmute = unmute;
+    unmute();
+  };
+};
+
+/**
+ * Unmute then write to the output stream that was used
+ * to create the readline interface, then re-mute the stream.
+ * Useful for debugging prompts.
+ *
+ * @api public
+ */
+
+UI.prototype.log = function(input) {
+  this.rl.output.unmute();
+  this.rl.output.write(util.inspect.apply(util, arguments));
+  this.rl.output.mute();
+};
+
+/**
+ * Expose `UI`
+ */
+
+module.exports = UI;
+
+/**
+ * Expose `UI.create` for using a single instance across
+ * multiple prompts.
+ */
+
+module.exports.create = function(options) {
+  if (cached) return cached;
+  cached = new UI(options);
+  return cached;
+};
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/index.js b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/index.js
new file mode 100644
index 00000000..c4aaecf5
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/index.js
@@ -0,0 +1,10 @@
+'use strict';
+
+module.exports = () => {
+	const pattern = [
+		'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\\u0007)',
+		'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))'
+	].join('|');
+
+	return new RegExp(pattern, 'g');
+};
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/license b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/license
new file mode 100644
index 00000000..e7af2f77
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/package.json b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/package.json
new file mode 100644
index 00000000..064ca683
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/package.json
@@ -0,0 +1,121 @@
+{
+  "_args": [
+    [
+      "ansi-regex@^3.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi"
+    ]
+  ],
+  "_from": "ansi-regex@>=3.0.0 <4.0.0",
+  "_id": "ansi-regex@3.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-ui/ansi-regex",
+  "_nodeVersion": "4.8.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/ansi-regex-3.0.0.tgz_1497985412590_0.5700640194118023"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.15.11",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ansi-regex",
+    "raw": "ansi-regex@^3.0.0",
+    "rawSpec": "^3.0.0",
+    "scope": null,
+    "spec": ">=3.0.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-ui/strip-ansi"
+  ],
+  "_resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+  "_shasum": "ed0317c322064f79466c02966bddb605ab37d998",
+  "_shrinkwrap": null,
+  "_spec": "ansi-regex@^3.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/chalk/ansi-regex/issues"
+  },
+  "dependencies": {},
+  "description": "Regular expression for matching ANSI escape codes",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "ed0317c322064f79466c02966bddb605ab37d998",
+    "tarball": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "0a8cc19946c03c38520fe8c086b8adb66f9cce0b",
+  "homepage": "https://github.com/chalk/ansi-regex#readme",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "color",
+    "colors",
+    "colour",
+    "command-line",
+    "console",
+    "escape",
+    "find",
+    "formatting",
+    "match",
+    "pattern",
+    "re",
+    "regex",
+    "regexp",
+    "rgb",
+    "shell",
+    "string",
+    "styles",
+    "terminal",
+    "test",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "dthree",
+      "email": "threedeecee@gmail.com"
+    },
+    {
+      "name": "qix",
+      "email": "i.am.qix@gmail.com"
+    },
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "ansi-regex",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/chalk/ansi-regex.git"
+  },
+  "scripts": {
+    "test": "xo && ava",
+    "view-supported": "node fixtures/view-codes.js"
+  },
+  "version": "3.0.0"
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/readme.md b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/readme.md
new file mode 100644
index 00000000..22db1c34
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ansi-regex/readme.md
@@ -0,0 +1,46 @@
+# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)
+
+> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
+
+
+## Install
+
+```
+$ npm install ansi-regex
+```
+
+
+## Usage
+
+```js
+const ansiRegex = require('ansi-regex');
+
+ansiRegex().test('\u001B[4mcake\u001B[0m');
+//=> true
+
+ansiRegex().test('cake');
+//=> false
+
+'\u001B[4mcake\u001B[0m'.match(ansiRegex());
+//=> ['\u001B[4m', '\u001B[0m']
+```
+
+
+## FAQ
+
+### Why do you test for codes not in the ECMA 48 standard?
+
+Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
+
+On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
+
+
+## Maintainers
+
+- [Sindre Sorhus](https://github.com/sindresorhus)
+- [Josh Junon](https://github.com/qix-)
+
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/.coveralls.yml b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/.eslintrc b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+  "rules": {
+    "no-console": 0,
+    "no-empty": [1, { "allowEmptyCatch": true }]
+  },
+  "extends": "eslint:recommended"
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/.npmignore b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/.travis.yml b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+  - "6"
+  - "5"
+  - "4"
+
+install:
+  - make node_modules
+
+script:
+  - make lint
+  - make test
+  - make coveralls
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/CHANGELOG.md b/input_devices/mag/node_modules/readline-ui/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+  * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+  * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+  * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+  * Fix: Inline extend function in node implementation (#452, @dougwilson)
+  * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+  
+  * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+  * Misc: clean up browser reference checks (#447, @thebigredgeek)
+  * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+  * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+  * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+  * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+  * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+  * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+  * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+  * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+  * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+  * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+  * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+  * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+  * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+  * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+  * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+  * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+  * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+  * Docs: fixed README typo (#391, @lurch)
+  * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+  * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+  * Fix: wrong reference in bower file (@thebigredgeek)
+  * Fix: webworker compatibility (@thebigredgeek)
+  * Fix: output formatting issue (#388, @kribblo)
+  * Fix: babel-loader compatibility (#383, @escwald)
+  * Misc: removed built asset from repo and publications (@thebigredgeek)
+  * Misc: moved source files to /src (#378, @yamikuronue)
+  * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+  * Test: coveralls integration (#378, @yamikuronue)
+  * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+  * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+  * Fix: custom log function (#379, @hsiliev)
+  * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+  * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+  * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+  * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+  * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+  * Fix: browser colors (#367, @tootallnate)
+  * Misc: travis ci integration (@thebigredgeek)
+  * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+  * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+  * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+  * Fix: revert "handle regex special characters" (@tootallnate)
+  * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+  * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+  * Improvement: allow colors in workers (#335, @botverse)
+  * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+  * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+  * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+  * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+  * Fix: be super-safe in index.js as well (@TooTallNate)
+  * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+  * Fix: Added electron compatibility (#324, @paulcbetts)
+  * Improvement: Added performance optimizations (@tootallnate)
+  * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+  * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+  * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+  * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+  * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+  * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+  * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+  * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+  * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+  * Readme: fix USE_COLORS to DEBUG_COLORS
+  * Readme: Doc fixes for format string sugar (#269, @mlucool)
+  * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+  * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+  * Readme: better docs for browser support (#224, @matthewmueller)
+  * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+  * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+  * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+  * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+  * package: update "ms" to v0.7.1 (#202, @dougwilson)
+  * README: add logging to file example (#193, @DanielOchoa)
+  * README: fixed a typo (#191, @amir-s)
+  * browser: expose `storage` (#190, @stephenmathieson)
+  * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+  * Updated stdout/stderr example (#186)
+  * Updated example/stdout.js to match debug current behaviour
+  * Renamed example/stderr.js to stdout.js
+  * Update Readme.md (#184)
+  * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+  * dist: recompile
+  * update "ms" to v0.7.0
+  * package: update "browserify" to v9.0.3
+  * component: fix "ms.js" repo location
+  * changed bower package name
+  * updated documentation about using debug in a browser
+  * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+  * browser: use `typeof` to check for `console` existence
+  * browser: check for `console.log` truthiness (fix IE 8/9)
+  * browser: add support for Chrome apps
+  * Readme: added Windows usage remarks
+  * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+  * node: implement `DEBUG_FD` env variable support
+  * package: update "browserify" to v6.1.0
+  * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+  * package: update "browserify" to v5.11.0
+  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+  * dist: recompile
+  * example: remove `console.info()` log usage
+  * example: add "Content-Type" UTF-8 header to browser example
+  * browser: place %c marker after the space character
+  * browser: reset the "content" color via `color: inherit`
+  * browser: add colors support for Firefox >= v31
+  * debug: prefer an instance `log()` function over the global one (#119)
+  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+  * Add support for multiple wildcards in namespaces (#122, @seegno)
+  * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+  * browser: update color palette (#113, @gscottolson)
+  * common: make console logging function configurable (#108, @timoxley)
+  * node: fix %o colors on old node <= 0.8.x
+  * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+  * browser: use `removeItem()` to clear localStorage
+  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+  * package: add "contributors" section
+  * node: fix comment typo
+  * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+  * make ms diff be global, not be scope
+  * debug: ignore empty strings in enable()
+  * node: make DEBUG_COLORS able to disable coloring
+  * *: export the `colors` array
+  * npmignore: don't publish the `dist` dir
+  * Makefile: refactor to use browserify
+  * package: add "browserify" as a dev dependency
+  * Readme: add Web Inspector Colors section
+  * node: reset terminal color for the debug content
+  * node: map "%o" to `util.inspect()`
+  * browser: map "%j" to `JSON.stringify()`
+  * debug: add custom "formatters"
+  * debug: use "ms" module for humanizing the diff
+  * Readme: add "bash" syntax highlighting
+  * browser: add Firebug color support
+  * browser: add colors for WebKit browsers
+  * node: apply log to `console`
+  * rewrite: abstract common logic for Node & browsers
+  * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+  * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+  * add `enable()` method for nodejs. Closes #27
+  * change from stderr to stdout
+  * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+  * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+  * fix: catch localStorage security error when cookies are blocked (Chrome)
+  * add debug(err) support. Closes #46
+  * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/LICENSE b/input_devices/mag/node_modules/readline-ui/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/readline-ui/node_modules/debug/Makefile b/input_devices/mag/node_modules/readline-ui/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+	@NODE_ENV= $(PKG) install
+	@touch node_modules
+
+lint: .FORCE
+	eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+	istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+	mkdir -p dist
+
+	@$(BROWSERIFY) \
+		--standalone debug \
+		. > dist/debug.js
+
+	karma start --single-run
+	rimraf dist
+
+test: .FORCE
+	concurrently \
+		"make test-node" \
+		"make test-browser"
+
+coveralls:
+	cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/README.md b/input_devices/mag/node_modules/readline-ui/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) 
+[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+  ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+
+## Conventions
+
+  If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+  When running through Node.js, you can set a few environment variables that will
+  change the behavior of the debug logging:
+
+| Name      | Purpose                                         |
+|-----------|-------------------------------------------------|
+| `DEBUG`   | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+  __Note:__ The environment variables beginning with `DEBUG_` end up being
+  converted into an Options object that gets used with `%o`/`%O` formatters.
+  See the Node.js documentation for
+  [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+  for the complete list.
+
+## Formatters
+
+
+  Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O`      | Pretty-print an Object on multiple lines. |
+| `%o`      | Pretty-print an Object all on a single line. |
+| `%s`      | String. |
+| `%d`      | Number (both integer and float). |
+| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%`      | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+  You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+  return v.toString('hex')
+}
+
+// …elsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+//   foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+  You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+  or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+  if you don't want to build it yourself.
+
+  Debug's enable state is currently persisted by `localStorage`.
+  Consider the situation shown below where you have `worker:a` and `worker:b`,
+  and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+  Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+  option. These are WebKit web inspectors, Firefox ([since version
+  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+  and the Firebug plugin for Firefox (any version).
+
+  Colored output looks something like:
+
+  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
+
+
+## Output streams
+
+  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+ 
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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/input_devices/mag/node_modules/readline-ui/node_modules/debug/component.json b/input_devices/mag/node_modules/readline-ui/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+  "name": "debug",
+  "repo": "visionmedia/debug",
+  "description": "small debugging utility",
+  "version": "2.6.9",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "main": "src/browser.js",
+  "scripts": [
+    "src/browser.js",
+    "src/debug.js"
+  ],
+  "dependencies": {
+    "rauchg/ms.js": "0.7.1"
+  }
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/karma.conf.js b/input_devices/mag/node_modules/readline-ui/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['mocha', 'chai', 'sinon'],
+
+
+    // list of files / patterns to load in the browser
+    files: [
+      'dist/debug.js',
+      'test/*spec.js'
+    ],
+
+
+    // list of files to exclude
+    exclude: [
+      'src/node.js'
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['progress'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false,
+
+    // Concurrency level
+    // how many browser should be started simultaneous
+    concurrency: Infinity
+  })
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/node.js b/input_devices/mag/node_modules/readline-ui/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/package.json b/input_devices/mag/node_modules/readline-ui/node_modules/debug/package.json
new file mode 100644
index 00000000..8b79d9c3
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/package.json
@@ -0,0 +1,128 @@
+{
+  "_args": [
+    [
+      "debug@^2.6.8",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui"
+    ]
+  ],
+  "_from": "debug@>=2.6.8 <3.0.0",
+  "_id": "debug@2.6.9",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-ui/debug",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196"
+  },
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "debug",
+    "raw": "debug@^2.6.8",
+    "rawSpec": "^2.6.8",
+    "scope": null,
+    "spec": ">=2.6.8 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-ui"
+  ],
+  "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+  "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+  "_shrinkwrap": null,
+  "_spec": "debug@^2.6.8",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "browser": "./src/browser.js",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "component": {
+    "scripts": {
+      "debug/debug.js": "debug.js",
+      "debug/index.js": "browser.js"
+    }
+  },
+  "contributors": [
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "http://n8.io"
+    },
+    {
+      "name": "Andrew Rhyne",
+      "email": "rhyneandrew@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "ms": "2.0.0"
+  },
+  "description": "small debugging utility",
+  "devDependencies": {
+    "browserify": "9.0.3",
+    "chai": "^3.5.0",
+    "concurrently": "^3.1.0",
+    "coveralls": "^2.11.15",
+    "eslint": "^3.12.1",
+    "istanbul": "^0.4.5",
+    "karma": "^1.3.0",
+    "karma-chai": "^0.1.0",
+    "karma-mocha": "^1.3.0",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "karma-sinon": "^1.0.5",
+    "mocha": "^3.2.0",
+    "mocha-lcov-reporter": "^1.2.0",
+    "rimraf": "^2.5.4",
+    "sinon": "^1.17.6",
+    "sinon-chai": "^2.8.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+    "shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+    "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
+  },
+  "gitHead": "13abeae468fea297d0dccc50bc55590809241083",
+  "homepage": "https://github.com/visionmedia/debug#readme",
+  "keywords": [
+    "debug",
+    "debugger",
+    "log"
+  ],
+  "license": "MIT",
+  "main": "./src/index.js",
+  "maintainers": [
+    {
+      "name": "thebigredgeek",
+      "email": "rhyneandrew@gmail.com"
+    },
+    {
+      "name": "kolban",
+      "email": "kolban1@kolban.com"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    }
+  ],
+  "name": "debug",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "version": "2.6.9"
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/browser.js b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+               && 'undefined' != typeof chrome.storage
+                  ? chrome.storage.local
+                  : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+  'lightseagreen',
+  'forestgreen',
+  'goldenrod',
+  'dodgerblue',
+  'darkorchid',
+  'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+  // NB: In an Electron preload script, document will be defined but not fully
+  // initialized. Since we know we're in Chrome, we'll just detect this case
+  // explicitly
+  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+    return true;
+  }
+
+  // is webkit? http://stackoverflow.com/a/16459606/376773
+  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+    // is firebug? http://stackoverflow.com/a/398120/376773
+    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+    // is firefox >= v31?
+    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+    // double check webkit in userAgent just in case we are in a worker
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+  try {
+    return JSON.stringify(v);
+  } catch (err) {
+    return '[UnexpectedJSONParseError]: ' + err.message;
+  }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var useColors = this.useColors;
+
+  args[0] = (useColors ? '%c' : '')
+    + this.namespace
+    + (useColors ? ' %c' : ' ')
+    + args[0]
+    + (useColors ? '%c ' : ' ')
+    + '+' + exports.humanize(this.diff);
+
+  if (!useColors) return;
+
+  var c = 'color: ' + this.color;
+  args.splice(1, 0, c, 'color: inherit')
+
+  // the final "%c" is somewhat tricky, because there could be other
+  // arguments passed either before or after the %c, so we need to
+  // figure out the correct index to insert the CSS into
+  var index = 0;
+  var lastC = 0;
+  args[0].replace(/%[a-zA-Z%]/g, function(match) {
+    if ('%%' === match) return;
+    index++;
+    if ('%c' === match) {
+      // we only are interested in the *last* %c
+      // (the user may have provided their own)
+      lastC = index;
+    }
+  });
+
+  args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+  // this hackery is required for IE8/9, where
+  // the `console.log` function doesn't have 'apply'
+  return 'object' === typeof console
+    && console.log
+    && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  try {
+    if (null == namespaces) {
+      exports.storage.removeItem('debug');
+    } else {
+      exports.storage.debug = namespaces;
+    }
+  } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  var r;
+  try {
+    r = exports.storage.debug;
+  } catch(e) {}
+
+  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+  if (!r && typeof process !== 'undefined' && 'env' in process) {
+    r = process.env.DEBUG;
+  }
+
+  return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+  try {
+    return window.localStorage;
+  } catch (e) {}
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/debug.js b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+  var hash = 0, i;
+
+  for (i in namespace) {
+    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
+    hash |= 0; // Convert to 32bit integer
+  }
+
+  return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+  function debug() {
+    // disabled?
+    if (!debug.enabled) return;
+
+    var self = debug;
+
+    // set `diff` timestamp
+    var curr = +new Date();
+    var ms = curr - (prevTime || curr);
+    self.diff = ms;
+    self.prev = prevTime;
+    self.curr = curr;
+    prevTime = curr;
+
+    // turn the `arguments` into a proper Array
+    var args = new Array(arguments.length);
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i];
+    }
+
+    args[0] = exports.coerce(args[0]);
+
+    if ('string' !== typeof args[0]) {
+      // anything else let's inspect with %O
+      args.unshift('%O');
+    }
+
+    // apply any `formatters` transformations
+    var index = 0;
+    args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+      // if we encounter an escaped % then don't increase the array index
+      if (match === '%%') return match;
+      index++;
+      var formatter = exports.formatters[format];
+      if ('function' === typeof formatter) {
+        var val = args[index];
+        match = formatter.call(self, val);
+
+        // now we need to remove `args[index]` since it's inlined in the `format`
+        args.splice(index, 1);
+        index--;
+      }
+      return match;
+    });
+
+    // apply env-specific formatting (colors, etc.)
+    exports.formatArgs.call(self, args);
+
+    var logFn = debug.log || exports.log || console.log.bind(console);
+    logFn.apply(self, args);
+  }
+
+  debug.namespace = namespace;
+  debug.enabled = exports.enabled(namespace);
+  debug.useColors = exports.useColors();
+  debug.color = selectColor(namespace);
+
+  // env-specific initialization logic for debug instances
+  if ('function' === typeof exports.init) {
+    exports.init(debug);
+  }
+
+  return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+  exports.save(namespaces);
+
+  exports.names = [];
+  exports.skips = [];
+
+  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+  var len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    if (!split[i]) continue; // ignore empty strings
+    namespaces = split[i].replace(/\*/g, '.*?');
+    if (namespaces[0] === '-') {
+      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+    } else {
+      exports.names.push(new RegExp('^' + namespaces + '$'));
+    }
+  }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+  exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+  var i, len;
+  for (i = 0, len = exports.skips.length; i < len; i++) {
+    if (exports.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (i = 0, len = exports.names.length; i < len; i++) {
+    if (exports.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/index.js b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+  module.exports = require('./browser.js');
+} else {
+  module.exports = require('./node.js');
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/inspector-log.js b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+  const stdout = console._stdout;
+  console._stdout = nullStream;
+  console.log.apply(console, arguments);
+  console._stdout = stdout;
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/node.js b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+  return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+  // camel-case
+  var prop = key
+    .substring(6)
+    .toLowerCase()
+    .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+  // coerce string value into JS value
+  var val = process.env[key];
+  if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+  else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+  else if (val === 'null') val = null;
+  else val = Number(val);
+
+  obj[prop] = val;
+  return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ *   $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+  util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+             2 === fd ? process.stderr :
+             createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+  return 'colors' in exports.inspectOpts
+    ? Boolean(exports.inspectOpts.colors)
+    : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts)
+    .split('\n').map(function(str) {
+      return str.trim()
+    }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var name = this.namespace;
+  var useColors = this.useColors;
+
+  if (useColors) {
+    var c = this.color;
+    var prefix = '  \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+    args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+    args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+  } else {
+    args[0] = new Date().toUTCString()
+      + ' ' + name + ' ' + args[0];
+  }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+  return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  if (null == namespaces) {
+    // If you set a process.env field to null or undefined, it gets cast to the
+    // string 'null' or 'undefined'. Just delete instead.
+    delete process.env.DEBUG;
+  } else {
+    process.env.DEBUG = namespaces;
+  }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+  var stream;
+  var tty_wrap = process.binding('tty_wrap');
+
+  // Note stream._type is used for test-module-load-list.js
+
+  switch (tty_wrap.guessHandleType(fd)) {
+    case 'TTY':
+      stream = new tty.WriteStream(fd);
+      stream._type = 'tty';
+
+      // Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    case 'FILE':
+      var fs = require('fs');
+      stream = new fs.SyncWriteStream(fd, { autoClose: false });
+      stream._type = 'fs';
+      break;
+
+    case 'PIPE':
+    case 'TCP':
+      var net = require('net');
+      stream = new net.Socket({
+        fd: fd,
+        readable: false,
+        writable: true
+      });
+
+      // FIXME Should probably have an option in net.Socket to create a
+      // stream from an existing fd which is writable only. But for now
+      // we'll just add this hack and set the `readable` member to false.
+      // Test: ./node test/fixtures/echo.js < /etc/passwd
+      stream.readable = false;
+      stream.read = null;
+      stream._type = 'pipe';
+
+      // FIXME Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    default:
+      // Probably an error on in uv_guess_handle()
+      throw new Error('Implement me. Unknown stream file type!');
+  }
+
+  // For supporting legacy API we put the FD here.
+  stream.fd = fd;
+
+  stream._isStdio = true;
+
+  return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+  debug.inspectOpts = {};
+
+  var keys = Object.keys(exports.inspectOpts);
+  for (var i = 0; i < keys.length; i++) {
+    debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+  }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/index.js b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/index.js
new file mode 100644
index 00000000..d506327c
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/index.js
@@ -0,0 +1,46 @@
+'use strict';
+/* eslint-disable yoda */
+module.exports = x => {
+	if (Number.isNaN(x)) {
+		return false;
+	}
+
+	// code points are derived from:
+	// http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt
+	if (
+		x >= 0x1100 && (
+			x <= 0x115f ||  // Hangul Jamo
+			x === 0x2329 || // LEFT-POINTING ANGLE BRACKET
+			x === 0x232a || // RIGHT-POINTING ANGLE BRACKET
+			// CJK Radicals Supplement .. Enclosed CJK Letters and Months
+			(0x2e80 <= x && x <= 0x3247 && x !== 0x303f) ||
+			// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
+			(0x3250 <= x && x <= 0x4dbf) ||
+			// CJK Unified Ideographs .. Yi Radicals
+			(0x4e00 <= x && x <= 0xa4c6) ||
+			// Hangul Jamo Extended-A
+			(0xa960 <= x && x <= 0xa97c) ||
+			// Hangul Syllables
+			(0xac00 <= x && x <= 0xd7a3) ||
+			// CJK Compatibility Ideographs
+			(0xf900 <= x && x <= 0xfaff) ||
+			// Vertical Forms
+			(0xfe10 <= x && x <= 0xfe19) ||
+			// CJK Compatibility Forms .. Small Form Variants
+			(0xfe30 <= x && x <= 0xfe6b) ||
+			// Halfwidth and Fullwidth Forms
+			(0xff01 <= x && x <= 0xff60) ||
+			(0xffe0 <= x && x <= 0xffe6) ||
+			// Kana Supplement
+			(0x1b000 <= x && x <= 0x1b001) ||
+			// Enclosed Ideographic Supplement
+			(0x1f200 <= x && x <= 0x1f251) ||
+			// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
+			(0x20000 <= x && x <= 0x3fffd)
+		)
+	) {
+		return true;
+	}
+
+	return false;
+};
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/license b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/package.json b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/package.json
new file mode 100644
index 00000000..dc37aa69
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/package.json
@@ -0,0 +1,105 @@
+{
+  "_args": [
+    [
+      "is-fullwidth-code-point@^2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/string-width"
+    ]
+  ],
+  "_from": "is-fullwidth-code-point@>=2.0.0 <3.0.0",
+  "_id": "is-fullwidth-code-point@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-ui/is-fullwidth-code-point",
+  "_nodeVersion": "4.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/is-fullwidth-code-point-2.0.0.tgz_1474526567505_0.299921662081033"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "3.10.7",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-fullwidth-code-point",
+    "raw": "is-fullwidth-code-point@^2.0.0",
+    "rawSpec": "^2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-ui/string-width"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+  "_shasum": "a3b30a5c4f199183167aaab93beefae3ddfb654f",
+  "_shrinkwrap": null,
+  "_spec": "is-fullwidth-code-point@^2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/string-width",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/is-fullwidth-code-point/issues"
+  },
+  "dependencies": {},
+  "description": "Check if the character represented by a given Unicode code point is fullwidth",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a3b30a5c4f199183167aaab93beefae3ddfb654f",
+    "tarball": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e94a78056056c5546f2bf4c4cf812a2163a46dae",
+  "homepage": "https://github.com/sindresorhus/is-fullwidth-code-point#readme",
+  "keywords": [
+    "char",
+    "character",
+    "check",
+    "code",
+    "codepoint",
+    "detect",
+    "full",
+    "full-width",
+    "fullwidth",
+    "is",
+    "point",
+    "str",
+    "string",
+    "unicode",
+    "width"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "is-fullwidth-code-point",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/is-fullwidth-code-point.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "2.0.0",
+  "xo": {
+    "esnext": true
+  }
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/readme.md b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/readme.md
new file mode 100644
index 00000000..093b0281
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/is-fullwidth-code-point/readme.md
@@ -0,0 +1,39 @@
+# is-fullwidth-code-point [![Build Status](https://travis-ci.org/sindresorhus/is-fullwidth-code-point.svg?branch=master)](https://travis-ci.org/sindresorhus/is-fullwidth-code-point)
+
+> Check if the character represented by a given [Unicode code point](https://en.wikipedia.org/wiki/Code_point) is [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms)
+
+
+## Install
+
+```
+$ npm install --save is-fullwidth-code-point
+```
+
+
+## Usage
+
+```js
+const isFullwidthCodePoint = require('is-fullwidth-code-point');
+
+isFullwidthCodePoint('谢'.codePointAt());
+//=> true
+
+isFullwidthCodePoint('a'.codePointAt());
+//=> false
+```
+
+
+## API
+
+### isFullwidthCodePoint(input)
+
+#### input
+
+Type: `number`
+
+[Code point](https://en.wikipedia.org/wiki/Code_point) of a character.
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/ms/index.js b/input_devices/mag/node_modules/readline-ui/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+  options = options || {};
+  var type = typeof val;
+  if (type === 'string' && val.length > 0) {
+    return parse(val);
+  } else if (type === 'number' && isNaN(val) === false) {
+    return options.long ? fmtLong(val) : fmtShort(val);
+  }
+  throw new Error(
+    'val is not a non-empty string or a valid number. val=' +
+      JSON.stringify(val)
+  );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  str = String(str);
+  if (str.length > 100) {
+    return;
+  }
+  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+    str
+  );
+  if (!match) {
+    return;
+  }
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'yrs':
+    case 'yr':
+    case 'y':
+      return n * y;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'hrs':
+    case 'hr':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'mins':
+    case 'min':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 'secs':
+    case 'sec':
+    case 's':
+      return n * s;
+    case 'milliseconds':
+    case 'millisecond':
+    case 'msecs':
+    case 'msec':
+    case 'ms':
+      return n;
+    default:
+      return undefined;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+  if (ms >= d) {
+    return Math.round(ms / d) + 'd';
+  }
+  if (ms >= h) {
+    return Math.round(ms / h) + 'h';
+  }
+  if (ms >= m) {
+    return Math.round(ms / m) + 'm';
+  }
+  if (ms >= s) {
+    return Math.round(ms / s) + 's';
+  }
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+  return plural(ms, d, 'day') ||
+    plural(ms, h, 'hour') ||
+    plural(ms, m, 'minute') ||
+    plural(ms, s, 'second') ||
+    ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+  if (ms < n) {
+    return;
+  }
+  if (ms < n * 1.5) {
+    return Math.floor(ms / n) + ' ' + name;
+  }
+  return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/ms/license.md b/input_devices/mag/node_modules/readline-ui/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/input_devices/mag/node_modules/readline-ui/node_modules/ms/package.json b/input_devices/mag/node_modules/readline-ui/node_modules/ms/package.json
new file mode 100644
index 00000000..de9e8c63
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ms/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "ms@2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/debug"
+    ]
+  ],
+  "_from": "ms@2.0.0",
+  "_id": "ms@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-ui/ms",
+  "_nodeVersion": "7.8.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945"
+  },
+  "_npmUser": {
+    "email": "leo@zeit.co",
+    "name": "leo"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ms",
+    "raw": "ms@2.0.0",
+    "rawSpec": "2.0.0",
+    "scope": null,
+    "spec": "2.0.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/readline-ui/debug"
+  ],
+  "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+  "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+  "_shrinkwrap": null,
+  "_spec": "ms@2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/debug",
+  "bugs": {
+    "url": "https://github.com/zeit/ms/issues"
+  },
+  "dependencies": {},
+  "description": "Tiny milisecond conversion utility",
+  "devDependencies": {
+    "eslint": "3.19.0",
+    "expect.js": "0.3.1",
+    "husky": "0.13.3",
+    "lint-staged": "3.4.1",
+    "mocha": "3.4.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+    "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
+  },
+  "eslintConfig": {
+    "env": {
+      "es6": true,
+      "node": true
+    },
+    "extends": "eslint:recommended"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4",
+  "homepage": "https://github.com/zeit/ms#readme",
+  "license": "MIT",
+  "lint-staged": {
+    "*.js": [
+      "git add",
+      "npm run lint",
+      "prettier --single-quote --write"
+    ]
+  },
+  "main": "./index",
+  "maintainers": [
+    {
+      "name": "leo",
+      "email": "leo@zeit.co"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "name": "ms",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zeit/ms.git"
+  },
+  "scripts": {
+    "lint": "eslint lib/* bin/*",
+    "precommit": "lint-staged",
+    "test": "mocha tests.js"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/ms/readme.md b/input_devices/mag/node_modules/readline-ui/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days')  // 172800000
+ms('1d')      // 86400000
+ms('10h')     // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h')      // 7200000
+ms('1m')      // 60000
+ms('5s')      // 5000
+ms('1y')      // 31557600000
+ms('100')     // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000)             // "1m"
+ms(2 * 60000)         // "2m"
+ms(ms('10 hours'))    // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true })             // "1 minute"
+ms(2 * 60000, { long: true })         // "2 minutes"
+ms(ms('10 hours'), { long: true })    // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/string-width/index.js b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/index.js
new file mode 100644
index 00000000..bbc49d29
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/index.js
@@ -0,0 +1,36 @@
+'use strict';
+const stripAnsi = require('strip-ansi');
+const isFullwidthCodePoint = require('is-fullwidth-code-point');
+
+module.exports = str => {
+	if (typeof str !== 'string' || str.length === 0) {
+		return 0;
+	}
+
+	str = stripAnsi(str);
+
+	let width = 0;
+
+	for (let i = 0; i < str.length; i++) {
+		const code = str.codePointAt(i);
+
+		// Ignore control characters
+		if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) {
+			continue;
+		}
+
+		// Ignore combining characters
+		if (code >= 0x300 && code <= 0x36F) {
+			continue;
+		}
+
+		// Surrogates
+		if (code > 0xFFFF) {
+			i++;
+		}
+
+		width += isFullwidthCodePoint(code) ? 2 : 1;
+	}
+
+	return width;
+};
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/string-width/license b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/license
new file mode 100644
index 00000000..e7af2f77
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/readline-ui/node_modules/string-width/package.json b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/package.json
new file mode 100644
index 00000000..ca9b9ff5
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/package.json
@@ -0,0 +1,115 @@
+{
+  "_args": [
+    [
+      "string-width@^2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui"
+    ]
+  ],
+  "_from": "string-width@>=2.0.0 <3.0.0",
+  "_id": "string-width@2.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-ui/string-width",
+  "_nodeVersion": "8.0.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/string-width-2.1.1.tgz_1500376154382_0.7171604454051703"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "5.0.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "string-width",
+    "raw": "string-width@^2.0.0",
+    "rawSpec": "^2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-ui"
+  ],
+  "_resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+  "_shasum": "ab93f27a8dc13d28cac815c462143a6d9012ae9e",
+  "_shrinkwrap": null,
+  "_spec": "string-width@^2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/string-width/issues"
+  },
+  "dependencies": {
+    "is-fullwidth-code-point": "^2.0.0",
+    "strip-ansi": "^4.0.0"
+  },
+  "description": "Get the visual width of a string - the number of columns required to display it",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+    "shasum": "ab93f27a8dc13d28cac815c462143a6d9012ae9e",
+    "tarball": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz"
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "74d8d552b465692790c41169b123409669d41079",
+  "homepage": "https://github.com/sindresorhus/string-width#readme",
+  "keywords": [
+    "ansi",
+    "char",
+    "character",
+    "chinese",
+    "cjk",
+    "cli",
+    "codes",
+    "column",
+    "columns",
+    "command-line",
+    "console",
+    "escape",
+    "fixed-width",
+    "full",
+    "full-width",
+    "fullwidth",
+    "japanese",
+    "korean",
+    "str",
+    "string",
+    "terminal",
+    "unicode",
+    "visual",
+    "width"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "string-width",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/string-width.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "2.1.1"
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/string-width/readme.md b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/readme.md
new file mode 100644
index 00000000..df5b7199
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/string-width/readme.md
@@ -0,0 +1,42 @@
+# string-width [![Build Status](https://travis-ci.org/sindresorhus/string-width.svg?branch=master)](https://travis-ci.org/sindresorhus/string-width)
+
+> Get the visual width of a string - the number of columns required to display it
+
+Some Unicode characters are [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) and use double the normal width. [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) are stripped and doesn't affect the width.
+
+Useful to be able to measure the actual width of command-line output.
+
+
+## Install
+
+```
+$ npm install string-width
+```
+
+
+## Usage
+
+```js
+const stringWidth = require('string-width');
+
+stringWidth('古');
+//=> 2
+
+stringWidth('\u001b[1m古\u001b[22m');
+//=> 2
+
+stringWidth('a');
+//=> 1
+```
+
+
+## Related
+
+- [string-width-cli](https://github.com/sindresorhus/string-width-cli) - CLI for this module
+- [string-length](https://github.com/sindresorhus/string-length) - Get the real length of a string
+- [widest-line](https://github.com/sindresorhus/widest-line) - Get the visual width of the widest line in a string
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/index.js b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/index.js
new file mode 100644
index 00000000..96e0292c
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/index.js
@@ -0,0 +1,4 @@
+'use strict';
+const ansiRegex = require('ansi-regex');
+
+module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input;
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/license b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/license
new file mode 100644
index 00000000..e7af2f77
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/package.json b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/package.json
new file mode 100644
index 00000000..9b6e4abf
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/package.json
@@ -0,0 +1,119 @@
+{
+  "_args": [
+    [
+      "strip-ansi@^4.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/string-width"
+    ]
+  ],
+  "_from": "strip-ansi@>=4.0.0 <5.0.0",
+  "_id": "strip-ansi@4.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-ui/strip-ansi",
+  "_nodeVersion": "4.8.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/strip-ansi-4.0.0.tgz_1497986904730_0.4528853143565357"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.15.11",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "strip-ansi",
+    "raw": "strip-ansi@^4.0.0",
+    "rawSpec": "^4.0.0",
+    "scope": null,
+    "spec": ">=4.0.0 <5.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-ui/string-width"
+  ],
+  "_resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+  "_shasum": "a8479022eb1ac368a871389b635262c505ee368f",
+  "_shrinkwrap": null,
+  "_spec": "strip-ansi@^4.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-ui/node_modules/string-width",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/chalk/strip-ansi/issues"
+  },
+  "dependencies": {
+    "ansi-regex": "^3.0.0"
+  },
+  "description": "Strip ANSI escape codes",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a8479022eb1ac368a871389b635262c505ee368f",
+    "tarball": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=4"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "c299056a42b31d7a479d6a89b41318b2a2462cc7",
+  "homepage": "https://github.com/chalk/strip-ansi#readme",
+  "keywords": [
+    "256",
+    "ansi",
+    "color",
+    "colors",
+    "colour",
+    "command-line",
+    "console",
+    "escape",
+    "formatting",
+    "log",
+    "logging",
+    "remove",
+    "rgb",
+    "shell",
+    "string",
+    "strip",
+    "styles",
+    "terminal",
+    "text",
+    "trim",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "dthree",
+      "email": "threedeecee@gmail.com"
+    },
+    {
+      "name": "qix",
+      "email": "i.am.qix@gmail.com"
+    },
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "strip-ansi",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/chalk/strip-ansi.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "4.0.0"
+}
diff --git a/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/readme.md b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/readme.md
new file mode 100644
index 00000000..dc76f0cb
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/node_modules/strip-ansi/readme.md
@@ -0,0 +1,39 @@
+# strip-ansi [![Build Status](https://travis-ci.org/chalk/strip-ansi.svg?branch=master)](https://travis-ci.org/chalk/strip-ansi)
+
+> Strip [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
+
+
+## Install
+
+```
+$ npm install strip-ansi
+```
+
+
+## Usage
+
+```js
+const stripAnsi = require('strip-ansi');
+
+stripAnsi('\u001B[4mUnicorn\u001B[0m');
+//=> 'Unicorn'
+```
+
+
+## Related
+
+- [strip-ansi-cli](https://github.com/chalk/strip-ansi-cli) - CLI for this module
+- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
+- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
+- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
+
+
+## Maintainers
+
+- [Sindre Sorhus](https://github.com/sindresorhus)
+- [Josh Junon](https://github.com/qix-)
+
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/readline-ui/package.json b/input_devices/mag/node_modules/readline-ui/package.json
new file mode 100644
index 00000000..762c15ef
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-ui/package.json
@@ -0,0 +1,139 @@
+{
+  "_args": [
+    [
+      "readline-ui@^2.2.3",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "readline-ui@>=2.2.3 <3.0.0",
+  "_id": "readline-ui@2.2.3",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-ui",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/readline-ui-2.2.3.tgz_1496623142843_0.20142228854820132"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.0.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "readline-ui",
+    "raw": "readline-ui@^2.2.3",
+    "rawSpec": "^2.2.3",
+    "scope": null,
+    "spec": ">=2.2.3 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base"
+  ],
+  "_resolved": "https://registry.npmjs.org/readline-ui/-/readline-ui-2.2.3.tgz",
+  "_shasum": "9e873a7668bbd8ca8a5573ce810a6bafb70a5089",
+  "_shrinkwrap": null,
+  "_spec": "readline-ui@^2.2.3",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/readline-ui/issues"
+  },
+  "dependencies": {
+    "component-emitter": "^1.2.1",
+    "debug": "^2.6.8",
+    "readline-utils": "^2.2.1",
+    "string-width": "^2.0.0"
+  },
+  "description": "Create a readline interface with default settings to use in prompts.",
+  "devDependencies": {
+    "ansi-cyan": "^0.1.1",
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.4.2"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-ix7jz0PxqQqcIuq3yQTHv1TOhlD2IHO74aNO+lSuXsRYm1d+pdyup1yF3zKyLK1wWZrVNGjkzw5tUegO2IDy+A==",
+    "shasum": "9e873a7668bbd8ca8a5573ce810a6bafb70a5089",
+    "tarball": "https://registry.npmjs.org/readline-ui/-/readline-ui-2.2.3.tgz"
+  },
+  "engines": {
+    "node": ">=4.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "f87116b2c95657c7c2bd133f28368aafe897b2ff",
+  "homepage": "https://github.com/enquirer/readline-ui",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "checkbox",
+    "choice",
+    "cli",
+    "command",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "interface",
+    "list",
+    "menu",
+    "password",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "readline-ui",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/readline-ui.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "enquirer",
+        "prompt-choices",
+        "prompt-question",
+        "readline-utils"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.2.3"
+}
diff --git a/input_devices/mag/node_modules/readline-utils/LICENSE b/input_devices/mag/node_modules/readline-utils/LICENSE
new file mode 100644
index 00000000..ece74b5e
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readline-utils/README.md b/input_devices/mag/node_modules/readline-utils/README.md
new file mode 100644
index 00000000..bb04f9f7
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/README.md
@@ -0,0 +1,359 @@
+# readline-utils [![NPM version](https://img.shields.io/npm/v/readline-utils.svg?style=flat)](https://www.npmjs.com/package/readline-utils) [![NPM monthly downloads](https://img.shields.io/npm/dm/readline-utils.svg?style=flat)](https://npmjs.org/package/readline-utils) [![NPM total downloads](https://img.shields.io/npm/dt/readline-utils.svg?style=flat)](https://npmjs.org/package/readline-utils) [![Linux Build Status](https://img.shields.io/travis/enquirer/readline-utils.svg?style=flat&label=Travis)](https://travis-ci.org/enquirer/readline-utils) [![Windows Build Status](https://img.shields.io/appveyor/ci/enquirer/readline-utils.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/enquirer/readline-utils)
+
+> Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save readline-utils
+```
+
+## Usage
+
+```js
+var utils = require('readline-utils');
+```
+
+## API
+
+### [.createInterface](index.js#L31)
+
+Create a readline interface with the given `options`.
+
+**Params**
+
+* `options` **{Object}**
+
+### [.up](index.js#L47)
+
+Move cursor up by `n` lines.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `n` **{Number}**: Lines up to move. Default is `1`.
+
+### [.down](index.js#L60)
+
+Move cursor down by `n` lines.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `n` **{Number}**: Lines down to move. Default is `1`.
+
+### [.left](index.js#L73)
+
+Move cursor left by `n` colums.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `n` **{Number}**: Characters to move left. Default is `1`.
+
+### [.right](index.js#L86)
+
+Move cursor right by `n` colums.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `n` **{Number}**: Characters to move right. Default is `1`.
+
+### [.move](index.js#L105)
+
+Move cursor up, down, left or right by `1` line.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+
+**Example**
+
+```js
+var utils = require('readline-utils');
+var rl = utils.createInterface();
+rl.input.on('keypress', function(str, key) {
+  utils.move(rl, key);
+});
+```
+
+### [.auto](index.js#L125)
+
+Callback function for the `keypress` event, to automatically move cursor up, down, left or right by `1` line.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+
+**Example**
+
+```js
+var utils = require('readline-utils');
+var rl = utils.createInterface();
+rl.input.on('keypress', utils.auto(rl));
+```
+
+### [.clearAfter](index.js#L151)
+
+Clear `n` lines after the cursor.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `n` **{Number}**: Number of lines to clear
+
+### [.clearScreen](index.js#L164)
+
+Clear the terminal.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `n` **{Number}**: Number of lines to clear
+
+### [.lastLine](index.js#L177)
+
+Get the last line from the given `str`
+
+**Params**
+
+* `str` **{String}**
+* `returns` **{String}**
+
+### [.height](index.js#L189)
+
+Get the height (rows) of the given `str`
+
+**Params**
+
+* `str` **{String}**
+* `returns` **{Number}**
+
+### [.hideCursor](index.js#L203)
+
+Hide the cursor so it doesn't show during a prompt. This is
+useful for multiple-choice or list prompts, or any prompt
+where the user will not be entering input.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `returns` **{Object}**: readline-utils object for chaining
+
+### [.showCursor](index.js#L216)
+
+Show the cursor.
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `returns` **{Object}**: readline-utils object for chaining
+
+### [.close](index.js#L229)
+
+Close the interface, remove event listeners, and restore/unmute prompt functionality
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `returns` **{Object}**: readline-utils object for chaining
+
+### [.forceClose](index.js#L250)
+
+Close the interface when the keypress is `^C`
+
+**Params**
+
+* `rl` **{Readline}**: Readline interface
+* `returns` **{Object}**: readline-utils object for chaining
+
+### [.eraseLines](index.js#L266)
+
+Erase `n` lines
+
+**Params**
+
+* `n` **{Number}**
+* `returns` **{String}**: Returns the unicode to erase lines
+
+**Example**
+
+```js
+utils.eraseLines(3);
+```
+
+### [.clearTrailingLines](index.js#L289)
+
+Remove lines from the bottom of the terminal.
+
+**Params**
+
+* `rl` **{Number}**: Readline interface
+* `lines` **{Number}**: Number of lines to remove
+* `height` **{Number}**: Content height
+* `returns` **{Object}**: Returns the readline-utils object for chaining
+
+### [.cursorPosition](index.js#L307)
+
+Remember the cursor position
+
+* `returns` **{Object}**: readline-utils object
+
+### [.restoreCursorPos](index.js#L317)
+
+Restore the cursor position to where it has been previously stored.
+
+* `returns` **{Object}**: readline-utils object
+
+### [.cliWidth](index.js#L333)
+
+Get the width of the terminal
+
+* `returns` **{Number}**: Returns the number of columns.
+
+### [.breakLines](index.js#L348)
+
+Break lines longer than the cli width so we can normalize the
+natural line returns behavior accross terminals. (I don't see how
+this can work consistently. It seems brittle and will probably be replaced
+with https://github.com/jonschlinkert/word-wrap)
+
+**Params**
+
+* `lines` **{Array}**: Array of lines
+* `width` **{Number}**: Terminal width
+
+### [.forceLineReturn](index.js#L373)
+
+Joins the lines returned from [.breakLines](#breakLines).
+
+**Params**
+
+* `lines` **{Array|String}**: String or array of lines.
+* `width` **{Number}**: Terminal width
+* `returns` **{String}**
+
+### [.normalizeLF](index.js#L392)
+
+Ensure the given `str` ends in a newline.
+
+**Params**
+
+* `str` **{String}**: The input string
+* `returns` **{String}**
+
+**Example**
+
+```js
+console.log(utils.normalizeLF('foo'));
+//=> 'foo\n'
+```
+
+### [.keypress](index.js#L437)
+
+This module offers the internal "keypress" functionality from node-core's `readline` module, for your own programs and modules to use.
+
+The `keypress` function accepts a readable Stream instance and makes it
+emit "keypress" events.
+Usage:
+
+**Params**
+
+* **{Stream}**: stream
+
+**Example**
+
+``` js
+require('keypress')(process.stdin);
+
+process.stdin.on('keypress', function(ch, key) {
+  console.log(ch, key);
+  if (key.ctrl && key.name === 'c') {
+    process.stdin.pause();
+  }
+});
+proces.stdin.resume();
+```
+
+### [.enableMouse](index.js#L475)
+
+Enables "mousepress" events on the _input_ stream. Note
+that `stream` must be an _output_ stream (i.e. a Writable
+Stream instance), usually `process.stdout`.
+
+**Params**
+
+* **{Stream}**: stream writable stream instance
+
+### [.disableMouse](index.js#L488)
+
+Disables "mousepress" events from being sent to the _input_
+
+stream. Note that `stream` must be an _output_ stream (i.e.
+a Writable Stream instance), usually `process.stdout`.
+
+**Params**
+
+* **{Stream}**: stream writable stream instance
+
+## Attribution
+
+Some of this code was initially borrowed from [Inquirer][].
+
+## About
+
+### Related projects
+
+* [choices-separator](https://www.npmjs.com/package/choices-separator): Separator for choices arrays in prompts. Based on the Separator from inquirer. | [homepage](https://github.com/enquirer/choices-separator "Separator for choices arrays in prompts. Based on the Separator from inquirer.")
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. Much faster and lighter alternative to Inquirer, with all… [more](https://github.com/enquirer/enquirer) | [homepage](https://github.com/enquirer/enquirer "Intuitive, plugin-based prompt system for node.js. Much faster and lighter alternative to Inquirer, with all the same prompt types and more, but without the bloat.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 41 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 7 | [doowb](https://github.com/doowb) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 21, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readline-utils/index.js b/input_devices/mag/node_modules/readline-utils/index.js
new file mode 100644
index 00000000..fbcccfed
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/index.js
@@ -0,0 +1,814 @@
+'use strict';
+
+var koalas = require('koalas');
+var isNum = require('is-number');
+var size = require('window-size');
+var readline = require('readline');
+var isBuffer = require('is-buffer');
+var flatten = require('arr-flatten');
+var extend = require('extend-shallow');
+var isWindows = require('is-windows');
+var MuteStream = require('mute-stream');
+var stripColor = require('strip-color');
+var sizeUtils = require('window-size/utils');
+var utils = module.exports;
+
+/**
+ * Create default options
+ */
+
+utils.createOptions = function(options) {
+  var opts = extend({ terminal: true }, options);
+  opts.output = opts.output || process.stdout;
+  opts.input = opts.input || process.stdin;
+  return opts;
+};
+
+/**
+ * Create a readline interface with the given `options`.
+ * @param {Object} `options`
+ * @api public
+ */
+
+utils.createInterface = function(options) {
+  var opts = utils.createOptions(options);
+  var ms = new MuteStream();
+  ms.pipe(opts.output);
+  opts.output = ms;
+  return readline.createInterface(opts);
+};
+
+/**
+ * Move cursor up by `n` lines.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @param {Number} `n` Lines up to move. Default is `1`.
+ * @api public
+ */
+
+utils.up = function(rl, n) {
+  readline.moveCursor(rl.output, 0, -(n || 1));
+  return this;
+};
+
+/**
+ * Move cursor down by `n` lines.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @param {Number} `n` Lines down to move. Default is `1`.
+ * @api public
+ */
+
+utils.down = function(rl, n) {
+  readline.moveCursor(rl.output, 0, n || 1);
+  return this;
+};
+
+/**
+ * Move cursor left by `n` colums.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @param {Number} `n` Characters to move left. Default is `1`.
+ * @api public
+ */
+
+utils.left = function(rl, n) {
+  readline.moveCursor(rl.output, -(n || 1));
+  return this;
+};
+
+/**
+ * Move cursor right by `n` colums.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @param {Number} `n` Characters to move right. Default is `1`.
+ * @api public
+ */
+
+utils.right = function(rl, n) {
+  readline.moveCursor(rl.output, n || 1);
+  return this;
+};
+
+/**
+ * Move cursor up, down, left or right by `1` line.
+ *
+ * ```js
+ * var utils = require('readline-utils');
+ * var rl = utils.createInterface();
+ * rl.input.on('keypress', function(str, key) {
+ *   utils.move(rl, key);
+ * });
+ * ```
+ * @param {Readline} `rl` Readline interface
+ * @api public
+ */
+
+utils.move = function(rl, key, n) {
+  if (key && exports[key.name]) {
+    exports[key.name](rl, n);
+  }
+  return this;
+};
+
+/**
+ * Callback function for the `keypress` event, to automatically move cursor
+ * up, down, left or right by `1` line.
+ *
+ * ```js
+ * var utils = require('readline-utils');
+ * var rl = utils.createInterface();
+ * rl.input.on('keypress', utils.auto(rl));
+ * ```
+ * @param {Readline} `rl` Readline interface
+ * @api public
+ */
+
+utils.auto = function(rl) {
+  return function(s, key) {
+    utils.move(rl, key);
+  };
+};
+
+/**
+ * Clear `n` lines.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @param {Number} `n` Number of lines to clear
+ */
+
+utils.clearLine = function(rl, n) {
+  rl.output.write(utils.eraseLines(n));
+  return this;
+};
+
+/**
+ * Clear `n` lines after the cursor.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @param {Number} `n` Number of lines to clear
+ * @api public
+ */
+
+utils.clearAfter = function(rl, n) {
+  utils.clearLine(rl, n || 1);
+  return this;
+};
+
+/**
+ * Clear the terminal.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @param {Number} `n` Number of lines to clear
+ * @api public
+ */
+
+utils.clearScreen = function(rl) {
+  rl.write(null, { ctrl: true, name: 'l' });
+  return this;
+};
+
+/**
+ * Get the last line from the given `str`
+ *
+ * @param {String} `str`
+ * @return {String}
+ * @api public
+ */
+
+utils.lastLine = function(str) {
+  return last(str.split('\n'));
+};
+
+/**
+ * Get the height (rows) of the given `str`
+ *
+ * @param {String} `str`
+ * @return {Number}
+ * @api public
+ */
+
+utils.height = function(str) {
+  return str.split('\n').length;
+};
+
+/**
+ * Hide the cursor so it doesn't show during a prompt. This is
+ * useful for multiple-choice or list prompts, or any prompt
+ * where the user will not be entering input.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @return {Object} readline-utils object for chaining
+ * @api public
+ */
+
+utils.hideCursor = utils.cursorHide = function(rl) {
+  rl.output.write('\x1B[?25l');
+  return this;
+};
+
+/**
+ * Show the cursor.
+ *
+ * @param {Readline} `rl` Readline interface
+ * @return {Object} readline-utils object for chaining
+ * @api public
+ */
+
+utils.showCursor = utils.cursorShow = function(rl) {
+  rl.output.write('\x1B[?25h');
+  return this;
+};
+
+/**
+ * Close the interface, remove event listeners, and restore/unmute prompt functionality
+ *
+ * @param {Readline} `rl` Readline interface
+ * @return {Object} readline-utils object for chaining
+ * @api public
+ */
+
+utils.close = function(rl, fn) {
+  fn = fn || utils.forceClose.bind(exports, rl);
+  process.removeListener('exit', fn);
+  rl.removeListener('SIGINT', fn);
+  if (typeof rl.output.unmute === 'function') {
+    rl.output.unmute();
+    rl.output.end();
+  }
+  rl.pause();
+  rl.close();
+  return this;
+};
+
+/**
+ * Close the interface when the keypress is `^C`
+ *
+ * @param {Readline} `rl` Readline interface
+ * @return {Object} readline-utils object for chaining
+ * @api public
+ */
+
+utils.forceClose = function(rl) {
+  utils.close(rl);
+  return this;
+};
+
+/**
+ * Erase `n` lines
+ *
+ * ```js
+ * utils.eraseLines(3);
+ * ```
+ * @param {Number} `n`
+ * @return {String} Returns the unicode to erase lines
+ * @api public
+ */
+
+utils.eraseLines = function(n) {
+  var num = toNumber(n);
+  var lines = '';
+  var i = -1;
+
+  while (++i < num) {
+    lines += '\u001b[1000D\u001b[K';
+    if (i < num - 1) {
+      lines += '\u001b[1A';
+    }
+  }
+  return lines;
+};
+
+/**
+ * Remove lines from the bottom of the terminal.
+ * @param  {Number} `rl` Readline interface
+ * @param  {Number} `lines` Number of lines to remove
+ * @param  {Number} `height` Content height
+ * @return {Object} Returns the readline-utils object for chaining
+ * @api public
+ */
+
+utils.clearTrailingLines = function(rl, lines, height) {
+  if (!isNumber(lines)) lines = 0;
+  var len = height + lines;
+
+  while (len--) {
+    readline.moveCursor(rl.output, -utils.cliWidth(80), 0);
+    readline.clearLine(rl.output, 0);
+    if (len) readline.moveCursor(rl.output, 0, -1);
+  }
+  return this;
+};
+
+/**
+ * Remember the cursor position
+ * @return {Object} readline-utils object
+ * @api public
+ */
+
+utils.cursorPosition = function(rl) {
+  return rl._getCursorPos();
+};
+
+/**
+ * Restore the cursor position to where it has been previously stored.
+ * @return {Object} readline-utils object
+ * @api public
+ */
+
+utils.restoreCursorPos = function(rl, cursorPos) {
+  if (!cursorPos) return;
+  var line = rl._prompt + rl.line;
+  readline.moveCursor(rl.output, -line.length, 0);
+  readline.moveCursor(rl.output, cursorPos.cols, 0);
+  cursorPos = null;
+  return this;
+};
+
+/**
+ * Get the width of the terminal
+ *
+ * @param  {Number} `fallback` A fallback width to use if the actual width is not found.
+ * @return {Number} Returns the number of columns.
+ * @api public
+ */
+
+utils.cliWidth = function(fallback) {
+  var windows = isWindows();
+  var modifier = windows ? 1 : 0;
+  size = size || (windows ? sizeUtils.win() : sizeUtils.tput());
+  return koalas(size && size.width, fallback, modifier) - modifier;
+};
+
+/**
+ * Break lines longer than the cli width so we can normalize the
+ * natural line returns behavior accross terminals. (I don't see how
+ * this can work consistently. It seems brittle and will probably be replaced
+ * with https://github.com/jonschlinkert/word-wrap)
+ *
+ * @param {Array} `lines` Array of lines
+ * @param {Number} `width` Terminal width
+ * @api public
+ */
+
+utils.breakLines = function(lines, width) {
+  var quantifier = '';
+  if (width > 1) {
+    quantifier = '{1,' + width + '}';
+  }
+
+  var regex = new RegExp('(?:(?:\\033[[0-9;]*m)*.?)' + quantifier, 'g');
+  return lines.map(function(line) {
+    var matches = line.match(regex);
+    if (!matches) return '';
+    // last match is always empty
+    matches.pop();
+    return matches || '';
+  });
+};
+
+/**
+ * Joins the lines returned from [.breakLines](#breakLines).
+ *
+ * @param {Array|String} `lines` String or array of lines.
+ * @param {Number} `width` Terminal width
+ * @return {String}
+ * @api public
+ */
+
+utils.forceLineReturn = function(lines, width) {
+  if (typeof lines === 'string') {
+    lines = utils.breakLines(lines.split('\n'), width);
+  }
+  return flatten(lines).join('\n');
+};
+
+/**
+ * Ensure the given `str` ends in a newline.
+ *
+ * ```js
+ * console.log(utils.normalizeLF('foo'));
+ * //=> 'foo\n'
+ * ```
+ * @param  {String} `str` The input string
+ * @return {String}
+ * @api public
+ */
+
+utils.normalizeLF = function(str) {
+  if (str.slice(-1) !== '\n') {
+    str += '\n';
+  }
+  return str;
+};
+
+/**
+ * Strip ansi styles from the given string.
+ */
+
+utils.unstyle = function(str) {
+  return stripColor(str);
+};
+
+/**
+ * The following code is based on code from the node.js core
+ * readline module and https://github.com/TooTallNate/keypress.
+ */
+
+/**
+ * This module offers the internal "keypress" functionality from node-core's
+ * `readline` module, for your own programs and modules to use.
+ *
+ * The `keypress` function accepts a readable Stream instance and makes it
+ * emit "keypress" events.
+ *
+ * Usage:
+ *
+ * ``` js
+ * require('keypress')(process.stdin);
+ *
+ * process.stdin.on('keypress', function(ch, key) {
+ *   console.log(ch, key);
+ *   if (key.ctrl && key.name === 'c') {
+ *     process.stdin.pause();
+ *   }
+ * });
+ * proces.stdin.resume();
+ * ```
+ *
+ * @param {Stream} stream
+ * @api public
+ */
+
+utils.keypress = function(stream) {
+  var StringDecoder = require('string_decoder').StringDecoder; // lazy load
+  stream._keypressDecoder = new StringDecoder('utf8');
+
+  function onData(b) {
+    if (stream.listenerCount('keypress') > 0) {
+      var r = stream._keypressDecoder.write(b);
+      if (r) utils.emitKeypress(stream, r);
+    } else {
+      // Nobody's watching anyway
+      stream.removeListener('data', onData);
+      stream.on('newListener', onNewListener);
+    }
+  }
+
+  function onNewListener(event) {
+    if (event === 'keypress') {
+      stream.on('data', onData);
+      stream.removeListener('newListener', onNewListener);
+    }
+  }
+
+  if (stream.listenerCount('keypress') > 0) {
+    stream.on('data', onData);
+  } else {
+    stream.on('newListener', onNewListener);
+  }
+};
+
+/**
+ * Enables "mousepress" events on the *input* stream. Note
+ * that `stream` must be an *output* stream (i.e. a Writable
+ * Stream instance), usually `process.stdout`.
+ *
+ * @param {Stream} stream writable stream instance
+ * @api public
+ */
+
+utils.enableMouse = function(stream) {
+  stream.write('\x1b[?1000h');
+};
+
+/**
+ * Disables "mousepress" events from being sent to the *input*
+ * stream. Note that `stream` must be an *output* stream (i.e.
+ * a Writable Stream instance), usually `process.stdout`.
+ *
+ * @param {Stream} stream writable stream instance
+ * @api public
+ */
+
+utils.disableMouse = function(stream) {
+  stream.write('\x1b[?1000l');
+};
+
+///////////////////////////////////////////////////////////////////////
+// Below this function is code from node-core's `readline.js` module //
+///////////////////////////////////////////////////////////////////////
+
+/*
+  Some patterns seen in terminal key escape codes, derived from combos seen
+  at http://www.midnight-commander.org/browser/lib/tty/key.c
+
+  ESC letter
+  ESC [ letter
+  ESC [ modifier letter
+  ESC [ 1 ; modifier letter
+  ESC [ num char
+  ESC [ num ; modifier char
+  ESC O letter
+  ESC O modifier letter
+  ESC O 1 ; modifier letter
+  ESC N letter
+  ESC [ [ num ; modifier char
+  ESC [ [ 1 ; modifier letter
+  ESC ESC [ num char
+  ESC ESC O letter
+
+  - char is usually ~ but $ and ^ also happen with rxvt
+  - modifier is 1 +
+                (shift     * 1) +
+                (left_alt  * 2) +
+                (ctrl      * 4) +
+                (right_alt * 8)
+  - two leading ESCs apparently mean the same as one leading ESC
+*/
+
+utils.normalize = function(s, key) {
+  var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
+  var functionKeyCodeRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
+
+  var events = [];
+  var parts;
+  var ch = s;
+  key = extend({
+    name: undefined,
+    ctrl: false,
+    meta: false,
+    shift: false,
+    value: s
+  }, key);
+
+  if (s === null && key.name === 'down') {
+    key.ctrl = true;
+    s = 'n';
+  }
+
+  if (s === null && key.name === 'up') {
+    key.ctrl = true;
+    s = 'p';
+  }
+
+  if (isBuffer(s)) {
+    if (s[0] > 127 && s[1] === undefined) {
+      s[0] -= 128;
+      s = '\x1b' + s.toString();
+    } else {
+      s = s.toString();
+    }
+  }
+
+  if (!s && key && key.sequence) {
+    s = key.sequence;
+  }
+
+  if (typeof s === 'number') {
+    s = String(s);
+    key.value = Number(s);
+    key.name = 'number';
+  }
+
+  key.sequence = String(s);
+
+  if (s === '\r') {
+    // carriage return
+    key.name = 'return';
+  } else if (s === '\n') {
+    // enter, should have been called linefeed
+    key.name = 'enter';
+  } else if (s === '\t') {
+    // tab
+    key.name = 'tab';
+  } else if (s === '\b' || s === '\x7f' || s === '\x1b\x7f' || s === '\x1b\b') {
+    // backspace or ctrl+h
+    key.name = 'backspace';
+    key.meta = s.charAt(0) === '\x1b';
+  } else if (s === '\x1b' || s === '\x1b\x1b') {
+    // escape key
+    key.name = 'escape';
+    key.meta = s.length === 2;
+  } else if (s === ' ' || s === '\x1b ') {
+    key.name = 'space';
+    key.meta = s.length === 2;
+  } else if (s <= '\x1a') {
+    // ctrl+letter
+    key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
+    key.ctrl = true;
+  } else if (s.length === 1 && s >= '0' && s <= '9') {
+    // number
+    key.value = Number(s);
+    key.name = 'number';
+  } else if (s.length === 1 && '!"#$%&()*+:<>?@^_{|}~'.indexOf(s) !== -1) {
+    // shift
+    key.name = s;
+    key.shift = true;
+  } else if ('.,-\\/;=[]`\''.indexOf(s) !== -1) {
+    key.name = s;
+  } else if (s.length === 1 && s >= 'a' && s <= 'z') {
+    // lowercase letter
+    key.name = s;
+  } else if (s.length === 1 && s >= 'A' && s <= 'Z') {
+    // shift+letter
+    key.name = s.toLowerCase();
+    key.shift = true;
+  } else if ((parts = metaKeyCodeRe.exec(s))) {
+    // meta+character key
+    key.name = parts[1].toLowerCase();
+    key.meta = true;
+    key.shift = /^[A-Z]$/.test(parts[1]);
+  } else if ((parts = functionKeyCodeRe.exec(s))) {
+    // ansi escape sequence
+    // reassemble the key code leaving out leading \x1b's,
+    // the modifier key bitflag and any meaningless "1;" sequence
+    var code = (parts[1] || '')
+      + (parts[2] || '')
+      + (parts[4] || '')
+      + (parts[6] || '');
+
+    var modifier = (parts[3] || parts[5] || 1) - 1;
+
+    // Parse the key modifier
+    key.ctrl = !!(modifier & 4);
+    key.meta = !!(modifier & 10);
+    key.shift = !!(modifier & 1);
+    key.code = code;
+
+    // Parse the key itself
+    switch (code) {
+      /* xterm/gnome ESC O letter */
+      case 'OP': key.name = 'f1'; break;
+      case 'OQ': key.name = 'f2'; break;
+      case 'OR': key.name = 'f3'; break;
+      case 'OS': key.name = 'f4'; break;
+      /* xterm/rxvt ESC [ number ~ */
+      case '[11~': key.name = 'f1'; break;
+      case '[12~': key.name = 'f2'; break;
+      case '[13~': key.name = 'f3'; break;
+      case '[14~': key.name = 'f4'; break;
+      /* from Cygwin and used in libuv */
+      case '[[A': key.name = 'f1'; break;
+      case '[[B': key.name = 'f2'; break;
+      case '[[C': key.name = 'f3'; break;
+      case '[[D': key.name = 'f4'; break;
+      case '[[E': key.name = 'f5'; break;
+      /* common */
+      case '[15~': key.name = 'f5'; break;
+      case '[17~': key.name = 'f6'; break;
+      case '[18~': key.name = 'f7'; break;
+      case '[19~': key.name = 'f8'; break;
+      case '[20~': key.name = 'f9'; break;
+      case '[21~': key.name = 'f10'; break;
+      case '[23~': key.name = 'f11'; break;
+      case '[24~': key.name = 'f12'; break;
+      /* xterm ESC [ letter */
+      case '[A': key.name = 'up'; break;
+      case '[B': key.name = 'down'; break;
+      case '[C': key.name = 'right'; break;
+      case '[D': key.name = 'left'; break;
+      case '[E': key.name = 'clear'; break;
+      case '[F': key.name = 'end'; break;
+      case '[H': key.name = 'home'; break;
+      /* xterm/gnome ESC O letter */
+      case 'OA': key.name = 'up'; break;
+      case 'OB': key.name = 'down'; break;
+      case 'OC': key.name = 'right'; break;
+      case 'OD': key.name = 'left'; break;
+      case 'OE': key.name = 'clear'; break;
+      case 'OF': key.name = 'end'; break;
+      case 'OH': key.name = 'home'; break;
+      /* xterm/rxvt ESC [ number ~ */
+      case '[1~': key.name = 'home'; break;
+      case '[2~': key.name = 'insert'; break;
+      case '[3~': key.name = 'delete'; break;
+      case '[4~': key.name = 'end'; break;
+      case '[5~': key.name = 'pageup'; break;
+      case '[6~': key.name = 'pagedown'; break;
+      /* putty */
+      case '[[5~': key.name = 'pageup'; break;
+      case '[[6~': key.name = 'pagedown'; break;
+      /* rxvt */
+      case '[7~': key.name = 'home'; break;
+      case '[8~': key.name = 'end'; break;
+      /* rxvt keys with modifiers */
+      case '[a': key.name = 'up'; key.shift = true; break;
+      case '[b': key.name = 'down'; key.shift = true; break;
+      case '[c': key.name = 'right'; key.shift = true; break;
+      case '[d': key.name = 'left'; key.shift = true; break;
+      case '[e': key.name = 'clear'; key.shift = true; break;
+
+      case '[2$': key.name = 'insert'; key.shift = true; break;
+      case '[3$': key.name = 'delete'; key.shift = true; break;
+      case '[5$': key.name = 'pageup'; key.shift = true; break;
+      case '[6$': key.name = 'pagedown'; key.shift = true; break;
+      case '[7$': key.name = 'home'; key.shift = true; break;
+      case '[8$': key.name = 'end'; key.shift = true; break;
+
+      case 'Oa': key.name = 'up'; key.ctrl = true; break;
+      case 'Ob': key.name = 'down'; key.ctrl = true; break;
+      case 'Oc': key.name = 'right'; key.ctrl = true; break;
+      case 'Od': key.name = 'left'; key.ctrl = true; break;
+      case 'Oe': key.name = 'clear'; key.ctrl = true; break;
+
+      case '[2^': key.name = 'insert'; key.ctrl = true; break;
+      case '[3^': key.name = 'delete'; key.ctrl = true; break;
+      case '[5^': key.name = 'pageup'; key.ctrl = true; break;
+      case '[6^': key.name = 'pagedown'; key.ctrl = true; break;
+      case '[7^': key.name = 'home'; key.ctrl = true; break;
+      case '[8^': key.name = 'end'; key.ctrl = true; break;
+      /* misc. */
+      case '[Z': key.name = 'tab'; key.shift = true; break;
+      default:
+        key.name = 'undefined';
+        break;
+    }
+  } else if (s.length > 1 && s[0] !== '\x1b') {
+    // Got a longer-than-one string of characters.
+    // Probably a paste, since it wasn't a control sequence.
+    for (var i = 0; i < s.length; i++) {
+      events = events.concat(utils.normalize(s[i]));
+    }
+  }
+
+  // XXX: this "mouse" parsing code is NOT part of the node-core standard
+  // `readline.js` module, and is a `keypress` module non-standard extension.
+  if (key.code === '[M') {
+    key.name = 'mouse';
+    s = key.sequence;
+    var b = s.charCodeAt(3);
+    key.x = s.charCodeAt(4) - parseInt('040', 8);
+    key.y = s.charCodeAt(5) - parseInt('040', 8);
+
+    key.scroll = 0;
+
+    key.ctrl = !!((1 << 4) & b);
+    key.meta = !!((1 << 3) & b);
+    key.shift = !!((1 << 2) & b);
+
+    key.release = (3 & b) === 3;
+
+    if ((1 << 6) & b) {
+      // scroll
+      key.scroll = 1 & b ? 1 : -1;
+    }
+
+    if (!key.release && !key.scroll) {
+      key.button = b & 3;
+    }
+  }
+
+  if (key.name === 'p' && key.ctrl && !key.shift && !key.meta) {
+    key.name = 'up';
+  }
+
+  if (key.name === 'n' && key.ctrl && !key.shift && !key.meta) {
+    key.name = 'down';
+  }
+
+  // Don't emit a key if no name was found
+  if (!key.name) {
+    return events;
+  }
+
+  if (s.length === 1) {
+    ch = s;
+  }
+
+  events.push({ch: ch, key: key});
+  return events;
+};
+
+utils.emitKeypress = function(emitter, s, key) {
+  var events = utils.normalize(s, key);
+  for (var i = 0; i < events.length; i++) {
+    var event = events[i];
+    if (event.key && event.key.name === 'mouse') {
+      emitter.emit('mousepress', event.key);
+    } else {
+      emitter.emit('keypress', event.key.name, event.key);
+      emitter.emit(event.key.name, event.key);
+    }
+  }
+};
+
+utils.key = {
+  up: '\u001b[A',
+  down: '\u001b[B',
+  left: '\u001b[D',
+  right: '\u001b[C',
+  ctrlc: '\u0003'
+};
+
+function last(arr) {
+  return arr[arr.length - 1];
+}
+
+function isNumber(n) {
+  return isNum(n) && String(n).trim() !== '';
+}
+
+function toNumber(n) {
+  return isNumber(n) ? Number(n) : 1;
+}
diff --git a/input_devices/mag/node_modules/readline-utils/node_modules/is-number/LICENSE b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/LICENSE
new file mode 100644
index 00000000..842218cf
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2016, Jon Schlinkert
+
+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/input_devices/mag/node_modules/readline-utils/node_modules/is-number/README.md b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/README.md
new file mode 100644
index 00000000..281165dc
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/README.md
@@ -0,0 +1,115 @@
+# is-number [![NPM version](https://img.shields.io/npm/v/is-number.svg?style=flat)](https://www.npmjs.com/package/is-number) [![NPM downloads](https://img.shields.io/npm/dm/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-number.svg?style=flat)](https://travis-ci.org/jonschlinkert/is-number)
+
+> Returns true if the value is a number. comprehensive tests.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-number
+```
+
+## Usage
+
+To understand some of the rationale behind the decisions made in this library (and to learn about some oddities of number evaluation in JavaScript), [see this gist](https://gist.github.com/jonschlinkert/e30c70c713da325d0e81).
+
+```js
+var isNumber = require('is-number');
+```
+
+### true
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber(5e3)      //=> 'true'
+isNumber(0xff)     //=> 'true'
+isNumber(-1.1)     //=> 'true'
+isNumber(0)        //=> 'true'
+isNumber(1)        //=> 'true'
+isNumber(1.1)      //=> 'true'
+isNumber(10)       //=> 'true'
+isNumber(10.10)    //=> 'true'
+isNumber(100)      //=> 'true'
+isNumber('-1.1')   //=> 'true'
+isNumber('0')      //=> 'true'
+isNumber('012')    //=> 'true'
+isNumber('0xff')   //=> 'true'
+isNumber('1')      //=> 'true'
+isNumber('1.1')    //=> 'true'
+isNumber('10')     //=> 'true'
+isNumber('10.10')  //=> 'true'
+isNumber('100')    //=> 'true'
+isNumber('5e3')    //=> 'true'
+isNumber(parseInt('012'))   //=> 'true'
+isNumber(parseFloat('012')) //=> 'true'
+```
+
+### False
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber('foo')             //=> 'false'
+isNumber([1])               //=> 'false'
+isNumber([])                //=> 'false'
+isNumber(function () {})    //=> 'false'
+isNumber(Infinity)          //=> 'false'
+isNumber(NaN)               //=> 'false'
+isNumber(new Array('abc'))  //=> 'false'
+isNumber(new Array(2))      //=> 'false'
+isNumber(new Buffer('abc')) //=> 'false'
+isNumber(null)              //=> 'false'
+isNumber(undefined)         //=> 'false'
+isNumber({abc: 'abc'})      //=> 'false'
+```
+
+## About
+
+### Related projects
+
+* [even](https://www.npmjs.com/package/even): Get the even numbered items from an array. | [homepage](https://github.com/jonschlinkert/even "Get the even numbered items from an array.")
+* [is-even](https://www.npmjs.com/package/is-even): Return true if the given number is even. | [homepage](https://github.com/jonschlinkert/is-even "Return true if the given number is even.")
+* [is-odd](https://www.npmjs.com/package/is-odd): Returns true if the given number is odd. | [homepage](https://github.com/jonschlinkert/is-odd "Returns true if the given number is odd.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+* [odd](https://www.npmjs.com/package/odd): Get the odd numbered items from an array. | [homepage](https://github.com/jonschlinkert/odd "Get the odd numbered items from an array.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
+
+To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
+
+```sh
+$ npm install -g verb verb-generate-readme && verb
+```
+
+### Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm install -d && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT license](https://github.com/jonschlinkert/is-number/blob/master/LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.30, on September 10, 2016._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/readline-utils/node_modules/is-number/index.js b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/index.js
new file mode 100644
index 00000000..7a2a45be
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/index.js
@@ -0,0 +1,22 @@
+/*!
+ * is-number <https://github.com/jonschlinkert/is-number>
+ *
+ * Copyright (c) 2014-2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+module.exports = function isNumber(num) {
+  var type = typeOf(num);
+
+  if (type === 'string') {
+    if (!num.trim()) return false;
+  } else if (type !== 'number') {
+    return false;
+  }
+
+  return (num - num + 1) >= 0;
+};
diff --git a/input_devices/mag/node_modules/readline-utils/node_modules/is-number/package.json b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/package.json
new file mode 100644
index 00000000..d683c56f
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/node_modules/is-number/package.json
@@ -0,0 +1,152 @@
+{
+  "_args": [
+    [
+      "is-number@^3.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-utils"
+    ]
+  ],
+  "_from": "is-number@>=3.0.0 <4.0.0",
+  "_id": "is-number@3.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-utils/is-number",
+  "_nodeVersion": "6.3.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/is-number-3.0.0.tgz_1473555089490_0.21388969756662846"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.10.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-number",
+    "raw": "is-number@^3.0.0",
+    "rawSpec": "^3.0.0",
+    "scope": null,
+    "spec": ">=3.0.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+  "_shasum": "24fd6201a4782cf50561c810276afc7d12d71195",
+  "_shrinkwrap": null,
+  "_spec": "is-number@^3.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-number/issues"
+  },
+  "contributors": [
+    {
+      "name": "Charlike Mike Reagent",
+      "url": "http://www.tunnckocore.tk"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Returns true if the value is a number. comprehensive tests.",
+  "devDependencies": {
+    "benchmarked": "^0.2.5",
+    "chalk": "^1.1.3",
+    "gulp-format-md": "^0.1.10",
+    "mocha": "^3.0.2"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "24fd6201a4782cf50561c810276afc7d12d71195",
+    "tarball": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "af885e2e890b9ef0875edd2b117305119ee5bdc5",
+  "homepage": "https://github.com/jonschlinkert/is-number",
+  "keywords": [
+    "check",
+    "coerce",
+    "coercion",
+    "integer",
+    "is",
+    "is-nan",
+    "is-num",
+    "is-number",
+    "istype",
+    "kind",
+    "math",
+    "nan",
+    "num",
+    "number",
+    "numeric",
+    "test",
+    "type",
+    "typeof",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "is-number",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-number.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-generate-readme"
+    ],
+    "related": {
+      "list": [
+        "even",
+        "is-even",
+        "is-odd",
+        "is-primitive",
+        "kind-of",
+        "odd"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.0.0"
+}
diff --git a/input_devices/mag/node_modules/readline-utils/package.json b/input_devices/mag/node_modules/readline-utils/package.json
new file mode 100644
index 00000000..8dac340e
--- /dev/null
+++ b/input_devices/mag/node_modules/readline-utils/package.json
@@ -0,0 +1,137 @@
+{
+  "_args": [
+    [
+      "readline-utils@^2.2.3",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "readline-utils@>=2.2.3 <3.0.0",
+  "_id": "readline-utils@2.2.3",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/readline-utils",
+  "_nodeVersion": "6.10.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/readline-utils-2.2.3.tgz_1499815120962_0.1295283487997949"
+  },
+  "_npmUser": {
+    "email": "brian.woodward@gmail.com",
+    "name": "doowb"
+  },
+  "_npmVersion": "4.6.1",
+  "_phantomChildren": {
+    "kind-of": "3.2.2"
+  },
+  "_requested": {
+    "name": "readline-utils",
+    "raw": "readline-utils@^2.2.3",
+    "rawSpec": "^2.2.3",
+    "scope": null,
+    "spec": ">=2.2.3 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base",
+    "/readline-ui"
+  ],
+  "_resolved": "https://registry.npmjs.org/readline-utils/-/readline-utils-2.2.3.tgz",
+  "_shasum": "6f847d6b8f1915c391b581c367cd47873862351a",
+  "_shrinkwrap": null,
+  "_spec": "readline-utils@^2.2.3",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/readline-utils/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "arr-flatten": "^1.1.0",
+    "extend-shallow": "^2.0.1",
+    "is-buffer": "^1.1.5",
+    "is-number": "^3.0.0",
+    "is-windows": "^1.0.1",
+    "koalas": "^1.0.2",
+    "mute-stream": "0.0.7",
+    "strip-color": "^0.1.0",
+    "window-size": "^1.1.0"
+  },
+  "description": "Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.3.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "6f847d6b8f1915c391b581c367cd47873862351a",
+    "tarball": "https://registry.npmjs.org/readline-utils/-/readline-utils-2.2.3.tgz"
+  },
+  "engines": {
+    "node": ">=4.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "6db705d40fd88c1c094abd775d60721a8ad98374",
+  "homepage": "https://github.com/enquirer/readline-utils",
+  "keywords": [
+    "enquirer",
+    "readline",
+    "utils"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "readline-utils",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/readline-utils.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "choices-separator",
+        "enquirer",
+        "prompt-choices"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.2.3"
+}
diff --git a/input_devices/mag/node_modules/safe-buffer/LICENSE b/input_devices/mag/node_modules/safe-buffer/LICENSE
new file mode 100644
index 00000000..0c068cee
--- /dev/null
+++ b/input_devices/mag/node_modules/safe-buffer/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Feross Aboukhadijeh
+
+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/input_devices/mag/node_modules/safe-buffer/README.md b/input_devices/mag/node_modules/safe-buffer/README.md
new file mode 100644
index 00000000..e9a81afd
--- /dev/null
+++ b/input_devices/mag/node_modules/safe-buffer/README.md
@@ -0,0 +1,584 @@
+# safe-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
+
+[travis-image]: https://img.shields.io/travis/feross/safe-buffer/master.svg
+[travis-url]: https://travis-ci.org/feross/safe-buffer
+[npm-image]: https://img.shields.io/npm/v/safe-buffer.svg
+[npm-url]: https://npmjs.org/package/safe-buffer
+[downloads-image]: https://img.shields.io/npm/dm/safe-buffer.svg
+[downloads-url]: https://npmjs.org/package/safe-buffer
+[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
+[standard-url]: https://standardjs.com
+
+#### Safer Node.js Buffer API
+
+**Use the new Node.js Buffer APIs (`Buffer.from`, `Buffer.alloc`,
+`Buffer.allocUnsafe`, `Buffer.allocUnsafeSlow`) in all versions of Node.js.**
+
+**Uses the built-in implementation when available.**
+
+## install
+
+```
+npm install safe-buffer
+```
+
+## usage
+
+The goal of this package is to provide a safe replacement for the node.js `Buffer`.
+
+It's a drop-in replacement for `Buffer`. You can use it by adding one `require` line to
+the top of your node.js modules:
+
+```js
+var Buffer = require('safe-buffer').Buffer
+
+// Existing buffer code will continue to work without issues:
+
+new Buffer('hey', 'utf8')
+new Buffer([1, 2, 3], 'utf8')
+new Buffer(obj)
+new Buffer(16) // create an uninitialized buffer (potentially unsafe)
+
+// But you can use these new explicit APIs to make clear what you want:
+
+Buffer.from('hey', 'utf8') // convert from many types to a Buffer
+Buffer.alloc(16) // create a zero-filled buffer (safe)
+Buffer.allocUnsafe(16) // create an uninitialized buffer (potentially unsafe)
+```
+
+## api
+
+### Class Method: Buffer.from(array)
+<!-- YAML
+added: v3.0.0
+-->
+
+* `array` {Array}
+
+Allocates a new `Buffer` using an `array` of octets.
+
+```js
+const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]);
+  // creates a new Buffer containing ASCII bytes
+  // ['b','u','f','f','e','r']
+```
+
+A `TypeError` will be thrown if `array` is not an `Array`.
+
+### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]])
+<!-- YAML
+added: v5.10.0
+-->
+
+* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or
+  a `new ArrayBuffer()`
+* `byteOffset` {Number} Default: `0`
+* `length` {Number} Default: `arrayBuffer.length - byteOffset`
+
+When passed a reference to the `.buffer` property of a `TypedArray` instance,
+the newly created `Buffer` will share the same allocated memory as the
+TypedArray.
+
+```js
+const arr = new Uint16Array(2);
+arr[0] = 5000;
+arr[1] = 4000;
+
+const buf = Buffer.from(arr.buffer); // shares the memory with arr;
+
+console.log(buf);
+  // Prints: <Buffer 88 13 a0 0f>
+
+// changing the TypedArray changes the Buffer also
+arr[1] = 6000;
+
+console.log(buf);
+  // Prints: <Buffer 88 13 70 17>
+```
+
+The optional `byteOffset` and `length` arguments specify a memory range within
+the `arrayBuffer` that will be shared by the `Buffer`.
+
+```js
+const ab = new ArrayBuffer(10);
+const buf = Buffer.from(ab, 0, 2);
+console.log(buf.length);
+  // Prints: 2
+```
+
+A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`.
+
+### Class Method: Buffer.from(buffer)
+<!-- YAML
+added: v3.0.0
+-->
+
+* `buffer` {Buffer}
+
+Copies the passed `buffer` data onto a new `Buffer` instance.
+
+```js
+const buf1 = Buffer.from('buffer');
+const buf2 = Buffer.from(buf1);
+
+buf1[0] = 0x61;
+console.log(buf1.toString());
+  // 'auffer'
+console.log(buf2.toString());
+  // 'buffer' (copy is not changed)
+```
+
+A `TypeError` will be thrown if `buffer` is not a `Buffer`.
+
+### Class Method: Buffer.from(str[, encoding])
+<!-- YAML
+added: v5.10.0
+-->
+
+* `str` {String} String to encode.
+* `encoding` {String} Encoding to use, Default: `'utf8'`
+
+Creates a new `Buffer` containing the given JavaScript string `str`. If
+provided, the `encoding` parameter identifies the character encoding.
+If not provided, `encoding` defaults to `'utf8'`.
+
+```js
+const buf1 = Buffer.from('this is a tést');
+console.log(buf1.toString());
+  // prints: this is a tést
+console.log(buf1.toString('ascii'));
+  // prints: this is a tC)st
+
+const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex');
+console.log(buf2.toString());
+  // prints: this is a tést
+```
+
+A `TypeError` will be thrown if `str` is not a string.
+
+### Class Method: Buffer.alloc(size[, fill[, encoding]])
+<!-- YAML
+added: v5.10.0
+-->
+
+* `size` {Number}
+* `fill` {Value} Default: `undefined`
+* `encoding` {String} Default: `utf8`
+
+Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the
+`Buffer` will be *zero-filled*.
+
+```js
+const buf = Buffer.alloc(5);
+console.log(buf);
+  // <Buffer 00 00 00 00 00>
+```
+
+The `size` must be less than or equal to the value of
+`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is
+`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will
+be created if a `size` less than or equal to 0 is specified.
+
+If `fill` is specified, the allocated `Buffer` will be initialized by calling
+`buf.fill(fill)`. See [`buf.fill()`][] for more information.
+
+```js
+const buf = Buffer.alloc(5, 'a');
+console.log(buf);
+  // <Buffer 61 61 61 61 61>
+```
+
+If both `fill` and `encoding` are specified, the allocated `Buffer` will be
+initialized by calling `buf.fill(fill, encoding)`. For example:
+
+```js
+const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');
+console.log(buf);
+  // <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
+```
+
+Calling `Buffer.alloc(size)` can be significantly slower than the alternative
+`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance
+contents will *never contain sensitive data*.
+
+A `TypeError` will be thrown if `size` is not a number.
+
+### Class Method: Buffer.allocUnsafe(size)
+<!-- YAML
+added: v5.10.0
+-->
+
+* `size` {Number}
+
+Allocates a new *non-zero-filled* `Buffer` of `size` bytes.  The `size` must
+be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit
+architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is
+thrown. A zero-length Buffer will be created if a `size` less than or equal to
+0 is specified.
+
+The underlying memory for `Buffer` instances created in this way is *not
+initialized*. The contents of the newly created `Buffer` are unknown and
+*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such
+`Buffer` instances to zeroes.
+
+```js
+const buf = Buffer.allocUnsafe(5);
+console.log(buf);
+  // <Buffer 78 e0 82 02 01>
+  // (octets will be different, every time)
+buf.fill(0);
+console.log(buf);
+  // <Buffer 00 00 00 00 00>
+```
+
+A `TypeError` will be thrown if `size` is not a number.
+
+Note that the `Buffer` module pre-allocates an internal `Buffer` instance of
+size `Buffer.poolSize` that is used as a pool for the fast allocation of new
+`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated
+`new Buffer(size)` constructor) only when `size` is less than or equal to
+`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default
+value of `Buffer.poolSize` is `8192` but can be modified.
+
+Use of this pre-allocated internal memory pool is a key difference between
+calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`.
+Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer
+pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal
+Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The
+difference is subtle but can be important when an application requires the
+additional performance that `Buffer.allocUnsafe(size)` provides.
+
+### Class Method: Buffer.allocUnsafeSlow(size)
+<!-- YAML
+added: v5.10.0
+-->
+
+* `size` {Number}
+
+Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes.  The
+`size` must be less than or equal to the value of
+`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is
+`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will
+be created if a `size` less than or equal to 0 is specified.
+
+The underlying memory for `Buffer` instances created in this way is *not
+initialized*. The contents of the newly created `Buffer` are unknown and
+*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such
+`Buffer` instances to zeroes.
+
+When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances,
+allocations under 4KB are, by default, sliced from a single pre-allocated
+`Buffer`. This allows applications to avoid the garbage collection overhead of
+creating many individually allocated Buffers. This approach improves both
+performance and memory usage by eliminating the need to track and cleanup as
+many `Persistent` objects.
+
+However, in the case where a developer may need to retain a small chunk of
+memory from a pool for an indeterminate amount of time, it may be appropriate
+to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then
+copy out the relevant bits.
+
+```js
+// need to keep around a few small chunks of memory
+const store = [];
+
+socket.on('readable', () => {
+  const data = socket.read();
+  // allocate for retained data
+  const sb = Buffer.allocUnsafeSlow(10);
+  // copy the data into the new allocation
+  data.copy(sb, 0, 0, 10);
+  store.push(sb);
+});
+```
+
+Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after*
+a developer has observed undue memory retention in their applications.
+
+A `TypeError` will be thrown if `size` is not a number.
+
+### All the Rest
+
+The rest of the `Buffer` API is exactly the same as in node.js.
+[See the docs](https://nodejs.org/api/buffer.html).
+
+
+## Related links
+
+- [Node.js issue: Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660)
+- [Node.js Enhancement Proposal: Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer() soft-deprecate](https://github.com/nodejs/node-eps/pull/4)
+
+## Why is `Buffer` unsafe?
+
+Today, the node.js `Buffer` constructor is overloaded to handle many different argument
+types like `String`, `Array`, `Object`, `TypedArrayView` (`Uint8Array`, etc.),
+`ArrayBuffer`, and also `Number`.
+
+The API is optimized for convenience: you can throw any type at it, and it will try to do
+what you want.
+
+Because the Buffer constructor is so powerful, you often see code like this:
+
+```js
+// Convert UTF-8 strings to hex
+function toHex (str) {
+  return new Buffer(str).toString('hex')
+}
+```
+
+***But what happens if `toHex` is called with a `Number` argument?***
+
+### Remote Memory Disclosure
+
+If an attacker can make your program call the `Buffer` constructor with a `Number`
+argument, then they can make it allocate uninitialized memory from the node.js process.
+This could potentially disclose TLS private keys, user data, or database passwords.
+
+When the `Buffer` constructor is passed a `Number` argument, it returns an
+**UNINITIALIZED** block of memory of the specified `size`. When you create a `Buffer` like
+this, you **MUST** overwrite the contents before returning it to the user.
+
+From the [node.js docs](https://nodejs.org/api/buffer.html#buffer_new_buffer_size):
+
+> `new Buffer(size)`
+>
+> - `size` Number
+>
+> The underlying memory for `Buffer` instances created in this way is not initialized.
+> **The contents of a newly created `Buffer` are unknown and could contain sensitive
+> data.** Use `buf.fill(0)` to initialize a Buffer to zeroes.
+
+(Emphasis our own.)
+
+Whenever the programmer intended to create an uninitialized `Buffer` you often see code
+like this:
+
+```js
+var buf = new Buffer(16)
+
+// Immediately overwrite the uninitialized buffer with data from another buffer
+for (var i = 0; i < buf.length; i++) {
+  buf[i] = otherBuf[i]
+}
+```
+
+
+### Would this ever be a problem in real code?
+
+Yes. It's surprisingly common to forget to check the type of your variables in a
+dynamically-typed language like JavaScript.
+
+Usually the consequences of assuming the wrong type is that your program crashes with an
+uncaught exception. But the failure mode for forgetting to check the type of arguments to
+the `Buffer` constructor is more catastrophic.
+
+Here's an example of a vulnerable service that takes a JSON payload and converts it to
+hex:
+
+```js
+// Take a JSON payload {str: "some string"} and convert it to hex
+var server = http.createServer(function (req, res) {
+  var data = ''
+  req.setEncoding('utf8')
+  req.on('data', function (chunk) {
+    data += chunk
+  })
+  req.on('end', function () {
+    var body = JSON.parse(data)
+    res.end(new Buffer(body.str).toString('hex'))
+  })
+})
+
+server.listen(8080)
+```
+
+In this example, an http client just has to send:
+
+```json
+{
+  "str": 1000
+}
+```
+
+and it will get back 1,000 bytes of uninitialized memory from the server.
+
+This is a very serious bug. It's similar in severity to the
+[the Heartbleed bug](http://heartbleed.com/) that allowed disclosure of OpenSSL process
+memory by remote attackers.
+
+
+### Which real-world packages were vulnerable?
+
+#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht)
+
+[Mathias Buus](https://github.com/mafintosh) and I
+([Feross Aboukhadijeh](http://feross.org/)) found this issue in one of our own packages,
+[`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht). The bug would allow
+anyone on the internet to send a series of messages to a user of `bittorrent-dht` and get
+them to reveal 20 bytes at a time of uninitialized memory from the node.js process.
+
+Here's
+[the commit](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8)
+that fixed it. We released a new fixed version, created a
+[Node Security Project disclosure](https://nodesecurity.io/advisories/68), and deprecated all
+vulnerable versions on npm so users will get a warning to upgrade to a newer version.
+
+#### [`ws`](https://www.npmjs.com/package/ws)
+
+That got us wondering if there were other vulnerable packages. Sure enough, within a short
+period of time, we found the same issue in [`ws`](https://www.npmjs.com/package/ws), the
+most popular WebSocket implementation in node.js.
+
+If certain APIs were called with `Number` parameters instead of `String` or `Buffer` as
+expected, then uninitialized server memory would be disclosed to the remote peer.
+
+These were the vulnerable methods:
+
+```js
+socket.send(number)
+socket.ping(number)
+socket.pong(number)
+```
+
+Here's a vulnerable socket server with some echo functionality:
+
+```js
+server.on('connection', function (socket) {
+  socket.on('message', function (message) {
+    message = JSON.parse(message)
+    if (message.type === 'echo') {
+      socket.send(message.data) // send back the user's message
+    }
+  })
+})
+```
+
+`socket.send(number)` called on the server, will disclose server memory.
+
+Here's [the release](https://github.com/websockets/ws/releases/tag/1.0.1) where the issue
+was fixed, with a more detailed explanation. Props to
+[Arnout Kazemier](https://github.com/3rd-Eden) for the quick fix. Here's the
+[Node Security Project disclosure](https://nodesecurity.io/advisories/67).
+
+
+### What's the solution?
+
+It's important that node.js offers a fast way to get memory otherwise performance-critical
+applications would needlessly get a lot slower.
+
+But we need a better way to *signal our intent* as programmers. **When we want
+uninitialized memory, we should request it explicitly.**
+
+Sensitive functionality should not be packed into a developer-friendly API that loosely
+accepts many different types. This type of API encourages the lazy practice of passing
+variables in without checking the type very carefully.
+
+#### A new API: `Buffer.allocUnsafe(number)`
+
+The functionality of creating buffers with uninitialized memory should be part of another
+API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that
+frequently gets user input of all sorts of different types passed into it.
+
+```js
+var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory!
+
+// Immediately overwrite the uninitialized buffer with data from another buffer
+for (var i = 0; i < buf.length; i++) {
+  buf[i] = otherBuf[i]
+}
+```
+
+
+### How do we fix node.js core?
+
+We sent [a PR to node.js core](https://github.com/nodejs/node/pull/4514) (merged as
+`semver-major`) which defends against one case:
+
+```js
+var str = 16
+new Buffer(str, 'utf8')
+```
+
+In this situation, it's implied that the programmer intended the first argument to be a
+string, since they passed an encoding as a second argument. Today, node.js will allocate
+uninitialized memory in the case of `new Buffer(number, encoding)`, which is probably not
+what the programmer intended.
+
+But this is only a partial solution, since if the programmer does `new Buffer(variable)`
+(without an `encoding` parameter) there's no way to know what they intended. If `variable`
+is sometimes a number, then uninitialized memory will sometimes be returned.
+
+### What's the real long-term fix?
+
+We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when
+we need uninitialized memory. But that would break 1000s of packages.
+
+~~We believe the best solution is to:~~
+
+~~1. Change `new Buffer(number)` to return safe, zeroed-out memory~~
+
+~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~
+
+#### Update
+
+We now support adding three new APIs:
+
+- `Buffer.from(value)` - convert from any type to a buffer
+- `Buffer.alloc(size)` - create a zero-filled buffer
+- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size
+
+This solves the core problem that affected `ws` and `bittorrent-dht` which is
+`Buffer(variable)` getting tricked into taking a number argument.
+
+This way, existing code continues working and the impact on the npm ecosystem will be
+minimal. Over time, npm maintainers can migrate performance-critical code to use
+`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`.
+
+
+### Conclusion
+
+We think there's a serious design issue with the `Buffer` API as it exists today. It
+promotes insecure software by putting high-risk functionality into a convenient API
+with friendly "developer ergonomics".
+
+This wasn't merely a theoretical exercise because we found the issue in some of the
+most popular npm packages.
+
+Fortunately, there's an easy fix that can be applied today. Use `safe-buffer` in place of
+`buffer`.
+
+```js
+var Buffer = require('safe-buffer').Buffer
+```
+
+Eventually, we hope that node.js core can switch to this new, safer behavior. We believe
+the impact on the ecosystem would be minimal since it's not a breaking change.
+Well-maintained, popular packages would be updated to use `Buffer.alloc` quickly, while
+older, insecure packages would magically become safe from this attack vector.
+
+
+## links
+
+- [Node.js PR: buffer: throw if both length and enc are passed](https://github.com/nodejs/node/pull/4514)
+- [Node Security Project disclosure for `ws`](https://nodesecurity.io/advisories/67)
+- [Node Security Project disclosure for`bittorrent-dht`](https://nodesecurity.io/advisories/68)
+
+
+## credit
+
+The original issues in `bittorrent-dht`
+([disclosure](https://nodesecurity.io/advisories/68)) and
+`ws` ([disclosure](https://nodesecurity.io/advisories/67)) were discovered by
+[Mathias Buus](https://github.com/mafintosh) and
+[Feross Aboukhadijeh](http://feross.org/).
+
+Thanks to [Adam Baldwin](https://github.com/evilpacket) for helping disclose these issues
+and for his work running the [Node Security Project](https://nodesecurity.io/).
+
+Thanks to [John Hiesey](https://github.com/jhiesey) for proofreading this README and
+auditing the code.
+
+
+## license
+
+MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org)
diff --git a/input_devices/mag/node_modules/safe-buffer/index.d.ts b/input_devices/mag/node_modules/safe-buffer/index.d.ts
new file mode 100644
index 00000000..e9fed809
--- /dev/null
+++ b/input_devices/mag/node_modules/safe-buffer/index.d.ts
@@ -0,0 +1,187 @@
+declare module "safe-buffer" {
+  export class Buffer {
+    length: number
+    write(string: string, offset?: number, length?: number, encoding?: string): number;
+    toString(encoding?: string, start?: number, end?: number): string;
+    toJSON(): { type: 'Buffer', data: any[] };
+    equals(otherBuffer: Buffer): boolean;
+    compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
+    copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
+    slice(start?: number, end?: number): Buffer;
+    writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+    writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+    writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+    writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+    readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
+    readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
+    readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
+    readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
+    readUInt8(offset: number, noAssert?: boolean): number;
+    readUInt16LE(offset: number, noAssert?: boolean): number;
+    readUInt16BE(offset: number, noAssert?: boolean): number;
+    readUInt32LE(offset: number, noAssert?: boolean): number;
+    readUInt32BE(offset: number, noAssert?: boolean): number;
+    readInt8(offset: number, noAssert?: boolean): number;
+    readInt16LE(offset: number, noAssert?: boolean): number;
+    readInt16BE(offset: number, noAssert?: boolean): number;
+    readInt32LE(offset: number, noAssert?: boolean): number;
+    readInt32BE(offset: number, noAssert?: boolean): number;
+    readFloatLE(offset: number, noAssert?: boolean): number;
+    readFloatBE(offset: number, noAssert?: boolean): number;
+    readDoubleLE(offset: number, noAssert?: boolean): number;
+    readDoubleBE(offset: number, noAssert?: boolean): number;
+    swap16(): Buffer;
+    swap32(): Buffer;
+    swap64(): Buffer;
+    writeUInt8(value: number, offset: number, noAssert?: boolean): number;
+    writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
+    writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
+    writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
+    writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;
+    writeInt8(value: number, offset: number, noAssert?: boolean): number;
+    writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
+    writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
+    writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
+    writeInt32BE(value: number, offset: number, noAssert?: boolean): number;
+    writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
+    writeFloatBE(value: number, offset: number, noAssert?: boolean): number;
+    writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
+    writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;
+    fill(value: any, offset?: number, end?: number): this;
+    indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
+    lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
+    includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;
+
+    /**
+     * Allocates a new buffer containing the given {str}.
+     *
+     * @param str String to store in buffer.
+     * @param encoding encoding to use, optional.  Default is 'utf8'
+     */
+     constructor (str: string, encoding?: string);
+    /**
+     * Allocates a new buffer of {size} octets.
+     *
+     * @param size count of octets to allocate.
+     */
+    constructor (size: number);
+    /**
+     * Allocates a new buffer containing the given {array} of octets.
+     *
+     * @param array The octets to store.
+     */
+    constructor (array: Uint8Array);
+    /**
+     * Produces a Buffer backed by the same allocated memory as
+     * the given {ArrayBuffer}.
+     *
+     *
+     * @param arrayBuffer The ArrayBuffer with which to share memory.
+     */
+    constructor (arrayBuffer: ArrayBuffer);
+    /**
+     * Allocates a new buffer containing the given {array} of octets.
+     *
+     * @param array The octets to store.
+     */
+    constructor (array: any[]);
+    /**
+     * Copies the passed {buffer} data onto a new {Buffer} instance.
+     *
+     * @param buffer The buffer to copy.
+     */
+    constructor (buffer: Buffer);
+    prototype: Buffer;
+    /**
+     * Allocates a new Buffer using an {array} of octets.
+     *
+     * @param array
+     */
+    static from(array: any[]): Buffer;
+    /**
+     * When passed a reference to the .buffer property of a TypedArray instance,
+     * the newly created Buffer will share the same allocated memory as the TypedArray.
+     * The optional {byteOffset} and {length} arguments specify a memory range
+     * within the {arrayBuffer} that will be shared by the Buffer.
+     *
+     * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()
+     * @param byteOffset
+     * @param length
+     */
+    static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
+    /**
+     * Copies the passed {buffer} data onto a new Buffer instance.
+     *
+     * @param buffer
+     */
+    static from(buffer: Buffer): Buffer;
+    /**
+     * Creates a new Buffer containing the given JavaScript string {str}.
+     * If provided, the {encoding} parameter identifies the character encoding.
+     * If not provided, {encoding} defaults to 'utf8'.
+     *
+     * @param str
+     */
+    static from(str: string, encoding?: string): Buffer;
+    /**
+     * Returns true if {obj} is a Buffer
+     *
+     * @param obj object to test.
+     */
+    static isBuffer(obj: any): obj is Buffer;
+    /**
+     * Returns true if {encoding} is a valid encoding argument.
+     * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'
+     *
+     * @param encoding string to test.
+     */
+    static isEncoding(encoding: string): boolean;
+    /**
+     * Gives the actual byte length of a string. encoding defaults to 'utf8'.
+     * This is not the same as String.prototype.length since that returns the number of characters in a string.
+     *
+     * @param string string to test.
+     * @param encoding encoding used to evaluate (defaults to 'utf8')
+     */
+    static byteLength(string: string, encoding?: string): number;
+    /**
+     * Returns a buffer which is the result of concatenating all the buffers in the list together.
+     *
+     * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.
+     * If the list has exactly one item, then the first item of the list is returned.
+     * If the list has more than one item, then a new Buffer is created.
+     *
+     * @param list An array of Buffer objects to concatenate
+     * @param totalLength Total length of the buffers when concatenated.
+     *   If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.
+     */
+    static concat(list: Buffer[], totalLength?: number): Buffer;
+    /**
+     * The same as buf1.compare(buf2).
+     */
+    static compare(buf1: Buffer, buf2: Buffer): number;
+    /**
+     * Allocates a new buffer of {size} octets.
+     *
+     * @param size count of octets to allocate.
+     * @param fill if specified, buffer will be initialized by calling buf.fill(fill).
+     *    If parameter is omitted, buffer will be filled with zeros.
+     * @param encoding encoding used for call to buf.fill while initalizing
+     */
+    static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;
+    /**
+     * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents
+     * of the newly created Buffer are unknown and may contain sensitive data.
+     *
+     * @param size count of octets to allocate
+     */
+    static allocUnsafe(size: number): Buffer;
+    /**
+     * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents
+     * of the newly created Buffer are unknown and may contain sensitive data.
+     *
+     * @param size count of octets to allocate
+     */
+    static allocUnsafeSlow(size: number): Buffer;
+  }
+}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/safe-buffer/index.js b/input_devices/mag/node_modules/safe-buffer/index.js
new file mode 100644
index 00000000..22438dab
--- /dev/null
+++ b/input_devices/mag/node_modules/safe-buffer/index.js
@@ -0,0 +1,62 @@
+/* eslint-disable node/no-deprecated-api */
+var buffer = require('buffer')
+var Buffer = buffer.Buffer
+
+// alternative to using Object.keys for old browsers
+function copyProps (src, dst) {
+  for (var key in src) {
+    dst[key] = src[key]
+  }
+}
+if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
+  module.exports = buffer
+} else {
+  // Copy properties from require('buffer')
+  copyProps(buffer, exports)
+  exports.Buffer = SafeBuffer
+}
+
+function SafeBuffer (arg, encodingOrOffset, length) {
+  return Buffer(arg, encodingOrOffset, length)
+}
+
+// Copy static methods from Buffer
+copyProps(Buffer, SafeBuffer)
+
+SafeBuffer.from = function (arg, encodingOrOffset, length) {
+  if (typeof arg === 'number') {
+    throw new TypeError('Argument must not be a number')
+  }
+  return Buffer(arg, encodingOrOffset, length)
+}
+
+SafeBuffer.alloc = function (size, fill, encoding) {
+  if (typeof size !== 'number') {
+    throw new TypeError('Argument must be a number')
+  }
+  var buf = Buffer(size)
+  if (fill !== undefined) {
+    if (typeof encoding === 'string') {
+      buf.fill(fill, encoding)
+    } else {
+      buf.fill(fill)
+    }
+  } else {
+    buf.fill(0)
+  }
+  return buf
+}
+
+SafeBuffer.allocUnsafe = function (size) {
+  if (typeof size !== 'number') {
+    throw new TypeError('Argument must be a number')
+  }
+  return Buffer(size)
+}
+
+SafeBuffer.allocUnsafeSlow = function (size) {
+  if (typeof size !== 'number') {
+    throw new TypeError('Argument must be a number')
+  }
+  return buffer.SlowBuffer(size)
+}
diff --git a/input_devices/mag/node_modules/safe-buffer/package.json b/input_devices/mag/node_modules/safe-buffer/package.json
new file mode 100644
index 00000000..f69debf1
--- /dev/null
+++ b/input_devices/mag/node_modules/safe-buffer/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "safe-buffer@~5.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream"
+    ]
+  ],
+  "_from": "safe-buffer@>=5.1.1 <5.2.0",
+  "_id": "safe-buffer@5.1.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/safe-buffer",
+  "_nodeVersion": "8.11.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/safe-buffer_5.1.2_1524687024555_0.6520279716197115"
+  },
+  "_npmUser": {
+    "email": "feross@feross.org",
+    "name": "feross"
+  },
+  "_npmVersion": "6.0.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "safe-buffer",
+    "raw": "safe-buffer@~5.1.1",
+    "rawSpec": "~5.1.1",
+    "scope": null,
+    "spec": ">=5.1.1 <5.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/bl",
+    "/readable-stream",
+    "/string_decoder",
+    "/tunnel-agent"
+  ],
+  "_resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+  "_shasum": "991ec69d296e0313747d59bdfd2b745c35f8828d",
+  "_shrinkwrap": null,
+  "_spec": "safe-buffer@~5.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream",
+  "author": {
+    "email": "feross@feross.org",
+    "name": "Feross Aboukhadijeh",
+    "url": "http://feross.org"
+  },
+  "bugs": {
+    "url": "https://github.com/feross/safe-buffer/issues"
+  },
+  "dependencies": {},
+  "description": "Safer Node.js Buffer API",
+  "devDependencies": {
+    "standard": "*",
+    "tape": "^4.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4OCyCRA9TVsSAnZWagAAwf8QAIlCcf+WlqWgpiGufGgi\n+P81J+YsGVk8haOYIgZX8FTI10RjPKiGN6R11R2B8YMJhxk3kX6O2SO/pl6A\n3tuw9/n+HBQClzobhWovJ6aymO+ozlaxxWADx0DrqKhoDOfpPLoIjaWNS2q2\nh1VxErOXagn/JP11Le89LHqcZs3s1jYyH/cAvA7ygaHvHaDhAiMMimAdz8Ze\n07VKtAM6PSnBYODducjXNTWdqotsRnzmqWEQrV2OQsk8OudJ3+YBZG8szsQ2\nVGrOLeQyj7g+q/WrjFi6I4S+Eg0dYYUg73X3PaAFzGXf7VIjDDNkFjwmtx5u\nUxQ/HczXVzHkcVOfBzbNk4rPTx9o6gr+oDIvWeAgOPYIv1YT5bnMHZ2w7M+8\n4b+SPqVeWHcNfnUhLcHmxim2TWkl0DD+oeYSucsOZ65dJdihMlNiOlVe5XXl\nIPJbfOqNcWCzkibq7pQmTSeM52l8JSekpNZGi3RQQkbrVR+cR3F53VrDzvZe\n3Jqwg7hGlGXyXl5i3TPL0oqD15n/1+wLxZEBVrqM5SeQzvD8l1iDv+3sPViP\ng3msNBtX8NH+Sf4kfCJzHRGestQb0zpVa8wvKeQBBlmpv1kqAgnuPR3k39hI\ncjpqjm2vkmAetW4XnOnCuuMk4SEqejwXh0w1TAHlFLqhywxgSZhH6SJhTbgQ\nKQZ7\r\n=EOr+\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "991ec69d296e0313747d59bdfd2b745c35f8828d",
+    "tarball": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+    "unpackedSize": 31686
+  },
+  "gitHead": "649435cc8e2d1f3ecdc7caf323f1cb1187307a16",
+  "homepage": "https://github.com/feross/safe-buffer",
+  "keywords": [
+    "buffer",
+    "buffer allocate",
+    "node security",
+    "safe",
+    "safe-buffer",
+    "security",
+    "uninitialized"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "feross",
+      "email": "feross@feross.org"
+    },
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    }
+  ],
+  "name": "safe-buffer",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/feross/safe-buffer.git"
+  },
+  "scripts": {
+    "test": "standard && tape test/*.js"
+  },
+  "types": "index.d.ts",
+  "version": "5.1.2"
+}
diff --git a/input_devices/mag/node_modules/semver/LICENSE b/input_devices/mag/node_modules/semver/LICENSE
new file mode 100644
index 00000000..19129e31
--- /dev/null
+++ b/input_devices/mag/node_modules/semver/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/semver/README.md b/input_devices/mag/node_modules/semver/README.md
new file mode 100644
index 00000000..e0edbb73
--- /dev/null
+++ b/input_devices/mag/node_modules/semver/README.md
@@ -0,0 +1,399 @@
+semver(1) -- The semantic versioner for npm
+===========================================
+
+## Install
+
+```bash
+npm install --save semver
+````
+
+## Usage
+
+As a node module:
+
+```js
+const semver = require('semver')
+
+semver.valid('1.2.3') // '1.2.3'
+semver.valid('a.b.c') // null
+semver.clean('  =v1.2.3   ') // '1.2.3'
+semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
+semver.gt('1.2.3', '9.8.7') // false
+semver.lt('1.2.3', '9.8.7') // true
+semver.valid(semver.coerce('v2')) // '2.0.0'
+semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
+```
+
+As a command-line utility:
+
+```
+$ semver -h
+
+A JavaScript implementation of the http://semver.org/ specification
+Copyright Isaac Z. Schlueter
+
+Usage: semver [options] <version> [<version> [...]]
+Prints valid versions sorted by SemVer precedence
+
+Options:
+-r --range <range>
+        Print versions that match the specified range.
+
+-i --increment [<level>]
+        Increment a version by the specified level.  Level can
+        be one of: major, minor, patch, premajor, preminor,
+        prepatch, or prerelease.  Default level is 'patch'.
+        Only one version may be specified.
+
+--preid <identifier>
+        Identifier to be used to prefix premajor, preminor,
+        prepatch or prerelease version increments.
+
+-l --loose
+        Interpret versions and ranges loosely
+
+-p --include-prerelease
+        Always include prerelease versions in range matching
+
+-c --coerce
+        Coerce a string into SemVer if possible
+        (does not imply --loose)
+
+Program exits successfully if any valid version satisfies
+all supplied ranges, and prints all satisfying versions.
+
+If no satisfying versions are found, then exits failure.
+
+Versions are printed in ascending order, so supplying
+multiple versions to the utility will just sort them.
+```
+
+## Versions
+
+A "version" is described by the `v2.0.0` specification found at
+<http://semver.org/>.
+
+A leading `"="` or `"v"` character is stripped off and ignored.
+
+## Ranges
+
+A `version range` is a set of `comparators` which specify versions
+that satisfy the range.
+
+A `comparator` is composed of an `operator` and a `version`.  The set
+of primitive `operators` is:
+
+* `<` Less than
+* `<=` Less than or equal to
+* `>` Greater than
+* `>=` Greater than or equal to
+* `=` Equal.  If no operator is specified, then equality is assumed,
+  so this operator is optional, but MAY be included.
+
+For example, the comparator `>=1.2.7` would match the versions
+`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6`
+or `1.1.0`.
+
+Comparators can be joined by whitespace to form a `comparator set`,
+which is satisfied by the **intersection** of all of the comparators
+it includes.
+
+A range is composed of one or more comparator sets, joined by `||`.  A
+version matches a range if and only if every comparator in at least
+one of the `||`-separated comparator sets is satisfied by the version.
+
+For example, the range `>=1.2.7 <1.3.0` would match the versions
+`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`,
+or `1.1.0`.
+
+The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`,
+`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`.
+
+### Prerelease Tags
+
+If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then
+it will only be allowed to satisfy comparator sets if at least one
+comparator with the same `[major, minor, patch]` tuple also has a
+prerelease tag.
+
+For example, the range `>1.2.3-alpha.3` would be allowed to match the
+version `1.2.3-alpha.7`, but it would *not* be satisfied by
+`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater
+than" `1.2.3-alpha.3` according to the SemVer sort rules.  The version
+range only accepts prerelease tags on the `1.2.3` version.  The
+version `3.4.5` *would* satisfy the range, because it does not have a
+prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`.
+
+The purpose for this behavior is twofold.  First, prerelease versions
+frequently are updated very quickly, and contain many breaking changes
+that are (by the author's design) not yet fit for public consumption.
+Therefore, by default, they are excluded from range matching
+semantics.
+
+Second, a user who has opted into using a prerelease version has
+clearly indicated the intent to use *that specific* set of
+alpha/beta/rc versions.  By including a prerelease tag in the range,
+the user is indicating that they are aware of the risk.  However, it
+is still not appropriate to assume that they have opted into taking a
+similar risk on the *next* set of prerelease versions.
+
+#### Prerelease Identifiers
+
+The method `.inc` takes an additional `identifier` string argument that
+will append the value of the string as a prerelease identifier:
+
+```javascript
+semver.inc('1.2.3', 'prerelease', 'beta')
+// '1.2.4-beta.0'
+```
+
+command-line example:
+
+```bash
+$ semver 1.2.3 -i prerelease --preid beta
+1.2.4-beta.0
+```
+
+Which then can be used to increment further:
+
+```bash
+$ semver 1.2.4-beta.0 -i prerelease
+1.2.4-beta.1
+```
+
+### Advanced Range Syntax
+
+Advanced range syntax desugars to primitive comparators in
+deterministic ways.
+
+Advanced ranges may be combined in the same way as primitive
+comparators using white space or `||`.
+
+#### Hyphen Ranges `X.Y.Z - A.B.C`
+
+Specifies an inclusive set.
+
+* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
+
+If a partial version is provided as the first version in the inclusive
+range, then the missing pieces are replaced with zeroes.
+
+* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4`
+
+If a partial version is provided as the second version in the
+inclusive range, then all versions that start with the supplied parts
+of the tuple are accepted, but nothing that would be greater than the
+provided tuple parts.
+
+* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0`
+* `1.2.3 - 2` := `>=1.2.3 <3.0.0`
+
+#### X-Ranges `1.2.x` `1.X` `1.2.*` `*`
+
+Any of `X`, `x`, or `*` may be used to "stand in" for one of the
+numeric values in the `[major, minor, patch]` tuple.
+
+* `*` := `>=0.0.0` (Any version satisfies)
+* `1.x` := `>=1.0.0 <2.0.0` (Matching major version)
+* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions)
+
+A partial version range is treated as an X-Range, so the special
+character is in fact optional.
+
+* `""` (empty string) := `*` := `>=0.0.0`
+* `1` := `1.x.x` := `>=1.0.0 <2.0.0`
+* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0`
+
+#### Tilde Ranges `~1.2.3` `~1.2` `~1`
+
+Allows patch-level changes if a minor version is specified on the
+comparator.  Allows minor-level changes if not.
+
+* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0`
+* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`)
+* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`)
+* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0`
+* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`)
+* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`)
+* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in
+  the `1.2.3` version will be allowed, if they are greater than or
+  equal to `beta.2`.  So, `1.2.3-beta.4` would be allowed, but
+  `1.2.4-beta.2` would not, because it is a prerelease of a
+  different `[major, minor, patch]` tuple.
+
+#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4`
+
+Allows changes that do not modify the left-most non-zero digit in the
+`[major, minor, patch]` tuple.  In other words, this allows patch and
+minor updates for versions `1.0.0` and above, patch updates for
+versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`.
+
+Many authors treat a `0.x` version as if the `x` were the major
+"breaking-change" indicator.
+
+Caret ranges are ideal when an author may make breaking changes
+between `0.2.4` and `0.3.0` releases, which is a common practice.
+However, it presumes that there will *not* be breaking changes between
+`0.2.4` and `0.2.5`.  It allows for changes that are presumed to be
+additive (but non-breaking), according to commonly observed practices.
+
+* `^1.2.3` := `>=1.2.3 <2.0.0`
+* `^0.2.3` := `>=0.2.3 <0.3.0`
+* `^0.0.3` := `>=0.0.3 <0.0.4`
+* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in
+  the `1.2.3` version will be allowed, if they are greater than or
+  equal to `beta.2`.  So, `1.2.3-beta.4` would be allowed, but
+  `1.2.4-beta.2` would not, because it is a prerelease of a
+  different `[major, minor, patch]` tuple.
+* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4`  Note that prereleases in the
+  `0.0.3` version *only* will be allowed, if they are greater than or
+  equal to `beta`.  So, `0.0.3-pr.2` would be allowed.
+
+When parsing caret ranges, a missing `patch` value desugars to the
+number `0`, but will allow flexibility within that value, even if the
+major and minor versions are both `0`.
+
+* `^1.2.x` := `>=1.2.0 <2.0.0`
+* `^0.0.x` := `>=0.0.0 <0.1.0`
+* `^0.0` := `>=0.0.0 <0.1.0`
+
+A missing `minor` and `patch` values will desugar to zero, but also
+allow flexibility within those values, even if the major version is
+zero.
+
+* `^1.x` := `>=1.0.0 <2.0.0`
+* `^0.x` := `>=0.0.0 <1.0.0`
+
+### Range Grammar
+
+Putting all this together, here is a Backus-Naur grammar for ranges,
+for the benefit of parser authors:
+
+```bnf
+range-set  ::= range ( logical-or range ) *
+logical-or ::= ( ' ' ) * '||' ( ' ' ) *
+range      ::= hyphen | simple ( ' ' simple ) * | ''
+hyphen     ::= partial ' - ' partial
+simple     ::= primitive | partial | tilde | caret
+primitive  ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
+partial    ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
+xr         ::= 'x' | 'X' | '*' | nr
+nr         ::= '0' | ['1'-'9'] ( ['0'-'9'] ) *
+tilde      ::= '~' partial
+caret      ::= '^' partial
+qualifier  ::= ( '-' pre )? ( '+' build )?
+pre        ::= parts
+build      ::= parts
+parts      ::= part ( '.' part ) *
+part       ::= nr | [-0-9A-Za-z]+
+```
+
+## Functions
+
+All methods and classes take a final `options` object argument.  All
+options in this object are `false` by default.  The options supported
+are:
+
+- `loose`  Be more forgiving about not-quite-valid semver strings.
+  (Any resulting output will always be 100% strict compliant, of
+  course.)  For backwards compatibility reasons, if the `options`
+  argument is a boolean value instead of an object, it is interpreted
+  to be the `loose` param.
+- `includePrerelease`  Set to suppress the [default
+  behavior](https://github.com/npm/node-semver#prerelease-tags) of
+  excluding prerelease tagged versions from ranges unless they are
+  explicitly opted into.
+
+Strict-mode Comparators and Ranges will be strict about the SemVer
+strings that they parse.
+
+* `valid(v)`: Return the parsed version, or null if it's not valid.
+* `inc(v, release)`: Return the version incremented by the release
+  type (`major`,   `premajor`, `minor`, `preminor`, `patch`,
+  `prepatch`, or `prerelease`), or null if it's not valid
+  * `premajor` in one call will bump the version up to the next major
+    version and down to a prerelease of that major version.
+    `preminor`, and `prepatch` work the same way.
+  * If called from a non-prerelease version, the `prerelease` will work the
+    same as `prepatch`. It increments the patch version, then makes a
+    prerelease. If the input version is already a prerelease it simply
+    increments it.
+* `prerelease(v)`: Returns an array of prerelease components, or null
+  if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]`
+* `major(v)`: Return the major version number.
+* `minor(v)`: Return the minor version number.
+* `patch(v)`: Return the patch version number.
+* `intersects(r1, r2, loose)`: Return true if the two supplied ranges
+  or comparators intersect.
+
+### Comparison
+
+* `gt(v1, v2)`: `v1 > v2`
+* `gte(v1, v2)`: `v1 >= v2`
+* `lt(v1, v2)`: `v1 < v2`
+* `lte(v1, v2)`: `v1 <= v2`
+* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
+  even if they're not the exact same string.  You already know how to
+  compare strings.
+* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
+* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
+  the corresponding function above.  `"==="` and `"!=="` do simple
+  string comparison, but are included for completeness.  Throws if an
+  invalid comparison string is provided.
+* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
+  `v2` is greater.  Sorts in ascending order if passed to `Array.sort()`.
+* `rcompare(v1, v2)`: The reverse of compare.  Sorts an array of versions
+  in descending order when passed to `Array.sort()`.
+* `diff(v1, v2)`: Returns difference between two versions by the release type
+  (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`),
+  or null if the versions are the same.
+
+### Comparators
+
+* `intersects(comparator)`: Return true if the comparators intersect
+
+### Ranges
+
+* `validRange(range)`: Return the valid range or null if it's not valid
+* `satisfies(version, range)`: Return true if the version satisfies the
+  range.
+* `maxSatisfying(versions, range)`: Return the highest version in the list
+  that satisfies the range, or `null` if none of them do.
+* `minSatisfying(versions, range)`: Return the lowest version in the list
+  that satisfies the range, or `null` if none of them do.
+* `gtr(version, range)`: Return `true` if version is greater than all the
+  versions possible in the range.
+* `ltr(version, range)`: Return `true` if version is less than all the
+  versions possible in the range.
+* `outside(version, range, hilo)`: Return true if the version is outside
+  the bounds of the range in either the high or low direction.  The
+  `hilo` argument must be either the string `'>'` or `'<'`.  (This is
+  the function called by `gtr` and `ltr`.)
+* `intersects(range)`: Return true if any of the ranges comparators intersect
+
+Note that, since ranges may be non-contiguous, a version might not be
+greater than a range, less than a range, *or* satisfy a range!  For
+example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
+until `2.0.0`, so the version `1.2.10` would not be greater than the
+range (because `2.0.1` satisfies, which is higher), nor less than the
+range (since `1.2.8` satisfies, which is lower), and it also does not
+satisfy the range.
+
+If you want to know if a version satisfies or does not satisfy a
+range, use the `satisfies(version, range)` function.
+
+### Coercion
+
+* `coerce(version)`: Coerces a string to semver if possible
+
+This aims to provide a very forgiving translation of a non-semver
+string to semver. It looks for the first digit in a string, and
+consumes all remaining characters which satisfy at least a partial semver
+(e.g., `1`, `1.2`, `1.2.3`) up to the max permitted length (256 characters).
+Longer versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`).
+All surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes `3.4.0`).
+Only text which lacks digits will fail coercion (`version one` is not valid).
+The maximum  length for any semver component considered for coercion is 16 characters;
+longer components will be ignored (`10000000000000000.4.7.4` becomes `4.7.4`).
+The maximum value for any semver component is `Integer.MAX_SAFE_INTEGER || (2**53 - 1)`;
+higher value components are invalid (`9999999999999999.4.7.4` is likely invalid).
diff --git a/input_devices/mag/node_modules/semver/bin/semver b/input_devices/mag/node_modules/semver/bin/semver
new file mode 100755
index 00000000..9100ed42
--- /dev/null
+++ b/input_devices/mag/node_modules/semver/bin/semver
@@ -0,0 +1,153 @@
+#!/usr/bin/env node
+// Standalone semver comparison program.
+// Exits successfully and prints matching version(s) if
+// any supplied version is valid and passes all tests.
+
+var argv = process.argv.slice(2)
+  , versions = []
+  , range = []
+  , gt = []
+  , lt = []
+  , eq = []
+  , inc = null
+  , version = require("../package.json").version
+  , loose = false
+  , includePrerelease = false
+  , coerce = false
+  , identifier = undefined
+  , semver = require("../semver")
+  , reverse = false
+  , options = {}
+
+main()
+
+function main () {
+  if (!argv.length) return help()
+  while (argv.length) {
+    var a = argv.shift()
+    var i = a.indexOf('=')
+    if (i !== -1) {
+      a = a.slice(0, i)
+      argv.unshift(a.slice(i + 1))
+    }
+    switch (a) {
+      case "-rv": case "-rev": case "--rev": case "--reverse":
+        reverse = true
+        break
+      case "-l": case "--loose":
+        loose = true
+        break
+      case "-p": case "--include-prerelease":
+        includePrerelease = true
+        break
+      case "-v": case "--version":
+        versions.push(argv.shift())
+        break
+      case "-i": case "--inc": case "--increment":
+        switch (argv[0]) {
+          case "major": case "minor": case "patch": case "prerelease":
+          case "premajor": case "preminor": case "prepatch":
+            inc = argv.shift()
+            break
+          default:
+            inc = "patch"
+            break
+        }
+        break
+      case "--preid":
+        identifier = argv.shift()
+        break
+      case "-r": case "--range":
+        range.push(argv.shift())
+        break
+      case "-c": case "--coerce":
+        coerce = true
+        break
+      case "-h": case "--help": case "-?":
+        return help()
+      default:
+        versions.push(a)
+        break
+    }
+  }
+
+  var options = { loose: loose, includePrerelease: includePrerelease }
+
+  versions = versions.map(function (v) {
+    return coerce ? (semver.coerce(v) || {version: v}).version : v
+  }).filter(function (v) {
+    return semver.valid(v)
+  })
+  if (!versions.length) return fail()
+  if (inc && (versions.length !== 1 || range.length))
+    return failInc()
+
+  for (var i = 0, l = range.length; i < l ; i ++) {
+    versions = versions.filter(function (v) {
+      return semver.satisfies(v, range[i], options)
+    })
+    if (!versions.length) return fail()
+  }
+  return success(versions)
+}
+
+function failInc () {
+  console.error("--inc can only be used on a single version with no range")
+  fail()
+}
+
+function fail () { process.exit(1) }
+
+function success () {
+  var compare = reverse ? "rcompare" : "compare"
+  versions.sort(function (a, b) {
+    return semver[compare](a, b, options)
+  }).map(function (v) {
+    return semver.clean(v, options)
+  }).map(function (v) {
+    return inc ? semver.inc(v, inc, options, identifier) : v
+  }).forEach(function (v,i,_) { console.log(v) })
+}
+
+function help () {
+  console.log(["SemVer " + version
+              ,""
+              ,"A JavaScript implementation of the http://semver.org/ specification"
+              ,"Copyright Isaac Z. Schlueter"
+              ,""
+              ,"Usage: semver [options] <version> [<version> [...]]"
+              ,"Prints valid versions sorted by SemVer precedence"
+              ,""
+              ,"Options:"
+              ,"-r --range <range>"
+              ,"        Print versions that match the specified range."
+              ,""
+              ,"-i --increment [<level>]"
+              ,"        Increment a version by the specified level.  Level can"
+              ,"        be one of: major, minor, patch, premajor, preminor,"
+              ,"        prepatch, or prerelease.  Default level is 'patch'."
+              ,"        Only one version may be specified."
+              ,""
+              ,"--preid <identifier>"
+              ,"        Identifier to be used to prefix premajor, preminor,"
+              ,"        prepatch or prerelease version increments."
+              ,""
+              ,"-l --loose"
+              ,"        Interpret versions and ranges loosely"
+              ,""
+              ,"-p --include-prerelease"
+              ,"        Always include prerelease versions in range matching"
+              ,""
+              ,"-c --coerce"
+              ,"        Coerce a string into SemVer if possible"
+              ,"        (does not imply --loose)"
+              ,""
+              ,"Program exits successfully if any valid version satisfies"
+              ,"all supplied ranges, and prints all satisfying versions."
+              ,""
+              ,"If no satisfying versions are found, then exits failure."
+              ,""
+              ,"Versions are printed in ascending order, so supplying"
+              ,"multiple versions to the utility will just sort them."
+              ].join("\n"))
+}
diff --git a/input_devices/mag/node_modules/semver/package.json b/input_devices/mag/node_modules/semver/package.json
new file mode 100644
index 00000000..e4093c6b
--- /dev/null
+++ b/input_devices/mag/node_modules/semver/package.json
@@ -0,0 +1,86 @@
+{
+  "_args": [
+    [
+      "semver@^5.4.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/node-abi"
+    ]
+  ],
+  "_from": "semver@>=5.4.1 <6.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "semver@5.6.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/semver",
+  "_nodeVersion": "10.10.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/semver_5.6.0_1539215545199_0.6768223257800898"
+  },
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "6.4.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "semver",
+    "raw": "semver@^5.4.1",
+    "rawSpec": "^5.4.1",
+    "scope": null,
+    "spec": ">=5.4.1 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/node-abi"
+  ],
+  "_resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+  "_shasum": "7e74256fbaa49c75aa7c7a205cc22799cac80004",
+  "_shrinkwrap": null,
+  "_spec": "semver@^5.4.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/node-abi",
+  "bin": {
+    "semver": "./bin/semver"
+  },
+  "bugs": {
+    "url": "https://github.com/npm/node-semver/issues"
+  },
+  "dependencies": {},
+  "description": "The semantic version parser used by npm.",
+  "devDependencies": {
+    "tap": "^12.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 6,
+    "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvpC6CRA9TVsSAnZWagAApbMP/3bk+fOFL1FLwS924EDm\nrwE9nR9Knp9+J6Gme1UH1HvMkNm92/ZSvrbMaW5Uzw3RhRJOEjdtDpQFpJ/N\n7SFdFf4RmrZKThr4EuVVi/Iuy2MwIpZ3UUbrDYWV1kTwfMeW6mDWqcNUOOIk\nHLW9icN0oyvbB4LfPwhr3SFDKlTi6TlyZseQHFGndSbw2/mS9wdLHaa6bz0x\nB85SW5PVPw7Y83RdzdPz59vrNmVytY0pEsepLR7IQkdyB+YU7cIxR7gLbzkY\nUV5F6FyvvOcrfEIiRZgprhH5a2RnYZ8Id/3/ca08yN1Q65SsjztKq4Bh7+JI\nO/pjNjRWKLYsRom9l4q4iAFhdy6fFHlqkUkM1Yy5jFmQNjSk5RnpuRrDUUXV\ntFbWGkEccYrXby5WOq1JZxJ/MfiUpxg22qlO3AcTHbKddhFZvYh/cQFIohV4\nbmV7TeWoodJ7KaF6MVhnwda1AWTBZTNSqrCmsmDSZZwNb6NQhVSrbkLXDbgu\ntN4RhRPjOE1mFYjuGJuN32oSdceOCT9x61Lr0uucw8JHZldVIe0o63Qb6/4t\ntl+wzR3JfbdkB1vGVo8oXm8KoghMhFwmpD+RKg4hPxJhxQTXRy4OUsSkU5+l\nRRK9JHTyBGXbpcyeVLtPAGYdsl42sYG9+lSqGI3at/HKDcJrnzp3KJ4fXcUB\nlkPD\r\n=LpzA\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "7e74256fbaa49c75aa7c7a205cc22799cac80004",
+    "tarball": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+    "unpackedSize": 59721
+  },
+  "gitHead": "46727afbe21b8d14641a0d1c4c7ee58bd053f922",
+  "homepage": "https://github.com/npm/node-semver#readme",
+  "license": "ISC",
+  "main": "semver.js",
+  "maintainers": [
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    },
+    {
+      "name": "othiym23",
+      "email": "ogd@aoaioxxysz.net"
+    }
+  ],
+  "name": "semver",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/npm/node-semver.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js --cov -J"
+  },
+  "version": "5.6.0"
+}
diff --git a/input_devices/mag/node_modules/semver/range.bnf b/input_devices/mag/node_modules/semver/range.bnf
new file mode 100644
index 00000000..d4c6ae0d
--- /dev/null
+++ b/input_devices/mag/node_modules/semver/range.bnf
@@ -0,0 +1,16 @@
+range-set  ::= range ( logical-or range ) *
+logical-or ::= ( ' ' ) * '||' ( ' ' ) *
+range      ::= hyphen | simple ( ' ' simple ) * | ''
+hyphen     ::= partial ' - ' partial
+simple     ::= primitive | partial | tilde | caret
+primitive  ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
+partial    ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
+xr         ::= 'x' | 'X' | '*' | nr
+nr         ::= '0' | [1-9] ( [0-9] ) *
+tilde      ::= '~' partial
+caret      ::= '^' partial
+qualifier  ::= ( '-' pre )? ( '+' build )?
+pre        ::= parts
+build      ::= parts
+parts      ::= part ( '.' part ) *
+part       ::= nr | [-0-9A-Za-z]+
diff --git a/input_devices/mag/node_modules/semver/semver.js b/input_devices/mag/node_modules/semver/semver.js
new file mode 100644
index 00000000..0cc57350
--- /dev/null
+++ b/input_devices/mag/node_modules/semver/semver.js
@@ -0,0 +1,1352 @@
+exports = module.exports = SemVer;
+
+// The debug function is excluded entirely from the minified version.
+/* nomin */ var debug;
+/* nomin */ if (typeof process === 'object' &&
+    /* nomin */ process.env &&
+    /* nomin */ process.env.NODE_DEBUG &&
+    /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG))
+  /* nomin */ debug = function() {
+    /* nomin */ var args = Array.prototype.slice.call(arguments, 0);
+    /* nomin */ args.unshift('SEMVER');
+    /* nomin */ console.log.apply(console, args);
+    /* nomin */ };
+/* nomin */ else
+  /* nomin */ debug = function() {};
+
+// Note: this is the semver.org version of the spec that it implements
+// Not necessarily the package version of this code.
+exports.SEMVER_SPEC_VERSION = '2.0.0';
+
+var MAX_LENGTH = 256;
+var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
+
+// Max safe segment length for coercion.
+var MAX_SAFE_COMPONENT_LENGTH = 16;
+
+// The actual regexps go on exports.re
+var re = exports.re = [];
+var src = exports.src = [];
+var R = 0;
+
+// The following Regular Expressions can be used for tokenizing,
+// validating, and parsing SemVer version strings.
+
+// ## Numeric Identifier
+// A single `0`, or a non-zero digit followed by zero or more digits.
+
+var NUMERICIDENTIFIER = R++;
+src[NUMERICIDENTIFIER] = '0|[1-9]\\d*';
+var NUMERICIDENTIFIERLOOSE = R++;
+src[NUMERICIDENTIFIERLOOSE] = '[0-9]+';
+
+
+// ## Non-numeric Identifier
+// Zero or more digits, followed by a letter or hyphen, and then zero or
+// more letters, digits, or hyphens.
+
+var NONNUMERICIDENTIFIER = R++;
+src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*';
+
+
+// ## Main Version
+// Three dot-separated numeric identifiers.
+
+var MAINVERSION = R++;
+src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
+                   '(' + src[NUMERICIDENTIFIER] + ')\\.' +
+                   '(' + src[NUMERICIDENTIFIER] + ')';
+
+var MAINVERSIONLOOSE = R++;
+src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
+                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
+                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')';
+
+// ## Pre-release Version Identifier
+// A numeric identifier, or a non-numeric identifier.
+
+var PRERELEASEIDENTIFIER = R++;
+src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
+                            '|' + src[NONNUMERICIDENTIFIER] + ')';
+
+var PRERELEASEIDENTIFIERLOOSE = R++;
+src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
+                                 '|' + src[NONNUMERICIDENTIFIER] + ')';
+
+
+// ## Pre-release Version
+// Hyphen, followed by one or more dot-separated pre-release version
+// identifiers.
+
+var PRERELEASE = R++;
+src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
+                  '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))';
+
+var PRERELEASELOOSE = R++;
+src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
+                       '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))';
+
+// ## Build Metadata Identifier
+// Any combination of digits, letters, or hyphens.
+
+var BUILDIDENTIFIER = R++;
+src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';
+
+// ## Build Metadata
+// Plus sign, followed by one or more period-separated build metadata
+// identifiers.
+
+var BUILD = R++;
+src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
+             '(?:\\.' + src[BUILDIDENTIFIER] + ')*))';
+
+
+// ## Full Version String
+// A main version, followed optionally by a pre-release version and
+// build metadata.
+
+// Note that the only major, minor, patch, and pre-release sections of
+// the version string are capturing groups.  The build metadata is not a
+// capturing group, because it should not ever be used in version
+// comparison.
+
+var FULL = R++;
+var FULLPLAIN = 'v?' + src[MAINVERSION] +
+                src[PRERELEASE] + '?' +
+                src[BUILD] + '?';
+
+src[FULL] = '^' + FULLPLAIN + '$';
+
+// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
+// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
+// common in the npm registry.
+var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
+                 src[PRERELEASELOOSE] + '?' +
+                 src[BUILD] + '?';
+
+var LOOSE = R++;
+src[LOOSE] = '^' + LOOSEPLAIN + '$';
+
+var GTLT = R++;
+src[GTLT] = '((?:<|>)?=?)';
+
+// Something like "2.*" or "1.2.x".
+// Note that "x.x" is a valid xRange identifer, meaning "any version"
+// Only the first item is strictly required.
+var XRANGEIDENTIFIERLOOSE = R++;
+src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*';
+var XRANGEIDENTIFIER = R++;
+src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*';
+
+var XRANGEPLAIN = R++;
+src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
+                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
+                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
+                   '(?:' + src[PRERELEASE] + ')?' +
+                   src[BUILD] + '?' +
+                   ')?)?';
+
+var XRANGEPLAINLOOSE = R++;
+src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
+                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
+                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
+                        '(?:' + src[PRERELEASELOOSE] + ')?' +
+                        src[BUILD] + '?' +
+                        ')?)?';
+
+var XRANGE = R++;
+src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$';
+var XRANGELOOSE = R++;
+src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$';
+
+// Coercion.
+// Extract anything that could conceivably be a part of a valid semver
+var COERCE = R++;
+src[COERCE] = '(?:^|[^\\d])' +
+              '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' +
+              '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
+              '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
+              '(?:$|[^\\d])';
+
+// Tilde ranges.
+// Meaning is "reasonably at or greater than"
+var LONETILDE = R++;
+src[LONETILDE] = '(?:~>?)';
+
+var TILDETRIM = R++;
+src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+';
+re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g');
+var tildeTrimReplace = '$1~';
+
+var TILDE = R++;
+src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$';
+var TILDELOOSE = R++;
+src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$';
+
+// Caret ranges.
+// Meaning is "at least and backwards compatible with"
+var LONECARET = R++;
+src[LONECARET] = '(?:\\^)';
+
+var CARETTRIM = R++;
+src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+';
+re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g');
+var caretTrimReplace = '$1^';
+
+var CARET = R++;
+src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$';
+var CARETLOOSE = R++;
+src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$';
+
+// A simple gt/lt/eq thing, or just "" to indicate "any version"
+var COMPARATORLOOSE = R++;
+src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$';
+var COMPARATOR = R++;
+src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$';
+
+
+// An expression to strip any whitespace between the gtlt and the thing
+// it modifies, so that `> 1.2.3` ==> `>1.2.3`
+var COMPARATORTRIM = R++;
+src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
+                      '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')';
+
+// this one has to use the /g flag
+re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g');
+var comparatorTrimReplace = '$1$2$3';
+
+
+// Something like `1.2.3 - 1.2.4`
+// Note that these all use the loose form, because they'll be
+// checked against either the strict or loose comparator form
+// later.
+var HYPHENRANGE = R++;
+src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
+                   '\\s+-\\s+' +
+                   '(' + src[XRANGEPLAIN] + ')' +
+                   '\\s*$';
+
+var HYPHENRANGELOOSE = R++;
+src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
+                        '\\s+-\\s+' +
+                        '(' + src[XRANGEPLAINLOOSE] + ')' +
+                        '\\s*$';
+
+// Star ranges basically just allow anything at all.
+var STAR = R++;
+src[STAR] = '(<|>)?=?\\s*\\*';
+
+// Compile to actual regexp objects.
+// All are flag-free, unless they were created above with a flag.
+for (var i = 0; i < R; i++) {
+  debug(i, src[i]);
+  if (!re[i])
+    re[i] = new RegExp(src[i]);
+}
+
+exports.parse = parse;
+function parse(version, options) {
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+
+  if (version instanceof SemVer)
+    return version;
+
+  if (typeof version !== 'string')
+    return null;
+
+  if (version.length > MAX_LENGTH)
+    return null;
+
+  var r = options.loose ? re[LOOSE] : re[FULL];
+  if (!r.test(version))
+    return null;
+
+  try {
+    return new SemVer(version, options);
+  } catch (er) {
+    return null;
+  }
+}
+
+exports.valid = valid;
+function valid(version, options) {
+  var v = parse(version, options);
+  return v ? v.version : null;
+}
+
+
+exports.clean = clean;
+function clean(version, options) {
+  var s = parse(version.trim().replace(/^[=v]+/, ''), options);
+  return s ? s.version : null;
+}
+
+exports.SemVer = SemVer;
+
+function SemVer(version, options) {
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+  if (version instanceof SemVer) {
+    if (version.loose === options.loose)
+      return version;
+    else
+      version = version.version;
+  } else if (typeof version !== 'string') {
+    throw new TypeError('Invalid Version: ' + version);
+  }
+
+  if (version.length > MAX_LENGTH)
+    throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters')
+
+  if (!(this instanceof SemVer))
+    return new SemVer(version, options);
+
+  debug('SemVer', version, options);
+  this.options = options;
+  this.loose = !!options.loose;
+
+  var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]);
+
+  if (!m)
+    throw new TypeError('Invalid Version: ' + version);
+
+  this.raw = version;
+
+  // these are actually numbers
+  this.major = +m[1];
+  this.minor = +m[2];
+  this.patch = +m[3];
+
+  if (this.major > MAX_SAFE_INTEGER || this.major < 0)
+    throw new TypeError('Invalid major version')
+
+  if (this.minor > MAX_SAFE_INTEGER || this.minor < 0)
+    throw new TypeError('Invalid minor version')
+
+  if (this.patch > MAX_SAFE_INTEGER || this.patch < 0)
+    throw new TypeError('Invalid patch version')
+
+  // numberify any prerelease numeric ids
+  if (!m[4])
+    this.prerelease = [];
+  else
+    this.prerelease = m[4].split('.').map(function(id) {
+      if (/^[0-9]+$/.test(id)) {
+        var num = +id;
+        if (num >= 0 && num < MAX_SAFE_INTEGER)
+          return num;
+      }
+      return id;
+    });
+
+  this.build = m[5] ? m[5].split('.') : [];
+  this.format();
+}
+
+SemVer.prototype.format = function() {
+  this.version = this.major + '.' + this.minor + '.' + this.patch;
+  if (this.prerelease.length)
+    this.version += '-' + this.prerelease.join('.');
+  return this.version;
+};
+
+SemVer.prototype.toString = function() {
+  return this.version;
+};
+
+SemVer.prototype.compare = function(other) {
+  debug('SemVer.compare', this.version, this.options, other);
+  if (!(other instanceof SemVer))
+    other = new SemVer(other, this.options);
+
+  return this.compareMain(other) || this.comparePre(other);
+};
+
+SemVer.prototype.compareMain = function(other) {
+  if (!(other instanceof SemVer))
+    other = new SemVer(other, this.options);
+
+  return compareIdentifiers(this.major, other.major) ||
+         compareIdentifiers(this.minor, other.minor) ||
+         compareIdentifiers(this.patch, other.patch);
+};
+
+SemVer.prototype.comparePre = function(other) {
+  if (!(other instanceof SemVer))
+    other = new SemVer(other, this.options);
+
+  // NOT having a prerelease is > having one
+  if (this.prerelease.length && !other.prerelease.length)
+    return -1;
+  else if (!this.prerelease.length && other.prerelease.length)
+    return 1;
+  else if (!this.prerelease.length && !other.prerelease.length)
+    return 0;
+
+  var i = 0;
+  do {
+    var a = this.prerelease[i];
+    var b = other.prerelease[i];
+    debug('prerelease compare', i, a, b);
+    if (a === undefined && b === undefined)
+      return 0;
+    else if (b === undefined)
+      return 1;
+    else if (a === undefined)
+      return -1;
+    else if (a === b)
+      continue;
+    else
+      return compareIdentifiers(a, b);
+  } while (++i);
+};
+
+// preminor will bump the version up to the next minor release, and immediately
+// down to pre-release. premajor and prepatch work the same way.
+SemVer.prototype.inc = function(release, identifier) {
+  switch (release) {
+    case 'premajor':
+      this.prerelease.length = 0;
+      this.patch = 0;
+      this.minor = 0;
+      this.major++;
+      this.inc('pre', identifier);
+      break;
+    case 'preminor':
+      this.prerelease.length = 0;
+      this.patch = 0;
+      this.minor++;
+      this.inc('pre', identifier);
+      break;
+    case 'prepatch':
+      // If this is already a prerelease, it will bump to the next version
+      // drop any prereleases that might already exist, since they are not
+      // relevant at this point.
+      this.prerelease.length = 0;
+      this.inc('patch', identifier);
+      this.inc('pre', identifier);
+      break;
+    // If the input is a non-prerelease version, this acts the same as
+    // prepatch.
+    case 'prerelease':
+      if (this.prerelease.length === 0)
+        this.inc('patch', identifier);
+      this.inc('pre', identifier);
+      break;
+
+    case 'major':
+      // If this is a pre-major version, bump up to the same major version.
+      // Otherwise increment major.
+      // 1.0.0-5 bumps to 1.0.0
+      // 1.1.0 bumps to 2.0.0
+      if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0)
+        this.major++;
+      this.minor = 0;
+      this.patch = 0;
+      this.prerelease = [];
+      break;
+    case 'minor':
+      // If this is a pre-minor version, bump up to the same minor version.
+      // Otherwise increment minor.
+      // 1.2.0-5 bumps to 1.2.0
+      // 1.2.1 bumps to 1.3.0
+      if (this.patch !== 0 || this.prerelease.length === 0)
+        this.minor++;
+      this.patch = 0;
+      this.prerelease = [];
+      break;
+    case 'patch':
+      // If this is not a pre-release version, it will increment the patch.
+      // If it is a pre-release it will bump up to the same patch version.
+      // 1.2.0-5 patches to 1.2.0
+      // 1.2.0 patches to 1.2.1
+      if (this.prerelease.length === 0)
+        this.patch++;
+      this.prerelease = [];
+      break;
+    // This probably shouldn't be used publicly.
+    // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
+    case 'pre':
+      if (this.prerelease.length === 0)
+        this.prerelease = [0];
+      else {
+        var i = this.prerelease.length;
+        while (--i >= 0) {
+          if (typeof this.prerelease[i] === 'number') {
+            this.prerelease[i]++;
+            i = -2;
+          }
+        }
+        if (i === -1) // didn't increment anything
+          this.prerelease.push(0);
+      }
+      if (identifier) {
+        // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
+        // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
+        if (this.prerelease[0] === identifier) {
+          if (isNaN(this.prerelease[1]))
+            this.prerelease = [identifier, 0];
+        } else
+          this.prerelease = [identifier, 0];
+      }
+      break;
+
+    default:
+      throw new Error('invalid increment argument: ' + release);
+  }
+  this.format();
+  this.raw = this.version;
+  return this;
+};
+
+exports.inc = inc;
+function inc(version, release, loose, identifier) {
+  if (typeof(loose) === 'string') {
+    identifier = loose;
+    loose = undefined;
+  }
+
+  try {
+    return new SemVer(version, loose).inc(release, identifier).version;
+  } catch (er) {
+    return null;
+  }
+}
+
+exports.diff = diff;
+function diff(version1, version2) {
+  if (eq(version1, version2)) {
+    return null;
+  } else {
+    var v1 = parse(version1);
+    var v2 = parse(version2);
+    if (v1.prerelease.length || v2.prerelease.length) {
+      for (var key in v1) {
+        if (key === 'major' || key === 'minor' || key === 'patch') {
+          if (v1[key] !== v2[key]) {
+            return 'pre'+key;
+          }
+        }
+      }
+      return 'prerelease';
+    }
+    for (var key in v1) {
+      if (key === 'major' || key === 'minor' || key === 'patch') {
+        if (v1[key] !== v2[key]) {
+          return key;
+        }
+      }
+    }
+  }
+}
+
+exports.compareIdentifiers = compareIdentifiers;
+
+var numeric = /^[0-9]+$/;
+function compareIdentifiers(a, b) {
+  var anum = numeric.test(a);
+  var bnum = numeric.test(b);
+
+  if (anum && bnum) {
+    a = +a;
+    b = +b;
+  }
+
+  return (anum && !bnum) ? -1 :
+         (bnum && !anum) ? 1 :
+         a < b ? -1 :
+         a > b ? 1 :
+         0;
+}
+
+exports.rcompareIdentifiers = rcompareIdentifiers;
+function rcompareIdentifiers(a, b) {
+  return compareIdentifiers(b, a);
+}
+
+exports.major = major;
+function major(a, loose) {
+  return new SemVer(a, loose).major;
+}
+
+exports.minor = minor;
+function minor(a, loose) {
+  return new SemVer(a, loose).minor;
+}
+
+exports.patch = patch;
+function patch(a, loose) {
+  return new SemVer(a, loose).patch;
+}
+
+exports.compare = compare;
+function compare(a, b, loose) {
+  return new SemVer(a, loose).compare(new SemVer(b, loose));
+}
+
+exports.compareLoose = compareLoose;
+function compareLoose(a, b) {
+  return compare(a, b, true);
+}
+
+exports.rcompare = rcompare;
+function rcompare(a, b, loose) {
+  return compare(b, a, loose);
+}
+
+exports.sort = sort;
+function sort(list, loose) {
+  return list.sort(function(a, b) {
+    return exports.compare(a, b, loose);
+  });
+}
+
+exports.rsort = rsort;
+function rsort(list, loose) {
+  return list.sort(function(a, b) {
+    return exports.rcompare(a, b, loose);
+  });
+}
+
+exports.gt = gt;
+function gt(a, b, loose) {
+  return compare(a, b, loose) > 0;
+}
+
+exports.lt = lt;
+function lt(a, b, loose) {
+  return compare(a, b, loose) < 0;
+}
+
+exports.eq = eq;
+function eq(a, b, loose) {
+  return compare(a, b, loose) === 0;
+}
+
+exports.neq = neq;
+function neq(a, b, loose) {
+  return compare(a, b, loose) !== 0;
+}
+
+exports.gte = gte;
+function gte(a, b, loose) {
+  return compare(a, b, loose) >= 0;
+}
+
+exports.lte = lte;
+function lte(a, b, loose) {
+  return compare(a, b, loose) <= 0;
+}
+
+exports.cmp = cmp;
+function cmp(a, op, b, loose) {
+  var ret;
+  switch (op) {
+    case '===':
+      if (typeof a === 'object') a = a.version;
+      if (typeof b === 'object') b = b.version;
+      ret = a === b;
+      break;
+    case '!==':
+      if (typeof a === 'object') a = a.version;
+      if (typeof b === 'object') b = b.version;
+      ret = a !== b;
+      break;
+    case '': case '=': case '==': ret = eq(a, b, loose); break;
+    case '!=': ret = neq(a, b, loose); break;
+    case '>': ret = gt(a, b, loose); break;
+    case '>=': ret = gte(a, b, loose); break;
+    case '<': ret = lt(a, b, loose); break;
+    case '<=': ret = lte(a, b, loose); break;
+    default: throw new TypeError('Invalid operator: ' + op);
+  }
+  return ret;
+}
+
+exports.Comparator = Comparator;
+function Comparator(comp, options) {
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+
+  if (comp instanceof Comparator) {
+    if (comp.loose === !!options.loose)
+      return comp;
+    else
+      comp = comp.value;
+  }
+
+  if (!(this instanceof Comparator))
+    return new Comparator(comp, options);
+
+  debug('comparator', comp, options);
+  this.options = options;
+  this.loose = !!options.loose;
+  this.parse(comp);
+
+  if (this.semver === ANY)
+    this.value = '';
+  else
+    this.value = this.operator + this.semver.version;
+
+  debug('comp', this);
+}
+
+var ANY = {};
+Comparator.prototype.parse = function(comp) {
+  var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
+  var m = comp.match(r);
+
+  if (!m)
+    throw new TypeError('Invalid comparator: ' + comp);
+
+  this.operator = m[1];
+  if (this.operator === '=')
+    this.operator = '';
+
+  // if it literally is just '>' or '' then allow anything.
+  if (!m[2])
+    this.semver = ANY;
+  else
+    this.semver = new SemVer(m[2], this.options.loose);
+};
+
+Comparator.prototype.toString = function() {
+  return this.value;
+};
+
+Comparator.prototype.test = function(version) {
+  debug('Comparator.test', version, this.options.loose);
+
+  if (this.semver === ANY)
+    return true;
+
+  if (typeof version === 'string')
+    version = new SemVer(version, this.options);
+
+  return cmp(version, this.operator, this.semver, this.options);
+};
+
+Comparator.prototype.intersects = function(comp, options) {
+  if (!(comp instanceof Comparator)) {
+    throw new TypeError('a Comparator is required');
+  }
+
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+
+  var rangeTmp;
+
+  if (this.operator === '') {
+    rangeTmp = new Range(comp.value, options);
+    return satisfies(this.value, rangeTmp, options);
+  } else if (comp.operator === '') {
+    rangeTmp = new Range(this.value, options);
+    return satisfies(comp.semver, rangeTmp, options);
+  }
+
+  var sameDirectionIncreasing =
+    (this.operator === '>=' || this.operator === '>') &&
+    (comp.operator === '>=' || comp.operator === '>');
+  var sameDirectionDecreasing =
+    (this.operator === '<=' || this.operator === '<') &&
+    (comp.operator === '<=' || comp.operator === '<');
+  var sameSemVer = this.semver.version === comp.semver.version;
+  var differentDirectionsInclusive =
+    (this.operator === '>=' || this.operator === '<=') &&
+    (comp.operator === '>=' || comp.operator === '<=');
+  var oppositeDirectionsLessThan =
+    cmp(this.semver, '<', comp.semver, options) &&
+    ((this.operator === '>=' || this.operator === '>') &&
+    (comp.operator === '<=' || comp.operator === '<'));
+  var oppositeDirectionsGreaterThan =
+    cmp(this.semver, '>', comp.semver, options) &&
+    ((this.operator === '<=' || this.operator === '<') &&
+    (comp.operator === '>=' || comp.operator === '>'));
+
+  return sameDirectionIncreasing || sameDirectionDecreasing ||
+    (sameSemVer && differentDirectionsInclusive) ||
+    oppositeDirectionsLessThan || oppositeDirectionsGreaterThan;
+};
+
+
+exports.Range = Range;
+function Range(range, options) {
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+
+  if (range instanceof Range) {
+    if (range.loose === !!options.loose &&
+        range.includePrerelease === !!options.includePrerelease) {
+      return range;
+    } else {
+      return new Range(range.raw, options);
+    }
+  }
+
+  if (range instanceof Comparator) {
+    return new Range(range.value, options);
+  }
+
+  if (!(this instanceof Range))
+    return new Range(range, options);
+
+  this.options = options;
+  this.loose = !!options.loose;
+  this.includePrerelease = !!options.includePrerelease
+
+  // First, split based on boolean or ||
+  this.raw = range;
+  this.set = range.split(/\s*\|\|\s*/).map(function(range) {
+    return this.parseRange(range.trim());
+  }, this).filter(function(c) {
+    // throw out any that are not relevant for whatever reason
+    return c.length;
+  });
+
+  if (!this.set.length) {
+    throw new TypeError('Invalid SemVer Range: ' + range);
+  }
+
+  this.format();
+}
+
+Range.prototype.format = function() {
+  this.range = this.set.map(function(comps) {
+    return comps.join(' ').trim();
+  }).join('||').trim();
+  return this.range;
+};
+
+Range.prototype.toString = function() {
+  return this.range;
+};
+
+Range.prototype.parseRange = function(range) {
+  var loose = this.options.loose;
+  range = range.trim();
+  // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
+  var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];
+  range = range.replace(hr, hyphenReplace);
+  debug('hyphen replace', range);
+  // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
+  range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);
+  debug('comparator trim', range, re[COMPARATORTRIM]);
+
+  // `~ 1.2.3` => `~1.2.3`
+  range = range.replace(re[TILDETRIM], tildeTrimReplace);
+
+  // `^ 1.2.3` => `^1.2.3`
+  range = range.replace(re[CARETTRIM], caretTrimReplace);
+
+  // normalize spaces
+  range = range.split(/\s+/).join(' ');
+
+  // At this point, the range is completely trimmed and
+  // ready to be split into comparators.
+
+  var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
+  var set = range.split(' ').map(function(comp) {
+    return parseComparator(comp, this.options);
+  }, this).join(' ').split(/\s+/);
+  if (this.options.loose) {
+    // in loose mode, throw out any that are not valid comparators
+    set = set.filter(function(comp) {
+      return !!comp.match(compRe);
+    });
+  }
+  set = set.map(function(comp) {
+    return new Comparator(comp, this.options);
+  }, this);
+
+  return set;
+};
+
+Range.prototype.intersects = function(range, options) {
+  if (!(range instanceof Range)) {
+    throw new TypeError('a Range is required');
+  }
+
+  return this.set.some(function(thisComparators) {
+    return thisComparators.every(function(thisComparator) {
+      return range.set.some(function(rangeComparators) {
+        return rangeComparators.every(function(rangeComparator) {
+          return thisComparator.intersects(rangeComparator, options);
+        });
+      });
+    });
+  });
+};
+
+// Mostly just for testing and legacy API reasons
+exports.toComparators = toComparators;
+function toComparators(range, options) {
+  return new Range(range, options).set.map(function(comp) {
+    return comp.map(function(c) {
+      return c.value;
+    }).join(' ').trim().split(' ');
+  });
+}
+
+// comprised of xranges, tildes, stars, and gtlt's at this point.
+// already replaced the hyphen ranges
+// turn into a set of JUST comparators.
+function parseComparator(comp, options) {
+  debug('comp', comp, options);
+  comp = replaceCarets(comp, options);
+  debug('caret', comp);
+  comp = replaceTildes(comp, options);
+  debug('tildes', comp);
+  comp = replaceXRanges(comp, options);
+  debug('xrange', comp);
+  comp = replaceStars(comp, options);
+  debug('stars', comp);
+  return comp;
+}
+
+function isX(id) {
+  return !id || id.toLowerCase() === 'x' || id === '*';
+}
+
+// ~, ~> --> * (any, kinda silly)
+// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
+// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
+// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
+// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
+// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
+function replaceTildes(comp, options) {
+  return comp.trim().split(/\s+/).map(function(comp) {
+    return replaceTilde(comp, options);
+  }).join(' ');
+}
+
+function replaceTilde(comp, options) {
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+  var r = options.loose ? re[TILDELOOSE] : re[TILDE];
+  return comp.replace(r, function(_, M, m, p, pr) {
+    debug('tilde', comp, _, M, m, p, pr);
+    var ret;
+
+    if (isX(M))
+      ret = '';
+    else if (isX(m))
+      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
+    else if (isX(p))
+      // ~1.2 == >=1.2.0 <1.3.0
+      ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
+    else if (pr) {
+      debug('replaceTilde pr', pr);
+      if (pr.charAt(0) !== '-')
+        pr = '-' + pr;
+      ret = '>=' + M + '.' + m + '.' + p + pr +
+            ' <' + M + '.' + (+m + 1) + '.0';
+    } else
+      // ~1.2.3 == >=1.2.3 <1.3.0
+      ret = '>=' + M + '.' + m + '.' + p +
+            ' <' + M + '.' + (+m + 1) + '.0';
+
+    debug('tilde return', ret);
+    return ret;
+  });
+}
+
+// ^ --> * (any, kinda silly)
+// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
+// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
+// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
+// ^1.2.3 --> >=1.2.3 <2.0.0
+// ^1.2.0 --> >=1.2.0 <2.0.0
+function replaceCarets(comp, options) {
+  return comp.trim().split(/\s+/).map(function(comp) {
+    return replaceCaret(comp, options);
+  }).join(' ');
+}
+
+function replaceCaret(comp, options) {
+  debug('caret', comp, options);
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+  var r = options.loose ? re[CARETLOOSE] : re[CARET];
+  return comp.replace(r, function(_, M, m, p, pr) {
+    debug('caret', comp, _, M, m, p, pr);
+    var ret;
+
+    if (isX(M))
+      ret = '';
+    else if (isX(m))
+      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
+    else if (isX(p)) {
+      if (M === '0')
+        ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
+      else
+        ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0';
+    } else if (pr) {
+      debug('replaceCaret pr', pr);
+      if (pr.charAt(0) !== '-')
+        pr = '-' + pr;
+      if (M === '0') {
+        if (m === '0')
+          ret = '>=' + M + '.' + m + '.' + p + pr +
+                ' <' + M + '.' + m + '.' + (+p + 1);
+        else
+          ret = '>=' + M + '.' + m + '.' + p + pr +
+                ' <' + M + '.' + (+m + 1) + '.0';
+      } else
+        ret = '>=' + M + '.' + m + '.' + p + pr +
+              ' <' + (+M + 1) + '.0.0';
+    } else {
+      debug('no pr');
+      if (M === '0') {
+        if (m === '0')
+          ret = '>=' + M + '.' + m + '.' + p +
+                ' <' + M + '.' + m + '.' + (+p + 1);
+        else
+          ret = '>=' + M + '.' + m + '.' + p +
+                ' <' + M + '.' + (+m + 1) + '.0';
+      } else
+        ret = '>=' + M + '.' + m + '.' + p +
+              ' <' + (+M + 1) + '.0.0';
+    }
+
+    debug('caret return', ret);
+    return ret;
+  });
+}
+
+function replaceXRanges(comp, options) {
+  debug('replaceXRanges', comp, options);
+  return comp.split(/\s+/).map(function(comp) {
+    return replaceXRange(comp, options);
+  }).join(' ');
+}
+
+function replaceXRange(comp, options) {
+  comp = comp.trim();
+  if (!options || typeof options !== 'object')
+    options = { loose: !!options, includePrerelease: false }
+  var r = options.loose ? re[XRANGELOOSE] : re[XRANGE];
+  return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
+    debug('xRange', comp, ret, gtlt, M, m, p, pr);
+    var xM = isX(M);
+    var xm = xM || isX(m);
+    var xp = xm || isX(p);
+    var anyX = xp;
+
+    if (gtlt === '=' && anyX)
+      gtlt = '';
+
+    if (xM) {
+      if (gtlt === '>' || gtlt === '<') {
+        // nothing is allowed
+        ret = '<0.0.0';
+      } else {
+        // nothing is forbidden
+        ret = '*';
+      }
+    } else if (gtlt && anyX) {
+      // replace X with 0
+      if (xm)
+        m = 0;
+      if (xp)
+        p = 0;
+
+      if (gtlt === '>') {
+        // >1 => >=2.0.0
+        // >1.2 => >=1.3.0
+        // >1.2.3 => >= 1.2.4
+        gtlt = '>=';
+        if (xm) {
+          M = +M + 1;
+          m = 0;
+          p = 0;
+        } else if (xp) {
+          m = +m + 1;
+          p = 0;
+        }
+      } else if (gtlt === '<=') {
+        // <=0.7.x is actually <0.8.0, since any 0.7.x should
+        // pass.  Similarly, <=7.x is actually <8.0.0, etc.
+        gtlt = '<';
+        if (xm)
+          M = +M + 1;
+        else
+          m = +m + 1;
+      }
+
+      ret = gtlt + M + '.' + m + '.' + p;
+    } else if (xm) {
+      ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
+    } else if (xp) {
+      ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
+    }
+
+    debug('xRange return', ret);
+
+    return ret;
+  });
+}
+
+// Because * is AND-ed with everything else in the comparator,
+// and '' means "any version", just remove the *s entirely.
+function replaceStars(comp, options) {
+  debug('replaceStars', comp, options);
+  // Looseness is ignored here.  star is always as loose as it gets!
+  return comp.trim().replace(re[STAR], '');
+}
+
+// This function is passed to string.replace(re[HYPHENRANGE])
+// M, m, patch, prerelease, build
+// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
+// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
+// 1.2 - 3.4 => >=1.2.0 <3.5.0
+function hyphenReplace($0,
+                       from, fM, fm, fp, fpr, fb,
+                       to, tM, tm, tp, tpr, tb) {
+
+  if (isX(fM))
+    from = '';
+  else if (isX(fm))
+    from = '>=' + fM + '.0.0';
+  else if (isX(fp))
+    from = '>=' + fM + '.' + fm + '.0';
+  else
+    from = '>=' + from;
+
+  if (isX(tM))
+    to = '';
+  else if (isX(tm))
+    to = '<' + (+tM + 1) + '.0.0';
+  else if (isX(tp))
+    to = '<' + tM + '.' + (+tm + 1) + '.0';
+  else if (tpr)
+    to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;
+  else
+    to = '<=' + to;
+
+  return (from + ' ' + to).trim();
+}
+
+
+// if ANY of the sets match ALL of its comparators, then pass
+Range.prototype.test = function(version) {
+  if (!version)
+    return false;
+
+  if (typeof version === 'string')
+    version = new SemVer(version, this.options);
+
+  for (var i = 0; i < this.set.length; i++) {
+    if (testSet(this.set[i], version, this.options))
+      return true;
+  }
+  return false;
+};
+
+function testSet(set, version, options) {
+  for (var i = 0; i < set.length; i++) {
+    if (!set[i].test(version))
+      return false;
+  }
+
+  if (!options)
+    options = {}
+
+  if (version.prerelease.length && !options.includePrerelease) {
+    // Find the set of versions that are allowed to have prereleases
+    // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
+    // That should allow `1.2.3-pr.2` to pass.
+    // However, `1.2.4-alpha.notready` should NOT be allowed,
+    // even though it's within the range set by the comparators.
+    for (var i = 0; i < set.length; i++) {
+      debug(set[i].semver);
+      if (set[i].semver === ANY)
+        continue;
+
+      if (set[i].semver.prerelease.length > 0) {
+        var allowed = set[i].semver;
+        if (allowed.major === version.major &&
+            allowed.minor === version.minor &&
+            allowed.patch === version.patch)
+          return true;
+      }
+    }
+
+    // Version has a -pre, but it's not one of the ones we like.
+    return false;
+  }
+
+  return true;
+}
+
+exports.satisfies = satisfies;
+function satisfies(version, range, options) {
+  try {
+    range = new Range(range, options);
+  } catch (er) {
+    return false;
+  }
+  return range.test(version);
+}
+
+exports.maxSatisfying = maxSatisfying;
+function maxSatisfying(versions, range, options) {
+  var max = null;
+  var maxSV = null;
+  try {
+    var rangeObj = new Range(range, options);
+  } catch (er) {
+    return null;
+  }
+  versions.forEach(function (v) {
+    if (rangeObj.test(v)) { // satisfies(v, range, options)
+      if (!max || maxSV.compare(v) === -1) { // compare(max, v, true)
+        max = v;
+        maxSV = new SemVer(max, options);
+      }
+    }
+  })
+  return max;
+}
+
+exports.minSatisfying = minSatisfying;
+function minSatisfying(versions, range, options) {
+  var min = null;
+  var minSV = null;
+  try {
+    var rangeObj = new Range(range, options);
+  } catch (er) {
+    return null;
+  }
+  versions.forEach(function (v) {
+    if (rangeObj.test(v)) { // satisfies(v, range, options)
+      if (!min || minSV.compare(v) === 1) { // compare(min, v, true)
+        min = v;
+        minSV = new SemVer(min, options);
+      }
+    }
+  })
+  return min;
+}
+
+exports.validRange = validRange;
+function validRange(range, options) {
+  try {
+    // Return '*' instead of '' so that truthiness works.
+    // This will throw if it's invalid anyway
+    return new Range(range, options).range || '*';
+  } catch (er) {
+    return null;
+  }
+}
+
+// Determine if version is less than all the versions possible in the range
+exports.ltr = ltr;
+function ltr(version, range, options) {
+  return outside(version, range, '<', options);
+}
+
+// Determine if version is greater than all the versions possible in the range.
+exports.gtr = gtr;
+function gtr(version, range, options) {
+  return outside(version, range, '>', options);
+}
+
+exports.outside = outside;
+function outside(version, range, hilo, options) {
+  version = new SemVer(version, options);
+  range = new Range(range, options);
+
+  var gtfn, ltefn, ltfn, comp, ecomp;
+  switch (hilo) {
+    case '>':
+      gtfn = gt;
+      ltefn = lte;
+      ltfn = lt;
+      comp = '>';
+      ecomp = '>=';
+      break;
+    case '<':
+      gtfn = lt;
+      ltefn = gte;
+      ltfn = gt;
+      comp = '<';
+      ecomp = '<=';
+      break;
+    default:
+      throw new TypeError('Must provide a hilo val of "<" or ">"');
+  }
+
+  // If it satisifes the range it is not outside
+  if (satisfies(version, range, options)) {
+    return false;
+  }
+
+  // From now on, variable terms are as if we're in "gtr" mode.
+  // but note that everything is flipped for the "ltr" function.
+
+  for (var i = 0; i < range.set.length; ++i) {
+    var comparators = range.set[i];
+
+    var high = null;
+    var low = null;
+
+    comparators.forEach(function(comparator) {
+      if (comparator.semver === ANY) {
+        comparator = new Comparator('>=0.0.0')
+      }
+      high = high || comparator;
+      low = low || comparator;
+      if (gtfn(comparator.semver, high.semver, options)) {
+        high = comparator;
+      } else if (ltfn(comparator.semver, low.semver, options)) {
+        low = comparator;
+      }
+    });
+
+    // If the edge version comparator has a operator then our version
+    // isn't outside it
+    if (high.operator === comp || high.operator === ecomp) {
+      return false;
+    }
+
+    // If the lowest version comparator has an operator and our version
+    // is less than it then it isn't higher than the range
+    if ((!low.operator || low.operator === comp) &&
+        ltefn(version, low.semver)) {
+      return false;
+    } else if (low.operator === ecomp && ltfn(version, low.semver)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+exports.prerelease = prerelease;
+function prerelease(version, options) {
+  var parsed = parse(version, options);
+  return (parsed && parsed.prerelease.length) ? parsed.prerelease : null;
+}
+
+exports.intersects = intersects;
+function intersects(r1, r2, options) {
+  r1 = new Range(r1, options)
+  r2 = new Range(r2, options)
+  return r1.intersects(r2)
+}
+
+exports.coerce = coerce;
+function coerce(version) {
+  if (version instanceof SemVer)
+    return version;
+
+  if (typeof version !== 'string')
+    return null;
+
+  var match = version.match(re[COERCE]);
+
+  if (match == null)
+    return null;
+
+  return parse((match[1] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0')); 
+}
diff --git a/input_devices/mag/node_modules/serialport/.jshintrc b/input_devices/mag/node_modules/serialport/.jshintrc
deleted file mode 100644
index a29cee3f..00000000
--- a/input_devices/mag/node_modules/serialport/.jshintrc
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "node": true,
-  "strict": true,
-  "mocha": true,
-
-  "curly": true,
-  "eqeqeq": true,
-  "expr": true,
-  "immed": true,
-  "latedef": true,
-  "loopfunc": false,
-  "noarg": true,
-  "shadow": false,
-  "supernew": false,
-  "undef": true,
-
-  "newcap": true,
-  "noempty": true,
-  "nonew": true,
-  "indent": 2,
-  "white": true,
-  "quotmark": true,
-
-  "maxparams": 5,
-  "maxdepth": 3,
-  "maxstatements": 60, //default 25
-  "maxcomplexity": 40 //default 6
-}
diff --git a/input_devices/mag/node_modules/serialport/.npmignore b/input_devices/mag/node_modules/serialport/.npmignore
deleted file mode 100644
index ff1f4553..00000000
--- a/input_devices/mag/node_modules/serialport/.npmignore
+++ /dev/null
@@ -1,5 +0,0 @@
-serialport_native/build
-serialport_native.node
-serialport_native/.lock-wscript
-*.node
-.DS_Store
diff --git a/input_devices/mag/node_modules/serialport/.travis.yml b/input_devices/mag/node_modules/serialport/.travis.yml
deleted file mode 100644
index f43cfff9..00000000
--- a/input_devices/mag/node_modules/serialport/.travis.yml
+++ /dev/null
@@ -1,74 +0,0 @@
-language: node_js
-node_js:
-- '0.10'
-- '0.11'
-compiler: clang
-env:
-  global:
-    - secure: "Zg7w8hTpgVfm6JeTScsMhaexFcVS5N2oI9O/6MLtsm3CUhb0Txq65y4y/a5DU3re6Pl1ryE21anVLdg4RGDeykCauQtg8nFzuGXBfNn9bRTnsIfkiS9LNkbSZ8h3c7EsyX0NJ7LVgnkPh/XXMqMj4Nh0ovbBCwZJ6k2ZvccvDvU="
-    - secure: "VS7JTJYfcCDOiWZH6g+Lm4y+QFuCB++4GnYvWqqaUljebuB2l8gZhDrmQtWKFPBEZP21ptjtpNWJC6hCUf07qJ81vVpb6wMUikfOOLN0nulED+AC5HtCxYnfwIu1i0z00YxaSfvozMXKk9TCLabE0ognoDV+XV1bQoYm8668z7E="
-
-before_install:
-# get commit message
-- COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
-# put local node-pre-gyp on PATH
-- export PATH=./node_modules/.bin/:$PATH
-# put global node-gyp on PATH
-- npm install node-gyp -g
-# install aws-sdk so it is available for publishing
-- npm install aws-sdk
-# figure out if we should publish
-- PUBLISH_BINARY=false
-# if we are building a tag then publish
-- if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]]; then PUBLISH_BINARY=true; fi;
-# or if we put [publish binary] in the commit message
-- if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then PUBLISH_BINARY=true; fi;
-- platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/")
-# If version is 0.9 do not publish to avoid duplicated binary error, caused by 0.9 and 0.10
-# returning same v number in node.js.
-- if [[ "$TRAVIS_NODE_VERSION" == '0.9' ]]; then PUBLISH_BINARY=false; fi;
-# Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages
-- sudo apt-get update -qq
-
-
-install:
-# ensure source install works
-- npm install --build-from-source
-# test our module
-- node serialport.js
-
-before_script:
-- echo "Publishing native platform Binary Package? ->" $PUBLISH_BINARY
-# if publishing, do it
-- if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp package publish; fi;
-# cleanup
-- node-pre-gyp clean
-- node-gyp clean
-
-script:
-# if publishing, test installing from remote
-- INSTALL_RESULT=0
-- if [[ $PUBLISH_BINARY == true ]]; then INSTALL_RESULT=$(npm install --fallback-to-build=false > /dev/null)$? || true; fi;
-# if install returned non zero (errored) then we first unpublish and then call false so travis will bail at this line
-- if [[ $INSTALL_RESULT != 0 ]]; then echo "returned $INSTALL_RESULT";node-pre-gyp unpublish;false; fi
-# If success then we arrive here so lets clean up
-- node-pre-gyp clean
-# node v0.8 and above provide pre-built 32 bit and 64 bit binaries
-# so here we use the 32 bit ones to also test 32 bit builds
-- NVER=`node -v`
-- wget http://nodejs.org/dist/${NVER}/node-${NVER}-${platform}-x86.tar.gz
-- tar xf node-${NVER}-${platform}-x86.tar.gz
-# enable 32 bit node
-- export PATH=$(pwd)/node-${NVER}-${platform}-x86/bin:$PATH
-# install 32 bit compiler toolchain and X11
-- if [[ "$platform" == 'linux' ]]; then sudo apt-get -y install gcc-multilib g++-multilib; fi
-# test source compile in 32 bit mode with internal libsqlite3
-- if [[ "$platform" == 'linux' ]]; then CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source; else npm install --build-from-source; fi
-- npm test
-# publish 32 bit build
-- echo "Publishing x86 32bit Binary Package? ->" $PUBLISH_BINARY
-- if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp package publish; fi;
-
-after_success:
-# if success then query and display all published binaries
-- node-pre-gyp info
diff --git a/input_devices/mag/node_modules/serialport/AUTHORS b/input_devices/mag/node_modules/serialport/AUTHORS
deleted file mode 100644
index fa57b592..00000000
--- a/input_devices/mag/node_modules/serialport/AUTHORS
+++ /dev/null
@@ -1,18 +0,0 @@
-# The main authors of this library
-
-Chris Williams <chris@iterativedesigns.com>
-Jay Beavers <jay@hikinghomeschoolers.org>
-Francis Gulotta <wizard@roborooter.com>
-Rob Giseburt <giseburt@gmail.com>
-
-# Other contributors ordered by first contribution.
-
-Joe Ferner <joe.ferner@nearinfinity.com>
-Esa-Matti Suuronen <esa-matti@suuronen.org>
-Nathan Rajlich <nathan@tootallnate.net>
-Rick Waldron <waldron.rick@gmail.com>
-<w1nk>
-Georges-Etienne Legendre <legege>
-Duane Johnson <duane.johnson@gmail.com>
-Rod Vagg <@rvagg>
-Edgar Silva <@edgarsilva>
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/CHANGELOG.md b/input_devices/mag/node_modules/serialport/CHANGELOG.md
new file mode 100644
index 00000000..7e9febd0
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/CHANGELOG.md
@@ -0,0 +1,578 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+<a name="7.0.2"></a>
+## [7.0.2](https://github.com/node-serialport/node-serialport/compare/serialport@7.0.1...serialport@7.0.2) (2018-08-29)
+
+**Note:** Version bump only for package serialport
+
+
+
+
+
+<a name="7.0.1"></a>
+## [7.0.1](https://github.com/node-serialport/node-serialport/compare/serialport@7.0.0...serialport@7.0.1) (2018-08-29)
+
+**Note:** Version bump only for package serialport
+
+
+
+
+
+<a name="7.0.0"></a>
+# 7.0.0 (2018-08-26)
+
+**Note:** Version bump only for package serialport
+
+
+
+
+
+<a name="6.2.2"></a>
+## 6.2.2 (2018-07-21)
+
+* fix: npm and git ignore for prebuild ([fb565fd](https://github.com/node-serialport/node-serialport/commit/fb565fd))
+* fix: Remove a new Buffer() call (#1603) ([e21fe7a](https://github.com/node-serialport/node-serialport/commit/e21fe7a)), closes [#1603](https://github.com/node-serialport/node-serialport/issues/1603)
+* Add support for beaglebone serial ports. (#1600) ([384eb37](https://github.com/node-serialport/node-serialport/commit/384eb37)), closes [#1600](https://github.com/node-serialport/node-serialport/issues/1600)
+* put back prebuild binary builders (#1602) ([4160aca](https://github.com/node-serialport/node-serialport/commit/4160aca)), closes [#1602](https://github.com/node-serialport/node-serialport/issues/1602)
+
+
+
+<a name="6.2.1"></a>
+## 6.2.1 (2018-06-28)
+
+Thanks to @shodan8192 for finding and fixing a memory leak on unix systems!
+
+* docs: fix link to parser docs ([f2285d0](https://github.com/node-serialport/node-serialport/commit/f2285d0))
+* docs: regenerate docs ([eb053db](https://github.com/node-serialport/node-serialport/commit/eb053db))
+* chore: change to new parser packages and upgrade (fix builds) (#1562) ([d829ada](https://github.com/node-serialport/node-serialport/commit/d829ada)), closes [#1562](https://github.com/node-serialport/node-serialport/issues/1562)
+* chore: drop node 4 EOL, add node 10 🎉 (#1556) ([e1998b3](https://github.com/node-serialport/node-serialport/commit/e1998b3)), closes [#1556](https://github.com/node-serialport/node-serialport/issues/1556)
+* chore(package): update conventional-changelog-cli to version 2.0.0 (#1571) ([1bf70ae](https://github.com/node-serialport/node-serialport/commit/1bf70ae)), closes [#1571](https://github.com/node-serialport/node-serialport/issues/1571)
+* chore(package): update package specs (#1557) ([4ed5182](https://github.com/node-serialport/node-serialport/commit/4ed5182)), closes [#1557](https://github.com/node-serialport/node-serialport/issues/1557)
+* chore(package): upgrade packages ([46d798d](https://github.com/node-serialport/node-serialport/commit/46d798d))
+* fix: a few warnings and deprecations (#1558) ([a250f09](https://github.com/node-serialport/node-serialport/commit/a250f09)), closes [#1558](https://github.com/node-serialport/node-serialport/issues/1558)
+* fix: build isn't using the right version on 32x (#1564) ([f9953f2](https://github.com/node-serialport/node-serialport/commit/f9953f2)), closes [#1564](https://github.com/node-serialport/node-serialport/issues/1564)
+* fix: memory leak in unix serialport poller (#1572) ([9006bd6](https://github.com/node-serialport/node-serialport/commit/9006bd6)), closes [#1572](https://github.com/node-serialport/node-serialport/issues/1572)
+
+
+
+<a name="6.2.0"></a>
+## 6.2.0 (2018-04-18)
+
+This is a recommended release for everyone on windows as it fixes a memory leak in write operations.
+
+* docs: fix missing options objects and descriptions (#1504) ([e8b73c2](https://github.com/node-serialport/node-serialport/commit/e8b73c2)), closes [#1504](https://github.com/node-serialport/node-serialport/issues/1504)
+* docs: node 9 is working well these days ([b585c11](https://github.com/node-serialport/node-serialport/commit/b585c11))
+* docs: Switch to @reconbot/jsdoc-theme for docs ([a31078f](https://github.com/node-serialport/node-serialport/commit/a31078f))
+* docs(contributing): clean up the instructions a little bit ([71f2480](https://github.com/node-serialport/node-serialport/commit/71f2480))
+* docs(parsers): improve the parser examples ([41f1d2d](https://github.com/node-serialport/node-serialport/commit/41f1d2d))
+* fix(windows): Reset Buffer after write operations are complete to free memory (#1547) ([a1eef11](https://github.com/node-serialport/node-serialport/commit/a1eef11)), closes [#1547](https://github.com/node-serialport/node-serialport/issues/1547)
+* chore: Avoid using deprecated Buffer constructor (#1510) ([0c1533b](https://github.com/node-serialport/node-serialport/commit/0c1533b)), closes [#1510](https://github.com/node-serialport/node-serialport/issues/1510) [/nodejs.org/api/deprecations.html#deprecations_dep0005](https://github.com//nodejs.org/api/deprecations.html/issues/deprecations_dep0005)
+* chore: fix package json indents ([7c9b609](https://github.com/node-serialport/node-serialport/commit/7c9b609))
+* chore: move parsers to their new packages and clean up docs ([4bccb62](https://github.com/node-serialport/node-serialport/commit/4bccb62))
+* chore: remove old doc file ([37a8373](https://github.com/node-serialport/node-serialport/commit/37a8373))
+* chore(docs): Minor spelling change ([8a13e9f](https://github.com/node-serialport/node-serialport/commit/8a13e9f))
+* chore(package): update eslint-config-standard to version 11.0.0 (#1492) ([cf5b8fb](https://github.com/node-serialport/node-serialport/commit/cf5b8fb)), closes [#1492](https://github.com/node-serialport/node-serialport/issues/1492)
+* chore(package): update proxyquire to version 2.0.0 (#1511) ([bac0237](https://github.com/node-serialport/node-serialport/commit/bac0237)), closes [#1511](https://github.com/node-serialport/node-serialport/issues/1511)
+* chore(package): update sinon to version 5.0.0 ([9dbccbc](https://github.com/node-serialport/node-serialport/commit/9dbccbc))
+* chore(packages): ugprade conventional-changelog-cli@1.3.15 ([270c2be](https://github.com/node-serialport/node-serialport/commit/270c2be))
+* chore(packages): ugprade nan@2.9.2 (#1503) ([557afa4](https://github.com/node-serialport/node-serialport/commit/557afa4)), closes [#1503](https://github.com/node-serialport/node-serialport/issues/1503)
+* chore(packages): upgrade conventional-changelog@1.3.12 ([2b8f957](https://github.com/node-serialport/node-serialport/commit/2b8f957))
+* feat: upgrade socket-io example to latest serialport and fix bug (#1505) ([86e5ab0](https://github.com/node-serialport/node-serialport/commit/86e5ab0)), closes [#1505](https://github.com/node-serialport/node-serialport/issues/1505)
+* feat(linter): Added 'cc' to lint the C++ code on 'npm lint' (#1501) ([59960a3](https://github.com/node-serialport/node-serialport/commit/59960a3)), closes [#1501](https://github.com/node-serialport/node-serialport/issues/1501)
+* feat(windows): Fetch USB serial number by lookups in win registry (#1483) ([45b3a2f](https://github.com/node-serialport/node-serialport/commit/45b3a2f)), closes [#1483](https://github.com/node-serialport/node-serialport/issues/1483) [#1459](https://github.com/node-serialport/node-serialport/issues/1459)
+
+
+
+<a name="6.1.1"></a>
+## <small>6.1.1 (2018-02-28)</small>
+
+* chore(docs): Minor spelling and grammer changes. ([093c85d](https://github.com/node-serialport/node-serialport/commit/093c85d))
+* fix(linux): Adds missing header file for musl libc (eg alpine) (#1487) ([02e2bfe](https://github.com/node-serialport/node-serialport/commit/02e2bfe)), closes [#1487](https://github.com/node-serialport/node-serialport/issues/1487) [#1470](https://github.com/node-serialport/node-serialport/issues/1470)
+* docs: Add appropriate thanks to the changelog ([a3b3663](https://github.com/node-serialport/node-serialport/commit/a3b3663))
+* docs(api): commit docs for github pages ([792459d](https://github.com/node-serialport/node-serialport/commit/792459d))
+* docs(changelog) :fix typo (#1484) ([2da025e](https://github.com/node-serialport/node-serialport/commit/2da025e)), closes [#1484](https://github.com/node-serialport/node-serialport/issues/1484)
+
+
+
+<a name="6.1.0"></a>
+# 6.1.0 (2018-02-06)
+
+* chore(github): lock old issues and prs ([c8d2655](https://github.com/node-serialport/node-serialport/commit/c8d2655))
+* chore(package): update eslint-plugin-node to version 6.0.0 (#1466) ([bac94a0](https://github.com/node-serialport/node-serialport/commit/bac94a0)), closes [#1466](https://github.com/node-serialport/node-serialport/issues/1466)
+* feat(linux): Custom baud rates for linux (eg 250k baudrate) (#1464) ([910438c](https://github.com/node-serialport/node-serialport/commit/910438c)), closes [#1464](https://github.com/node-serialport/node-serialport/issues/1464) Thanks to @Fumon for closing this long standing issue!
+
+
+
+<a name="6.0.5"></a>
+## 6.0.5 (2018-02-04)
+
+* fix(changelog): drop the augular changelog as it misses commits ([7d0ff88](https://github.com/node-serialport/node-serialport/commit/7d0ff88))
+* fix(docs): Put gitter link back ([f8f3ce5](https://github.com/node-serialport/node-serialport/commit/f8f3ce5))
+* fix(terminal): specifying a port now behaves correctly (#1463) ([1fa20e7](https://github.com/node-serialport/node-serialport/commit/1fa20e7)), closes [#1463](https://github.com/node-serialport/node-serialport/issues/1463)
+* chore(build): build on node 9 ([a819bca](https://github.com/node-serialport/node-serialport/commit/a819bca))
+* chore(docs): fix appveyor links in readme ([388d37b](https://github.com/node-serialport/node-serialport/commit/388d37b))
+* chore(package): update commander to version 2.13.0 ([a94fea0](https://github.com/node-serialport/node-serialport/commit/a94fea0))
+* chore(package): update mocha to version 5.0.0 (#1446) ([e728ff3](https://github.com/node-serialport/node-serialport/commit/e728ff3)), closes [#1446](https://github.com/node-serialport/node-serialport/issues/1446)
+* chore(package): update prebuild to version 7.0.0 ([bc46149](https://github.com/node-serialport/node-serialport/commit/bc46149))
+* chore(package): update prebuild-install to version 2.4.1 ([13e8d0a](https://github.com/node-serialport/node-serialport/commit/13e8d0a))
+* chore(package): update sinon to version 4.1.5 ([699a907](https://github.com/node-serialport/node-serialport/commit/699a907))
+* chore(packages): upgrade eslint ([416cfe3](https://github.com/node-serialport/node-serialport/commit/416cfe3))
+* chore(packages): upgrade sinon ([17148df](https://github.com/node-serialport/node-serialport/commit/17148df))
+* Add null check code ([602793d](https://github.com/node-serialport/node-serialport/commit/602793d))
+* Adding in port selection to serialport-term. (#1448) ([9f543b6](https://github.com/node-serialport/node-serialport/commit/9f543b6)), closes [#1448](https://github.com/node-serialport/node-serialport/issues/1448)
+* Bumping prebuild version and updating docs with info about building against NW.js headers. (#1461) ([672c198](https://github.com/node-serialport/node-serialport/commit/672c198)), closes [#1461](https://github.com/node-serialport/node-serialport/issues/1461)
+* docs(readme): Fix broken link to gitter (#1457) ([3e68e8f](https://github.com/node-serialport/node-serialport/commit/3e68e8f)), closes [#1457](https://github.com/node-serialport/node-serialport/issues/1457)
+* docs(readyParser): correct the required parameters (#1392) ([dcd256d](https://github.com/node-serialport/node-serialport/commit/dcd256d)), closes [#1392](https://github.com/node-serialport/node-serialport/issues/1392)
+* feat(docs): Switch to JSDOC docs not in the readme (#1383) ([60fc047](https://github.com/node-serialport/node-serialport/commit/60fc047)), closes [#1383](https://github.com/node-serialport/node-serialport/issues/1383)
+* feat(parsers): Adding option to include delimiter in the DelimiterParser transform. (#1453) ([6a3ab65](https://github.com/node-serialport/node-serialport/commit/6a3ab65)), closes [#1453](https://github.com/node-serialport/node-serialport/issues/1453)
+* feat(parsers): ByteLength is now more efficient (#1402) ([f7eb2f0](https://github.com/node-serialport/node-serialport/commit/f7eb2f0)), closes [#1402](https://github.com/node-serialport/node-serialport/issues/1402)
+
+
+
+<a name="6.0.4"></a>
+## [6.0.4](https://github.com/node-serialport/node-serialport/compare/v6.0.3...v6.0.4) (2017-10-26)
+
+
+### Bug Fixes
+
+* **packages:** just-extend isn't necessary anymore ([#1376](https://github.com/node-serialport/node-serialport/issues/1376)) ([8f650c3](https://github.com/node-serialport/node-serialport/commit/8f650c3))
+* **windows:** bad parameter for ReadThread (windows) ([#1377](https://github.com/node-serialport/node-serialport/issues/1377)) ([6f3afbe](https://github.com/node-serialport/node-serialport/commit/6f3afbe))
+
+
+
+<a name="6.0.3"></a>
+## [6.0.3](https://github.com/node-serialport/node-serialport/compare/v6.0.0...v6.0.3) (2017-10-22)
+
+### Bug Fixes
+
+* **windows:** Fix async handle leak ([#1367](https://github.com/node-serialport/node-serialport/issues/1367)) ([c1d9d88](https://github.com/node-serialport/node-serialport/commit/c1d9d88)), closes [#1363](https://github.com/node-serialport/node-serialport/issues/1363)
+* **windows:** Fix read & write bugs for windows ([#1364](https://github.com/node-serialport/node-serialport/issues/1364)) ([0e4b1f9](https://github.com/node-serialport/node-serialport/commit/0e4b1f9))
+
+
+
+<a name="6.0.0"></a>
+# [6.0.0](https://github.com/node-serialport/node-serialport/compare/5.0.0...v6.0.0) (2017-10-09)
+
+
+### Features
+
+* **open:** Throw on incorrect baudrate option ([#1347](https://github.com/node-serialport/node-serialport/issues/1347)) ([a3b8d35](https://github.com/node-serialport/node-serialport/commit/a3b8d35))
+* **parsers:** Add cctalk parsers ([#1342](https://github.com/node-serialport/node-serialport/issues/1342)) ([bcb492f](https://github.com/node-serialport/node-serialport/commit/bcb492f))
+* **test:** tone down codecov comments ([#1289](https://github.com/node-serialport/node-serialport/issues/1289)) ([749ffac](https://github.com/node-serialport/node-serialport/commit/749ffac))
+* **windows:** Add ERROR_INVALID_PARAMETER to supported bindings errors ([#1354](https://github.com/node-serialport/node-serialport/issues/1354)) ([4ff9c67](https://github.com/node-serialport/node-serialport/commit/4ff9c67))
+
+
+### Bug Fixes
+
+* **docs:** Add a note about windows support ([76b7191](https://github.com/node-serialport/node-serialport/commit/76b7191)), closes [#1299](https://github.com/node-serialport/node-serialport/issues/1299)
+* **docs:** add missing parsers to properties list ([3faadac](https://github.com/node-serialport/node-serialport/commit/3faadac))
+* **docs:** correct default highWaterMark to 65536 bytes ([e83ec4e](https://github.com/node-serialport/node-serialport/commit/e83ec4e))
+* **docs:** Fixed typo in upgrade guide ([#1321](https://github.com/node-serialport/node-serialport/issues/1321)) ([bf251a9](https://github.com/node-serialport/node-serialport/commit/bf251a9))
+* **linux:** The productID should be a number not a description string ([#1279](https://github.com/node-serialport/node-serialport/issues/1279)) ([bf46f68](https://github.com/node-serialport/node-serialport/commit/bf46f68))
+* **package:** update debug to version 3.0.0 ([#1292](https://github.com/node-serialport/node-serialport/issues/1292)) ([4987750](https://github.com/node-serialport/node-serialport/commit/4987750))
+* **tests:** fixup for [#1279](https://github.com/node-serialport/node-serialport/issues/1279) ([#1285](https://github.com/node-serialport/node-serialport/issues/1285)) ([56074f6](https://github.com/node-serialport/node-serialport/commit/56074f6))
+* **windows:** Add option to disable RTS ([#1277](https://github.com/node-serialport/node-serialport/issues/1277)) ([5b8d163](https://github.com/node-serialport/node-serialport/commit/5b8d163))
+* **windows:** Asynchronous callbacks for reading and writing ([#1328](https://github.com/node-serialport/node-serialport/issues/1328)) ([69de595](https://github.com/node-serialport/node-serialport/commit/69de595)), closes [#1221](https://github.com/node-serialport/node-serialport/issues/1221)
+* **windows:** Parse more types of pnpIds ([#1288](https://github.com/node-serialport/node-serialport/issues/1288)) ([0b554d7](https://github.com/node-serialport/node-serialport/commit/0b554d7)), closes [#1220](https://github.com/node-serialport/node-serialport/issues/1220)
+
+
+### Chores
+
+* **binaries:** Lets switch to prebuild! ([#1282](https://github.com/node-serialport/node-serialport/issues/1282)) ([8c36e99](https://github.com/node-serialport/node-serialport/commit/8c36e99))
+
+### BREAKING CHANGES
+
+* **binaries:** We switched to `prebuild` a breaking change because it's substantially changes our install processes. It's also possible the install flags to ensure downloading or building from source has changed slightly. That's not our api per say, but it's enough.
+* **windows:** We previously hard coded to have RTS on for windows at all times it now default to off.
+
+
+Version 5.0.0 🎉
+-------------
+Nearly [a year in the making](https://github.com/node-serialport/node-serialport/compare/4.0.7...5.0.0-beta9) Node SerialPort 5.0.0 is a major rewrite that improves stability, compatibility and performance. The api surface is similar to version 4 there have been a number of changes to ensure consistent error handling and operation of a serial port. Notably we are now a [`Stream`](https://nodejs.org/api/stream.html)! We can also introduce a bindings layer. A small low level api to provide access to underlying hardware. External bindings written in other languages or targeting other platforms can now be used.
+
+Some major cpu performance gains on unix platforms can be found and we're less buggy and better performing on Windows too.
+
+With this release we are now only supporting LTS nodejs platforms and we are dropping NodeJS 0.10, 0.12, 5 and 7 support. We loved directly supporting so many platforms but it was getting in the way making a solid library.
+
+See our [upgrade guide](./UPGRADE_GUIDE.md) for detail on what to change to upgrade your app to use `serialport@5.0.0`. It's not much!
+
+Thank you to the 25 people who committed code and documentation and every person who submitted bug reports and tested changes!
+
+Notable Changes
+- [all] Streams rewrite, node serialport is now a node stream! 🎉
+- [all] Drop NodeJS 0.10, 0.12, 5, and 7 support
+- [all] Add node 8 support (we now only support LTS node versions)
+- [all] Introduce a binding layer to provide a common low level interface to work with different platforms.
+- [unix] New read/write subsystem. Write CPU dropped from 100% to 0-2%. @reconbot (Thanks to @indutny for getting me unstuck many times!)
+- [windows] Rewrite reading so it's pausable thanks to @munyirik
+- [docs] An overhaul how we document the api leveraging JSDOC
+- [docs] An overhaul of the format and language in our docs thanks to @LappleApple
+
+Features
+- [all] `isOpen` is now a property #899
+- [all] `SerialPort.list` now has more consistent output across all platforms.
+- [all] `SerialPort.list` returns a promise if a callback is not provided thanks to @MikeKovarik for bug fixes
+- [all] A promise aware `serialport-repl` script for debugging and testing.
+- [all] add `#get` to retrieve modem status flags thanks to @jgillick!
+- [all] Add a `MockBinding` object for testing serialports in your project. Used internally too!
+- [all] Add electron precompiled binaries thanks to @Mike-Dax
+- [all] Add regex stream parser and tests @jessicaquynh
+- [all] Allow reopening after an open error #910
+- [all] calls to `.drain` now queue behind port open and in progress writes reported by and with lots of testing help from @tuna-f1sh
+- [all] Change parsers to be transform streams #922
+- [all] Change the default `highWaterMark` to 64k to match `fs.ReadStream`
+- [all] Conform to NodeJS error message formats
+- [all] Exposed mocking serialport via `require('serialport/test')`
+- [all] Have drain wait for pending JS write operations before calling system drain thanks to @digitalhack for reporting it
+- [all] port.path is now read only #898
+- [all] Refactor internals to make use of es6 and promises
+- [all] Remove lowercase options #898
+- [all] Remove the c++ write queue
+- [all] Remove unnecessary dependencies and polyfills thanks to @mscdex
+- [all] Remove v8 deprecation warnings thanks to @indutny again
+- [all] Removed the `disconnect` event. The `close` event now fires with a disconnect error object in the event of a disconnection.
+- [all] SerialPort can now be compressed with `uglify-es` thanks to @rwaldron
+- [all] update bindings to version 1.3.0
+- [all] Upgrade debug and node-pre-gyp
+- [all] Upgrade to non deprecated buffer methods
+- [docs] Add more installation notes on sudo, windows 10, electron and node 7
+- [docs] Add socketio example @jessicaquynh
+- [docs] Electron build docs #965 via @chalkers
+- [docs] Mark new features in 5.0.0 with the fact they started in 5.0.0
+- [docs] Update parser docs to be correct #970 via @jacobq
+- [linux] `SerialPort.list` is now faster and less resource intensive thanks to @akaJes!
+- [linux] Add the `ttyAP` subsystem to serialport list thanks to @fly19890211 for reporting it
+- [osx] `SerialPort.list` now returns the `tty` instead of the `cu` thanks to @kishinmanglani
+- [unix] Flush now gives errors and flushes tx and rx #900
+- [unix] Move setting up the baudrate to the end of the `open()` to better support custom baudrates
+- [windows] Refactoring of `.list` for Windows so it's significantly smaller thanks to @Zensey
+
+Fixes
+- [all] Fix baud rate parsing in `serialport-terminal` thanks to @radio-miskovice for reporting it!
+- [all] Fix memory leak during opening a port thanks to @indutny
+- [all] fixed a crash when pausing while reading thanks to @bminer and @baffo32 and others to debug and fix this
+- [all] Upgrade nan to fix compile issues on some platforms thanks to @thom-nic
+- [docs] fixed a typo thanks to @amilajack
+- [docs] Spelling fixes via @Awk34
+- [unix] fix a bug when poller errors would be unhandled thanks to @thiago-sylvain for reporting
+- [windows] Fix file handle leak during opens when errors occur thanks to @enami
+- [windows] Fix flush behavior using PurgeComm fixing #962 via @samisaham
+- [windows] Fix unhandled promise rejection when calling read on Windows
+- [windows] Remove read and write timeouts solving #781 via @giseburt
+
+We also had help testing, debugging, and designing from; @alaq @arve0 @techninja @noopkat @HipsterBrown and more!
+
+Version 4.0.7
+-------------
+- [all] Fix baud rate parsing in `serialport-terminal` thanks to @radio-miskovice for reporting it!
+- [windows] Refactor `SerialPort.list` to be a lot smaller and pickup vendorId, productId and locationId thanks to @zensey for #877!
+
+Version 4.0.6
+-------------
+- [all] Upgrade nan to fix compile issues on some platforms thanks to @thom-nic
+- [all] Upgrade debug and node-pre-gyp
+
+Version 4.0.5
+-------------
+- [windows] Fix file handle leak during opens when errors occur thanks to @enami
+- [all] Fix memory leak during opening a port thanks to @indutny
+
+Version 4.0.4
+-------------
+- Add precompiled binaries for node 7
+
+Version 4.0.3
+-------------
+- Switch to the lie promise library as it's smaller and mimics nodejs's promise closer
+- Fix a bug that prevented reopening a port after an open error
+
+Version 4.0.2
+-------------
+- [unix] Fix a bug when we'd crash when pausing during a read
+
+Version 4.0.1
+-------------
+- [linux] Do not replace the native Promise when it is available thanks to @zewish for the fix
+
+Version 4.0.0
+-------------
+- Requiring `serialport` now returns the SerialPort constructor function instead of a factory object. `SerialPort.SerialPort` is now deprecated.
+- `SerialPort` constructor now throws on argument errors immediately.
+- `.write(writeCallback)` now only calls it's callback once after the entire write operation, it used to be called for each write cycle and return the bytes written. This reduces the number of callbacks by hundreds of thousands over a megabyte at low bandwidth.
+- Disconnections now always attempt to close the port, and you'll always get a `close` event after a `disconnect` event
+- All callbacks are called in the context of the port, `this` now equals the port.
+- Removed `openImmediately` from the constructor's api, the functionality is now named `autoOpen` on the options object.
+- Removed extraneous flow control settings from the `flowControl` option, use the specific options to set these flags now.
+- Removed undocumented callbacks from the options object `disconnectedCallback` and `dataCallback`
+- Renamed `serialportlist` to `serialport-list`
+- Renamed `serialportterm` to `serialport-term`
+- Added a contributors guide
+- Added our first Arduino required integration tests
+- [unix] `.drain` and `.set` now properly report errors
+- [unix] Ports are now locked by default with the new `lock` options matches windows default behavior
+- [windows] `.update()` now supports windows for changing baud rates
+- [windows] Fixed a bug where we weren't properly opening ports (provides better support virtual com ports too) thanks to @RogerHardiman
+- [windows] known issue `lock: false` doesn't work (no change in behavior)
+
+Version 3.1.2
+-------------
+- Documentation around "Illegal Instruction" errors
+- Resolve some ambiguities around publishing that was causing some issues on some versions and platforms of npm and node
+- [linux] bug fix in `.list()` where we weren't filtering out non block devices that are named like serial ports
+- [unix] Better unix error messages
+- [unix] Refactor `setBaudrate` for Unix making it easier for custom baudRate support
+- [unix] Update now has less memory leaks, documentation and better error messages
+- [windows] Better error messages for opening ports
+
+Version 3.1.1
+-------------
+- fix an issue with bundled deps for node-pre-gyp on npm
+
+Version 3.1.0
+-------------
+- Upgrade nan and fix warnings for node 6.0
+- Update the cli tools. serialport-term can now list ports, serialport-list can now output in different formats
+
+Version 3.0.1
+-------------
+- Change from BlueBird to es6-promise to save 9.5MB from the package size (19M -> 9.5) and 130k bundle size (186.1kb -> 55.2kb)
+- Experimental node 6 support
+
+Version 3.0.0
+-------------
+- `close` and `disconnect` events no longer call `removeAllListeners` and removes your event listeners. This was particularly bad for the `error` event. This is the only change and if you didn't have a special code to deal with this behavior you should probably upgrade from v2.1.2
+
+Version 2.1.2
+-------------
+- Start bundling node-pre-gyp but upgrade it to the latest as the previous version doesn't install
+
+Version 2.1.1
+-------------
+- `.list` errors are consistent across platforms and no longer has blocking `statSync` calls
+- Stop bundling node-pre-gyp to prevent issues when it's already installed
+- Internal restructuring
+
+Version 2.1.0
+-------------
+- Major refactor, bug fixes and docs improvements thanks to @ecksun, @fivdi, @gfcittolin, @jacobrosenthal, @mhart, @nebrius, @pabigot, @paulkaplan, @reconbot, @rodovich, @rwaldron, @sayanee, @tigoe and everyone who reported and helped debug issues!
+- Fix binary paths to confirm with modern standards
+- Integration tests on CI's that support it or for the folks at home with an arduino handy
+- Upgrade to nan-2.2.1 for memory leak fixes and node 6 compatibility (still not supported)
+- Confirm nw.js and electron compatibility
+- Make the outpout of `.list` consistent between platforms and docs
+- Define ambiguous flow control flags and document them
+- Fix support systems who provide 0 as a valid file descriptor
+- Fix race conditions when opening and closing ports that led to errors while reading and writing while closing or opening the port.
+- [unix] Fix a double open bug on unix that would cause opening and closing ports repetitively to error.
+- [unix] Listing serialports on linux now include more ports (including bluetooth devices eg. `/dev/rfcommXX`) and have less bugs in the output
+- [windows] Remove deprecated BuildCommDCB for windows 10 support
+- [windows] Fix a memory leak on windows
+- [windows] Fix a 100% cpu and possible hang bug when ports were disconnected on windows.
+
+Version 2.0.6
+-------------
+- Add 5.x build to matrix, thanks @deadprogram
+- Re add nmpignore, thanks @rwaldron
+- Swap to upstream version of node-pre-gyp-github
+
+Version 2.0.5
+-------------
+- Fix linux port listing crash since 2.0.3 refactor, thanks @monkbroc
+
+Version 2.0.4
+-------------
+- Fix heap corruption issue affecting windows users since 2.0.0, thanks @kunalspathak
+
+Version 2.0.3
+-------------
+- Move node-pre-gyp binaries away from Amazon S3 to Github Releases page
+- Fix for missing node-pre-gyp binaries, especially for windows users, since the 2.0.0 refactor which forced windows users to build from source -- generally failing due to lack of dependencies
+- Unix port listing moved away from udev which was not available on all platforms, to whitelisting ttyS ttyACM ttyUSB ttyAMA devices, see #610
+
+Version 2.0.2
+-------------
+- Cleanup minor Unix gcc warnings, Thanks @rwaldron
+
+Version 2.0.1
+-------------
+- El Capitan Support, thanks @tmpvar
+
+Version 2.0.0
+-------------
+- Upgrade to NAN2 to support Node 4 support. Technically not api breaking, though NAN2 requires gcc 4.8 which for Pi Wheezy users at the very least, would be breaking. For those affected users looking to utilize serialport 2.x.x and Node 4 see https://github.com/fivdi/onoff/wiki/Node.js-v4-and-native-addons
+
+Version 1.7.4
+-------------
+- Fix OSX 10.10 build errors
+
+Version 1.7.3
+-------------
+- Fix OSX 10.10 build errors
+
+Version 1.7.2
+-------------
+- Fix OSX 10.10 build errors
+
+Version 1.7.1
+-------------
+- Fixed breaking issues in underlying code. (@voodootikigod)
+
+Version 1.7.0
+-------------
+- Fix for #518 and #498 If you pass to SerialPort function (constructor) the same object for argument "options", inside SerialPort will use it as internal object and adds handlers to it. That causes only one callback to work on different SerialPort instances. (@bullmastiffo)
+- Update README.md #515 (@arahlf)
+- Fix a memory leak in SerialportPoller::New (@jpilet)
+- unix support for update baudrate #502 (@jacobrosenthal)
+- set cloexec after open, possible fix for #468 (@jacobrosenthal)
+- Added hang up on close option to constructor. #495 (@jbendes)
+- Upgraded NAN to 1.8.4 due to complaints from io.js 2.x users. (@imyller)
+
+Version 1.6.1
+-------------
+- Upgraded to NAN 1.7.0
+- #476 adding break signal
+
+Version 1.6.0
+-------------
+- Long standing issue resolved thanks to @jacobrosenthal for adding control signals into the serialport. YAY!
+- Fix for #426
+- Ability to return from inside loop #453
+- Emits for close/disconnect. #452
+
+Version 1.5.0
+-------------
+- Fixed to work with io.js and node 0.11.x by upgrading to recent nan 1.6.2
+
+
+Version 1.4.8
+-------------
+- Simple bump for the binary.
+
+Version 1.4.7
+-------------
+- Fix for Issue #398 - Dropped sent characters on OSX and Linux
+- Fix for Issue #387 - added isOpen
+- removed a residual comment
+- Added osx control signalling
+- Fix for Issue #401
+- Fix for double write callbacks.
+- detect a serialport disconnect on linux.
+
+Version 1.4.6
+-------------
+- Emit error on serialport when explicit handler present. Fixes gh-369
+- Fix for windows and Node 0.11.13 (atom-shell)
+- Fix for broken Travis-CI build.
+
+Version 1.4.5
+-------------
+- Identified and report issue to node.js core about recent 0.11.x system.
+- Removed support for 0.8.x
+- Updated dependencies
+
+Version 1.4.4
+-------------
+- Fix for delete error.
+
+Version 1.3.0
+-------------
+- Merged NAN integration for Node 0.8->0.11+ compatibility (#270)
+
+Version 1.2.5
+-------------
+- Fixed an issue with pool handlers being global instead of instance isolation (Issue #252 and #255 thanks: foobarth !!! )
+
+
+Version 1.2.4
+-------------
+- Resolved parity error under linux as reported here: https://github.com/voodootikigod/node-serialport/issues/219
+
+
+Version 1.1.3
+-------------
+- Remove ATL dependency on Windows (added Visual Studio Pro requirement)
+- Update build instructions
+- Four small bugfixes
+
+Version 1.0.7
+-------------
+- Guaranteed in-order delivery of messages thanks to Jay Beavers and bnoordhuis
+
+Version 1.0.6
+-------------
+- Support higher baud rates in Mac OS X
+
+Version 1.0.5
+-------------
+- Added flush support.
+
+Version 1.0.4
+-------------
+- Fix for arduino firmata support on windows thanks to @jgautier.
+
+Version 1.0.3
+-------------
+- Fixed issue 65 - https://github.com/voodootikigod/node-serialport/issues/65
+- Added note in readme about what is required for the system to be able to compile module, should solve 90% of issues.
+
+Version 1.0.2
+-------------
+- Fixed issue 59 - https://github.com/voodootikigod/node-serialport/issues/59
+
+Version 1.0.1
+-------------
+- Fixed items from Firmata
+- Added flexibility for options (camelcase or all lower)
+
+Version 1.0.0
+-------------
+- Added Windows support thanks to Joe Ferner.
+- Merged in the various underlying changes from node-serialport2 complete thanks to Joe Ferner for that!
+- Verified against known installations.
+
+
+Version 0.6.5
+-------------
+- Added SetBaudRate, SetDTR; Custom Baud Rates
+- New "close" listener when device being disconnected
+
+Version 0.2.8
+-------------
+- BufferSize fix for readstream (thanks jgautier, you rock)
+
+Version 0.2.7
+-------------
+- Make no port available be an exception not error emitted - Ticket #12.
+
+Version 0.2.5 - Version 0.2.6
+-----------------------------
+- Debugging issue with IOWatcher not holding in the event loop in node.js.
+- Converted to ReadStream instead of IOWatcher.
+
+Version 0.2.4
+-------------
+- Integrated arduino tests (rwaldron)
+- Integrated options bug fix (w1nk)
+- Integrated hardware flow control for crazier serial port action (w1nk)
+
+Version 0.2.3
+-------------
+- Something amazing that has since been lost and forgotten.
+
+Version 0.2.2
+-------------
+- Integrated enhanced version of arduino/readline that actually buffers the data (epeli)
+
+Version 0.2.1
+-------------
+- Refactored the parsing code upon data receipt, now allows for dynamic specification of how incoming data is handled.
+- Revised creation interface to use named parameters as an object versions positional parameters.
+
+Version 0.2.0
+------------
+- Upgraded to node v. 0.4.X compatibility
+
+All other version are not recorded.
diff --git a/input_devices/mag/node_modules/serialport/Gruntfile.js b/input_devices/mag/node_modules/serialport/Gruntfile.js
deleted file mode 100644
index 40e03f2c..00000000
--- a/input_devices/mag/node_modules/serialport/Gruntfile.js
+++ /dev/null
@@ -1,24 +0,0 @@
-'use strict';
-
-module.exports = function(grunt) {
-
-  grunt.initConfig({
-    mochaTest: {
-      test: {
-        options: { reporter: 'spec' },
-        src: ['test/**/*.js']
-      }
-    },
-    jshint: {
-      all: ['*.js', 'test/**/*.js', 'arduinoTest/**/*.js'],
-      options:{
-        jshintrc: true
-      }
-    }
-  });
-
-  grunt.loadNpmTasks('grunt-mocha-test');
-  grunt.loadNpmTasks('grunt-contrib-jshint');
-  grunt.registerTask('default', ['jshint', 'mochaTest']);
-
-};
diff --git a/input_devices/mag/node_modules/serialport/LICENSE b/input_devices/mag/node_modules/serialport/LICENSE
index e3c325e1..800d7767 100644
--- a/input_devices/mag/node_modules/serialport/LICENSE
+++ b/input_devices/mag/node_modules/serialport/LICENSE
@@ -1,4 +1,7 @@
-Copyright 2010, 2011, 2012 Christopher Williams. All rights reserved.
+The MIT License (MIT)
+
+Copyright 2010 Christopher Williams. All rights reserved.
+
 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
@@ -15,4 +18,4 @@ 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.
\ No newline at end of file
+IN THE SOFTWARE.
diff --git a/input_devices/mag/node_modules/serialport/Makefile b/input_devices/mag/node_modules/serialport/Makefile
deleted file mode 100644
index 54053fa5..00000000
--- a/input_devices/mag/node_modules/serialport/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-VERSION := $(shell node -e "console.log(require('./package.json').version)")
-
-.PHONY: default release
-
-# Add a default task so we don't release just because someone ran 'make'
-default:
-	@echo "Did you mean to release a new version?"
-	@echo "If so, run 'make release'."
-
-release:
-	@echo "Tagging release $(VERSION)"
-	@git tag -m "$(VERSION)" v$(VERSION)
-
-	@echo "Pushing tags to GitHub"
-	@git push --tags
-
-	@echo "Switching to osx-binaries branch"
-	@git checkout osx-binaries
-
-	@echo "Merging master into osx-binaries"
-	@git merge --no-ff --commit -m "Merge master into osx-binaries [publish binary]" master
-
-	@echo "Pushing osx-binaries"
-	@git push
-
-	@echo "Switching to master branch"
-	@git checkout master
-
-	@echo "Publishing to NPM"
-	@npm publish ./
diff --git a/input_devices/mag/node_modules/serialport/README.md b/input_devices/mag/node_modules/serialport/README.md
index beedeb7f..9b67f68c 100644
--- a/input_devices/mag/node_modules/serialport/README.md
+++ b/input_devices/mag/node_modules/serialport/README.md
@@ -1,411 +1,469 @@
+# Node Serialport
+
+## Quick Answers to Important Questions
+- [**API Docs**](https://node-serialport.github.io/node-serialport/)
+- **For support**, open a [GitHub issue](https://github.com/node-serialport/node-serialport/issues/new).
+- **For discussions, design ideas, and clarifications**, please join our [Gitter chat room](https://gitter.im/EmergingTechnologyAdvisors/node-serialport).
+- **To contribute**, please review our [contribution guide](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md). You might want to check out our [roadmap](https://github.com/node-serialport/node-serialport/issues/746). We also have issues tagged ["good first PR"](https://github.com/node-serialport/node-serialport/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+pr%22), if you'd like to start somewhere specific. We'll do our best to support you until we merge your PR.
+
+***
+## Helpful Resources for Getting Started with Node-Serialport
+
+In addition to reading the [article mentioned above](http://www.voodootikigod.com/nodebots-the-rise-of-js-robotics), these others might help you:
+* [Johnny-Five](http://johnny-five.io/#hello-world): The Johnny-Five Robotics and IoT platform's six-line "Hello World" (awesome).
+* [Arduino Node Security Sensor Hacking](http://nexxylove.tumblr.com/post/20159263403/arduino-node-security-sensor-hacking): A great all-around "how do I use this" article.
+
+***
+## Table of Contents
+
+* [Platform Support](#platform-support)
+* [Installation](#installation-instructions)
+* [Installation Special Cases](#installation-special-cases)
+  * [Alpine Linux](#alpine-linux)
+  * [Electron](#electron)
+  * [Illegal Instruction](#illegal-instruction)
+  * [Mac OS X](#mac-os-x)
+  * [Raspberry Pi Linux](#raspberry-pi-linux)
+  * [sudo / root](#sudo--root)
+  * [Ubuntu/Debian Linux](#ubuntudebian-linux)
+  * [Windows](#windows)
+* [Usage](#usage)
+  * [Opening a Port](#opening-a-port)
+  * [Testing](#testing)
+  * [Debugging](#debugging)
+  * [Error Handling](#error-handling)
+* [Command Line Tools](#command-line-tools)
+  * [Serial Port List](#serial-port-list)
+  * [Srial Port Terminal](#serial-port-terminal)
+  * [Serial Port Repl](#serial-port-repl)
+* [License](#license)
+
+***
+
+### Platform Support
+`serialport` officially supports all Active, Maintenance and Current LTS releases. The platforms, architectures and Node versions that `serialport` supports are the following;
+
+| Platform / Arch | Supported |
+|       ---       | --- |
+| Linux / ia32    |  ☑⁴ |
+| Linux / x64     |  ☑  |
+| Linux / ARM v6¹ |  ☐  |
+| Linux / ARM v7¹ |  ☐  |
+| Linux / ARM v8¹ |  ☐  |
+| Linux / MIPSel¹ |  ☐  |
+| Linux / PPC64¹  |  ☐  |
+| OSX³ / x64      |  ☑  |
+| Windows² / x86  |  ☑  |
+| Windows² / x64  |  ☑  |
+
+¹ ARM, MIPSel and PPC64¹ platforms are not currently part of our testing or build matrix, but will probably work.
+
+² Windows 7, 8, 10, and 10 IoT are supported, but our CI tests only Windows Server 2012 R2.
+
+³ OSX 10.4 Tiger and above are supported, but our CI tests only 10.9.5 Mavericks with Xcode 6.1.
+
+⁴ NodeJS has dropped prebuilt binaries for NodeJS 10 and above for 32bit linux. As a result it's too difficult to maintain support. However if you build nodejs and serialport yourself it will probably work.
+
+For NodeJS versions 0.10 and 0.12, the last functioning release was `serialport@4`. For node 4.0 the last functioning release was `serialport@6`.
+
+## Installation Instructions
+
+For most "standard" use cases (Node v4.x on Mac, Linux, or Windows on a x86 or x64 processor), Node-Serialport will install nice and easy with:
+
 ```
-  eeeee eeeee eeeee eeee       e  eeeee
-  8   8 8  88 8   8 8          8  8   "
-  8e  8 8   8 8e  8 8eee       8e 8eeee
-  88  8 8   8 88  8 88      e  88    88
-  88  8 8eee8 88ee8 88ee 88 8ee88 8ee88
-
-  eeeee eeee eeeee  e  eeeee e     eeeee eeeee eeeee eeeee
-  8   " 8    8   8  8  8   8 8     8   8 8  88 8   8   8
-  8eeee 8eee 8eee8e 8e 8eee8 8e    8eee8 8   8 8eee8e  8e
-     88 88   88   8 88 88  8 88    88    8   8 88   8  88
-  8ee88 88ee 88   8 88 88  8 88eee 88    8eee8 88   8  88
+npm install serialport
 ```
 
-[![Build Status](https://travis-ci.org/voodootikigod/node-serialport.png?branch=master)](https://travis-ci.org/voodootikigod/node-serialport)
-[![Gitter chat](https://badges.gitter.im/voodootikigod/node-serialport.png)](https://gitter.im/voodootikigod/node-serialport)
-[![Dependency Status](https://david-dm.org/voodootikigod/node-serialport.png)
-
-For all discussions, designs, and clarifications, we recommend you join our Gitter Chat room: [https://gitter.im/voodootikigod/node-serialport](https://gitter.im/voodootikigod/node-serialport)
+### Installation Special Cases
 
+We use [prebuild](https://github.com/mafintosh/prebuild) to compile and post binaries of the library for most common use cases (Linux, Mac, Windows on standard processor platforms). If you have a special case, Node-Serialport will work, but it will compile the binary during the install. Compiling with nodejs is done via `node-gyp` which requires Python 2.x, so please ensure you have it installed and in your path for all operating systems. Python 3.x will not work.
 
+This assumes you have everything on your system necessary to compile ANY native module for Node.js. If you don't, then please ensure the following are true for your system before filing a "Does not install" issue.
 
-Version: 1.6.1 - Released March 5, 2015
+#### Alpine Linux
 
-*****
+[Alpine](http://www.alpinelinux.org/) is a (very) small distro, but it uses the [musl](https://www.musl-libc.org/) standard library instead of [glibc](https://www.gnu.org/software/libc/) (used by most other Linux distros) so it requires compilation. It's commonly used with Docker. A user has confirmed that Node-Serialport works with [alpine-node](https://github.com/mhart/alpine-node).
 
-Imagine a world where you can write JavaScript to control blenders, lights, security systems, or even robots. Yes, I said robots. That world is here and now with node-serialport. It provides a very simple interface to the low level serial port code necessary to program [Arduino](http://www.arduino.cc/) chipsets, [X10](http://www.smarthome.com/manuals/protocol.txt) wireless communications, or even the rising [Z-Wave](http://www.z-wave.com/modules/ZwaveStart/) and [Zigbee](http://www.zigbee.org/) standards. The physical world is your oyster with this goodie. For a full break down of why we made this, please read [NodeBots - The Rise of JS Robotics](http://www.voodootikigod.com/nodebots-the-rise-of-js-robotics).
+```
+# If you don't have node/npm already, add that first
+sudo apk add --no-cache nodejs
 
-*****
+# Add the necessary build and runtime dependencies
+sudo apk add --no-cache make gcc g++ python linux-headers udev
 
-Robots, you say?
-================
+# Then we can install serialport, forcing it to compile
+npm install serialport --build-from-source
 
-This library is admittedly a base level toolkit for building amazing things with real world (including robots). Here are a couple of those amazing things that leverage node-serialport:
+# If you're installing as root, you'll also need to use the --unsafe-perm flag
+```
 
-* [Johnny-Five](https://github.com/rwaldron/johnny-five) - JavaScript IoT and Robotics programming framework.
-* [Cylon.js](http://cylonjs.com/) - JavaScript Robotics, By Your Command.
-* [node-l8smartlight](http://jakobwesthoff.github.io/node-l8smartlight/) ([source](https://github.com/jakobwesthoff/node-l8smartlight)) A node library to control the L8 Smartlight via Bluetooth or USB port
-* [firmata](https://github.com/jgautier/firmata) Talk natively to Arduino using the firmata protocol.
-* [tmpad](http://tmpvar.com/project/tmpad/) [source](https://github.com/tmpvar/tmpad) - a DIY midi pad using infrared, arduino, and nodejs. [Video](http://vimeo.com/34575470)
-* [duino](https://github.com/ecto/duino) - A higher level framework for working with Arduinos in node.js.
-* [Arduino Drinking Game Extravaganza](http://jsconf.eu/2011/arduino_drinking_game_extravaganza.html) - AKA "The Russian" a hexidecimal drinking game for geeks by Uxebu presented at JSConf EU 2011.
-* [Arduino controlling popcorn.js](https://gist.github.com/968773) - Controlling a popcorn.js video with an Arduino kit.
-* [Robotic JavaScript](http://jsconf.eu/2010/speaker/livingroombindmotion_function.html) - The first live presentation of the node-serialport code set as presented at JSConf EU 2010.
-* [devicestack](https://github.com/adrai/devicestack) - This module helps you to represent a device and its protocol.
-* [reflecta](https://github.com/JayBeavers/Reflecta) A communication protocol that combines Arduino Libraries and NodeJS into an integrated system.
-* [rc4pt-node](https://github.com/comsolid/rc4pt-node) - Control Popcorntime with an Infrared receiver and Arduino.
+#### Electron
 
-For getting started with node-serialport, we recommend you begin with the following articles:
+[Electron](https://electron.atom.io/) is a framework for creating cross-platform desktop applications. It comes with its own version of the Node.js runtime.
 
-* [Arduino Node Security Sensor Hacking](http://nexxylove.tumblr.com/post/20159263403/arduino-node-security-sensor-hacking) - A great all around "how do I use this" article.
-* [NodeBots - The Rise of JS Robotics](http://www.voodootikigod.com/nodebots-the-rise-of-js-robotics) - A survey article of why one would want to program robots in JS.
-* [Johnny-Five Getting Started Guide](https://github.com/rwldrn/johnny-five#setup-and-assemble-arduino) - Introduction to using the high level Johnny-Five library (awesome).
+If you require `serialport` as a dependency for an Electron project, you must compile it for the version of Electron your project's using.
 
-How To Use
-==========
+When you first install `serialport` it will compile against the version of Node.js on your machine, not against the Node.js runtime bundled with Electron.
 
-Using node-serialport is pretty easy because it is pretty basic. It provides you with the building block to make great things, it is not a complete solution - just a cog in the (world domination) machine.
+To recompile `serialport` (or any native Node.js module) for Electron, you can use `electron-rebuild`; more info at Electron's [README](https://github.com/electron/electron-rebuild/blob/master/README.md).
 
-**Special Notes**
+1. `npm install --save-dev electron-rebuild`
+2. Add `electron-rebuild` to your project's package.json's install hook
+3. Run `npm install`
 
-* Support for Node.js version 0.8.x has been removed. Version 1.4.0 is the last version that supported node.js version 0.8.x.
-* Currently support for Node.js version 0.11.x is dealing with an issue in the latest version of v. 0.11.13. We have confirmed things are fine with 0.11.10 and earlier, but not 0.11.11+.
+For an example project, check out [`electron-serialport`](https://github.com/johnny-five-io/electron-serialport).
 
-Good luck.
+#### NW.js
 
+[NW.js](https://nwjs.io/) is an app runtime based on Chromium and node.js.
 
-To Install
-----------
+Like Electron, NW.js also requires compilation against its own specific headers.
 
-For most "standard" use cases (node v0.10.x on mac, linux, windows on a x86 or x64 processor), node-serialport will install nice and easy with a simple
+To instruct `prebuild` to build against the correct headers, place a file named `.prebuildrc` on your package root with the following content:
 
 ```
-npm install serialport
+build_from_source=true
+runtime=node-webkit
+target=<target_version>
 ```
 
-We are using [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) to compile and post binaries of the library for most common use cases (linux, mac, windows on standard processor platforms). If you are on a special case, node-serialport will work, but it will compile the binary when you install. Follow the instructions below for how that works.
+Where `<target_version>` is the NW.js version you are building against (for example, `0.26.6`).
 
-### Installation Special Cases
+OBS: NW.js support requires `prebuild >= 7.3.0`.
 
+#### Illegal Instruction
 
-This assumes you have everything on your system necessary to compile ANY native module for Node.js. This may not be the case, though, so please ensure the following are true for your system before filing an issue about "Does not install". For all operatings systems, please ensure you have Python 2.x installed AND not 3.0, node-gyp (what we use to compile) requires Python 2.x.
+The pre-compiled binaries assume a fully capable chip. Intel's [Galileo 2](https://software.intel.com/en-us/iot/hardware/galileo), for example, lacks a few instruction sets from the `ia32` architecture. A few other platforms have similar issues. If you get `Illegal Instruction` when trying to run Node-Serialport, you'll need to ask npm to rebuild the Serialport binary.
+
+```bash
+# Will ask npm to build serialport during install time
+npm install serialport --build-from-source
 
-#### Windows:
+# If you have a package that depends on serialport, you can ask npm to rebuild it specifically...
+npm rebuild serialport --build-from-source
+```
 
- * Windows 7 or Windows 8.1 are supported.
- * Install [Visual Studio Express 2013 for Windows Desktop](http://www.microsoft.com/visualstudio/eng/2013-downloads#d-2013-express).
- * If you are hacking on an Arduino, be sure to install [the drivers](http://arduino.cc/en/Guide/windows#toc4).
- * Install [node.js 0.10.x](http://nodejs.org/) matching the bitness (32 or 64) of your operating system.
- * Install [Python 2.7.6](http://www.python.org/download/releases/2.7.6/) matching the bitness of your operating system.  For any questions, please refer to their [FAQ](http://docs.python.org/2/faq/windows.html). Default settings are perfect.
- * Open the 'Visual Studio Command Prompt' and add Python to the path.
+#### Mac OS X
 
-#### Mac OS X:
+Ensure that you have at a minimum the xCode Command Line Tools installed appropriate for your system configuration. If you recently upgraded the OS, it probably removed your installation of Command Line Tools, please verify before submitting a ticket. To compile `node-serialport` with Node.js 4.x+, you will need to use g++ v4.8 or higher.
 
-Ensure that you have at a minimum the xCode Command Line Tools installed appropriate for your system configuration. If you recently upgraded the OS, it probably removed your installation of Command Line Tools, please verify before submitting a ticket.
+#### Raspberry Pi Linux
 
-#### Desktop (Debian/Ubuntu) Linux:
+Follow the instructions for [setting up a Raspberry pi for use with Johnny-Five and Raspi IO](https://github.com/nebrius/raspi-io/wiki/Getting-a-Raspberry-Pi-ready-for-NodeBots). These projects use Node Serialport under the hood.
 
-You know what you need for you system, basically your appropriate analog of build-essential. Keep rocking! Ubuntu renamed the `node` binary `nodejs` which can cause problems building `node-serialport`. The fix is simple, install the [nodejs-legacy package](https://packages.debian.org/sid/nodejs-legacy) that symlinks `/usr/bin/nodejs => /usr/bin/node` or install the more up to date nodejs package from [Chris Lea's PPA](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).
+| Revision       |      CPU              | Arm Version |
+|   ----         |      ---              |     ---     |
+| A, A+, B, B+   | 32-bit ARM1176JZF-S   |    ARMv6    |
+| Compute Module | 32-bit ARM1176JZF-S   |    ARMv6    |
+| Zero           | 32-bit ARM1176JZF-S   |    ARMv6    |
+| B2             | 32-bit ARM Cortex-A7  |    ARMv7    |
+| B3             | 32-bit ARM Cortex-A53 |    ARMv8    |
 
+#### sudo / root
+If you're going to use `sudo` or root to install Node-Serialport, `npm` will require you to use the unsafe parameters flag.
 
+```bash
+sudo npm install serialport --unsafe-perm --build-from-source
 ```
-# Ubuntu node
-sudo apt-get install nodejs nodejs-legacy
 
-# Or Chris Lea's PPA Node (more up to date)
-sudo add-apt-repository ppa:chris-lea/node.js
-sudo apt-get update
-sudo apt-get install nodejs
+Failure to use the flag results in an error like this:
 
-sudo apt-get install build-essential
-npm install serialport
-```
+```bash
+root@rpi3:~# npm install -g serialport
+/usr/bin/serialport-list -> /usr/lib/node_modules/serialport/bin/serialport-list.js
+/usr/bin/serialport-term -> /usr/lib/node_modules/serialport/bin/serialport-terminal.js
 
-#### Raspberry Pi Linux:
 
- * Starting with a a vanilla New Out of the Box Software (NOOBS) Raspbian image (currently tested: 5/25/2013)
- * Log into your Raspberry Pi through whatever means works best and ensure you are on a terminal prompt for the remaining steps. This could be local or through an SSH (or a serial connection if you like).
- * Issue the following commands to ensure you are up to date:
+> serialport@6.0.0-beta1 install /Users/wizard/src/node-serialport
+> prebuild-install || node-gyp rebuild
 
-```bash
-   sudo apt-get update
-   sudo apt-get upgrade -y
-```
+prebuild-install info begin Prebuild-install version 2.2.1
+prebuild-install info install installing standalone, skipping download.
 
- * Download and install node.js:
+gyp WARN EACCES user "root" does not have permission to access the dev dir "/root/.node-gyp/6.9.1"
+gyp WARN EACCES attempting to reinstall using temporary dev dir "/usr/lib/node_modules/serialport/.node-gyp"
+make: Entering directory '/usr/lib/node_modules/serialport/build'
+make: *** No rule to make target '../.node-gyp/6.9.1/include/node/common.gypi', needed by 'Makefile'.  Stop.
+make: Leaving directory '/usr/lib/node_modules/serialport/build'
+gyp ERR! build error
+gyp ERR! stack Error: `make` failed with exit code: 2
 
-```bash
-   wget http://nodejs.org/dist/v0.10.12/node-v0.10.12-linux-arm-pi.tar.gz
-   tar xvfz node-v0.10.12-linux-arm-pi.tar.gz
-   sudo mv node-v0.10.12-linux-arm-pi /opt/node/
 ```
 
- * Set up your paths correctly:
+#### Ubuntu/Debian Linux
+
+The best way to install any version of Node.js is to use the [NodeSource Node.js binary distributions](https://github.com/nodesource/distributions#installation-instructions). Older versions of Ubuntu install Node.js with the wrong version and binary name. If your Node binary is `nodejs` instead of `node`, or if your Node version is [`v0.10.29`](https://github.com/fivdi/onoff/wiki/Node.js-v0.10.29-and-native-addons-on-the-Raspberry-Pi), then you should follow these instructions.
+
+You'll need the package `build-essential` to compile `serialport`. If there's a binary for your platform, you won't need it. Keep rocking!
 
-```bash
-   echo 'export PATH="$PATH:/opt/node/bin"' >> ~/.bashrc
-   source ~/.bashrc
 ```
+# Using Ubuntu and Node 6
+curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
+sudo apt-get install -y nodejs
 
- * Install using npm, note this will take a while as it is actually compiling code and that ARM processor is getting a workout.
+# Using Debian and Node 6 as root
+curl -sL https://deb.nodesource.com/setup_7.x | bash -
+apt-get install -y nodejs
+```
 
-```bash
-   npm install serialport
+#### Windows
+Node-Serialport supports Windows 7, 8.1, 10, and 10 IoT. Precompiled binaries are available, but if you want to build it from source you'll need to follow the [node-gyp installation](https://github.com/nodejs/node-gyp#installation) instructions. Once you've got things working, you can install Node-Serialport from source with:
+
+```powershell
+npm install serialport --build-from-source
 ```
 
-To Use
-------
+Node-gyp's documentation doesn't mention it, but it sometimes helps to create a C++ project in [Visual Studio](https://www.visualstudio.com/) so that it will install any necessary components not already installed during the past two hours of setup. This will solve some instances of `Failed to locate: "CL.exe"`.
+
+An old issue that you may still run into. When working with multiple Serial Ports you can set the `UV_THREADPOOL_SIZE` environment variable to be set to 1 + the number of ports you wish to open at a time. (Defaults to `4` which supports 3 open ports).
 
-Opening a serial port:
+## Usage
+
+### Opening a Port
 
 ```js
-var SerialPort = require("serialport").SerialPort
-var serialPort = new SerialPort("/dev/tty-usbserial1", {
-  baudrate: 57600
+var SerialPort = require('serialport');
+var port = new SerialPort('/dev/tty-usbserial1', {
+  baudRate: 57600
 });
 ```
 
-When opening a serial port, you can specify (in this order).
+When opening a serial port, specify (in this order)
 
 1. Path to Serial Port - required.
 1. Options - optional and described below.
 
-The options object allows you to pass named options to the serial port during initialization. The valid attributes for the options object are the following:
-
-* baudrate: Baud Rate, defaults to 9600. Should be one of: 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1800, 1200, 600, 300, 200, 150, 134, 110, 75, or 50. Custom rates as allowed by hardware is supported.
-* databits: Data Bits, defaults to 8. Must be one of: 8, 7, 6, or 5.
-* stopbits: Stop Bits, defaults to 1. Must be one of: 1 or 2.
-* parity: Parity, defaults to 'none'. Must be one of: 'none', 'even', 'mark', 'odd', 'space'
-* buffersize: Size of read buffer, defaults to 255. Must be an integer value.
-* parser: The parser engine to use with read data, defaults to rawPacket strategy which just emits the raw buffer as a "data" event. Can be any function that accepts EventEmitter as first parameter and the raw buffer as the second parameter.
+Constructing a `SerialPort` object immediately opens a port. While you can read and write at any time (it will be queued until the port is open), most port functions require an open port. There are three ways to detect when a port is opened.
 
-**Note, we have added support for either all lowercase OR camelcase of the options (thanks @jagautier), use whichever style you prefer.**
+- The `open` event is always emitted when the port is opened.
+- The constructor's openCallback is passed to `.open()`, if you haven't disabled the `autoOpen` option. If you have disabled it, the callback is ignored.
+- The `.open()` function takes a callback that is called after the port is opened. You can use this if you've disabled the `autoOpen` option or have previously closed an open port.
 
-open event
-----------
+```js
+var SerialPort = require('serialport');
+var port = new SerialPort('/dev/tty-usbserial1');
 
-You MUST wait for the open event to be emitted before reading/writing to the serial port. The open happens asynchronously so installing 'data' listeners and writing
-before the open event might result in... nothing at all.
+port.write('main screen turn on', function(err) {
+  if (err) {
+    return console.log('Error on write: ', err.message);
+  }
+  console.log('message written');
+});
 
-Assuming you are connected to a serial console, you would for example:
+// Open errors will be emitted as an error event
+port.on('error', function(err) {
+  console.log('Error: ', err.message);
+})
+```
 
+Detecting open errors can be moved to the constructor's callback.
 ```js
-serialPort.on("open", function () {
-  console.log('open');
-  serialPort.on('data', function(data) {
-    console.log('data received: ' + data);
-  });
-  serialPort.write("ls\n", function(err, results) {
-    console.log('err ' + err);
-    console.log('results ' + results);
-  });
+var SerialPort = require('serialport');
+var port = new SerialPort('/dev/tty-usbserial1', function (err) {
+  if (err) {
+    return console.log('Error: ', err.message);
+  }
 });
-```
 
-You can also call the open function, in this case instanciate the serialport with an additional flag.
-
-```js
-var SerialPort = require("serialport").SerialPort
-var serialPort = new SerialPort("/dev/tty-usbserial1", {
-  baudrate: 57600
-}, false); // this is the openImmediately flag [default is true]
-
-serialPort.open(function (error) {
-  if ( error ) {
-    console.log('failed to open: '+error);
-  } else {
-    console.log('open');
-    serialPort.on('data', function(data) {
-      console.log('data received: ' + data);
-    });
-    serialPort.write("ls\n", function(err, results) {
-      console.log('err ' + err);
-      console.log('results ' + results);
-    });
+port.write('main screen turn on', function(err) {
+  if (err) {
+    return console.log('Error on write: ', err.message);
   }
+  console.log('message written');
 });
-```
 
-List Ports
-----------
+```
 
-You can also list the ports along with some metadata as well.
+When disabling the `autoOpen` option you'll need to open the port on your own.
 
 ```js
-var serialPort = require("serialport");
-serialPort.list(function (err, ports) {
-  ports.forEach(function(port) {
-    console.log(port.comName);
-    console.log(port.pnpId);
-    console.log(port.manufacturer);
-  });
-});
-```
-
-Parsers
--------
+var SerialPort = require('serialport');
+var port = new SerialPort('/dev/tty-usbserial1', { autoOpen: false });
 
-Out of the box, node-serialport provides two parsers one that simply emits the raw buffer as a data event and the other which provides familiar "readline" style parsing. To use the readline parser, you must provide a delimiter as such:
+port.open(function (err) {
+  if (err) {
+    return console.log('Error opening port: ', err.message);
+  }
 
-```js
-var serialport = require("serialport");
-var SerialPort = serialport.SerialPort; // localize object constructor
+  // Because there's no callback to write, write errors will be emitted on the port:
+  port.write('main screen turn on');
+});
 
-var sp = new SerialPort("/dev/tty-usbserial1", {
-  parser: serialport.parsers.readline("\n")
+// The open event is always emitted
+port.on('open', function() {
+  // open logic
 });
 ```
 
-To use the raw parser, you just provide the function definition (or leave undefined):
+Get updates of new data from the serial port as follows:
 
 ```js
-var serialport = require("serialport");
-var SerialPort = serialport.SerialPort; // localize object constructor
-
-var sp = new SerialPort("/dev/tty-usbserial1", {
-  parser: serialport.parsers.raw
+// Switches the port into "flowing mode"
+port.on('data', function (data) {
+  console.log('Data:', data);
 });
-```
 
-
-You can get updates of new data from the Serial Port as follows:
-
-```js
-serialPort.on("data", function (data) {
-  sys.puts("here: "+data);
+// Read data that is available but keep the stream from entering "flowing mode"
+port.on('readable', function () {
+  console.log('Data:', port.read());
 });
 ```
 
-You can write to the serial port by sending a string or buffer to the write method as follows:
+You can write to the serial port by sending a string or buffer to the write method:
 
 ```js
-serialPort.write("OMG IT WORKS\r");
+port.write('Hi Mom!');
+port.write(Buffer.from('Hi Mom!'));
 ```
 
 Enjoy and do cool things with this code.
 
-Reference Guide
----------------
-
-## Methods
-
-### SerialPort (path, options, openImmediately, callback)
+### Testing
 
-Create a new serial port on `path`.
+Testing is an important feature of any library. To aid in our own tests we've developed a `MockBinding` a fake hardware binding that doesn't actually need any hardware to run. This class passes all of the same tests as our hardware based bindings and provides a few additional test related interfaces. To use the mock binding check out the example [here](/examples/mocking.js).
 
-**_path_**
-
-The system path of the serial port to open. For example, `/dev/tty` on Mac/Linux or `COM1` on Windows.
+```js
+const SerialPort = require('serialport/test');
+const MockBinding = SerialPort.Binding;
 
-**_options (optional)_**
+// Create a port and enable the echo and recording.
+MockBinding.createPort('/dev/ROBOT', { echo: true, record: true })
+const port = new SerialPort('/dev/ROBOT')
+```
 
-Port configuration options.
+### Debugging
 
-* `baudRate`
-* `dataBits`
-* `stopBits`
-* `parity`
-* `rtscts`
-* `xon`
-* `xoff`
-* `xany`
-* `flowControl`
-* `bufferSize`
-* `parser`
-* `encoding`
-* `dataCallback`
-* `disconnectedCallback`
-* `platformOptions` - sets platform specific options, see below.
+We use the [debug](https://www.npmjs.com/package/debug) package and log under the `serialport` namespace:
 
-#### Unix Platform Options
+ - `serialport:main` for all high-level/main logging
+ - `serialport:binding` for all low-level logging
 
-An object with the following properties:
+You can enable logging through environment variables. Check the [debug](https://www.npmjs.com/package/debug) docs for info.
 
-* `vmin` (default: 1) - see [`man termios`](http://linux.die.net/man/3/termios)
-* `vtime` (default: 0) - see [`man termios`](http://linux.die.net/man/3/termios)
+```bash
+DEBUG=serialport:main node myapp.js
+DEBUG=serialport:* node myapp.js
+DEBUG=* node myapp.js
+```
 
-**_openImmediately (optional)_**
+You can enable core dumps on osx with;
+```bash
+ulimit -c unlimited for core dumps
+```
 
-Attempts to open a connection to the serial port on `process.nextTick`. The default is `true`. Set to `false` to manually call `open()` at a later time, but note you'll need to use factory error listener in the case of constructor errors.
+You can "console.log" from c++ with;
+```c++
+fprintf(stdout, "Hellow World num=%d str=%s\n", 4, "hi");
+```
 
-**_callback (optional)_**
+You can make use of the `serialport-repl` command with;
+```bash
+serialport-repl # to auto detect an arduino
+serialport-repl /path/name # to connect to a specific port
+```
 
-Called when a connection has been opened. The callback should be a function that looks like: `function (error) { ... }`
+It will load a serialport object with debugging turned on.
 
-### .open (callback)
+### Error Handling
 
-Opens a connection to the given serial port.
+All functions in Node-Serialport follow two conventions:
 
-**_callback (optional)_**
+- Argument errors throw a `TypeError` object. You'll see these when functions are called with invalid arguments.
+- Runtime errors provide `Error` objects to the function's callback or emit an [`error event`](#module_serialport--SerialPort+event_error) if no callback is provided. You'll see these when a runtime error occurs, like trying to open a bad port or setting an unsupported baud rate.
 
-Called when a connection has been opened. NOTE: Will NOT be called if openImmediately is set to false as open will not be performed. The callback should be a function that looks like: `function (error) { ... }`
+You should never have to wrap a Node-Serialport object in a try/catch statement if you call the functions with the correct arguments.
 
-### .write (buffer, callback)
+## Command Line Tools
+If you install `serialport` globally (e.g., `npm install -g serialport`), you'll receive two command line tools.
 
-Writes data to the given serial port.
+### Serial Port List
+`serialport-list` will list all available serial ports in different formats.
 
-**_buffer_**
+```bash
+$ serialport-list -h
 
-The `buffer` parameter accepts a [`Buffer` ](http://nodejs.org/api/buffer.html) object, or a type that is accepted by the `Buffer` constructor (ex. an array of bytes or a string).
+  Usage: serialport-list [options]
 
-**_callback (optional)_**
+  List available serial ports
 
-Called once the write operation returns. The callback should be a function that looks like: `function (error) { ... }` _Note: The write operation is non-blocking. When it returns, data may still have not actually been written to the serial port. See `drain()`._
+  Options:
 
-### .pause ()
+    -h, --help           output usage information
+    -V, --version        output the version number
+    -f, --format <type>  Format the output as text, json, or jsonline. default: text
 
-Pauses an open connection.
 
-### .resume ()
+$ serialport-list
+/dev/tty.Bluetooth-Incoming-Port
+/dev/tty.usbmodem1421    Arduino (www.arduino.cc)
 
-Resumes a paused connection.
+$ serialport-list -f json
+[{"comName":"/dev/tty.Bluetooth-Incoming-Port"},{"comName":"/dev/tty.usbmodem1421","manufacturer":"Arduino (www.arduino.cc)","serialNumber":"752303138333518011C1","locationId":"14200000","vendorId":"2341","productId":"0043"}]
 
-### .flush (callback)
+$ serialport-list -f jsonline
+{"comName":"/dev/tty.Bluetooth-Incoming-Port"}
+{"comName":"/dev/tty.usbmodem1421","manufacturer":"Arduino (www.arduino.cc)","serialNumber":"752303138333518011C1","locationId":"14200000","vendorId":"2341","productId":"0043"}
+```
 
-Flushes data received but not read. See [`tcflush()`](http://linux.die.net/man/3/tcflush) for Mac/Linux and [`FlushFileBuffers`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa364439) for Windows.
+### Serial Port Terminal
+`serialport-term` provides a basic terminal interface for communicating over a serial port. `ctrl+c` will exit.
 
-**_callback (optional)_**
+```bash
+$ serialport-term -h
 
-Called once the flush operation returns. The callback should be a function that looks like: `function (error) { ... }`
+  Usage: serialport-term -p <port> [options]
 
-### .drain (callback)
+  A basic terminal interface for communicating over a serial port. Pressing ctrl+c exits.
 
-Waits until all output data has been transmitted to the serial port. See [`tcdrain()`](http://linux.die.net/man/3/tcdrain) for more information.
+  Options:
 
-**_callback (optional)_**
+    -h, --help                     output usage information
+    -V, --version                  output the version number
+    -l --list                      List available ports then exit
+    -p, --port, --portname <port>  Path or name of serial port
+    -b, --baud <baudrate>          Baud rate default: 9600
+    --databits <databits>          Data bits default: 8
+    --parity <parity>              Parity default: none
+    --stopbits <bits>              Stop bits default: 1
+    --echo --localecho             Print characters as you type them
 
-Called once the drain operation returns. The callback should be a function that looks like: `function (error) { ... }`
+$ serialport-term -l
+/dev/tty.Bluetooth-Incoming-Port
+/dev/tty.usbmodem1421    Arduino (www.arduino.cc)
+```
 
-**Example**
+### Serial Port Repl
+`serialport-repl` provides a nodejs repl for working with serialport. This is valuable when debugging.
 
-Writes `data` and waits until it has finish transmitting to the target serial port before calling the callback.
+You can make use of the `serialport-repl` command with;
+```bash
+$ serialport-repl # to auto detect an arduino
+$ serialport-repl /dev/tty.usbmodem1421 # to connect to a specific port
+```
 
+It will load a serialport object with debugging turned on.
 ```
-function writeAndDrain (data, callback) {
-  sp.write(data, function () {
-    sp.drain(callback);
-  });
-}
+  serialport:binding:auto-detect loading DarwinBinding +0ms
+port = SerialPort("/dev/tty.usbmodem1421", { autoOpen: false })
+globals { SerialPort, portName, port }
+> SerialPort.list()
+  serialport:main .list +6s
+[ { comName: '/dev/tty.usbmodem1421',
+    manufacturer: 'Arduino (www.arduino.cc)',
+    serialNumber: '752303138333518011C1',
+    pnpId: undefined,
+    locationId: '14200000',
+    vendorId: '2341',
+    productId: '0043' } ]
+> port.write('Calling all Autobots!')
+true
+> port.read()
+  serialport:main _read queueing _read for after open +1m
+null
+> port.open()
+  serialport:main opening path: /dev/tty.usbmodem1421 +30s
+  serialport:bindings open +1ms
 ```
 
-### .close (callback)
-
-Closes an open connection.
-
-**_callback (optional)_**
-
-Called once a connection is closed. Closing a connection will also remove all event listeners. The callback should be a function that looks like: `function (error) { ... }`
-
-## Events
-
-### .on('open', callback)
-
-### .on('data', callback)
-
-### .on('close', callback)
-
-### .on('error', callback)
-
-&nbsp;
-&nbsp;
-
----
-
-&nbsp;
-&nbsp;
-
-
-# Credit
-
-A special thanks to [The Hybrid Group](http://hybridgroup.com) for helping create and hosting the precompiled binaries for OSX, Linux, & Windows. This makes installing node-serialport much easier and much simpler for individuals using those platforms. Thank you.
+## License
+SerialPort is [MIT licensed](LICENSE) and all it's dependencies are MIT or BSD licensed.
diff --git a/input_devices/mag/node_modules/serialport/appveyor.yml b/input_devices/mag/node_modules/serialport/appveyor.yml
deleted file mode 100644
index 7802f895..00000000
--- a/input_devices/mag/node_modules/serialport/appveyor.yml
+++ /dev/null
@@ -1,80 +0,0 @@
-# environment variables
-environment:
-  node_pre_gyp_secretAccessKey:
-    secure: wJRlPhmqDgwxllTxhhG5JJosBf3nKYxcXO6NfGnrUUnxmECHeNTsBrldqW8+EjyK
-  node_pre_gyp_accessKeyId:
-    secure: cgGBaLa6xiPo5duak1/xU5hxPCn1aUQqkQQZf27QQp0=
-
-
-# to add several platforms to build matrix:
-platform:
-  - x64
-
-install:
-  - cmd: ECHO "INSTALL:"
-  - cmd: ECHO "APPVEYOR_REPO_COMMIT_MESSAGE ->"
-  - cmd: ECHO %APPVEYOR_REPO_COMMIT_MESSAGE%
-  - cmd: SET COMMIT_MSG="%APPVEYOR_REPO_COMMIT_MESSAGE%"
-  - cmd: SET PATH=C:\nodist\bin;%PATH%
-  - cmd: SET PUBLISH_BINARY=false
-  # Check to verify the branch is the same than latest tag, if so
-  # then we publish the binaries if everything else is successful.
-  - cmd: git describe --tags --always HEAD > _git_tag.tmp
-  - cmd: SET /p GIT_TAG=<_git_tag.tmp
-  - cmd: ECHO "LATEST LOCAL TAG:"
-  - cmd: ECHO %GIT_TAG%
-  - cmd: ECHO "APPVEYOR REPO BRANCH/TAG:"
-  - cmd: ECHO %APPVEYOR_REPO_BRANCH%
-  - cmd: DEL _git_tag.tmp
-  - cmd: IF x%APPVEYOR_REPO_BRANCH%==x%GIT_TAG% SET PUBLISH_BINARY=true
-  # Or look for commit message containing `[publish binary]`
-  - cmd: IF not x%COMMIT_MSG:[publish binary]=%==x%COMMIT_MSG% SET PUBLISH_BINARY=true
-  - cmd: ECHO "Env Var PUBLISH_BINARY:"
-  - cmd: ECHO %PUBLISH_BINARY%
-  - cmd: git clone https://github.com/marcelklehr/nodist.git c:\nodist 2>&1
-  - cmd: SET NODIST_X64=0
-  - cmd: call nodist update
-  - cmd: call nodist stable
-  - cmd: npm install -g node-gyp
-
-# to run your custom scripts instead of automatic MSBuild
-build_script:
-  - cmd: ECHO "BUILDING ia32 version:"
-  - cmd: npm install --build-from-source
-  - cmd: SET PATH=%cd%\node_modules\.bin\;%PATH%
-  - cmd: node serialport.js
-  - cmd: ECHO "PUBLISH ia32 package:"
-  - cmd: npm install aws-sdk
-  - cmd: IF %PUBLISH_BINARY%==true (node-pre-gyp package publish 2>&1)
-  - cmd: node-pre-gyp clean
-  - cmd: node-gyp clean
-  - cmd: rmdir /q /s node_modules
-  - cmd: ECHO "INSTALLING x64 node.js:"
-  # We add newest MSBuild so we can use the correct libs for the x64 version
-  - cmd: SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
-  - cmd: SET PATH=C:\python27;%PATH%
-  - cmd: set NODIST_X64=1
-  - cmd: call nodist update
-  - cmd: call nodist stable
-  - cmd: npm install -g node-gyp
-  - cmd: ECHO "BUILDING x64 version:"
-  - cmd: npm install --build-from-source --msvs_version=2013
-  - cmd: ECHO "PUBLISH package:"
-  - cmd: npm install aws-sdk
-  - cmd: IF %PUBLISH_BINARY%==true (node-pre-gyp package publish 2>&1)
-  - cmd: node-pre-gyp clean
-  - cmd: node-gyp clean
-
-on_success:
-  # test installing from binary package works
-  - cmd: ECHO "ON SUCCESS:"
-  - cmd: ECHO "Try installing from binary:"
-  - cmd: IF %PUBLISH_BINARY%==true npm install --fallback-to-build=false
-  # Clean Directories.
-  - cmd: node-pre-gyp clean
-  # Print Available Binaries
-  - cmd: node-pre-gyp info
-
-test: OFF
-
-deploy: OFF
diff --git a/input_devices/mag/node_modules/serialport/arduinoTest/arduinoEcho/arduinoEcho.ino b/input_devices/mag/node_modules/serialport/arduinoTest/arduinoEcho/arduinoEcho.ino
deleted file mode 100644
index 177a3278..00000000
--- a/input_devices/mag/node_modules/serialport/arduinoTest/arduinoEcho/arduinoEcho.ino
+++ /dev/null
@@ -1,18 +0,0 @@
-const int ledPin = 11;
-
-void setup() {
-  pinMode(ledPin, OUTPUT);
-  Serial.begin(9600);
-  Serial.write("READY");
-}
-
-void loop() {
-
-  while (Serial.available()) {
-    digitalWrite(ledPin, HIGH);
-    Serial.write(Serial.read());
-  }
-
-  delay(100);
-  digitalWrite(ledPin, LOW);
-}
diff --git a/input_devices/mag/node_modules/serialport/arduinoTest/requiresComPort.js b/input_devices/mag/node_modules/serialport/arduinoTest/requiresComPort.js
deleted file mode 100644
index f8dd3308..00000000
--- a/input_devices/mag/node_modules/serialport/arduinoTest/requiresComPort.js
+++ /dev/null
@@ -1,118 +0,0 @@
-'use strict';
-
-var chai = require('chai');
-var util = require('util');
-var serialPort = require('../serialport');
-
-describe ('requiresComPort', function() {
-
-  describe('echo hello', function() {
-    it('sends hello to the last port and validates that it is received back (see arduinoEcho.ino for echo sketch)', function(done) {
-      serialPort.list(function(err, ports) {
-
-        chai.assert.isUndefined(err, util.inspect(err));
-        chai.assert.isDefined(ports, 'ports is not defined');
-        chai.assert.isTrue(ports.length > 0, 'no ports found');
-
-        var data = new Buffer('hello');
-
-        var port = new serialPort.SerialPort(ports.slice(-1)[0].comName, null, false);
-        port.on('error', function(err) {
-          chai.assert.fail(util.inspect(err));
-        });
-
-        port.on('data', function(d) {
-          chai.assert.equal(data.toString(), d.toString(), 'incorrect data received');
-          port.close(function(err) {
-            chai.assert.isUndefined(err, util.inspect(err));
-            done();
-          });
-        });
-
-        port.open(function(err) {
-          chai.assert.isUndefined(err, util.inspect(err));
-          port.write(data);
-        });
-      });
-    });
-  });
-
-  describe('relaxed baud rate', function() {
-    it('opens a port with a non-standard baud rate', function(done) {
-      serialPort.list(function(err, ports) {
-
-        chai.assert.isUndefined(err, util.inspect(err));
-        chai.assert.isDefined(ports, 'ports is not defined');
-        chai.assert.isTrue(ports.length > 0, 'no ports found');
-
-        var port = new serialPort.SerialPort(ports.slice(-1)[0].comName, {baudrate: 5}, false);
-        port.on('error', function(err) {
-          chai.assert.fail(util.inspect(err));
-        });
-
-        port.open(function(err) {
-          chai.assert.isUndefined(err, util.inspect(err));
-          port.close(function(err) {
-            chai.assert.isUndefined(err, util.inspect(err));
-            done();
-          });
-        });
-      });
-    });
-  });
-
-  describe('simple write', function() {
-    it('opens a port and sends data without encountering error', function(done) {
-      serialPort.list(function(err, ports) {
-
-        chai.assert.isUndefined(err, util.inspect(err));
-        chai.assert.isDefined(ports, 'ports is not defined');
-        chai.assert.isTrue(ports.length > 0, 'no ports found');
-
-        var data = new Buffer('hello');
-
-        var port = new serialPort.SerialPort(ports.slice(-1)[0].comName, null, false);
-        port.on('error', function(err) {
-          chai.assert.fail(util.inspect(err));
-        });
-
-        port.open(function(err) {
-          chai.assert.isUndefined(err, util.inspect(err));
-          port.write(data);
-          port.close(function(err) {
-            chai.assert.isUndefined(err, util.inspect(err));
-            done();
-          });
-        });
-      });
-    });
-  });
-
-    describe('validate close event', function() {
-    it('opens a port then closes it using events', function(done) {
-      serialPort.list(function(err, ports) {
-
-        chai.assert.isUndefined(err, util.inspect(err));
-        chai.assert.isDefined(ports, 'ports is not defined');
-        chai.assert.isTrue(ports.length > 0, 'no ports found');
-
-        var port = new serialPort.SerialPort(ports.slice(-1)[0].comName, null, false);
-
-        port.on('error', function(err) {
-          chai.assert.fail(util.inspect(err));
-        });
-
-        port.on('open', function() {
-          port.close();
-        });
-
-        port.on('close', function() {
-          done();
-        });
-
-        port.open();
-      });
-    });
-  });
-
-});
diff --git a/input_devices/mag/node_modules/serialport/arduinoTest/stress.js b/input_devices/mag/node_modules/serialport/arduinoTest/stress.js
deleted file mode 100644
index 5662cf88..00000000
--- a/input_devices/mag/node_modules/serialport/arduinoTest/stress.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*jslint node: true */
-/*global describe, it */
-'use strict';
-
-var chai = require('chai');
-var util = require('util');
-var serialPort = require('../serialport');
-var colors = require('colors');
-var fs = require('fs');
-var memwatch = require('memwatch');
-
-describe ('stress', function() {
-
-  describe('long running', function() {
-    it('opens a port and sends data, repeated indefinately', function (done) {
-
-      var hd = new memwatch.HeapDiff();
-
-      memwatch.on('leak', function(info) {
-        fs.appendFile('leak.log', util.inspect(info));
-        console.log(util.inspect(info).red);
-
-        var diff = hd.end();
-        fs.appendFile('heapdiff.log', util.inspect(diff));
-        hd = new memwatch.HeapDiff();
-      });
-
-      memwatch.on('stats', function (stats) {
-        fs.appendFile('stats.log', util.inspect(stats));
-        console.log(util.inspect(stats).green);
-      });
-
-      serialPort.list(function(err, ports) {
-
-        chai.assert.isUndefined(err, util.inspect(err));
-        chai.assert.isDefined(ports, 'ports is not defined');
-        chai.assert.isTrue(ports.length > 0, 'no ports found');
-
-        var data = new Buffer('hello');
-
-        var port = new serialPort.SerialPort(ports.slice(-1)[0].comName, null, false);
-        port.on('error', function(err) {
-          chai.assert.fail(util.inspect(err));
-        });
-
-        port.on('data', function (data) {
-        });
-
-        port.open(function(err) {
-          chai.assert.isUndefined(err, util.inspect(err));
-
-
-          var intervalId = setInterval(function () {
-            port.write(data);
-          }, 20 );
-
-          setTimeout(function() {
-
-            clearInterval(intervalId);
-
-            var diff = hd.end();
-            fs.appendFile('heapdiff.log', util.inspect(diff));
-
-            console.log(util.inspect(diff).green);
-
-            done();
-
-          }, 3590000);
-        });
-      });
-    });
-  });
-
-});
diff --git a/input_devices/mag/node_modules/serialport/bin/echo.js b/input_devices/mag/node_modules/serialport/bin/echo.js
new file mode 100755
index 00000000..b2c38dd4
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/bin/echo.js
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+
+const args = require('commander')
+
+const SerialPort = require('../')
+const version = require('../package.json').version
+
+const readyData = Buffer.from('READY')
+
+args
+  .version(version)
+  .usage('-p <port>')
+  .description(
+    'A basic terminal interface for communicating over a serial port. Pressing ctrl+c exits.'
+  )
+  .option('-p, --port <port>', 'Path or Name of serial port')
+  .parse(process.argv)
+
+if (!args.port) {
+  args.outputHelp()
+  args.missingArgument('port')
+  process.exit(-1)
+}
+
+const port = new SerialPort(args.port)
+
+port.on('open', () => {
+  console.log(`echo: Port open: ${args.port}`)
+  setTimeout(() => {
+    console.log('echo: READY!')
+    port.on('data', data => port.write(data))
+    port.write(readyData)
+  }, 250)
+})
diff --git a/input_devices/mag/node_modules/serialport/bin/list.js b/input_devices/mag/node_modules/serialport/bin/list.js
new file mode 100755
index 00000000..8e1406db
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/bin/list.js
@@ -0,0 +1,48 @@
+#!/usr/bin/env node
+
+const serialport = require('../')
+const version = require('../package.json').version
+const args = require('commander')
+
+args
+  .version(version)
+  .description('List available serial ports')
+  .option(
+    '-f, --format <type>',
+    'Format the output as text, json, or jsonline. default: text',
+    /^(text|json|jsonline)$/i,
+    'text'
+  )
+  .parse(process.argv)
+
+const formatters = {
+  text(err, ports) {
+    if (err) {
+      console.error(err)
+      process.exit(1)
+    }
+    ports.forEach(port => {
+      console.log(
+        `${port.comName}\t${port.pnpId || ''}\t${port.manufacturer || ''}`
+      )
+    })
+  },
+  json(err, ports) {
+    if (err) {
+      console.error(JSON.stringify(err))
+      process.exit(1)
+    }
+    console.log(JSON.stringify(ports))
+  },
+  jsonline(err, ports) {
+    if (err) {
+      console.error(JSON.stringify(err))
+      process.exit(1)
+    }
+    ports.forEach(port => {
+      console.log(JSON.stringify(port))
+    })
+  },
+}
+
+serialport.list(formatters[args.format])
diff --git a/input_devices/mag/node_modules/serialport/bin/repl.js b/input_devices/mag/node_modules/serialport/bin/repl.js
new file mode 100755
index 00000000..97dd8e55
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/bin/repl.js
@@ -0,0 +1,52 @@
+#!/usr/bin/env node
+
+const repl = require('repl')
+const promirepl = require('promirepl').promirepl
+
+process.env.DEBUG = process.env.DEBUG || '*'
+const SerialPort = require('../')
+
+// outputs the path to an arduino or nothing
+function findArduino() {
+  return new Promise((resolve, reject) => {
+    const envPort = process.argv[2] || process.env.TEST_PORT
+    if (envPort) {
+      return resolve(envPort)
+    }
+    SerialPort.list((err, ports) => {
+      if (err) {
+        return reject(err)
+      }
+      let resolved = false
+      ports.forEach(port => {
+        if (!resolved && /arduino/i.test(port.manufacturer)) {
+          resolved = true
+          return resolve(port.comName)
+        }
+      })
+      if (!resolved) {
+        reject(
+          new Error(
+            'No arduinos found. You must specify a port to load.\n\nFor example:\n\tserialport-repl COM3\n\tserialport-repl /dev/tty.my-serialport'
+          )
+        )
+      }
+    })
+  })
+}
+
+findArduino()
+  .then(portName => {
+    console.log(`port = SerialPort("${portName}", { autoOpen: false })`)
+    console.log('globals { SerialPort, portName, port }')
+    const port = new SerialPort(portName, { autoOpen: false })
+    const spRepl = repl.start({ prompt: '> ' })
+    promirepl(spRepl)
+    spRepl.context.SerialPort = SerialPort
+    spRepl.context.portName = portName
+    spRepl.context.port = port
+  })
+  .catch(e => {
+    console.error(e.message)
+    process.exit(1)
+  })
diff --git a/input_devices/mag/node_modules/serialport/bin/serialportList.js b/input_devices/mag/node_modules/serialport/bin/serialportList.js
deleted file mode 100755
index f3748823..00000000
--- a/input_devices/mag/node_modules/serialport/bin/serialportList.js
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env node
-
-var serialport = require('../');
-var sf = require('sf');
-
-serialport.list(function (err, results) {
-  if (err) {
-    throw err;
-  }
-
-  for (var i = 0; i < results.length; i++) {
-    var item = results[i];
-    console.log(sf('{comName,-15} {pnpId,-20} {manufacturer}', item));
-  }
-});
diff --git a/input_devices/mag/node_modules/serialport/bin/serialportTerminal.js b/input_devices/mag/node_modules/serialport/bin/serialportTerminal.js
deleted file mode 100755
index 21549046..00000000
--- a/input_devices/mag/node_modules/serialport/bin/serialportTerminal.js
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env node
-
-var SerialPort = require('../').SerialPort;
-var optimist = require('optimist');
-
-var args = optimist
-  .alias('h', 'help')
-  .alias('h', '?')
-  .options('portname', {
-    alias: 'p',
-    describe: 'Name of serial port. See serialPortList.js for open serial ports.'
-  })
-  .options('baud', {
-    describe: 'Baud rate.',
-    default: 9600
-  })
-  .options('databits', {
-    describe: 'Data bits.',
-    default: 8
-  })
-  .options('parity', {
-    describe: 'Parity.',
-    default: 'none'
-  })
-  .options('stopbits', {
-    describe: 'Stop bits.',
-    default: 1
-  })
-  .options('localecho', {
-    describe: 'Enable local echo.',
-    boolean: true
-  })
-  .argv;
-
-if (args.help) {
-  optimist.showHelp();
-  return process.exit(-1);
-}
-
-if (!args.portname) {
-  console.error("Serial port name is required.");
-  return process.exit(-1);
-}
-
-process.stdin.resume();
-process.stdin.setRawMode(true);
-process.stdin.on('data', function (s) {
-  if (s[0] === 0x03) {
-    port.close();
-    process.exit(0);
-  }
-  if (args.localecho) {
-    if (s[0] === 0x0d) {
-      process.stdout.write('\n');
-    } else {
-      process.stdout.write(s);
-    }
-  }
-  port.write(s, function (err) {
-    if (err) {
-      console.log(err);
-    }
-  });
-});
-
-var openOptions = {
-  baudRate: args.baud,
-  dataBits: args.databits,
-  parity: args.parity,
-  stopBits: args.stopbits
-};
-var port = new SerialPort(args.portname, openOptions);
-
-port.on('data', function (data) {
-  process.stdout.write(data.toString());
-});
-
-port.on('error', function (err) {
-  console.log(err);
-});
diff --git a/input_devices/mag/node_modules/serialport/bin/terminal.js b/input_devices/mag/node_modules/serialport/bin/terminal.js
new file mode 100755
index 00000000..f8f90910
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/bin/terminal.js
@@ -0,0 +1,116 @@
+#!/usr/bin/env node
+
+const SerialPort = require('../lib/')
+const version = require('../package.json').version
+const args = require('commander')
+const List = require('prompt-list')
+
+function makeNumber(input) {
+  return Number(input)
+}
+
+args
+  .version(version)
+  .usage('[options]')
+  .description(
+    'A basic terminal interface for communicating over a serial port. Pressing ctrl+c exits.'
+  )
+  .option('-l --list', 'List available ports then exit')
+  .option('-p, --port <port>', 'Path or Name of serial port')
+  .option('-b, --baud <baudrate>', 'Baud rate default: 9600', makeNumber, 9600)
+  .option('--databits <databits>', 'Data bits default: 8', makeNumber, 8)
+  .option('--parity <parity>', 'Parity default: none', 'none')
+  .option('--stopbits <bits>', 'Stop bits default: 1', makeNumber, 1)
+  // TODO make this on by default
+  .option('--echo --localecho', 'Print characters as you type them.')
+  .parse(process.argv)
+
+function logErrorAndExit(error) {
+  console.error(error)
+  process.exit(1)
+}
+
+function listPorts() {
+  SerialPort.list().then(
+    ports => {
+      ports.forEach(port => {
+        console.log(
+          `${port.comName}\t${port.pnpId || ''}\t${port.manufacturer || ''}`
+        )
+      })
+    },
+    err => {
+      console.error('Error listing ports', err)
+    }
+  )
+}
+
+function askForPort() {
+  return SerialPort.list().then(ports => {
+    if (ports.length === 0) {
+      console.error('No ports detected and none specified')
+      process.exit(2)
+    }
+
+    const portSelection = new List({
+      name: 'serial-port-selection',
+      message: 'Select a serial port to open',
+      choices: ports.map(
+        (port, i) =>
+          `[${i + 1}]\t${port.comName}\t${port.pnpId ||
+            ''}\t${port.manufacturer || ''}`
+      ),
+    })
+
+    return portSelection.run().then(answer => {
+      const choice = answer.split('\t')[1]
+      console.log(`Opening serial port: ${choice}`)
+      return choice
+    })
+  })
+}
+
+function createPort(selectedPort) {
+  const openOptions = {
+    baudRate: args.baud,
+    dataBits: args.databits,
+    parity: args.parity,
+    stopBits: args.stopbits,
+  }
+
+  const port = new SerialPort(selectedPort, openOptions)
+
+  process.stdin.resume()
+  process.stdin.setRawMode(true)
+  process.stdin.on('data', s => {
+    if (s[0] === 0x03) {
+      port.close()
+      process.exit(0)
+    }
+    if (args.localecho) {
+      if (s[0] === 0x0d) {
+        process.stdout.write('\n')
+      } else {
+        process.stdout.write(s)
+      }
+    }
+    port.write(s)
+  })
+
+  port.on('data', data => {
+    process.stdout.write(data.toString())
+  })
+
+  port.on('error', err => {
+    console.log('Error', err)
+    process.exit(1)
+  })
+}
+
+if (args.list) {
+  listPorts()
+} else {
+  Promise.resolve(args.port || askForPort())
+    .then(createPort)
+    .catch(logErrorAndExit)
+}
diff --git a/input_devices/mag/node_modules/serialport/binding.gyp b/input_devices/mag/node_modules/serialport/binding.gyp
deleted file mode 100644
index 06ceef2f..00000000
--- a/input_devices/mag/node_modules/serialport/binding.gyp
+++ /dev/null
@@ -1,62 +0,0 @@
-{
-  'targets': [
-    {
-      'target_name': 'serialport',
-      'sources': [
-        'src/serialport.cpp',
-      ],
-      'include_dirs': [
-        '<!(node -e "require(\'nan\')")'
-      ],
-      'conditions': [
-        ['OS=="win"',
-          {
-            'sources': [
-              'src/serialport_win.cpp',
-              'src/win/disphelper.c',
-              'src/win/enumser.cpp',
-            ],
-            'msvs_settings': {
-              'VCCLCompilerTool': {
-                'ExceptionHandling': '2',
-                'DisableSpecificWarnings': [ '4530', '4506' ],
-              },
-            },
-          },
-        ],
-        ['OS=="mac"',
-          {
-            'sources': [
-              'src/serialport_unix.cpp',
-              'src/serialport_poller.cpp',
-            ],
-            'xcode_settings': {
-              'OTHER_LDFLAGS': [
-                '-framework CoreFoundation -framework IOKit'
-              ]
-            }
-          }
-        ],
-        ['OS!="win"',
-          {
-            'sources': [
-              'src/serialport_unix.cpp',
-              'src/serialport_poller.cpp',
-            ],
-          }
-        ],
-      ],
-    },
-    {
-      "target_name": "action_after_build",
-      "type": "none",
-      "dependencies": [ "<(module_name)" ],
-      "copies": [
-        {
-          "files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
-          "destination": "<(module_path)"
-        }
-      ]
-    }
-  ],
-}
diff --git a/input_devices/mag/node_modules/serialport/build/Makefile b/input_devices/mag/node_modules/serialport/build/Makefile
deleted file mode 100644
index d53a91d9..00000000
--- a/input_devices/mag/node_modules/serialport/build/Makefile
+++ /dev/null
@@ -1,355 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ..
-abs_srcdir := $(abspath $(srcdir))
-
-# The name of the builddir.
-builddir_name ?= .
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Release
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS)
-AR.target ?= $(AR)
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(CXX.target)
-
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= $(CXX.host)
-LDFLAGS.host ?=
-AR.host ?= ar
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_objc = CXX($(TOOLSET)) $@
-cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-quiet_cmd_objcxx = CXX($(TOOLSET)) $@
-cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-# Commands for precompiled header files.
-quiet_cmd_pch_c = CXX($(TOOLSET)) $@
-cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
-cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-quiet_cmd_pch_m = CXX($(TOOLSET)) $@
-cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
-quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
-cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
-
-# gyp-mac-tool is written next to the root Makefile by gyp.
-# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
-# already.
-quiet_cmd_mac_tool = MACTOOL $(4) $<
-cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
-
-quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
-cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
-
-quiet_cmd_infoplist = INFOPLIST $@
-cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = rm -rf "$@" && cp -af "$<" "$@"
-
-quiet_cmd_alink = LIBTOOL-STATIC $@
-cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^)
-
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
-
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds until one fails.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    E=$$?;\
-    if [ $$E -ne 0 ]; then\
-      break;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 2,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare the "all" target first so it is the default,
-# even though we don't have the deps yet.
-.PHONY: all
-all:
-
-# make looks for ways to re-generate included makefiles, but in our case, we
-# don't have a direct way. Explicitly telling make that it has nothing to do
-# for them makes it go faster.
-%.d: ;
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD
-	@$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD
-	@$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD
-	@$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD
-	@$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD
-	@$(call do_cmd,objc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD
-	@$(call do_cmd,objcxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,action_after_build.target.mk)))),)
-  include action_after_build.target.mk
-endif
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,serialport.target.mk)))),)
-  include serialport.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/Users/webgeek/Projects/node-serialport/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/webgeek/.node-gyp/0.10.36/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/webgeek/.node-gyp/0.10.36" "-Dmodule_root_dir=/Users/webgeek/Projects/node-serialport" binding.gyp
-Makefile: $(srcdir)/../../.node-gyp/0.10.36/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi
-	$(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  include $(d_files)
-endif
diff --git a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/action_after_build.stamp.d b/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/action_after_build.stamp.d
deleted file mode 100644
index 71e13c40..00000000
--- a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/action_after_build.stamp.d
+++ /dev/null
@@ -1 +0,0 @@
-cmd_Release/obj.target/action_after_build.stamp := touch Release/obj.target/action_after_build.stamp
diff --git a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport.o.d b/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport.o.d
deleted file mode 100644
index 902c9a59..00000000
--- a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport.o.d
+++ /dev/null
@@ -1,32 +0,0 @@
-cmd_Release/obj.target/serialport/src/serialport.o := c++ '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/webgeek/.node-gyp/0.10.36/src -I/Users/webgeek/.node-gyp/0.10.36/deps/uv/include -I/Users/webgeek/.node-gyp/0.10.36/deps/v8/include -I../node_modules/nan  -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/serialport/src/serialport.o.d.raw  -c -o Release/obj.target/serialport/src/serialport.o ../src/serialport.cpp
-Release/obj.target/serialport/src/serialport.o: ../src/serialport.cpp \
-  ../src/serialport.h ../node_modules/nan/nan.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-darwin.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8stdint.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_object_wrap.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_buffer.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_version.h \
-  ../node_modules/nan/nan_new.h \
-  ../node_modules/nan/nan_implementation_pre_12_inl.h \
-  ../src/serialport_poller.h
-../src/serialport.cpp:
-../src/serialport.h:
-../node_modules/nan/nan.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-darwin.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8stdint.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_object_wrap.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_buffer.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_version.h:
-../node_modules/nan/nan_new.h:
-../node_modules/nan/nan_implementation_pre_12_inl.h:
-../src/serialport_poller.h:
diff --git a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_poller.o.d b/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_poller.o.d
deleted file mode 100644
index e3735fb7..00000000
--- a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_poller.o.d
+++ /dev/null
@@ -1,32 +0,0 @@
-cmd_Release/obj.target/serialport/src/serialport_poller.o := c++ '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/webgeek/.node-gyp/0.10.36/src -I/Users/webgeek/.node-gyp/0.10.36/deps/uv/include -I/Users/webgeek/.node-gyp/0.10.36/deps/v8/include -I../node_modules/nan  -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/serialport/src/serialport_poller.o.d.raw  -c -o Release/obj.target/serialport/src/serialport_poller.o ../src/serialport_poller.cpp
-Release/obj.target/serialport/src/serialport_poller.o: \
-  ../src/serialport_poller.cpp ../node_modules/nan/nan.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-darwin.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8stdint.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_object_wrap.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_buffer.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_version.h \
-  ../node_modules/nan/nan_new.h \
-  ../node_modules/nan/nan_implementation_pre_12_inl.h \
-  ../src/serialport_poller.h ../src/serialport.h
-../src/serialport_poller.cpp:
-../node_modules/nan/nan.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-darwin.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8stdint.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_object_wrap.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_buffer.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_version.h:
-../node_modules/nan/nan_new.h:
-../node_modules/nan/nan_implementation_pre_12_inl.h:
-../src/serialport_poller.h:
-../src/serialport.h:
diff --git a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_unix.o.d b/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_unix.o.d
deleted file mode 100644
index ded66648..00000000
--- a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/obj.target/serialport/src/serialport_unix.o.d
+++ /dev/null
@@ -1,33 +0,0 @@
-cmd_Release/obj.target/serialport/src/serialport_unix.o := c++ '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/webgeek/.node-gyp/0.10.36/src -I/Users/webgeek/.node-gyp/0.10.36/deps/uv/include -I/Users/webgeek/.node-gyp/0.10.36/deps/v8/include -I../node_modules/nan  -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/serialport/src/serialport_unix.o.d.raw  -c -o Release/obj.target/serialport/src/serialport_unix.o ../src/serialport_unix.cpp
-Release/obj.target/serialport/src/serialport_unix.o: \
-  ../src/serialport_unix.cpp ../src/serialport.h \
-  ../node_modules/nan/nan.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-darwin.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8.h \
-  /Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8stdint.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_object_wrap.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_buffer.h \
-  /Users/webgeek/.node-gyp/0.10.36/src/node_version.h \
-  ../node_modules/nan/nan_new.h \
-  ../node_modules/nan/nan_implementation_pre_12_inl.h \
-  ../src/serialport_poller.h
-../src/serialport_unix.cpp:
-../src/serialport.h:
-../node_modules/nan/nan.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-unix.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/ngx-queue.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/uv/include/uv-private/uv-darwin.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8.h:
-/Users/webgeek/.node-gyp/0.10.36/deps/v8/include/v8stdint.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_object_wrap.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_buffer.h:
-/Users/webgeek/.node-gyp/0.10.36/src/node_version.h:
-../node_modules/nan/nan_new.h:
-../node_modules/nan/nan_implementation_pre_12_inl.h:
-../src/serialport_poller.h:
diff --git a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/serialport.node.d b/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/serialport.node.d
deleted file mode 100644
index 1638e401..00000000
--- a/input_devices/mag/node_modules/serialport/build/Release/.deps/Release/serialport.node.d
+++ /dev/null
@@ -1 +0,0 @@
-cmd_Release/serialport.node := ./gyp-mac-tool flock ./Release/linker.lock c++ -bundle -framework CoreFoundation -framework IOKit -Wl,-search_paths_first -mmacosx-version-min=10.5 -arch x86_64 -L./Release  -o Release/serialport.node Release/obj.target/serialport/src/serialport.o Release/obj.target/serialport/src/serialport_unix.o Release/obj.target/serialport/src/serialport_poller.o -undefined dynamic_lookup
diff --git a/input_devices/mag/node_modules/serialport/build/Release/.deps/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node.d b/input_devices/mag/node_modules/serialport/build/Release/.deps/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node.d
deleted file mode 100644
index 6b8bef39..00000000
--- a/input_devices/mag/node_modules/serialport/build/Release/.deps/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node.d
+++ /dev/null
@@ -1 +0,0 @@
-cmd_/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node := rm -rf "/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node" && cp -af "Release/serialport.node" "/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node"
diff --git a/input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport.o b/input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport.o
deleted file mode 100644
index e2bcefa0158f97e02483facedfb4fab68fd4d735..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 193672
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%0AS^fmZb~FfcSgX|Nzf9zmKw
z4RM9)WMqizf-=pa`WP878d&yFT_sQ&OB@rSBp0f?21;Ye2lY^?IZzr)E1?f6g;0W#
z3|2vv?1a)-EZPH=dIP1gSacdHg;0W#XKte@!P?S*DS8Z5j8)MGsH8MBGO(mvQ>YXy
z>ab=|k`#ef9D<StBSSDO5nO;;g2nz&s8kY^#!}MdL#1k<G?sv$36;WQ5lqQxs8TF$
zfl0lCE5Yb$3P6*y5|qYLTo9pTEmZejD9y+a3S+*93k5R@fP#^M!3#=baq%&z>RV76
zi;~AsDJ%wa;x<?kDrE?zu^0?f0&^a?`s;_PPZWf>9V`f8B1kK!BA8ArhDSk_q(f;e
z$)W@*)d;1rB#R?ZsfSP+i$yRgn1it>X@L4=3Y2DK2!%02gdo0RWQc_^r$U988Oj>!
z=RrA_p)^<!#^Do&Yu1J`yP!0dn)D*n_BT)(ONhXf+{3Np7gUN9>L4tE#sifyhtgOI
zF=?oj9+busXx31v04R;MT!ATagDPTV2!^T8MF>Gc2|>c7U?I)O5DyFIO>kWp#Wzef
zOevNiCPK+ks0DAKG?rMn36;7FrLp?_J5&;p1~7(=U`qZ#m141q2qgy46cq-gu|yS2
zDuW^=8=$%mKxsyXP#E(QTnMB2brLFd7fNGs-ZQ8a9#fd0WApq_8cR^gK&3RHG?s*4
z1(gy59c%?2kH%=SOv6xu;UiP1Zcix9$Pfx+R>FmXVazK~A#k$_#<>j@WMl}2G1rSj
z(mz<;4k(9L3P}*g5r+z534=PQxhtVG9wptll`MivZG_TTLUIdK3g#g!MaW?cB^V+3
z0;*&+)VoX!f($S=B0ORzv%tc`1?qK>LP*FUNF6Z<+Zsw^@jFZj%xo-5(xAFap)?*P
zcubiK)x8EvV=)D$1dl0Kpt>JJX)LC|l;AOi8ydJ$P#TLVFeP|Qaf0d&gwj|{fhoab
zN+ncx2b9KQ3QP$eQ;tD(Uxm_G(&r7R)ITVVC4D}JN+FbBq)#RZNRm>A(pbtan3N?&
zN|K?voh2a_GBU)tLz!oxG?u;-dAeYEC<L097#Tug%r>}C@C+#PA(Y1A^;oD>A(Y0V
zqzWp9#oz@{DJ;4+K&4JVX*^0`&I7kX)ubVz_XA3U1tCHR@*>nwm`*H)e}pRe2c@y3
zQf{af5>OgT5{!mQRX}Mh7Qv)o4#uKHTn6HFZ79vi5DH^PK&P3pbi5;=s+*xS79YTr
zq~cam1C{EA(pWs%2bEe4rLp9*xlk#D5{!Jd6RP9{l*VGwX{gk1D2>IUTTm&45)6x8
zp((-Ir-mu|1XYYx(SN9<3Oo`pEQ3jzQKY0Es(T`oW@HG3F%QFqf^R^XigJ+T!pIP8
z3}u!;X)K9r7F5?dD2+wQcBm8<yB<KLu;}^#mEyo{H%tl4#mo%xlUdN+3>Lf!HDr?l
z#BX3h2opgHLKVS`Lka+Es1z1=Izy$Rp)?jHDNrdq!Po*-G7(B+$!+tXQmdgfmK4q{
z5AlsI)SFn`q6}4H0Hv{56b_Y2fznu%bVH?PKxr&W_Cux4Kxr&WK0~D#;LgS9-@qd5
z7(xk*`5APgGWHhuXQ*m9xDpJ5VM-WqD-nlEsX=Kh0j>#^a)Z)XiWCc|6ha9`E)Rh!
zNruu`EJ}k)O@q={EGmUcA(UWP)QYAAYq11V)C*ONRnaV{<bEiPC8fcnE>fgKN(qvr
zLFb}?Sd0vzFlG!?ijg5W56avQrLj227%JrsrLiapfJ$L8xC|<VMOPbCY95rvqXgzW
zaI4}ERQ);7+1sE!LZI0vkQb5ha;PGhPArBWhbp-OrLknRhft|^P#Q}DGlaUr4@zUP
z2qpz{Fcu|mVY*cyo?v7MWrQ;IRAE9G9cDeKl1M0x#Ro7Y*0_}fL8TI*G!{>$K&2X?
zG?rXc43$DC!N^7ZP$l!AG!}~%LZvQ3X)G3PfJz~hU|4hjO$pYV2vc+dsu-)Ht5C^b
zP#R0r!K8TL@r2<XB9y=uYI?wq0AUD$F@xbk0Wf9~TnM9lh8g4vR}u(gB6J1Am|1XD
z7zV)(GhB{P0%O9C7{n49FkK6wx|kUPC$qpf$KZnTlUZOK*r{q@m5`*4AYsPMgX&~t
z2!b(B!iC~sOqfxO3_%DZAS~GFh&SQ7FlGZ`zIp>!f)SB03t$JjF*1b0n6M+mu!IRr
z7aR0cF-C?E7!!V!9OeWb>`*jYxGs!QSJ)|Oc<lCp>W+reSn^yVRH_k5W9id478K;9
zD){(>`6`s978Pga=P8)!87OEZ=OpH(>zWxD=o#plnrJF$BqbK7rYPj+LDU-SnHHDj
zX@a&i7Z)Y#qirTe+a?}Rln>feTnyg*tcy^qpH!NelY+Dp8M-qXyc3xL>Kum5yb^|#
z;{5oG#JrT8RED(7oYcI;+*Ah8K3ImL)bz~alGLL3w9>p}hB6C=vc#Nt2A9N=M27e%
zKX0Ql3)8T~oYGW7L(k&Syp+_m%)HbT*D?kq9z#-oeh#W?GtXkb(wrQyIuHXxHl(OD
z6)X#4pvszi7P}?p6hoxJEL3?5&*I<`&~{v~eh3p)g`t6Gv0G_gGH7QlSP_has?6N8
z*s-W6u@bBV%tDp7@GSNRZ{`LofG|;2Sb7#a<>%+5Cgy>aK-s8jEI>h#o0M7vR^nF*
zVxp=5IoGwKB(*3n5fWlB4yrP9&tgx|esHikU>2&pg=cXnc*8hY0fdRF!pyVSC9wn&
zupkDitf48~HxR#q&4Ky}B7&yD1m-n}ELc6ngAf5s<&fBd$byw43!o`C_AK^GEXgcO
zbuB8&hlU=4kE+<hvp6U<-L;|sY$$|@s=_iPAL<p?G6p!CA)qKTHxpzDOtm>w6(rTW
zmN9@+KS<W7%mOB9?3Y^Zn#ACjTFwAf&fo#bT+lpY2H|@81;@kmxVoBq7Q5yalt9uO
zm<2T!t7=o{oYX{+x4|?>B`7muRa#KuTE>uHkXi)V6|ZZDS8WO?`eACd7($>9w<)u*
zvV!`>j=?8CIT4(rLD?V7LG=mP|9-*oFxLbd#=E*gbfFpq4Gu_PT7=|7QU^E&AWXPh
zAzX+;*D{8b{L-YHRFJGunS~id5^QS<s+fs$VsVLUfM0MtR4W5WfB~WbRjH+OMrv|4
zNE%f=OcbOVEr_8OqeNYNlpn}RhzN!&g2x!t*Raq51r)?VuCCyy!Xpok9*EiCkc8+1
zM=45Nz%2y_3djbCCQtOJKr#U2IY=m3gycgq9ylf-Ot|+UTr;24y!4U`*D?kO15Mh{
zAhaaS0wU#F#(?0UtF!P;taQ%LD@n}E^UKe3EKbhMbS-1R6hzZ!8eWuHlIj{zl9`#w
z0A@3k<`rkA=cT476ldfYl`wz~r2w6wfu_;W0IV8fQ9v?WJ6HfsttD6~$nCBH$(aE#
zn?M2}m7r*b1coU%x4M=wfN899pd@JSS)88(Dqx{1V0>^Km7xh58n~yHIF}X`rRIUM
zFM@-n&d5ACwZt(gzo^7NFElSXu{1rS#I+(hwE$eZ1-K=Zxia8U!H@{j8lRsRUkcS6
zp9<3*UxH?rscT*dxS|5nXp$zb6`3HHf+#d8bC=BGf_!k54P~J#2u>{lwJBT!%0P|<
zG0|1HLsgV9Kv@jX&}68CF(6qF7OIKCu0h_x2J!Hc&lb(dymHrExTHc}YB@treqOo)
zJRO1BMe*?|iACj^dC+rL7$C>5pc#~s;~G$gWK>FOPHG9bZ~|p1Ge{aitHoh?94cw*
zSq!Vy!6^}3Poao_>_jro$kIKv1f~FDNKk5VerZv1s#9WdDyRrEh_`UfOU_Tp%u9C#
z1sZPE4Dn?JB}FRu6vUU6B;~||PhF`jNM)$QqZW@8B!-|NVq}I}B~pqZS`Q?`4dWR?
z{k;AB!~No2{ha+>JpJ4mLc;yyogzbA5h9Mk&YqqKE-akT1KAX3AiILoA$AYo3LSLQ
zjj(GsNl7e81l4g!jcizu;m~5111pUo3<m5bqdCABRK&nkf|DI;LPGT;76k~8Vv|Ho
z;zs6pY=U{21T6?J<1rWHVMH;F*%&}cTi{|iz&kk;RTosa1Wnk|FSR_lGB+td#}%vx
z&PCO2=A56GoLJ(DTm>7%ySfG&#WO&pP}Lh6g4&L-)_#CrutB^Lj!1U}H85eGM>EC9
zH!(XECI=}Da2tcH7R?+iuE7_Nu4vk^IfE4arp}3Z$gXoOV?Yx@v(VHpwH(w9ElEu-
zNleN~g~tuDAYna_$VMt|jg7)mi!#$HVL^(TQ4l3AzB0`f6q!gxG9eQ|&O~y8kp(^t
zgyI;VUXVqIT!Nz=4Dm5YDcDWW<|HUtLu3dvf?<mAHG*Mka5aKq^5~6Vh&Yx;Fhs)D
z6`X}ZPKCM}y%7vi2Q~oYIY=Ye&?F?^CAB0mGY29KZVMv|z`_Ee+#)0&-fx95K`Kz2
z<xnLAT?A2w<|50Ge9yd+)O2tY49<pHVh)u8`!y3Zr~^6+4o%V!lt0{x@^eF>jb+y?
zP$7aWf@nvB+CQLHG!}CpmSAtwLR^T&CJg1Eu!cDs5{Ry4kTw{&AqKJ^dWapGH!urw
zsOQnt;YiA`S_YaLK%H=?e*B3T=2ll%JgFF=2uCtTC_qogP)C4c9VOWyw15L1PfA8M
z0u;QEV6_Ozhm7}t(=dby3M!BaGYA)=5Y$xzj}gIT5n%*Xh(CznitvOGTn&x@g3F_a
z55%RI!2{PoD0Gkv0C^qaXLE2)GByH-4eGcVm<Le>YLJ6Q*RTYPDOef)aDl186D%+#
zI6?&`jUFgq%Q3?QrkqfaAhaVw#Ly@tA3WaanU|7U0S*@g7Zw1JU@<g;4hn&X!CcE=
z<6U4bno>i^SOZwfwG2821LmPAG=ipLupA`dL4_Wei>A~N5~W}%c;W@~&=eYgJqnhA
zm}qPS=AbGwb1f`Q%qhlbtua8vVTzGPZXm%xAo9UB;Vm^_#^8#4s0rwi4;BVTK631V
z>Z{}uh?6nBf-DR35X5>zv%u2K<ZPs&d)G1sbRje?hERFXC_X|ph=-=o7^)CteO@|3
zDTI%v*wn2wCkNFXXd-AD3?R}VdtJ*I5F9jRMi3c@op6N^E=Vb;6$Ghzje}EB8tsS?
zL|4~f<9NT|cti7mBG5o-Nu^^+Nl|7}X-O)0q=msRKQEObC^a#~KQE_}!6iSh#5J!p
z7tC;hj0|9C#A0_AQYnvYIjT|%xBQ~yRPx*k(~4@MF{sOn%Wn5n*pQGZeApL~b_h4J
z5NQ=DltGqdp*q0G&^@&TBZN@$BuaQ-RgG$-u}31herSi<)zy{3Be57&xfvvykh2ab
zKp@Ekqyr+4s>#q09G(y<G_9~8a%DhLgQ^|uM6{5AxdTnu&=549mz<nhT%2EoW)s3&
z0d9W5hVh_rdARMMV1q<kuu;6LYmhf66&pE1P4di3%Xf7Ra4QQokM|2Ui}wsR0rgWI
z<6VPI!Rg%?q7pP(Ta=#zvKUtufGEr_Vn{4XFOCPbMZuF-43MnF0FwsU2nq#I*=300
z4)EY7bXX5E3IXL{S8f6tFmwfvpkkV35|WWw464L3GQshTslv=7KPLs;sD?1$4s=f~
zDM>AYbAusV7gsmOP@fP6M<1VfXGg#IAXi5hI43;FGsKl4Ajsdt)5$X=INm?ZH3%dI
z8is=S8ybEfpCB@Vp&3##_Djr71-Teq2&4t%dQ)(1j2MB3jAB4U4NaVL^7B$%A%_P$
zmbhjypbCHt0W~hcW`J7<uz?MT0hn!Tuu2qdM7OIUMiQtU!RF(y9id8a)s9eU^x6?D
z46YqP9)_fRP#yq_6E3j8%3#{fAZgbSH0<hMo(C(RkfI7*6dGbMjYg2zEXfBQb`43>
z0Y&)`F1pfSZ~+LB1LZR;?G12MgTnwL3%AU?6wkcklEl2^R8Np&A!a#eBxdHJ8E9w*
zoBa++%`E^=Pq?}=;4=W~S__zZELA0<7=jf-kSyv7vK(uvf!Qa6>Oh(mg`{(&z<?^j
z)2N23z>#pEvgqjsRGPrz9o3fs-pQbv0MRLen&8R+3k+!BV1_C<tAPq-_^c=>DS|6S
zS7=#m=~$Fr3Oe(<7}~~wl;4)Yndy0nC8b5Fpt=VV2#D$z(<Z_x8$HJD7_y<|E4ana
zkPQj}DAPGHCnq%(%7K)R5Dw^s^33GSl6XiVUj|wQQXJ0!8Gw#w$SjUe&d)0@DJo4a
ziBC?<$%zLA4XF4+coU@vLzT*`aLt5I&P2yz(F<`HctjB7LWXRg%)C_pw6x;X62JTs
zxBSvP@LVv+SPPhk!K16Ni~;I{q?W^YFdJ~F%><2JASFF`r3%t#RAvF!W&&~-D48QE
zhL!=YuC5?sAhC)t0Hguk6wss|sBA$u2+;-!PAvf`0BJ<=qPaUn0#d|aRbmL5*6_?r
zOD!r&O#!KZs6`gRFcw_!1t%9}7L<U(8Pb)5=tCF9&<k$SK~y>C=alB=Vd_Q}$Ix#G
zY7s*8dxF*$xu=%Ec$jKIeuK#R7iFerf>z$Z)k8!Wil7r^@t|c+@d$2CW?pK1J~#y-
zi6(=c3>QZ>8)mzq5wfVE5o{(78n(z>99k@3YCwStNyM&Y448u0wHq10R6@cL!vJJq
zkP&DJ7Hx?HEVrPmB)Zy%X9oN=Kaw&$ML3cw9K|@23iP5J<`r0Rjwm;gG=Ym|q;eg7
zco@YHP-a7vV6es|wE99wAlj4|QlN!Y&ak2pl=(pe62&MYppZwi2vj5^nz#sy(3;Bd
zDulr^uMBh#MrM8<$d07M<ZO_sMr9U=`UKtMp#A{1=0IjZurav!MrlVO%pqLkz^gDj
z1~?Ps9FQlG3QA-n@m2iD>hL5TWMw$g4zd#T!~=IJEcIa4wcw%&mOdcGA&dv|o>7?v
z7Ck1xsU@H|fixqETuEvbfYwJKX~u1f8LVc5HBCUt4B94y3Bh!mKw7sjVQ{(tcc(xe
zK$AqTLm>?kLkv}exswWOl^U8u`egY<@VG{_v9L&j0|u$2z?ET;*1BO>V29{W!rFD9
zXh6#eSS-h1m}1p{CvRX?k0X;{Rg0cmuy_=E(l7#b7(i8H3al4JFe8AP%JBXhqH}>`
z1S8luKG-bYFW4mB6FkrnY#9&EV~~ayVlu@w*eo7R4mz6c>WV1`>&v==w1CP(XbTM8
z7Yry~gAO5}h(X5@P{aaDQ;RB5wL*rHickeXLy3@uoS;O5C3_l~2B(&QTj;6iE&~Sw
z*6v3Z?vMnHLqcm!NMM@b2+XWtR2f82qRAiv(kvb{mI^A-usfImO&A)OXrj>IL=%Ms
zD4HNFNYR7|2P&+{c7!h+CzxizL5irS!Cg9#S3!k0hA}uI)6l{<u_)USys{p?qye-%
z5?v67esETUWK8Jl)|?zrOQ6^_z%2<iQ$cC~S5OZfl270r6i^{&05K$_vLF>S90<}L
zY#a}Y*kIFm<W35B&@c()PlygwYZ)A!on3>2<K10DV9a0y)59?sChFqq;~L@$<9WMA
z2183tkP9F=A~-d<v?#Nr5)_^wKfw|UhB)?8$j|~b%LH0e@0OXGlj59T3SMW4DTpg*
zL8Gvks$DZde#aDtj(x&vSR95DUB5sZl}Jq|^a_|jZGl!@;~jp(G#Xbufnh3oB>_og
zuuy=ttDxlzD4}7PfF301jdScKVz#=>J@YbBi!xCrb%H@Fu^6BduqeT30E5S?AOmPH
zhr5<Bz{lQTVz~7if!cdHiN(dB5+6CUfLanLJ$h%DD%^%y1gDmGWTvE~B8K%`!TAkM
z5Vr~Du(>I?7r<Rj$b1!C47YwmkHlhF+Y-$;@G=85sRC2O0BaEw3@IaX#}xRuC9H7(
zDMtq3Ob3BRBp$Ee3|nJRp#n-J7@<J0x<M_?;i(E-3!zS~fF^n9+(d#U1z4OyeS<q3
zKuttwC5=Px;BU;}a5!#HgUSh*CQz-0(MrJWXK*xQX>8y%4&)N_ZU;u`N1z_Tq8?wT
z1B-H8bqN-w=(P!Y!2+vKpyREEmXOK;T&5vyX~7~23JRpzI1|uz3)m11cyk%50Ge_O
zR9R34hKvQk2X*p`K!WJnFq;XG5gsI$faV2Jl(}Yt*7BnWp&4ri?f^jc3xeA=u9={U
z29oDcCWJAXDySwIfyR;p@-so3K0r$ZQ7nbH1D7nCL7+YfRH<hknlX?qAJ}D4jWIOw
zNGwL0W<#rd5dA_>?SrHa)f6KGkHq4j)WjT6jKI4{c+J94jb@?|)I?~B1uNxTvp^03
zX-1Pk({2IP4t5YI<Aa*Ba6?ez4%L$&v$5(zwZRyair{KtCKH$#M6$^}wS=H<R2z*z
zTMIDs;0|PLHlUek>X8U;K&ANP=VzA|fKw4@n-e&D;*>)(#2nmqNlC3p#bpdMsxT};
zHOSCBq_il{KM&G40e5mhOAOG(&@_SOCOlJ8^GY&HDm@a5LA&SNQ%jIV&@_O$osf1N
zWTFsPT7Wf05bZB`D-o;_-B@>68xkywH(HRaM>EA7(wjz7fZHGprKo0^dltK77D2bZ
zf?25YrjRuZWstQDsB(s;&PA!<TarO5D^e>!d(hBCpc>4f3e4Pd@{_=OsUZwBX+tB>
zD(~bBh@@*712Pv~tw~U7Vo6CNTs2w@L8=<im?Ek=G-JS>9MB9SWRpf7=$HWK{JgZx
z^wJ`**U&;1vq$FY7i^5W+J_+kblgC3NopQ!&6c47LI_k3z`_I9@IAESj8hlJCN10+
zSb%nMgr_EEy9Sg6xRrr+LV#QVPp`qo@vaOoHPFC8Hw~s399T%<4CxVKcPvZ~L8rnL
zqB%6!C?4!I{H9xi_h5s)2TG!;iA5kb0dE+Zg2r}0#Z5tK9;i?N?|UuEMiK#;0BWG&
z3JF7F(4PO4RD=O2e1h5yJ&XNP6N_9@6Tv%qk$8l(nt2w3ya<|705d@9L4%QKX$2Ol
zhM@WE@S?<mg47~#AJ;R*wFK1qKotX-g4e$$sOnwI7*GX}(mZ&3G`M)PV*oidC^ap$
zC^auR6;{E5EW_etM5aKARqP1>p%`0iLI-KkV-HCaM*I=hf)-~4H6UV&pck-45<v?L
zF(U<0%z$G7TI|{}falwjK_hMPV0Ljlc%vd_aR-eXSV)2AIKg|4!Dowr7L9`1q^aNq
z9-wm<pf-TjA@)o|Jd9!pDDpx3VZpmMp&WF}K<#JPAYw><b}IUcDOjQgFTp}lh-Q+J
zacFU>OKMtTX-)}>I?zgW>@sL3fR_cLYXvQ5fR25Fork8!6dX|Sjs(p6u<hBXfno$&
zcj{kS;-BW5nwwu#iP$+_25P%vlR>l2(lZYl`k=x9#zs>FN?G6uY@}ivG++VFpP<?i
z)m5N=2Ut054ie@GV*|&Wocwa<{FGGp)I88UNM?Q>sA~cl?<jUnV!*Ee&0WSOp2au~
z1Dga+aD)}1nQH<XzW|?0;+tAroS2^KmS2R^9<;h0sof1)*9|({ga|`Gn@LMjE5KDf
zs0c+G8HNQO{+>KS6`uY(LJ^K$J3;|^UmcoAU|n>?kS{_D_KF=m?}u8BKvD~|mk%B@
z167(8@CmQX)Z&o*fXs^29B?WM$bb&YgWLVk?hmRO#I85+sYjq~Zx-<558xIdIu8g#
zJo6A1f%6Q8Q;<|ZlL^#7@E(2)<;cc?dIz9AILJPO%cB}*4DMXuR180g1Fw+~RcHoV
zg2xju!Vb0-7Q9Rr63%6y5q!k{UeMu5p!piuoCskf7_woeI#rgWf=xyU!S*a-kqQPK
z`GG?@HaX9{5*(^AW!!S|6VX+><b#f%K{EmzF%U7BFTgxd5TFMs_LPL84IHGnQWS<t
zGz&l_C`QV{&;%KzBCHP8a1+pSJi?kl-X_)pkXkfLK>JV#TLMY2#99MUjcO6-Tn<n}
z0K8iqbZ!}pgQg6;t`jjLi(F`fr;%{2>_limGteAlkt1T=SAG$Abtu;Pc?Jx%sD^<{
zPFQ6LEnP4d@}m@+xEJ#wMjwrg!6O@~Dd0i_WkityhYXs#41;s>%RwvOagQPrP=RWo
zk!fgNGU!AmtZu?72Qmb$R)mHU{z?(92v3~|SA(NUgv+DXh>)=XJBGxRl>EGS)PweN
z^HV^LW$;0L&_ny;A#14_%0VX|#TS;QmZlan#HXb&#3P9?6r~n2fOZ%#goee3LeD`7
zat#D=p_H?~pP#F92uK99F~t?c2=)jKaq$oL1F=J00^);R{aiq7w_p$%?jPh0qTO9X
z99>+3JpJ7KLEIqM!1$2J0M~e5#|VbfviPFZ!g#RNiOHZ7(;!Y{C@4xTW5@%wO!Cqz
zAY$>w3<!1!Lr#8v0Ygq=aY=k?Q4vFOeo89Hbg1J&On<QLuKsQyjw`YgT*2!JAj0mB
zo?!Pw6@&(ZeFo<F`G+`$IePj)6uSBO2Zsg(_y>W*z}3+Qw1FoQEa&9t0<pv?G#DZR
z3N1$`|DX_8aDcdi_(862p}{D8&?1J=uy|J&*I;lEL4z8)Q3xdC;U63l>KEkd=<ETu
z$<r?+2+9a^ggDGI7-TqD(AUk=2jYC+VE16pC<xon6&^{hey%9S`N1{#`8$O|qRrLM
z-`CX_Y@VNgh>IuGzF-*3&)?4#5(Iw!A#khx{6m8MogpC(VuuDmO>p&tDGrVVCkxjA
z&j5(S0)qTQz)8Xt%t8%cun;JnfXxZ<^mTRd4}}=z?BN&$3pz(nH%DJoosOQtu0dg*
z&Jar+Jwfh*8-$!>U0owQgCRx+2SEea&(YU4#NXe?-_IRvae!+OBrJUV{UKh8aB&R-
zOZoYSxcUZ!KqB1FKRCb{EbIyKQjkA9IAI!s;XZeE^mBIgfu;pFCr^l7e*R!j`v*YW
z6cQ2Q1Wissj(+YC@AySP&G+^3^aBUCuVX~KYfzAXP%tPrr4|*%gY!ahWicpY<mJc1
zgo|N}5(a2igB;yi%mASwxeO*(lv-HKP+XE<5TBNln9cwqiWxvN45@i3pyC5Gc$Ar!
z4%JkiSdyHPT7=3gW=Ku~*%_aiAD^7WP>@=dnpaZH0HxAW7>dB1dWLccRazDgQVDh@
zh*83j2Q{{sAulbZn4!Fop}a6Yx3na+f+0S>I5Qn`>I3M&hxqvXg2ckoR0b#=Ur>@!
zl$w|VQ4MO6$3su#LYF}2mzKfxlo!S)7FXsaGbHEa7pH=}fK)nqIQqFjGMi&?q#roy
zojqJ3IlwJA-Zc!G@ZEyr1N?o!Srwth6RH)I+Fasc$pWS>AjmbqF$f&r0YUztl~16A
z6&w=e>IhDYA<p2G2+9-S%ozengP|^9;b2d9KS<F4%iIuqQ3_pXjDyQvP$?S^@?vIQ
zIw-oJa^QG?vP(eXASK{X00#;vI7-VP0R&=$YZeA*ssJg6r~;b;VU~cy5tL>irWP|4
z6y<}qqe7361@Ti05{pvdd~lTw=VhkkAfzBh!VH4&ps599Il^6;`SCFE^0X9$979QF
zZfX(S@S>!Q_@ey$5{8nZ)YSOYypp0yhN7g@_?*<V5-_7EGd%;s0y!}c!c5N3$uEMM
z1WD@<Q^DZ{VJ0Vm<?~BHHCA4_0{Dy)l*8gcy+$*W_!5Sq)PmH+5{BZE#G;b;Ot4!a
zW`F}R9?UKVo5lb-voJ9yz96$8H7y0kL-J~JMrKY5+~ZKy5EmjiAXaHE1LW{OP=3lw
z%qeC_$t*4a=jIf+P-z*I84q>|NMB-3d<jEpF6h)>P-y^mTRb=)rxr0Jr^Q3EA47b6
zGUy!J(t`Nn67W`n_@eyMlFYnRhWPlzqI8D%cu?wNfS;EK%Z-qTEs8HnO~%O5C78-f
z7+@M9ArHy>B_M|+CxJ+CV<9;WlC?ns#i_XnW5C<wz&?UIBsVcRBfcQNs06ax2gy!^
zObG)ryErvBu^=PAC^a7JhT_!Rc(4N?p#=^&kSicT2xgTql;;;^gECKPSv-uHm<BpF
z8O8(UFcbl>1gNzJVlbrS=cR&^G?)i71#A~cB))_pDX}C!k0GfvEiJVO)HQ@Mp<Not
zt|h1#sI`k_WE<WP1@{(^M&j^IpujZ|oI!!BM4LjvKGy^3i=YpU!_6RK>>aL_grRqY
z9%4t{5juz)c!#SeH0};ph<$DZ$FMs>7r{|?SoZ?7_YzdyLmLMS*`U58NC4csX7Ecy
z><_9#=EO(&85$x9fR7!3t+)Xl9suem!WWeo#3OB}0*{Qtl!8*DH=0TAsU<LJ$Urr!
z0@STPsB++bxGU-zy9V*_Z~^zB!3&rTU`PJCf={KxW=duNx;cokeNY6TxY`sHZt<kr
z4AunNVpy6}!jK9Y%!Le9Lk_KV0%z(#P+u+ueAp~Q9Wn<T1xNyBMX9;@WvQ-Z3=jq=
zXblaK6c`$2<`t(FmBfRNEprVB2A#bC=VPcgO@$se4W?20k<juLTBw7a2DS!bMm$2m
zBqu*P8+>dRWPh2VA(Et7X&zJ>!objNoSq7ru1^OaE8=5lgw&HQX2|wPO)P+<V&B99
z$eu=qY~REJ*rGPjs1ZyU5~{FmkT6mIl$4~zoE-1WycC#_TYgb$W_q4uN=i{`aWPEP
zD;Q#tM`~h9YEf`zRVqU^=&Tr+u?0n`#i@BE;JJ9;#Nup*Y={i(;82JdY=AAKJRdYj
z8I+2wEhI4=F_sBFFB6MAbQ^YXNn#0fFEe~=wrg%uYDx;E@P|1Ysyrw^zXa};P}nK_
z;K>z`6eOc(gAT_*7Xuxyk1hs2Qy*Ore6lg*yh|h_VZjE935IO9%%b8FKk%}-%)E4n
z7&HbT9B9}>IB<7Dm4G6N0qjU*0Z2Vz0bYZamzZM-UiJfO-WZyBBo-r5NJwHj<OoDq
zNdTI@LXid~KG42bOrtD45{rX#GqD;05y!39A~-h_99C$y!-R3`gzmzI9MS*^5;POQ
zV{QmpJO-J#r<Ndv8KyZ%lDLgA0!<*mQZRHm9(ZakHxtuD?CNkEZU|Z;iKdC5skn_Z
zGDe)249#rN{FuprLk72DkX00!C7FpinN_JNAZNwH4v}_c0IjHi%i%Euw8RlPi=r9>
zS>%W;kIyL31UFJ{M>Ptx{F69?K$8HV%!;ZXynYlUjK>9*&Y)I7aY;x%A`7_&fDc~<
z9gvSKOtLAU;})Tlf#8Z6d!97J?gUV)6&llISd3^VkfAx=96Al_%8>1s589^>ImQ5d
zicz*-K4gzQm<MV*fR-gdHGrlvpv@d4QA3b$F!;o7kYSKH3<MwKLeP*k%vPjB6kxR+
zXyqqV8~9)bWN~!u5Zl1YK)nZKZ6H2&<)EHkNKs-ksKo(VbpYoh-wF{77X{DlBD)!E
zDadn>kb+o>;A2<{TBaHd>NE%B7iWUcuLrNwKoP>w1S<Vp^HNZ?APHdA05%d5V-Qy%
z31Dad9o^%amx8Pu&IKt(ic}+`fTGMi*tz|Ppm7Z_kB=_~kK<rhzz|=+5MRU)U(Ns?
zrYmNE++q+9>X$RbC#5mOgYE}n0G~q-8Z%2OO=F19NlF79NY4<ToS&banaThj{7Geq
z2Mw4p#22TgW;4Xc!;esf4V>ktrNx&pq!r{BgND<<O)iG`(j<oX)QXa#M3CVicSbP8
zmllD<K^Emftz(E!%E^XU3GH#hd<D|N08Q`EFu_)7<IL5D21tPgG60m0kOe^%h+9!&
zZmMe*s00Kvk+xZbb%O=rsSsH=I3<FmVH^EGT@a9QU_Qt~aE}>m3^>V~JHl`OfwHhD
zGBk&-HbUqFEw(p^H#A3x_=B%vD0XGQP>b$<u*G(elWZVah9Mi0>R=5%$T=gRj1Ov`
zLas1^@H~rM%Mx=ytwp3w2MpN=4gN)t!X-4whaua)EVZaCGqs!{8??AJGbc5L0mH#a
zB2cfB6Qkfj2N(26F$xw0#|fe|K$MWshyyFK1aGYX9U244r;y+Pxd*Fp2=79aBly^~
z7=g+Tgc76>Lf4HXh0P#vTMpKv1;qzMKe7lmZDx>211+3_#2&QbKn?&<>jWuA!D^BC
zkVpat6$89&jNEkscRLWZct~P8xUT{qAIr=u0pIEXI;9W7h>tSyFG$S`@&<K|k@gfZ
zfJ7PMqYRB*J^kYyL8Dn9kpN4?a21LKLwpqEnifox;-d^r;A+90Nvx)TWkAL_gU0PK
zjR6aTT!b(TEQHlCuna?dl!;GfaS5hbAW@J}2+x5;u$lyt0J+L7r?fZ&(<HDk$S8!X
zz(QEf0?RPOM}ZcMVHy=5WoQHsC(x;I*upv(+<P{4DN4-55@}#zRM&uou(}2;!;qPm
zS;A0~Sd^Yx0;(aR{7mxlQ&K_8fP7O+GV)VAK?wt~z|0V7^u^V+EF?a_I~jDOi4kZ$
zx*=i|2DC@bFdivEfrp78MuOLOK?ak+Oh|9sPQi{L7?g2PhMM3eIvax4kRy*ffyWv{
zK$lHH`i%%jA~YG1pb7bO7-vIB35Dtw6cwN|q;Xpeb}jty1EQUZMMrT-3PWB&elbIQ
ze0pAKd~!tvLtbimd}2-x=)|A=B8ECtE~r?sgsU|)Mv?VQb~R6gjE1-dC4*KYfCfew
z3Lq;s7>Z!)ra|%GO`Iv-$qeAL-{N70KzJxd;WNns>XTI0+yL(~1{e=|`wr;-nfNF_
zd<GaAq@==hxdtTXG9b7Fy<w4?SOIQkxt1}&m>^B~?6U-W5Oma?Yd~@k%=;idA)V$a
zsl_El`IW8#$qY~?Lwra9YJA#&7A4xj!T}V&P|xKTF~mE9VjUp|RU7Xc54uLCAg8pL
zA>J3%xCE<<&&W(kEdn{pJGj^!stA;>A<97#Na6v>AOY{-VzYSP_@Y$M?RgLe$VkXR
ze;`(JVnJeZW=SQ8U6h&zo;+fRcPz=z%}fSOhomsX2c;H38?eFgh(HaFFG(%R&CCN`
zCKntJ9)$#16JK1CUzC`h3bH)7*aW26&?p{B0m#8fT#!0%ghJo=%;NZ*)WmG?+TD00
zE;fb58Hq(m3L#vOLYRTZ@xJlJsU;{TBKXKEO`$45W<Zydp@|@=HUfny#2nB?YVnDA
zDe-WPxuBrLA&F#$p#eBL(m*i{3KLKyfjLNOK#`nYl$Zp%3@gzy8GP|fyl*^62uYP?
zd~kd+Xd6|kYi@3kcQ8mL16&MAA=t_k=yhIjg}(7nAq<t!)QzkXB809IoNx+2mmfm>
zl$>8siKNCN-WSxn$xDU#0~|!jptEklsSBjkJGj^q6x~UwkaPdwY|!jveo<~>PJCtw
zXwi6n5jdA9Xz3^vm!w!(B_$STCWF>jW#*-WWk3}VOexf4P&j6$=7G*11eu!(Ib9Nx
zSwM*m68<0-R0G(>8L7$Hph7Ge6rtc*aHy;yD6xPA;vpHyH8(fF8=(v;3RMj<D+hEF
zrE4zO-(WUW&d?B)jWdh0KsTC#?z;h5l>+61)Ii(_3QyO7<N)tvun8b8LJ~ZyfRF@n
zA(Ei*Oe_Y?e1eKmu=5~Xh_s<GD2?P7RK|l!sAAWEWaMJmJU%`THP}6a<AaMKmmi^M
zB-6A2?_{uXCh^!}7&H*A0CE@pcm@~U@PvWOCBgB*;1lqIi!uESa)u#H)&T6WT+rGA
zaAXC?C+CBC5R*Xxnp+AQ-gnJ~#3h6Wku@}m_XQU;@fnFl(4+=RQeZAz2~yGLTE>8!
zcp2(Yc=1tw!Nrhk(ZEMvgE`<-29*Gp@4>~Uup9%XLH2kf34%>Ah9rGxviA-yh6;cs
z&5FPpLGw~z218LQ=yKsyc&OUI8y{9y7>NR$<M76jf*pp5P)8!!Oq!L%B@P8UXhR0w
zLm=yei%p6kp#q{nBA`kL#0HfGQGOsEXspDw4BT*mDnQ&@25OZB7b7<}pn;hR)|HzK
znl=Q@M4<{p&9Q*hx~^pmFeXSUxY!&tS5;J&>Y58OAhoCrT9KN9R&aoBj0MvmwV+rA
z*Sc^AXI8l8f@Fe=VJz?9Vxz<o*Ib4~@ZJ&_5A3D_A5dvr3_qt=+ZLj?zz0$efl^t4
zk1I5lnSr+d<)uKhK-duF$P%DD0n!E&gOpcjBB<JOq2^l_lon^igJ!l}lNsP_m|937
z7UUgV%z#{inL#*UM<MKnC`Ps$E`n+v%x*KtysImL;x7PPUgah;K$Jtxf^b|x^)57<
z!i)n8!JP$DhvY6KAvD9tav3xvO;d|NcSz>uGJqKnlc9n{`H*xSp!@K^Y0A7PwIByH
z<P2_y6ob}Mfw&M8(IjCZgCvXy8&p9I{jl(XD<jHd!A9}mB!uczVzpv%90^*{yg;l@
zvOOAX7#|F))<_N|P@M>>mO(j}WX+&m*GA9^m1ND}jy1@7P(#BMYKox=xK#;GS@DUb
z6`;x&+?s)=Hjo%3e8CMfm}qfg8mK`Gi8oN|8e#xQ7^)i7F9Ek8K%G6;++=t|7gX;<
zk3R<~1yu&1HW#QFmCFEPfkcCgO^VAC3tWSOiy1%+kQk^?1~*1Q1v{uw3Kc}YBNNmL
z0gcYUyMeA{3@Cg=e-N@HA5zztq-Ex%fQshaTm}#mW-^EkDFIPLAl`;lWMCzrrX!eZ
zS_I~UvO+Ecm<`nkl>q4k*CQa$faSrqqAG%$W@rpDEj|sjd>}qQ4eAmUF{n;-mB{vB
zlf$76VY3m~7Vzc+REwcPFauE4p;(J4g<TWEQgg7S5bx&YmtgfWL>y)k79A*Vz#)%E
zJHj<)VAp{C3$YYA{E>uVhGD8laSC>6+?wGIF)J=jDlRDkHJTwTs2+1@`x)#k1}Fzz
z4q912k~v%lL=;j>fW|wZnn7t1(*S6@7+D>-OP0$J@0^iX6avx_Tw-Vl>QTg(6eVVs
z6niGS!rKp!VV{h|B6x<wRBV)5=o;jm465r=3$dGLlv4szk^^aQVOR<G9;lEriU;R2
zOuJz1OsKao6(9<OAXqVvVU-D}CkX2`g4oy{Z2~IKV9G#MBZfh+U<ycvR!0~r42??i
z!M#Xu__+poXEGoQfTkzFGT2>UXjqaDn&|{90R<pPb7o!%n2$?KY9X?gOh~lAg|O=~
zPR&nqEn`T{Ps1*64$4CyH6RZ_*$hZY2He@PV~7s{Cm@v08%)YK9yHtz>cvBrRQtw*
z_fSE?)ifS7`v6t}9#DhTAMv1@&ao@8C@D(JD^5!-0xbvxDTDE$K0r6p9NO6db>|?R
zDjW(;GV=4YL54Db7&sJ}mF9tDUCS6C3<fk0K>4VnEhUB~5M?l7&j3TnyiICxX-<h}
zNouYucspHkelBRbjiI=t2(;-TH!-g?EioB%S4t5>acWU!Vh(g3wIHv+Glc;>KAxGM
z=b6G#mYSE6U*ws>P*9YgQkq=inZf`H*&w(DApdv=6XO!t#y{c|gGNz7_r@ib<QHjc
zGsFj{=D^YtVNVwnxPq^1BFd`VT-P#q-%M8*<RN19fh{4<_uw)Oly_jBvIX}7iPH=j
z&ohdLJ5$jXEkW3z#)^WL9VlmjE}sGU2hW5AW{N>fbAX%+sw;4h>EqMw4b@JHZnP;4
zyz>{BcB9T`1Vambl01(#&OnOWk!Lp`9Uw^KoD?$<^BkbSLz#fW62tIzEfzUQ!2l{E
zu}Ov$7%~*4CS~TO*no$2@u^mTEEU1+jo=bP1B3xs${?hfvtUSX2Tz=kVwyM9I7-|`
zN|Gb&Hnb#Y0%><p<XxhZBw^Q~BvBJk9~}}Ml!PBrk~N7(n~)<WZ6OjdF{<-RGC&h^
ze)%b>kcnJq(*;!g#lwm_L_mO6gJCAf;6zXGW*+dI0H{L<$|j(}J>Pg34^(QBWK2P6
z3Anl88i3FSG8SwTs4RvlAjM=O(4+;(NeKUf>O+K6QN=+<gDMngZp80-JZ6JBukbvL
z-xNd8NIl4fAq9~5Ky@FoD6GH%MHQm`0IsQE%Ak=+iv6Iy5vVqU%m+9680sLU637Rj
zpg}|oNCbDX08Jx-2Y(^q3}%v|A3O(^mkHXk0h$8?EfYaF1fw*DPOc%c0m%I*;R7jv
zgG)?uGK))aI~zQB1DTzKq{JX^aF4|oI%NqKWQYeP83yn*bdb;n84B?o0rMd<B#;}9
z2s#GVlK~CQLPp2D3F<M#jLRrLg1X?dGN6_U393QC47qy`G5-P*LkW7K0tPY1L)ec9
zwFI4tXVM0#q=Ys7G13)ia+atdA<iD~=pCMrA~KP}=7NZF8A*!a+q8%?8a#OfJ`09$
zq@mToM8q6)ZVH_Lh)Kg~MWFky%NW2kDA5silqpy(sE8uM0u%6j4`>z?vj2>*@h~0W
z&N6|L!O#Faj|6cLq|`wOfP6zR#4HOy2QNSa0nR2;D||i+Vl^=?wgA}y4HFoXDBECD
zPFQ+~pe6<JE+AkKqTD1HcF-9o94;ctSNM$xhE5L<s(@gFEJRij@QGGpBFwC~ASW|9
z)fI;?gMy9Y86ZlC@-Pv`5$kK>j3U}J$d*;mC@!ShBpCf>rFof!rJ%hh5C&2HH_c5g
zN>6nK2OF44lrE$pFJj`%q&U9_)CdAmM44|0YI&t)=H$eK*4Ac%H=2RxdqF|r3)<v?
zEJK`;pcyT&k<b}zSjK`H2N5OCC{SY@HYkWIAqJbqgQMCPH1-W1P9(}~P%9cbNsTLo
z!y0oCWki_@3Qq9UG%nYI`XyimL>Xs<Sd5igSelrFXm%GvQW9wK8E7e2Ji0UksF8`$
zLLt88OT;**vmv<Wg+59P@fb1sjd1BV^GnS0ODzX4=Z38^_OtX$gx=6#?v|Kbl3!Hm
z84~YmQIuLzT9g+LO7#$3;APt2^9}7lX9z&{9xy<)I3*URA}fID200pw1)%lhFb9AS
zrvNu!h*6jcvk}=gM+1iVC}hvUj#Ldub|vV)5QBJ-fBaI*!A3$h8|pyUk=enlgL@Dn
z4<1Ou;a-^Kt^|FCsxrVk89WM0l(7NcCB!QRP21v$2{dQ;1slafj->}(mIm=JY^Nc3
zUk`B(1RH}m8?-n%GZWn`zr;M)7GeLqRL~B3R29U#**gO@VL;5WL*BL+Py|{}nOT+!
zjyuq1BBad%mT+18=K~_E!*fI+vNG6Y0UjH{GaCf<5g;4s3SRO+%(e%TbwTzlc;=ND
z8@Yn61~iBVl?LEwN8JYjJ2=A`yuHGd6dhRiRUpiRbOcat9)?L8ITqvG%u&YRSPag=
zuuWLtct$Y>Y3B&|uuPCyFrz{1q!Gai+Vl)I47}AJuSw2^;DIsMfDrJ~6I>QL8=)&h
zN`6QVa|V^(pjJYZk%3=go(p8<HR6DEaN!L*^T4$%2;^pzQ+2?}0-H{-f1vwpK>LG0
z+1L@h%#B3TK~};X54tSD6;ytrn}lW?sKiHcCTL?f#4)a}m_dkJDZXHY2MZz)3D^ry
zYj`Y#tAY6$#p#eOKq!?D%v%Jjo-$Ct!73hzF3buCCJvfG!mO%6{)2lPTH!$JWGpd&
z<O5i`hwQ0>R{_KqE!ef71O%iM2CcpzzZynbw+qUK$mT-}olKGq2Nza43YmE&n86K}
z1KETWdxj>U)=qkA5j14Mc@Szlq?SjkiwSGU0&m_#7zvInY<3%k<fB;U3cC6SdYC#W
ztAn_RXf=#Sy6u=DBp=OK97Q;|(1)iY5|RKUZK72ahQ^?)*YXRTGD|@B?4~fFa2bMK
zgFGF5K&P?B2Z#6vIC+Ky$NT%a;u4Q{^9;i-84~W#5DcF356CYn2`&NK2wG2TXcUqk
zkO;ae7GytUlO-aE;t>g#0a+cg0|Fd_JVPSmK?kN{5%zTq^2Q<zIye%Gu)m877SZ4U
zM`zG>NYIJ}kn<t#1)b*xDicCW(kvjE2h;@eHZ=B2%tMHofQ~D2En@&t*yLd=fxwMw
zG`+B<2D+JGanNyK2x~w_qv?hWoP+B*G#O_@jDxaZB@DRnfUevKkMbh$l8j>T@(jp<
zS#_Y{YzPxn48nOX(58eXLIhME*MT}|Am<Yta)22?SRu$<@K6D4h8X|Miwj6Sbk>IC
z$vo(+7f2t%fyCJhQw7!was$ZCiJpiFBk)Wf=7IxPu!BK?3*WhczHO9vGlCN_=XPA-
zKEWypbt>-ZTTCazT#VH=P?G{a@dx%Z_|SIHXjCGoMGH<H*jxf?rxDUfiYuK#J_Dy;
z#B>bEa`fd*u;9TE2k8ezVlhlba532Db&!pqhz*{>#fC=6VhHtU;xH3Id;Y*i;f?lW
zc+voG5`>!y((P;r3Q%x)0G4z%g7a~QQL-yU8Mu*)w5Z+3$UHtiwIVqqF)uw8ygf28
zB?Y|C5Ok=iYd~fu10H!$m?G@-F*3!Xwm35{Jtq~HNf22ya||so&2bF~!|E1>_$VKc
z`gF(<s`1dXnhVN6+qTifz}CP^E!b9bL^%ddHlS!HG*k_V0?7Itf~6QF;9-hkWd;6{
z3`Gx7B?+`pMwA!$Er2-#RAfPXgJBD3LIPZkkYy$~QQ|QZLkhF3fhJkVd;lVukzPbX
zLK8X-L6pVN?j?AiK}b9#6o}FY?I|H^q|oKy1_h4d7Sc<?E(s}cd<>0JQgc#EQUl%c
zi`-l?8IXAlbx6lZf-(onxstF#2UQSatRKpOm<W~N<0~PDY(fh;AG1QJ%@7)54U#%o
zHbgNImJ<yPz^9XdTOn|T$YNmUlogZ|sX&^=pquKTXRyYDPE{z5XF!suLt@86Puwsx
zKnQ}5dqry`As@T}z6cNG1MpcL$T|_n@q*(EL*6(j6||x`C>6X46+_xIG_MG(08C@G
z!O#eF!5-+OQ}Dzis1J(Pe?~e5B%lm@9Un|J=s?d3=pn}7nRw7Xn*5^plGNOSoWv6F
z)<y8iOvr;0!SRM>uwk7Ls6tmr&kNKU_eji3$w`HbuYep(q<(@Y9AmQ-5xRITwuFr3
zp@j)nKM-;5F*a9_a0D_|?Zlpjj8!vn2P0$CO6ZJaY<fsKE*Yx<;H-pn5oH<rt&!+S
z%Z>qbz(PC&>?GxQhBVOG@-Qw!JOi}j0F>guxyZ~3d|0=kA^5T<$Vr|UIT)o^gsja3
zbSxjK$^$^l`(ecg)P6Ha?jqhOm<DWy8Jc(&hi8^#Wac^Lm*%AugZ9xepb9b6LHvy#
z4&c!!P}zX!dmAEmzR{d*XyBO#J9iVq?TEn%281fC7J_%jAcrg18K50YSd|AP=LWcy
z1slc(lz~Qov8sWLARwJ%gs#fa&?z%7v8XZ_Jh6|d97z^Ks{#0AU|c#8k{B8dK~qv@
zCb)DW$)anu1o!cAxD_sksVlkI2$yZ4FgbKx79Ob;xHQ3}(DlHA6I|ay4<1JjeMoSE
zWwB^YEKW5u0ZU@jijc+73W*6^I>9jkmPFSG4o<KP77Iba36{gum0WBDmcgbACWo#I
z6r8v;d8Af=rO@>l8V02%rhsp?^Kr#u8Imj>txkBgI)U4z$l1=&2xKng-aMSv!lW_m
zMbeDZVu)sJHiLr!w}+9XF>OZ3Vzn7r8bh-&SQg?ite!@Z$EzK;<q+es_}c(9g9<JD
zu@pj;C8-ce40}yL7je5K7MDN@ax7^CRROvICT^KIIaqXogfY}Q=ND9BQ411gfY^_&
z#XJalLI8SU4HXBe$3C(Roi9Yx9-yf!(D08de6|qM;sy`+qnZKNL}02A($+)Nafrk5
zzzaDH;~6rG^Fb}!c<|L|;1l+tOz^2bAbHS9N5!cr@zD9|;N<**RE9c8vlhaE*aB)=
zfSS5sF+)?xRyY4Nh{9smG6pmeXvm;yGjax>`vlPhJ}Mf1%qPsx49H4IHN?;War&ey
z1A>js9LRvO0eA!n)M__`xC-pQymD7?WsWYMlH(dshE>MYCp8g#TLPHIW}ih+VmbI+
zNY{V>zu<UGkHh4#X*LDxM42=O-DwQIuNIuBkozJgphF448o+ZfIOdUItwGRmrD41)
z)=6Zz8fb?eG0}{a=n#rr10ZX4eJt}*%VAw@I1}VAlwP#6A!LIgs-O`}5a~V;MAsTw
z5ZvpHGBg6sP{1xC0MBcN!gwGnQD()F7bSpOXUO3O3I(KNa^dSTKsgk7@(<Y%P_9Oq
z5;K5bstKQ;hE21g7zk>eLN)pY$0HkwFG5h%;foYhg|LXhXDMV91!ri%#v)KlDl}`r
zy?*pegGjr`szH~ULj4b!OGJblTKYu|Hk5l(z+-kGPa%>c+T}3dYfX?64R{cYfDYui
zh80WTnMow~f({rph)3yWL*g4!T0&KVQWvC@$F|Y{n<9)j#ij^4%83$JaEF2;s<@;m
zo&nSV1ZRGRIs_BqKIlXwxcvxL0-l5eE&2z=FJ%6YNJ*3_KWw@o1ub~U-O$`GF)t*e
zD8C$h2?gki8qk>m7=jr27GB0+^EzA-QXqh07hbv|F7dDgH45D_Q*%;0GhAIm;sZcg
z7Zz%n3~*T+_&sZ&t@NP0PuM^dvp|Lio5Uj<S!Q8n1-lEx$_kPqz<ai$KxQMN8157B
zv^Yw3K@`1Ml!F&SVJI(1EXe>5C%^~5QZkE^^YijjlS@)l;DX?rg5bQQ#L|=?&|ny7
z9KtEHq!=_YoCdw8rl_Pixulq(B0rCzB0nvSp&~J_k|CwID5a!`p&$`7?G3*D5v&a~
zq?VRnlnXtQ9DJfPcmy*bC$R*p1OvFv0;^#FpH&QD7L^n;fNTX>l2Tm6kW`e-5S&^9
zkp!P23}HfM4^vW;N<mk|LFkf<%wmR2hWw-~27kzYErx=UBJjbp47rH~3}qI@B}ELy
z;6@MREKv|Yttda2p(H;Tq_QX-bmkc7f`DR%)S{x?;&g_RjKq?7kTGd_3`wbJ`9-M=
z;0xFo5{uFe7z#mD8Hh+mzCV`%eAgjlP?#YnHID&w?rKE|(hx9cP&&SlA-}XFz7TZN
z9YcIP=*r4m@TGI0^VTy<7&1#zbD_s2Gk`Dc1-S*}G0>%XpfmL2OL7Ys;z4Jy#zW?^
z84Al8G8pn1WEmj9141!GK<R~08l8fv3xP_&)UAZ_(W&=Pfxl2Xm=VHghSCrof+SV_
zE~wVqP?}WzFnzC~`eE*5#o<0)sJI@Kc7oD=P#S6soPw#dgUZAF-2vsp6+#)lOb|vK
zl&*l%iOdjjbTR`fUJ0eAK<QIZ8eKgHD?~&RN*h6GD<}<-MUZ|_@pvd*0i_$DG(shW
zH3cfZ6iV-d(#N1QL=}QO!U<ttg3^Ip5Pl7mhVT$1sp_Xg&D{c}N!1V2cL1s%=FVGC
zKEh=X)+?wu6V(0OP+A#ELsTJ1n0g(kyaSZ>fzk+-5Ee|G4OD(UlwJ;{A*vAMdZ_p*
zD7}FPB6kK#KZDX=pfp4lLBjMsh3ZGwhfoP&!PK#FL-=w~S|3V7L=hxRofK5w7)o0}
zX@p7$ON|dg8$oGPDD4WRA+iYaFjV|Fls*lmFF<L8N(c*=`gb_gf98kiV-$eU@ld)S
zN<%~uB&q6;LCt>*rAgHf)At^#ALdR@9PX2Zid#WxKPVjqr4c@Xuwd%Epz<((Pl56w
zst}~Q5QJ?GrLCcK0F;KvBFJ2*cqx=#1f@4YX@p7$3#NW5RDK?m#-)BARQ@WIz6qtZ
zg(2pllP96#&!F@-C~Yo+t`fqBsr!Vc&IX72FQO2AtYQ#)wK#-c52YbI1Stenrvjxl
zp|k~*MyQ0a(A674)!|a_2bGV7(n(Od2uedtMUd#~v!Uv6sc(hKPl3`iq4Y{9jW8L)
zLRY^Cst%X>Jy7}6Q2GLtegLH*rXomm^*5pFaH;<cm1ly+4?C0=htdd>AuM$D0#J3h
z)N4WIEupj>l=g$t5K|E(x_Wo0I$Y`#q4EV#x)e&cLTQA_5Ei=nI;c8a>fIzD`of{~
zRY?f{29$>I5M%~aoikKE07{>Q(g>9h)^Jgu3-xygl<tMnE1>jRD18D-pM}ydp!8cP
z%>fN3UMQ^rrFEe+B-9WjEc^z_epvj5Lfw}HrPHBw36!pc(rr+>8%ocB(sQBoDk!}k
zO7DTv2cR^<=MYwx6oj4urN2RGHED=AI!UVfSg3hbP?}WzFnw)M{V;bffb!AZw*e}C
z5lTOW(jTETx_X$phfsN#zqN7r|2VY6cmqmz%0W!r0;M551WBs;Sx|GgLupd=!}J}7
z>W8`W0hEt$8HDu#DlQ0hzbceAhSCsK2ok1F5h@Q;XAR{eR6<zJQ1KKfT>+(Apfp4k
zf`q9nfy!Tn(zl>ALM4Qipah}wp!69i{Rc`zWDz8(>W!i11VCw0^~3bVK=s4iSq9}J
zTn1saLB*Ft>D^HJIFyE{LXa?Z+oAF>e={m0)L^pGz~GzxteGJ2(;lkAA=IPusbjcf
zSa5(x=Vg!151yU>_Wl3=|G!7)@fRR9o}I@HzZqWg=)4c+!h{V^`gDHx>HO!>dB~&r
z2uHMIoMU|KOOS>MFcTd^9YcaWn%`)6cAj(Wyzbfg#iR4LPjBuHpU(FXv%0Mfzkyjk
zozFcwkGXXI^6C5t6?pH_c?`_-=sXP9(0Rk7`G`ieV~k@g*uujwyFm7Mcy@mC==|+*
z96S!-(ObI$tRGBxb{_ZWw)SZKU&0FJ8y@g&{a?c2)A=9F_2^{w=&d~gVRthd{`Y7-
zP{QreZ2=MKJnq>o26ZYz9n1oc<|7^u{~re5#jKE6lwO*fnpdKbTUuPAkd&&Br~o}F
zGdMLlKQ9G~f;@%%q^#8B5{8hB%pz<G6w*K!jb!HMG2k7RL?3#@I!uW^9tj%XgpYa>
zF))hDmwBMgTnsq<sE`C+nZ*#2ky@0hUaXLpuK>OVQvp04sF0RlqyQSjQvhAQsgROd
z48Arszeqs?tV&anbdBJ#NQfnxig+9b4_jP5Lxeu;=u^thJOvHhq7UX4r<Q=u<IIB$
zl`<rQF5d$mbij}Xy77)71$5IKgPxv#aZ$29<doHd{Gt-Q<bnd|p{pP+LtcJfDnn{n
zY92#wVo^3jeo6{MaY15oDg$)cfqrOlYEiL%d1_L6YHGH=9%x&JZhB>bzJZ>hfu6A$
z*m#g&JS4jGGC+f>x^|w$kimKlO$N{!IR+eq6`&FT1$zWLdVmK0;ushh_AoFozy@7F
zVvG!I44|?GqyaSO2g<mhK{Iv+1_sdJ3oio$1E>=Z>R1ahFff2RiXio%h7G8)mS<pK
z02P9&3=9lv3=9nF3=9l<3=9m$3=9lr3=9kw3=9m`3=9l53=9l*3=9ko3=9k|3=Cj9
z-53}cJQ)}mycrl6d>9xQ{1_M*{GoC|P&$->fgzlMfgzHCfgy^4fgzfKfgy&0fgzTG
zfdS+nkXzyz7#I>57#NZm7#PwR7#K1b7#K1c7#Ok`7#Ok{7#Q*x7#Io|7#NBe7#K<z
z7#PYJ7#PYK7#OOdcGNO3Fw`?JFf=kSFf=hRFtkI(yBQc5`WP4(CNnTFOk-eRn8Con
zFq46SVHN`e!yE<%hPez344{$d#ZdK27#J9qGB7Z#U|?VXjZA~www8f`VIu<r!zKm>
zhRqBN4BHqO7<Mo)Fzg2TVeY)6Tj$wn|B7gPyID`-`$bmUrO)y&EUpS)pY!}F|Af}E
z4(|WQ&)E6(7wt+hn!vLwednh{u~{|e6$%erS&;j+xI{;CLroP&h=)i{REW;Y6#Iiq
zOVb6DMQ6Sj-7a8bGWn+9ul9oGDqihVT+5W16h54pc`wBJ=H6*e8>8Ny(^GS0SK#(#
zO_6?Q|G4Tv9>emS*dILFd;gskdnIdX-Sva#VR>_nb;m-7!;*{o^e4=pXwTYG<Ji?v
z!?oVz+Oicn+!Z^2Uf}W3Su19Ie79p|;XH16%cj-Gjh<SBgioIrR;n{uGvnaxeuG)z
z-d#0uzqj8yefZDA_iygjJy>*->tAgALC<NILfqf#@t$8<J*!*d%-<uCHhKGI39brC
zu{byDbmeWY9@%xBU2?OTXLb4+O|o5DsMx{1Fi}=p>$isg(R~wm*8Zve$$WFRLMW43
zQ}u-#GZ#Poe)qBF#LBzLMiG899xg9)C@4z*a{pt<H`%xPJRRIz5%1Va1#az_!rOk^
zU}-8}y_kw%;E~tcYVH=#5!*L+)4w0wzY<D5@%YMqTm7)bZquuFResCX88t^#`i(f%
zzI8n9eZ2Nz|Np3#v)2PFB15)*_D)^c{{6pSljx#8Auijc#v6EfQ<vm$H%xsQvD9n=
zPilL?;`dr#)pSoCW7}e2``e*Nk+WuBYq7{77Ki!sPI9FeFBg$$5Phu8Tb(0lb522U
z9rJ<D(ObfnU+Xw9N&U>TE|&v*e)^}le!XY-yhiASnBHYQHIFvA*~y1eraKGXaP)us
z@b72dl56R!)*s0^`0wnQZzn%Rh#yZfKcc=<)OYDjo5!XP_2-uUGKopxx0!G$Bz}Iw
z$rCeQGn$y5PMqR>J#3Nc#LC3w(UpoEt5R9sYx|$momJ!SasR~gbddu$FRGa&Y_wpl
zZn+cty#G>2d&hFth1begTEAIT@&4$9pDV37w2P<NE`1f%acX*qZKTDkYbI=mC-8(B
znl7r&Xj5TrpY)T@Fm0=!ned{d_9GiktJ@r^U}s?HU}s>M!Op<2f}Me34?6?H1$G98
z2kZ<CKiC-<csLjsR5%zIY&aMgYB(4edN>#u=5R1DY~WyEIKaWc@PLDX;SUD`!vanQ
zhBKTD40kvg7+AO%7-YB@7!0@=7(k=g0bC3W30w>e1zZda8@L!44uA?VZUzPcZUzPg
zZUzPeZUzPyZU%-BZU%-FZU%-5ZU%-9ZU%-q+zbqBxEUC(a5FGG;bvgq;bCBq;bCCV
z;bCB~;bCC#;bCBi;bCCN;bCB?;bCAn!Nb77!OOtl!OOsq!pp!=!OOtV!OOrfgO`Ef
z1TO=_4PFL@7rYD%e|Q-fc=#9?6!;hz4EPur_V6(<oZ(|&xWmW5@P?0p;SV1J0}np~
zgA6|dgAP9fgAG3eLjgYnLjykp!xVl7h9&$A3|sga7#{F5FnoX(#3BL=3=0Gp7&Ztn
zFdPtIV7MT_z`!HOz@Q_@z+fZDz~Cduzz`$Iz>p)vz)&N^z|bSaz%WOMfnkjh1H%C!
z1_lmc1_lXX1_ljb28J2J3=AuT85meZ7#Jc%7#K1{7#J!<7#KQ47#L=VFfgnUVPH5T
z!oYAxgn{9W2m^zNC<B9vC<B9!C<8-+C<8-*C<8--C<DV3Q3i%3q6`dML>U+!h%zvI
z096!X3=9Hd3=9Ec3=9ck3=Ab=3=9**7#J3aF))Be#9oLoF#Hf>VBisFV2}}KU@#D8
zU~mv;U<eRrU^pPoz;HpFf#HET1A~YJ14DoW14DuY14DrX1H%jn1_saw#SRGu2GGbv
zh$I6;fg}S%gCqmP1W5*l4U!BDCnOmdK%+e`BpDcfNHQ>pNHH*|NHH*&NHH+@NHH+P
zNHH+vNHH+9NHH)>kz!z2BE`UPK#GCkf)oS86DbCUFCewj3=9F%3=9*b85kBwGcatB
zW?(oX&A{+Pnt|bqGy?;R3<HCR3<HCT3<HCY3<E=q3<E=s3<E=r3<JXj83u;mISdS-
zIyNpBRJ$@Th~+`}vp^LK0|SHBMhIW279#(7F#`jr4t8i}V3>OsBDQ)XL~Lm`1A})C
zMC`91MBnmz5dNDu1_n^Q-B!rJP+!Ktzy&ogVhKcVL^A`!R;YO@@esAjg$xYoWeg0?
zH4rm&mq5f}cK1Wgjy%Y~0BQrAO=n=R&SGE)EM{O3E@5B@sb*jhZem~%Z)0FM)x*Hh
z+snXkbP5AQ$5aM}d9xT85@$oqRbK~jt3(5YuW|&!X9HE%3=9la6CrMNZ(v}EgQ|&H
z3sIBS0nyXFjDZ2vCi#)Y!0@7kfg!n%fgx@h1A{rJ5@ujv2#aH2U}0cj;3#8Y*k8`T
zaIA)b;XE`9Oj#i9lHLRc2Cqa02F(lxhVBdo2H8vohV_{Y4AZk17=&^e7`EmyFib6A
zVAx;Gz|dI2z;LCMf#G-=1A}Wh1H-Ed28Kh`3=C^(7#Q;F7#Ob9GcYtZF)*~YF)%2#
zGcYuDF)&#4GBEt^WnlQ%$H0&}fq}tzDg(o}sSFH1r!g>u&0t{Qna#j(el`Qcr8x`?
zfA2Cd*xh4bI1dfusYMJ79H2HrGXn!}3j;$&3j@R976t~nRtAR3RtAPEtqcqkpkXm{
z4kT<&ff_0d3=9tsF))DIYH_Iy4C@OR7*16(FsyE1U`Xm_V0bu@fx!&aU}0cjI1f!D
zJcSGlA4(Y*w4w3twGtBkp!hL>hX0HS5IZD0A>rSD6vF=mYG^SqFgz)N@IQhYN}%=}
zG#y7n!~F9BNSaxj&cGm@#lWCd%)s!bn1Mm3nt|bUBLl<xRtAPeJq!$~y$lR<r!X)i
zOl4pwo5jFj2~9H<&@=-}53JBMNUnKD(cIg!7~+04Xr2&04B@}H1M#oO8c3KdZ)adQ
z2=(LrK8PAaXqcoy^Rnx7h@M0ih@J;!3=B2UuvJ+D(E~CEq^imRq6TEI9n|iaT!@;R
zpav<ZEv*8H&lx!k49ukr4DV|h7#6iLFx2%iFjP)sU<iVy`7JCEeXx9_wh*FEGM#~8
zS`h<7X%z!QSR(@iZw~_l#}o#JhtPE34GmjRegnDbDg(rvwtNtefnf#IJ-h25{7|&G
z-?S2<{v|X${*r+3%b{swAvEpuLDN#3KLZ1(?|_`=K=}=n*I@Yzmajm036y_8c?MfP
znF37*<d#K3Q2mS<3=H{M3=GqY85kl<7#L<%GcZIpF)+loF)#@9GB8~3Wnkc*%D`}L
zDg(olSqu!zq3LqQMo2lMk<GyHw19!ZtdxP_E~pa$>Q_WT;x@N{fk6zKuZ^K$`Kk~S
zmZ0((R3CUi)6iLQ1_sc?J*;d3l|i6#2UOmG${0|&0xC;D<p;=w)6n{42dLx2z`$??
znvTPuY3a)%h#SHR7#Pk%#gd?IV5$O{z`(HO07OlBHUon!v_1iKoIvh60gXc&Wd;TX
z1_p+Jcm{@*2@DLU5*QfL5*ZlU6B!s@B{DE*<uNc^%wu5qo5#QqpU=Q>FrR@zzkq=u
zu7ZJqt&)MkxRQZkQ6&R|K|KS*hk6EvZ=DPb^ST%qPIoadSamZn-0WvyXq>>nux<ha
zgX}~G2Cs<>3_B+>Fr1psz)&=Ufnoj(1_nN8di?}-e<3u?nxW|x)XxO@NE}-B!0ON!
z?U3}?1<kib+aUaf(DYrI2;nb-`qc}XUdy2ARcsPOUL0f*0|Udo1CV}jW(EVp?+gZp
z-b@CD4>=4B^5qN+o^=cif7%!rZuBuQT%N|jum+kpH=)H-9<&ahP|m=x5L!mQlZ4pg
z)erIo1H%$%d6Eb9_c9Xdgm`G4Tnx>VviT6RU7teCUWO%Is12ex{sE0+Si8s;8WvM0
zL);$+Ek~b1<Fs`VWDH|*1_Og>CIiFqOa=z6Tn2{eWeg0l<qQl3H4F^xbqowv?F<ZJ
z{R|9((-|0ELF4AwQb=3kQWgWlp%MlL+dc*ci)joDf>3!^Xk7qn|8(|1!V;EeZ$RA&
zOOL;q85kTH7#LC$7#Nfi85o?C7#RAJ7#MCQF)$b>GcasUW?=Z2%)sE8!oV;kg@NII
z3Il^yDg(pbR0amAGzNz9GzNysbOr`knFMlIZyo~!s2urLgeapxZe3H#z;LL7f#F&e
zq|91V&%m&~5mI(NYGPmjwez~085o{5GcY)|Ffhz%VPN>)!oU#J%D}L;6;i%MbulpH
z^&rYQkpFEbFfbTQVqmD5#K3T35(9(CWCn(W$qWpcQxN4KD2()GFfcgHLX?T1FaxzK
zLFFB+EqVc(_Sb+0Vi*`0?9uWY&jCnycHe}=Z8AHA4{IYgL)#;lIv5yWbqqTTWDJTa
zoq+*VzttB(>bTe{NIhrQ2&wD7c0=mB50fEv-pQE^;Cc^MK3XP0?1GhZOQCfkEbsqW
z!oUC;*V0L1U?@*wU^tY-z`&c#z%V13f#G>F1A|ct14C^J1H*|F1_t3&28JoA3=AJr
z85sQ17#Iqg85mACGcc&NFfcT>FfiO{VPG(CWnh@p%D^BoiGd+y5(C4ANem2sCNVI0
zK-2aAScrRgp<%HmhJgXJK*J@2fdN$BT!WT58JUoB2UPxp%ATKPkn%^l4pIhPYlD<S
zoBAMS(b{Q{@~CYNqD-29gn<FH$V4xJf#G`s1H*wt28N_O1_sl71_oA8ySI>mp`?_7
zVR{7vLq#P6Luow&gMJqSgFrU}gU|#9hR+ii82TqNFfh+xV0Z!=2xDMiSX%*cKdh|W
z49&N4pn);aSRpj8!0Nx)IEeZLXnnZGA5s?~x0zy~`Eyei1H+sW1_rS{1_r@t3=FTJ
zb@0v@h#3*kI<^g(o&-SyeGCi?TjoOALBZ(^3>S(R7}i%YFidD<U~unYU~rnkz#t78
zykmg0!$Ec4DQG*I1KNH9r7=+Y0;Mfbx&oysP<jHTB~Xez04>W;Wiv1o<bXsN7#g7d
zhP4Gdq2)0s4TDrTu7LP6Et!F#E*T`kz+eeYd$2aQ4qBgQK@6l%fUjK-Yp?c0!x`3Q
zTMOkshSq5>pk~)X>j!>LNc((u1_Og{CIiF$Oa=z0Tn2{qWeg0Z<qQl{Y8V*i*D){z
zwKFj2^)oPNPG?|Xn#;iO6xycHgx0CBHsgF~o5C}jf#E$g9+u!~E1ma;#9=Ws-GgR>
zLG2(|844=@U}YVsj02TfpfU<n{(wS{4cdnVwWpB#yHnB9LI|`h0o9AUp?-hJ2C*B~
z9x#W-C#dhz0Ii#k?}w;?l~Iw<HU>=IdMSO&i34cyw*lJjgY_X!Lfa^yasyOmfXWL{
zSph01KxG7|d;paVpmG6JCV;}woq{^F9xWeh#6!ZX5j2nw8eb<e4+aLH>a&5?^RPbG
zZD>AXgtq+z=Rw+~<kqpE`V>@mg6d3s^(3f%#8n@H>OWBU=|jgHKyA7e(01JpX!?<a
zw(VejB2{Sl0Bh^bAW+6Ff%es{3K<ww%NQ8$L;I5*&^{k5-$X*qg|(AFc^Fit!TOSi
zp>71_OHg|sls92*{)uS)*$`;h--5QWx^cK+2U?wV9ol||_4l4b^`Vb52t(r%R{pg?
z-41K-Dns208s`F)t)Q_kSoxX=wF5RDkyimJPeE>lwFyN#AZZEK?q3;2Ss7;obq}^N
zrN#3hW`o9(K;uWSF(c3z5o}xtHXZ~U2ZD|NfYQz>wDP$D%7^vQnxSP9C|$wQloNq5
zuy1JfVkk7sV0oty8vd|y@E|n&VSR+wSV+A|Xx!l~TKn$F3P`wv>Nb$y_~t_Rp!O(;
zzk>$t4qj;ak3NP8o96`O0g&C;<~d<%K;vy7jIIWx4>WHFG6OWG2x7x9Xq>HJbqDvU
zhYgiR#^-k_>6-Ke2S>%NcAH(ZxiXR=KB4j!sLGwdz`y{S3*5rMz;FcAPX~>eF)%QE
zVPIegDS(7e+&qv?3=CYyA!#{yKLf+@!w|72&@n!y;}AZxEJV*k6$t;|F$ll+34}it
z+9w9huYyF*Lize^ARYrlEY!|~{SZDZ3_$asZy6wMPLK>}3>h>Z%*?>bz{0={o}&ec
zgZvK)3y^W3FaS-dfWi$V4#J@EVNlx=)OH08`-2u|g64+h7#J8p^TVLA1lSxgsNW9K
zqY0fe)n{N}FkoO{FhrU&HfLa9u!7DRgZfrZpfN@U1_oCK1_pQNoH1y=7-UWW0|NtS
zt~eNKUKn(q7&Jc&>f(c%TPX|-4C&B$VNmk~G#?Ba4gl$gVNjD4#0Jd|mohLgRDi~&
z85kHq!(gB|1<8SMD+2=qs5<ImU|{Hh&JTm)dm?n6cnZ>7F-SeAxe02zE?{6_0L>GF
z=7(29-MWr}fnfu5ei$?-3{nr;Sp=G+-wRa(in0R?3=BsZ7#L16Ffg0~jpZ^hFkE0@
zV7Sb{z;J_sf#DVd0|TgO25J)DXJBA>02&vDra92+8IZXk3|brX1~l*dB3KYKN4)>9
z-C@In+)VcIL91>jwe?1oeGFP%<x(<n^OTz44+U=w=Gd6`1npe>khL)F(-$9|FS9=v
zW>uGV2T2_3R0*ovv)yl6hUx!;?|I=*`K~&p@upU|K3}uww}(*TU%5lGrQ?~Vg$gDs
zOs&xmnfl6DL~fmoq|CvsdS1J?Ie(bCVEO5vk5`*neY{e8J36}N$$_&aJ06|M5O$2e
zcJ8Z#fsbX%pPug#K22M@3^^}y+3!lvV--ER`S?0-$9LO*HU6sMeER6&-Wt>20`|Mb
zel<VS-V~o?;vS#aeeGdgm6{sEG_RBL*LvT1DSMxkzh)p{G7~f>TgCqIT;Dq{<#pc^
z`<5C`y7l9A{*0hE?8$4Zum1k!Ff(e0gPrKr4^aZ_Yl7P{zHt~UxqI>b3w^9Malz9G
zncp~!AMZPP@1~TU<ZIcSf4oZP9b;tgL~i%GF?Zv)6R%At{CuE2=cV^cF6A5Ta-nOu
z?>~Mc7IV#>>+mDKZ}s-8Cq6#Wee#x}-nRP3x_4&3yZC4QWSKiYX9cR$Ojq4G<$v6b
z*Ey^v&2$yF;Y0BcnnL<geu4RUJR!%_Ux{9iW;|CKD01B9&W>~E^p7q4Q^=cdIDK(*
z&&8KpuY%@j&6VGr{IZpa!DZ|H!zH0^_guH$KWwkAwMN2f-PJ25)zwQDPoM9guC+$e
zYTebsUtHq9R2H#tT|Ix*pm*z30iLoguax3z9)HbX5|xP3e!Oe%?e)iN43#E5jhP#I
zLhkyc`koC*-fCNtYj#h5@?#Nb4Zw`fz51E%M$cMbdbxZ%$~A{QIIDE)M(t)5=kHQG
z7HQmlUEaKu)9kW+{R{6!4KKVGEt$Q+WEGQ<iO{0|v$i-+S9I00ZQuGp?fvcjy=NYr
z2=rCcytrFEOJl|7rE(1R#~V2_8D_Ga%*oj0yUR?$=Z<jYw$r=j-1GM97I79`{$}5I
zZFjdXF4MLaayK2b7c9CX(V`&zrvKEke{wHAc+Riet7>pL+`H^>+3D)r=ed3#ZC9#J
zdDyF)zwG$0rJGu6=06A$l;FFi#&TADu|l-%&wzv9{(|Pid*c;n$<MsD`s`$zO~Uhz
zO;}{x?R9nPW0}Ra-Co=d89OJIRvJ(KbV0f)-S)VrzQobqdEWEa+kZ2E#k=Nyg{gLM
zlF7RT1`QqDT}OAkGhS$P^>4lVp*IoFyLbYht!G(xokvlsvuK&Ae>Z47fXRnXv;CJQ
z#Pz>R-lWdxdPv3~#HfM4X-NR*3hh_bf2TcXmK1n&X8)sKv1>KuJ_JXdo;ax{gOh=w
znv;Q{kCTC6AtwU^XouKwP6h_hj<C0&&Jz~{gD@8ZgBlkDgC!ROLlhSSLoOEsLjxBB
z!(=W7hGkp~3_H0P7|w7pFx=;2VEDwvz`)AQz#zfRz@W{|z+lJCzz_(X6EEjxVCdpz
zV3^Czz_5Xvf#EPW1H(0L28Ng13=Ds`85sC^7#Ngz7#K`>7#KWw7#N~?7#Ny)7#ODU
zFfgp-VPM$9!@zK!hk@Y{4+Fzj=sdYJF9U-fF9U-kF9SmeF9Sm!F9Sm(F9X9AUIvEc
zybKJxco`VZ@-i?y;ALR=%*(*Q#>c=Q$;ZH;!^gm2&&R+J#K*vp%E!P^!N<VR&Bwqn
zkB@<2BOe395k3Zn>wF9hulN`k{_-&}2=Fs7DDyKgnDH|(c=9ta#PBmP<nuEyH1RVq
zOyy@_Si#T0u$!NO;T%5$!$W=shA;dK4D1373{nCN47vgg3=RSe48Z~n47maf3=IMd
z43h;I7?uezFzggyU^pYdz;IuHf#H(?0|Tod1A~Mh1B1381B0C)14E!714D`+14FqW
z14EY}1H)WF28IoS3=D?_85ph!GBCUpWMKFs$iToa#K52=#K2%G#K7Po#K4dw#J~XB
zWz-?Wz%W~gfnl8x1H(Zf28Js_3=GeO7#MyDF);87GcYI!GcXtnGcdRbGcZI7Gce=`
zGcdFXGce2)W?)z&%)qc;n1SJvFayI=VFrdD!VC=DA`A?2A`A?MA`A>JA`A@SA`A>!
zA`A?*A`A=@L>L$ri!d;36JcOD37y-2FT%jUB+9@bD$2m1A<DpDEy}>)C(6K(D9XT4
zBFezfF3P|#OO%0OttbP-0Z|5q%c2YnzeO1sWW*R4^u-t$oWvLyLd6&uGQ=1ds>K)>
z`otI*7K$-2Y=O@4bBi-D$cZyB7>YA6xQH__go`sUWQj8{)QU4OOb};aSS-%KuuYtS
z;iNbN!yR!3hWFwO3``OX45AVY3>p#)4Av413|SHk47Cyr3=<?67#2$~Fl>`xU^pqk
zz;H)`f#JOb0|S#J1B0j}1B1RK1A~(!0|RJve}*IjL$xFWL!TrA!$L_0hAol|4Cf>n
z7#>P8Fnp0@U|^SGV33kxV9=FfU~rIPU<j6CU`Uf<V5pR0VCa!zV3;q(z_3Y*f#IkW
z1H%m|28P#C3=IFI7#IYl85mTg85qo^85q2z85m-v85qi?85p{x85oXBGceqeW?%sA
z@&dIZ|GG0UKsW4wrdvTmXD=`?2!kj483ds-7B{xSg;?4k4ZJIx;6gTgAws7aK<!1)
zDglP+(5Cp>IJog0MG#f<=D{`AXF!A`5UQ9NAwpB!7#N^U$`Gik>9KH)O-mrE3Qxd=
zz863i3H;m-w$b|_n3{M9Oo3X8&lMqhRCM94{ObV~vV;ri>Oq7&E#MkYhCqb=1i^*w
z=|F_c&EXpPp#uhHY;d9SNQkQJNVvvMs9$&yK30JC4vn_LRh<%rXk4ubH|sw$L?}TR
zF2uzO5y}^W3uT5vgp7jWX30Vwu_OX6^g0}(N-rEP1ZvuW;$EB$9_)dZ5LLBWaN`5J
zAwo;{!GnD+w7swW7%nswI*hdw;nWko5RLy2!p&Ol2@%TnhTAv`x^~1s6t2o1IuuZ_
z2X4Ft)Q=v)aG_$TyG#-8;*WqBzuF(J%BK)AMcO<M?CoWnz|`BrU@G|-m;xn~N~i_u
zh(KHkP0ouD(WbEsV!=E_5|o2xjpTW7_cuXfvP&K=v;vwA`w;0+3YzF_5sA)rAH?`p
z7r4e05s1(}S-22Cbj6CgG+by6Cqz}MJ3L$uRDxs~7)+Of{ph*_Oo6<rJs+aD?j&3&
z6FTW3jnK~?1yMB*k&f>}({V@)Ja`kJVf5Y+WE;2?@PX!>xdCuh6=4vw(n8=up-@$m
z0^p8F;)SUC2`V`uMG<JA8k9nV&%=#Zf@V3;v?R0)Yk?Xc9RfG2O9^6@g&tg^%Rz{c
zk{ev;In=CXU%1Ad>JU`|25?nZpgG4f93Hq<(EQbh$X^RMAR66d;AUAs!)rn;Tw@sz
zL{$XBk6eKep<BN2z<B`8_n>upOpuV+2Nha|$X_W?N0cFANDOM$d4z|yK>O-8DsXps
z8bWMbX#vU`;7Hpb4-tB<0r&O+=-}QqL`f3^4d@4mfELt*XcRMnYYd0x!gNI7EQ2~V
z6yem(Y7mXihH#A&pvK!Fj5mkYAL;wys<NQ2zlg{;@1VvvB8<<3F5}w14eafI7r_)L
z`P=G4EKWq|_h^L(No|3v`Y#0$nxqW3SY{JMNS+lgbV2|kq$ma#N`uy()ewt8Hcl0T
zsM@6fS9J;MVlh8>r1L-{ijf_zsu!A5*E_+5?m#ti`@x-h9y-F6eH?DqR%kh!;0;&x
zNf+V>RfM;vLhF)Mpr#fynL&-WM}(vTv;<<6gFE6F7sRYGcgQ>_0|UbkXhf+Uf!i1Y
zji|W@8<#?3I4KmaY9iFe1cZ&+(4uE|B-}%w(O6JH;O_$$GU|jlV$v44knC}g6B!r|
zJpdd38bX1hzyxX}CnA#tKudgEM2T+)RrSvYtRJLtKh(uj5Eaj7Xwg+21h?1@T9AMS
zgrKb`VQ6%EsDRuA&Sa;cW_2QL`~x+s0MX2Fg4PS6h+va<g?N?Q4sO;4XslEt(o`ih
zwR9lTfq^hYqm&1{1agPg3j&aOK^{>r<WGbsK8#4YdeEA9*B*F)=m<eng(E7Y)zBn=
z^awmaE~r9O9X5iySQJ`c?*vcIfdk}=3q;ilYq%;KXkmK{kwTVig{X>jhO7G94-xX*
z3wIZ6-B>W9xJrO#3^hc6WW_)<PDF$xYcWLV(gL{agQ1NX(BwC?{AD(Us8ZL4J0cre
z_q{{Ja0Ik5Q;ulNa2P=}PBVpT+y-qv{e1|x@&0Uxs<v%#RlU$+G&~%xY9>_32hoOm
z+YHh871FQ)CD{yU1NR)Ff$IQmkz7QyNKB#8@pv!X##c~xZA3Kd_CXsKQHUNxz6Qj`
zZba2;0L{Z7_d)CA9R;Aeg@J(&(!f0mX`qWk8tAcz26}k|qy;}~EjT8hL(*P8B3{#=
zNq9Y?_z5$HxL_%w&f$i-U`qr%u)cajR0Z0BTmnvSQ=vuwL`2rAg!-ml4{Sdu{8nZ`
zG%j$2YXmLU1{FUA%5b3r1(5mh)yu#d_dvq`6{H5?-3b=V-v_2HKs>Jm@q7lt^GmrQ
zHYrKKjr|Ob1NSFzk3>P^;18m`m%ALI@!&bQMpI}>avag1QiGOo`N8nq{|4G5xoZ!P
z^>S#2{)C9)KhQvlLj-U!v|Th4(Js<~&a~*9hdbgl)b-hj6!Z?7W<MZe2GsKdg{Dpv
z+>fAr${?Yg8sHEEMZ<HbQ$1tgLZJN`AXNegr?Sq4ET57(4pvnIp;AwPdB-6XE25#h
zekmm2z91U#VbEIeETZ!{18OxBqU8^ox&&E0-y81cU(o)|`F-%P+yHG2<ru?-HbR4!
z15pIOgHES#BFZHeXefOQg&V)H9ApLqL(3wtUyg1EQ=pL93N0g*5ygN5v~L`O@RuXB
z4RF^2WDYp}pM$0(e?<5NL$gFKB1^P5L&E5a4ctaMXeQ+MfD7#`1sTi0ptKMyG#}x-
zAm|F*SBQ=*w;aUCqZ;s}0vhiF1!xy&Tm{njSi}HP#fs>U3Pbzc4-tLttI+B|ml13+
zC_q5tJRq|e5jI9Z!)O8`KntL4Ts=*Y%fSJ12<omI2%$`9fK(y^gbi9F8zO{2t6@Mk
zUIMSO1)FsMY9k{eRt`Y3g9#!#<Us@Xz75<FPoR}q5TYZy30j<aAsR)@&_eGGB2U&q
zo!W|U*KTOprH1H_Y4m|?VqkEC6h_Gq3KVSjp;NNqdq66{o?tD6%(^y0O0|uUQq34r
zoK-=zvK#;hd>EuSn}aCM(xGj@kWFy&l1m{`>M$Rku94>V7^{L97%K!A1$fvwCNMHE
z=rAxa$bjaHK$AoN|Nn0TP4IzS>c}V1#^lV)=G)BP!`92%$I=g)8U(8c&AV-Ys{aD^
z0|NsC9`&H53k^{9RbW%_t6u|JcMMg(lYsf4v8y`_3=9fT^_M|O1lj$b&0x2K{K>+|
z!0_WAM4<r@=9(}vFr0v@Z^dJ73?l=>0;oEE&?XgR`_aM=<lY`e28IHtdVKEP!pOkj
z0acfQZa<p2ApbpKWMGhhsy9XtXYXdV9&kv290!Sa5hezP7k?q)LCAcNyIq(V7<NF_
z<8yZo69dBps5)ZIox{YykN{N=nzshK5SE_Yn_2ppA(iP7CI$uzsJcL~BBXTWhKT1k
zObiSHP<7Ddc{tN2$X_zd3=9wcK*9mK6dR!)ntnvp7#PAB7<75nz;n&ItZLx7Xx+c6
z;I+T9-&7eGj2IYX->X8zpQ|!3I59BDK2QbEYs=n*ieFR(?}3&*r3#+&mOTs=->nMX
z7cIL*m4QK@fkAdHRD7u_1A{XIgX}z2@SbYf=}_^0RR#uo1_s#<RR#uK1_s$isCcC+
z1A{FCgKUv1IF4nrRT&sU85nc}RT&tX85nepRU!V+QU&jK)|G|Q0#KSm6}-n<_mc_(
zgBt^b?mZRoK5E@-D&RfUx+hf_7)lu!bPuX9fc94FZc%}lw^D_HA%uZJca{nRLofq_
zZnp{pLoNe@Zkr0k{&J|g9H_cjs5(EWI!~xN8x`<=ZCw);28I*{23=98IExAcLkk0g
z?QLa<edm=S=ATk#VCZFF(A}>LUN0cKLm9k(+;*cfc#dAzT^YQmTh~$<yysk33(A*O
zW?*P#V9@1;^8YG9%=@eaG5?hk#2<H+z<bYiuPQMx<S;Pko>hXl>#!07gB$~c>>eeE
z|K=+(FcdN{=uU^4Q?CTxZ?0Re1PQNvsCb4FxFnZNgzEE90`EuHb%4t2L&e3EAo2A>
z5#pZrijeqv1f{P+>9dNE_}Z=riLb?qkocOd2#K#gMTq@vijerKgqoM92#K$FMTkEG
z6e0fiR)qM+2CB{ws!j>2P8h0=52_AS|7SBW=>AlIgv%`ji2jobkoa1u0EwS@3gEK<
zWTz{D_xjsTP=LgbngS$#L=+epiWwMmc@!8Jsu&n_Srou~`*nZHL(F|I&%mG!%1`nT
zbvNW8>MqDb)E$MY+bz$)pvAx-y9TOm2~^!2sJe+zb?x#D44MoKvK3Hupq2{A-VCU^
zSg5*Sc?Jdz1_oIds5%>{c_vVGnoxD}^5An1WQFA+>5N4l;;(OVkaYG$4#K}C2MOnc
za*%l43gvHr@|Vj&;$xN^B;8GtgQUAIIY>A(fcs<&vXyd>aE_6Kq`MHPIW}_Obt}3i
zP`)mtxh1OxRnI90KKnqI5i0*u7LraM%0kk~O<9Qh&dWm5=?PhgJ?mv5>2x_%ei~G~
zS{9N{V`U-!36X`QQ+FtB1*MH-A?Z{`mH}L@aL7W^DT6E|oqm>q*#BAvl1}f*K+L-=
z14*YxWFX<PRR-d|4KfgSErhC@236M%RaXI3R}58`CIcx~;$$G<Xb%<FlYyjDR;W2Y
zr6J~n_V$9xm6y`svnymDf%XA|${%S+x-FE3#AmWJB)&tSe0OO`e49e~pcw;DIVdX)
z@sEf!#2@U^koW}+dV<Q8?@|zVy_JHLE6=1L{yQlJiQj`#5O=MVg2dNCDM)zDgo;m+
zg2Y!hR9}%4B)+ns@{v$+(EKK-9#97DduCv;m63wDOIQjLZ%k17lO%+H5lUN0GBDJF
zrbwYQXwM&re+x7p%fO(!3rf#|(p6A8N&>uo%GOo_VxFl4Bpt|0K+*xX1SB0WOF+`W
zYjKEs9*9HY{h~M|ybg&&{J&Qm5-xMa!DoHw_KPzxBr-7Q){8^JFB3|qh=ce1%0@ut
zJ)q)7P+C`<fkBmlK~@neF9;R?Ee0{?n;5vwA^S=UV*V|t_z@_*UyOl4nSnueGgN*t
zRJ<2TcZh+{M3Jq5%I84E!=QAa7z2YM1B0w9RNe?GE(N7U#lY*FW!XUc<{21tABuv{
zJkdQa3JIS*qLA<b&BcT2+j*jp@R=zJ37;NONP2G(h4?21Dh}GS52{C%q2`D~^$CeW
z%4v2{1_pBm23gP{FFp(mwm(H6>AhbBlHQv@YY7+_bc>;U(0Ku%dejZdw-AB2Lr(<a
zPE`>|{7Hb;AApuuh(O9S4iSjE{t1KE2g-gIhPeBlFeJTS6NZ>`6e<o{-vCOt{lXA)
zLF*ps85ndcg(2w*v=#!yPZ5TsFJI6)2?hpTOJPX*G8BfSFLkJT(7Fmy1_s&FLXi9q
zT5kd3?*g5bz`&pjIwv8Dfk8J}h=HM-fk9VG2z>61th^A!ei0!^__GQ@{P#@|;@*#f
z5P#ekgoOWf(3%hi2HoXQ@#%sP`|<=K<|IM&#R@{gKS+>)!IFVN)>{yK7LKipASC>6
z2|&UhwEo0}fkAgKln*-p0Tll8p!^A-bt|BDmjJ~4TF_b+1_s>%0Z4h1Api;g1OZ6+
zhY3K+8-D?ayNv`O;jaZXM@Rrt-f#&(${QxA_-}qlc>`KI18QI1=7*Fwm-!*#aEKpb
z-b#K*{m{b?@pmgf#9cM~5dWs}GcW`)FxbZPL;M-R4~b7>D6Iyi<@h1-3Oa}g6fd9n
zz-upcL2G_M<@60ch&dPeAm&U3tr22i&~4;{*auoO1j;Abe2{QR=7WSoG#?}!0{K9R
zo<Y`&58`f3K1h7?@<Ga}pS+NC^pO{mj-K#B!s8Avq`o@O3$f=2Xl)Y%gYH&dNV-_Y
z3ki>fybyCILDjWG)q&0o0l6y^st$CH2q-+mc_Hb?A9S_|1B0#-RKE}}Bpg5RfX^w?
zz01SEAkDxadyR*IL5hJv7PRI{hJiu$AXI!8RD3fJc)yD5avlZ-2?hq)1w2sq@Ib<`
ziw6=P^`Ns(K<y$PNO%_VK*H0T2a*poc_87kk{gm9XM@gCVPMehf%4P2!RIsShH*pc
zK_{rV2{$Ah)VM(d6%4ZS+z|W!aY54CH_%!&1_s@GTnr4!3=F#GxFGG6!(8BVo^&@u
z`75{}?VANq^_^UhaIb~(E1>**E=c$%aY5o6v=$Cj&jxWp;@g9ZfkB*sLDrEA;tmxq
z28MhF23^oOGNAgJ8EW5ePKdi7b3*dLZB9tMUxtc<&Y%%vV30k^2{8w>ETDveL3asM
zelk?Nj1!U%A~+%L_2-17b0;Wm3Z->9A?aKM%4g<;q`&tZko5PQ1Csu3bAZpy(%r=Y
ziI2@33=CZi47#8*a~eVUodc3ilAz++9FX|>#tu>cmL1}sr|b~_+=S8>*&*rqAUnjJ
z+t?xH+;VnEc!JLD0fo<Gc8Gsl*&+U@Wrw&s0m_en^6jB~b0}X5YA!$2T+qQ4p!ENd
z4HC|8*dXTKXM?2w>uiwtS_c)M%LegR0UN}9>1^P2-MZ0G{b6j7bnMLrK6gykg^hv1
zmx007mJO1QFSA0z;SejN-L{4m(tlXU3bAK8D|juuY%f$@4OCqkR9!SwT_7uHbd5pQ
z9jeX@s!jo_P86z+n-#q0QkD^_?gI<N-iIs@cU)j$VDJK!=PZzPy_E&xo>eRm_bgyx
zU=U<rke$Q=>GyQ8K>9sRP<7={b-66yGZtjyq3Xh+>inVVT%hW#Ap2-#b)f20pz36x
z>I9+cK>KY$MdD9ph`k?~A@;sxhPdw@GsJyYn8EvCWVbSd_sEMbhte~k^aN(`nQOWo
z%;59ZbQ_@hOQHI+nZf(GWn-Bk@#)IUz|g_Kplij<06N=FRtw6PhnOeJ59PBkgU?Nn
z1&u#~)W2i`&kf1mWP<2F#{?c#l?9C%wKFj2?qOnJr~&0mCI*HEP<h1!KKo6#k%@t!
z64Z`hf~31#C_j}6;?F21h(80E7#P?X7-XH8Ao<3M36gJ&pz742>SUR~lOwYHP<8B3
zb^jS5=6zv=nD>eiG%U{`dj~WY$iSd`g%M)j8K}C0P<7iG!IO2e8yFcF+Cc7Sgp{k3
z7$NDWg%Of(su&^RSI7v-rzwn(at|~%2`cwOpyqioLdsufMu>ma7$N1a9Ml{(Mo2pR
z#{e<+J7j`D_5%Y%J!ro{83ThZXbmE$8~~kVm&U-LyNUr4j-UwzkT_^R3Wx^nivW$A
zfwq)^@;T@Tif{%7UC=pvAa{Yz=L3!NfX?n?U|;~Pq63dtX+iA=?ZpPwhrv(5>4D7~
zO5eE$;a`E$TcGqBC_M*CPl3{@P&yV$dqZhwD6I^orJ*zzlxBj`pYB5Jdj+L$LFr3S
z`Vf@f1*KO(=|xbw5=s|B>0~G!4W+%Iv@?`8hSJ(l`qv$Z{hy%pjGGYt1Ss7Ar7NJc
zG?W&G(gu);c{U9w%@3v7q4ami1R2|VD19GFUx(5=q4Y*5JsC=OL+N-Z9S)^kptKE?
zmV?q_Q2IM$_MPoLl)eL{uR!T7P<joN&V$lvP}&Vj+d*kVD6I*lC84w+l>RsiJS)QX
z5=yUz(u<*VGnB4|(*97|9ZG9JX$2@P45hiDG!vBmH4|dbJ1G4ON?(K0=b&^8l&*o&
z&QRJKN`IUIG3O<ez5}JNK<PD5dI^+HhSJec+8Rn5L+R_&A?BTj((zC_97>x(X+0<{
z2c^ZJG#ixuHw|LW11Nn1O7DWwo1k<Xl&*u)*-$zeO1na7TPQ6DrNy8$GnD>46=L6Q
zD18}9PleLGP&yY%r$XrnC>;Q$9iX%Yl$L<f0#N$W6o@^ip!6yzy$DK|LFqgw?GL5h
zp|lm0HiFWcP+Ad6i$ZB$DE)Ub#J;akdNq_@45f3SbSjh%h0?xIS`kW1LTOGY%?PEh
zLe8*ZI}4@vLg}qgx)Vw_Lg_*%oe8CFp|mNKR)x~CQ2HHY<r3R7C_M*CPl3|yP`VyU
zheK(9D9r$+e?TTg*<M5G$547Vl->-bi=cECl!l(!!{!9#KZDHZvfYEyDNs5FN?Su|
zV<@c*rKO=XH<V_E(oZ4Fu-NWG>HSc8JCyE*(#=r107_>-X)h@41f`Xsv^13FfYPAD
zWf>V5*d9PuHn81*(zBrSBq&`3rL&-PER+s~(ymb27D~%PX;CPB9dd>Z+j%Ix9!f8V
z($!G97)pmgX&)$U52ekav>udJgVIt^S_n!rLFr$RHBW3Cp!5nToe!ncp|mWNhAvrS
z<ACx(gD;@)xzPp5FBhP6Ka_5V(&<n-9!fJq>EDngi)`Icx*1A`LTO(pZ3m^zptKs4
zmV?rKP?`-&f9rs_=N**352dd|=@U@;0F>SUrB^`d`H%&CY}2818I;b0((zC_97?-G
zX?rNG52e+iG$)j1gwl^8YvkE(L+SNUdO4Jy1f{#6bQY9Og3>BbS_Vr0fvneM`vRpO
zLg|}Ox(!O#L1}F$tqi3vv_Qh^1e7j?(z#Gt3Q7w>>HUyJc5K_BbSjjNh0?xI+7(Lc
zKxq{y%?zb~H$m)u52c?&>FZGXJd|DrrRPEEJ}BJ=rPH8v9F$go(h^YmM<c|Z4^a9D
zl->iS=R)bJP`U$3H$drfD4h?blc97pl=g<w&QSVi1H`_MP<jWH-T<X%L+Qy-x*1AW
zL+NZNoeZTzptKK^wuREBP+ApA%R=dg^$`1SLg}4QdLxu>g3?t`Iu}Z(LTOtlZ3?BY
z)<MiW3#HdU=_OEl3Y6}F(lt=J1WJcNX+J1!0Hrmc^q*RY`Cp*)9VmSTN*{&Nd!h6?
zD7_3y_d@AbD4hYN6QHy>l;(%hZ)za+J%Q4fq4a4ey%S1rgwhM4^h_w-38fpMbO4n0
zfYKIF+5k!mLuqa(%><=?RYTly9!ejF(#xUrd?=j=r6ZxVC6qRV(jrir2TDJ#f|z?7
zO7DTvTcGrEC_NuaPlM8ZP`U|9S3&74D4hhQC7`qbl)hdGvF|*TZiUjdP`Ut0XFzEO
zC~X0yzgIx?zlYN2q4aSmoeiavq4ei+i2B!1`V5pl0;RV?>9tULE|i`MrJJC16_n0`
z(n(M{2ugcFX&or70;SoY^uIEQJKjR+r%?I|ls*Hc_dw|_P<jcJo&%+OpmYnAE`icH
zP}&ztyFzJED9sC{|3X%kv3-To525r;C=FVh2&$(yLivqQx)Ms~K<N}H9Sx;}p|k*$
z=77>)A?LNSy@k@}q4aSmy%I_<gwlObx(!OFLFqUstpKGZp!8435_GnYQ2Gg!z5}Jt
zK<Oh;dI^-C1Eu4jbQqL2htm2`ni)#}hAhxyy9=eSLg^Dw`T&&P4yD&a>BUfbHk9sx
z(k)Q>e<37Ye23C!p!5+ay&X!ghtkWS^gJj%8A^9U>0BtC3Z>nlv^|tIfYKUJS`tbN
zLg`PC^F`QRLFqkEdJB|Z1f^#|=_)8)1f`RqbTpI}g3?@2`Y+@>OSZ32`W%!#2Bn>#
zv=x-rh0>}}`Vi!-8@63gdKQ$P1f|WPv_6zB&xM3<K9u%{((X{&97^j$X?Z9u4yFG>
zb}F!ah0-^mH1uplwxv-1Tqs=&rAwi71e6Yd(ppej2}=LThPdwwl)et7&qL`=P<j=V
zZh_J@P&y1s`$1__D6I>n<)E|}lxBs}e<7<~+3rK>>ri?>l->@dmq6(`P`U<6mq2L`
zDD42HHK4QtlxBg_e=;Hdd;_JQK<O(``V5rb1Ese>=~+;E5|l25(z#GN3Q7k-X(uRc
z1*Ns1v=Wr&fYP8#ML^};W5{}Sw%btp1e87ir8hw76;K+wzMX9XlwSs=^PqGfl=g(u
zW>8uWO7lT!HYj}ybY3U}1KTAiy$ecjg3@hJx(-SwK<Nl5?G2@!p|lm0HiFV>P+AU3
z^FwKND19&u5-&TUbPJTOfzs+wS{_QDN`<ID1f{c~bTX7Shtm2`S^-K+K<PIr5dBY}
z^i?Q*7D_LK(leoS7nE*-(qT~A4@%oZX>%ye4W*f(^p|9aeQ%)j0Vur#N_Ru)W++_@
zrL&>51C+La($660j<Vf@(&wS{aVR|-N>7H;El|1!N(Vq`4=4>i$CS+w$`^*x+)(-~
z<jhsJqfmMWl->ZPr$Ff*C>;)^{h_ozlvan**ApP&aUM#~g3^<qbP<%!g3{Jd+89c!
zL1{TC{U35(Alr8+eHBWdh0>d$^lB*G0;Ox9bS#t(h0+%x=Ml1<gwlQ93=Dh>3~ZqL
zhd@V(fbJaPW?*0goihc>zo7G|K;oct$wBJY3PQ%yQz2V$*`{ej_<c~i7)obD=>RD0
z0i|`Jv?`S5g3?S-`nwjyy!TN03Y0zrr4K^soltrnl%58qtD$r;l#YPX0Z`f%O4~wd
zBPgu}rFo$=E0q4B331N{DE$~p--gl$p!5zXy%tI@h0<M6x(P~`L+N}dodTs}ptK{D
zwuI849U-9jP=oTNp|miR{-FU$Zy%uaRVaNHN^gSFtDtl*lx~I68BjU_O1na7TPUpr
zrKO<sf5>Jlw(n5-4wSwErJ<YD*)~G?)1Y)8l!k8BV#|i|1E91Al-7mPs!&=AN(({h
z?~uLOZ117;6)1fMN^gYHE1`5Blx~C4*-$zeO1nX6J1A`kr8S{6ACzW;(yt-AN7)`j
z=^IcQx~r6JE0hmfmk!E5lc4-AC|wVw%b|1*lum)to>1BmN~=L>IVjBxrGKkH;vKZ^
z9Apn@-8qQf2^HT6rKdsZJ}6xbrL&=Q0F?HC(z;Mu6-skKX(lNBTp42TeJFhdO7DTv
z3!(H(C|w7o%b;{Nlum}y9#Gl=N~=O?(7JPwf0&^BUyxH1*zQB=>rfiBt{kLp3zR<-
zN>7B+pj#|K@}OHSL3A)w+#5<8Kxqvq%?qVjp)_cx7)T#zJvoTJ4mmA@?L3s;1f^F&
z>A6sPDwOVk(hX2L6-viKX(uRc1*P?&v^tdLfzm8c`lSLS{2xN;Yf$<els*ilcSGq7
zP<jQF?uF8=P&x}rCqZd<C~Xg=m7uf~l>Q6ZsmAsdO5cLgm!R}^D7_v^Pl3`sP`VIG
zXF_Q|DD4KNwV|{!l;(ia3{d(hWSutKT__FRCdal5$_MSm1;rC+eK?5jfr^7}a|Q7;
zq5MQB?FOaoptLfSmWI-x%?luXKOlSN*=|GW%TW3llm;Dw0#dga%AXCT8=!Orl+K0H
zsZiPrN;^Smbto+lrA44L^autvMkxQM3?v<Z)_;TSy$0o<hSG<j^a?1w07_4V(!Ef+
z2uf!`X@4l~4yARVH0a(YkUgAGJ|mQVCJl85ls*ilcSC8=T~Hu>GobuhC|wGrqo8yU
zlm?v<1yZjM<%8CNgZMm9KIoQY5dWnV#NKmI`WTd64W$=D=?*B}0Hsr*H0ai6kU36J
zz7>>~htlFu`VZuMVm8qES0ME_p?uJKZxDYgl)n~AFM!gZTdzU#Jy3oNl+J|GiBQ@N
zO4~tcWhgBTr9p@6gUtB>*}2Mg7fN4+(xCO^Ao)#D{!%DC7fOT9{{qQ(K>46E!9e^{
zC?9mYIEW9rFAPM7LdAWdv=fxJg3_S%=pc3CQ2rlrNIZOj(l?<rXgxYe-8LwH9h9C7
zrMsat=vI4>x(q1a7fQQAX)7oVT8|D=Cl2NFL+LMK5c}Ui>5EYMB$QqUrI$hJZYbRh
zr9o$~fy@Qnxdx)0q2kt1S^-K+K<U4b;|kcmLg`yj`Vy4h4yD&aY0y1yAamzH`HfJz
z5=!Sm=`<+q38fvOv>KF_gVM}U`Zwf|4YmhR`UaHV3#GS0=~+;E5|l27()mytdWaKS
z43zH=rQM;l6_hrD(&|uJ9!iTqX&xy35wabd?In~x2c?fe>D5qrF_i9r(hX2L6-viK
zX$L560j0H}v@(<i-OmRKUj``uDP&JO+g&Jq2}+-W((9r0awrYD?+>KE1<J34(uGhu
z4NAvBX=f;H4W$*Jv;>rf-Z#hg6>{7L+bt-42}*B=((9r06e!&Tr3;~SCY1Jr(r!@N
z8cG{OX)!3x2c<tkj{RYK38l|L>0?lOC6rzWrCXqM4U|rV(veWw4oaIrX=x}e45feY
zL-HT!zC}<tUWM|{Lg`IVdKHxJhtlm(ItNOpKxxo9lpu2)p?uKUlpwwylrIRSIiWP@
zPDqga7e0tPUP9@IQ2H8_J_n^YL+RB}dIFU0fYP~88gzap$Xw7mcM$Ca6*q^{`cPT~
zN`ubB0;vP7dk4`kAt#2horBWHp!8}ey%<V^?!g49Z-DYkp>!^k4uI02yE8%RbfJ7z
zC=I$-6C@70co0N`&JYFBZy~37u|0s&H=y)cD18)4uY%HxpmaNw2CZ)gnUezLgYNSL
z@dKfJPbjSerB$FbJCyzpIX{H$6O?`hrSC%Nt5Es`ls*8Zq34dUfzDF}**6I)4mx8M
z#LtKFLF?y1{1_-d1WH>%X+tP22BrC+G&7X`4LK)@?E{p40j2Lk>8ntB7nI%vrKdyb
zekff6rE{QkAe8om(t1!Dbk;1$z1&bfXx%)B{{nLE1=|BC4O$-$65k8uFM`supmaTy
zE{D=FP&x!kn?q@RC@ln~xuEo0$XRe~PoeY;D18A+gVx7`>|YJ#&x6v_pmZgaE`-u4
zP&x)m+e2w{C@lr0g`o6T$Z>vbpmp^idoDrwr=awDC=FUi50dYJ@>`%Z^f*AaL@3`4
zO4~tcWhgBTr9tcFLFW8mgOm?<q4ZTKy$ecjg3{BWbU&0XfzmlpIuJ^GLTNoHtp=sJ
zp)@m;e!&W{_W_i?3Z>6N=}l026_oCW((O<>2TG?vX-_Ea2&L7av>cRXhSI;G<8u$7
z^bIJz7fOTH&x68c7L*TKHxJ^2*2#nDe5iN`l=gwrhEQ4)O7lT!HYoiXau^`nV<>$C
zN?(A|p!M${^VdT8lc01Ll+J_FX;3-}N(Vt{Hz;ifrIn$yG?WHi?g}#h2NNXR??UOT
zP<j`X-UOwmL+O4fT>_;+XET7z354=Jp|l>9R)f;qP?{M^|A3qq%k}|EUxm_Vq4Xvw
zy$VYAL+N%Xodcyo>(W8?M?(35P}&Si>p^K@D9sI}LF>;!`aoydgJ{q>5g;0LCO(J;
ztv?6Rp!Me<8noUVM1$^h2hpJO|3Nh9-gpoVx>Eo|TSC^igU*`)-O~#i4g=Gmy9+?_
z!cck8JrN*2=-3GmeFNG~0NuL`;zN%mWCPvB4C1eV%7gA`2JvS=`JnxIAbtgu589Up
z;)C|(foRaaJP_>xl?R<g4dPos`36v014=7EX$~k2x@Z%m9=-i?1KO^*0Hser=>t$2
zbS5@P-vTIq29%xvr7NH`=w51&x(p~k0ZMy7X$L560i_L~v;>p}oy`r>&jICw_Va=G
zFQDy>2T&TcpARH{0m|P2r8hw76;OHsl%4^lVeKB!em{`@0;qTflum%s9#Gl=N?Sl_
z(EZ#XeG*W<0F>r{(x6ENkUZ#KZx9VSs~kjw?)nDN7ohEz9Z-4$lwJX)7eHzB_7P|w
zAV_}!R6YYrCqQXfJIMjcw}8?HP+9^?3qWb~_R|Y!`vtw-bO9<3y2~77{{bj}2bA6b
zrB^^{(7r*Cx*1UZ1Ss7Br5m7h29!>K(h*QP07`?-j0c(H0OeaiX#*&&0i_k7v;>qE
zfYKaLngL3`fVO`gK<OJ$`T~?jZ;$POii6I!2f1Sfl)nH<&w$bspfu=yc#ygVC_e*A
zCqU^4C>;Q$Eub{$u6d9?4JaRU|2&A#0p)`>If3{;pzSAEyX^*)e*sFLfYPA5>_O^5
z`yfFyXdfhqo&lAg0Hs0uAVJ~<P<{rKPJq&&{f{7d2PoeHN*h3F2`DW9r8%H91C&N@
z-`#+=!!AJS9Z-4$lwJX)7eMI_DBS?1E1+}%lm_jS1i3E&%J+cM4p3SHN-IEV2`DW9
zrGG%%WgnpQ3n={nN}qtz2cYy0D7^tn&w$bspmYb6Zh+DmP&xrhM?mQSC~X0y4WP6J
zlvaS!98el`={LxqKcMZp4^a9Bl)eC^PeADdP<jQFUI3**`!Yf1On~yC=k~D`K=~O^
z8nizXq|O7%cYx9sP}%@WOF(G>D9r(-VeQTr(01ShD18G;Ux3m(p!5bPy#h)vfYKdM
zx&ca8KxxpvPLTT|p!@(R?E$47ptJ^*R)EqHP+9;=|A4j^KR{{p_UZ|!_yH)r14?gz
z(kr0!0w~=9r5m7h1(Ys;(h*QP07`p6X$L5+0i{9vLqYzNfbs>P^bcq|6SO}RB>w`+
zhqZH0K>5%kqS<yp`5U103@AMTN<;67V{3r&GoW+=l#YPX0Z`fkN*h3F4JfSur8%H9
z1C;&&ZI^z4(l4Mi^c-!r6HxvED7^zpZ-COE{h=U#g7$}kXwd#p5DnTN3ZgTh>Jp%I
z1e6Yd(iTwK07`2>X$2_F0j1H~%^#rc*%wgy0hB%gr4K;q9Z-4$l%4^lCqU^ADBS?1
zGoW+=l#YPXpnant|5!lzpmXOyd<`gH0ZMZ~X$B~b-rl|eZ3ka~(kGzw0Vur!N-u!Y
zGoUo+j6aZl6;OTwlm?y41`<zz@;#um1C+La(gsjk0!j-&X$~k2YAl1yfwjv)_fCQM
zpgXBRH0X{h5PbsLjt1Rh1>&!O@<DfEf%u^7WI;4&zbJ?X-Ms~(3!v&UpfqToC`jA`
z$_K6M0P!uLeAxO92`C@5z5^tW-hQ`(?w2)%(mITg^JL_q`)7Hf`(qgyA?F!<g4`*l
z`-p*oA%THG_bzllEXW_A{jH$uZb9dtO=4hR$OD}_!N9-}&%mHt4pryN069m-n1O*I
zf`I|FT!bMKblw2y-e?8}UC??I69xu8kh|R(82CW$HfCVpD`5wp_Z<SISwQ7EKj;cM
zh&W3QgbsnyETD28BoC!oQlRosngvw;gXEz!OAJ&VO0$6W?Stf@G)o9n9!j$WK>1Lb
z#RtlV(k!5Q1*9KJv$#Ozp)?Dqz5&TYX%-u(Jd|bu)k7e8D9vI5m50(Sp!x|U52aaj
zpz=_fMFYx*(kv=aK9purfbyX<iwu+xrCC7r9>{zs%_0Johte#d`Vb@!rCE5O@=%%u
zR8NBBp)?B%R31vRfa*_>Jd|en!v=|8D9r*I&jHCpX_hZgc__{D0m_HcETHoeK<c41
z3#eWO@u4)!6R3J9%>t^gLGn<V<qlLHO0$6KagaQeX1M~Dhte#d`W++>rCH8E<)Jjo
z2`C>*vmAl)p)|_@C?86*?1A#3Gz+NR05Ts+vuuINLunRJdjcd6rCHWM<)JhSsGR|l
zhte!dpz=_f1=Rik$wO(DIZ$~h%`yYZhte!lpnNFJG6Bkm(kwktK9ptwwQE4;Lur;4
zs63Qr0kwBP@=%(k1}YDwSwQU|kUW%T0gcmv_)wY!)II|7p)?C<{0_v2(kvNJ^Pn_K
z3X~6}SrVXpD9sWB<wI!}P`e9c9+YMYfyzT^7EpT(BoC!oe4z4Bng!HO1Ia^a7SQ<{
zAU>340kz*id??Lg1Jw_uSuCJ@D9vI5<wI!}11KL#v*<wiP?`nQE(DnmrCC&<@=%%u
z)LsP1LunQns63Qr0ktDR@=%&Z1S$`uSwQVekUW%T;epCSX%-GBA4;>ZK>1Lb1$2l6
zNI#Tj`NIm${}7r5)NTdILur;T5b+Qw%>ruAg5;qz%NwXXlx6|7b3yV@n&k;p9!j%-
z#%n?HP@3fqR31vR+<@|-G|LqzA4;=afbyX<%NZyiO0$64)gbesG|LgFJd|buwYNd?
zP?}{AR31vRfZE|8c__`Y1u74vSwQV`kUW%T0iE9h;zMZ`P`e$(hte!dp!%US3#dI0
zl84ePbD;82nq>x*52abAK>1LbWdf8BrCEBQd??KV>L-BAhte!9P<bfL(g5W{X%^7=
zG9dL(ng!Ia0P&$TO9@mxlx6|-H$d`GngukD4&p;;mJFzRD9r*IUkAxUX_f@2Jd|dM
zf%2g=3#cChQV*qBLZI?cng!Iq0m(yY79XfQlx6|-dqDC~n#Bbw52aZ^{UMM%lxDGk
z%0p=u3n(8-vzS2nP@2U6%7@Y{I#528W&!oHK;}bf78R&Glx6|-zd-U(nneaG52aZ^
z{W6d|lx7iu%0p=uP=5_152aanpz=_fg#*fm(kv`cK9pu*fbyX<%OA*jJRwk;1=J4&
znGdB|zCh)nGz+MI2$F}=EN`IlP?`nQZv@FhX_hBYc__^S>Q92?p)|`Ks63Qr0nMj?
z<e@an6{tLvW&xd71d@l+EN7tdP?`nQPX)<CX_g~Uc__^S>c4{Ip)|`Ls63Qr0rhJ^
z@=%&(3sfFTvw-@$AbBXwvIZ&-rCC-$`B0i=36u||SwQD0f%HRZmN`&)D9r-uM}y>{
zG|LpIJd|bu^{+wlP@1I&Di5VuK>cozJd|buoqaCIzz_nZSwQ_75FbjjfbJRw@u4&e
zsJ{c^LunS!`PCpklx6|-gFt*J%>tU&0P&$T3#fkt;zMbc6i)E@Qz1~AB>~EZ(k!5P
zR?ty~P?`la?grvRX%^7@D~J!JSwQ1)AU>34@qwBLrCC7ZbRc;s&Ef);hte#d@jH+_
zlxDGk%0p=u3n(8-vzS2nP@2U6%7@Y{I#528W&w>0g3O1~EGkfWD9r*IF9gX$X%-o%
zJd|bujU$5Op)?EV95xUiO0$5*7eRa|&B6oK52aZ+pnNFJ!UE+(X%+@3A4;?Q;ef;s
zlx6{qTY}7o(kx$~@=%%uG@c2Phte!>pz=_f1vJhHl84ePPoVNpngule36h7>EO(&t
zP?`laZw``&(kxe?@=%%uG@lNVhte!(pz=_f1vIV-l84ePN1*ahngul83X+G?EPJ5x
zP?`la4hxcp(kxq`@=%%uG(HQGhte!-pz=_fWd)QErCF9h`B0h#bY~n$Ka^&f1C@u;
zETC~;kUW%TnF5uE(k!6yV30hNX6b>-LunS!I59{bO0%>;<)JhSX#5x?52aZ^=k<a3
zP@1Izsvb(SltB4Vnxz2Bhte!LP(GAq0gX$8%!AS_pmhu&K9ptwjaP&CP?`m_z5&FC
z(k!5HY!DwxvxGp+hte#d@okVilxFdP%0p=u4=5i>v$#O{P@2U7%7@Y{Hc&p4W&w?x
zgUpB0EGAHSD9r*IPY20EX%-!*Jd|bujkAN~p)`vMR31vRfX3fJ@=%&Z1}YDwStOu*
zD9s`Q<wI!}0Vp3zv+zLqP?`lat`9OFO0%#)<)JhSXuKaJ52acDutW1dgk}NF1AyeA
zG|Lx=cnFkc0nHD9<e@an8>l>#W_bbSLur;LP(GAqc>v`@X_h-sK9ptw%{ze1hte!p
zpz=_f1vDQ4l84ePXQ1*>ngujZ0g{K(EJvX7P?`lae*uz*(ky$R@=%&(2b2$`S++p=
zP?}`}ln<p@)<F4Cnguj30x};;vn+wiLunS!d<jS%O0&#?%0p=u&^!uA9!j%JfyzT^
z7SQ|(NFGYFfY$MV_)waq1F9ZMvw+t3faIYxO9NCMO0(2J`B0h#G;ae^52aZ^<9;AM
zlm?Igf%u?tKp_SO@c18y4;udi@j>H$AU>1^kN<)Apz%MDJZRhx#D~)0@jnnBH2w#Y
z2aWrI_)r=={s-cN#{WR_pm9GCA4-GA|3G}u_#a3fH0}rDLuv5%ABYbc{{zW`#{EEi
zC=DL}1MxxQe;|3#xF3iQrNQHWAU<gP4<rv7_XF{vG<f_E#0QQ4f#gBsejq-S29N)N
z_@MDWkUVJI55$Mk;PF2YA2j|4k_V0Zf%s4wJpKpbgU0_r@}O})5Fbi|$NxZl(D)xn
z9yIO;;zMch_#cQ58vg^ygU0<pd?*bb{{!(s<9{G|(6}Fn52eB5e;__+{0}4#8utV7
zp)`2>55xzJ|AFK|<9;AMlm?Igf%u^DKaf0V+z-Tu(%|tw5Fa%D2a*Sk`+@jS8a)07
z;)BNjK=Pn*KM)^EgUA0se9-tGNFFrq2jW9%@c18y4;udi$%DrIKzt|-9{&UJLF0cQ
zdC<5Yh!3T~<9{GNX#5W(zkv->UP5W`_#a3fH2w#Y2aWrI_)r=={s-cN#{WR_pm9GC
zA4-GA|3G}u_#a3fH0}rDLuv5%ABYbc{{zW`#{EEiC=DL}1MxxQe;|3#xF3iQrNQHW
zAU<gP4<rv7_XF{vG<f_E#0QQ4f#gBsejq-S29N)N_@MDWkUVJI55$Mk;PF2YA2j|4
zk_V0Zf%s4wJpKpbgU0_r@}O})5Fbi|$NxZl(D)xn9yIO;;zMch_#cQ58vg^ygU0<p
zd?*bb{{!(s<9{G|(6}Fn52eB5e;__+{0}4#8utV7p)`2>55xzJ|AFK|<9;AMlm?Ig
zf%u^DKaf0V+z-Tu(%|tw5Fa%D2a*Sk`+@jS8a)07;)BNjK=Pn*KM)^EgUA0se9-tG
zNFFrq2jW9%@c18y4;udi$%DrIKzt|-9{&UJLF0cQdC<5Yh!3T~<9{GNX#5W(4;uFa
z@u4(${13zjjRS(@LF0ZPK9mNJ|AF|R@js9}XxtCPhtlBjKM)@@{s)o=jr)Q4P#Qe`
z2jYXq|3LDfaX%0rN`uG$Kzz{nA4ncF?g!#SY4G?Thz}b71IdHN{Xl#u4Icjk@j>H%
zAbHTZABYd7!Q+1*K4|<8Bo7+*1M#6Wc>E8<2aW%M<U!+pAU>1^kN<)Apz%MDJZOH`
zlz|}*M7uCB@PX!YL3|MH#=yV_n#Tq4L9{Ca1K$EB1_lrxM1$tl3ZQ%tZN<RA=K<w|
zXh+ce8<a1>1ir6^?*$`7KZv$vVBp&U<%4Kz1_nOR{3^(N5beakzz3R71@S?&IRgV9
zXdV^B2hny641Az@QxG3STQV^4f#yp=d=Txxz`(bG0b(DBwqao4Yk=}Wv@-((UjUR3
zqAeI0_(1c9ApIcPo`Hc+j+=pjkB5PwRR?mxnJSdO6w23y@{dFLrcnM%DBl*!{{-c`
zLixX;d|xP^O&4N*D3s5k58=l_`Mgj*Xgxc~Jwi}^0aRWb%CCg-rJ?*LD4!Q<K4^VB
zNWU1A4_Y@5;>$w$v!Ln~q5Q>Az8aLj2Flll^0z|y)=>UFDBlChKMv)`LiwQeV|;uJ
z3^zavXBik69z*4`q4IB_{7xwUE0n(q%Kr!DXG8r5TIU9GzXp`=$ODP5Xei$c%2$N)
z+o1f%Q1kksd?nC=T?PgQ&^kPjd9G0YLa2N?ln>em0g}&$@<I0ifcP~~{vN3MPADI=
ze*z@m59ObO%FlxGuS5BZp?uJKLXi5kQ2tA({6;AM6O_Ld%Kr`J?}YMMcp?7Z3+3}d
z`3IqVF)05ilrInEpMvr=p!^F^z9E!<4a&EI@^3@=&QShCDBlOle-7n`LivB8{5TL_
zn1NwNCM11>##Q(k85lN!G8_W~Ll$U$7gQ#Qf>s7IFo4#3gXCfNC`v-*8w4TpmYfU>
zAo;h-5dKUK2wxm@2_pjo!*bAk5hDY`7aoW_XdDEjzFro>2epeq{0*Rm$&fV;VDlid
z3=B`9`q%P9L|CErNhv}2sZje|q#*os(0DW>149)jgs;cUz`)Pl!0=5Q;@>!se(nYa
z3n-r#q@KHhp$p0fjT3_06RHZ)&&|!iz|YITPykK8t0C)!Ad(CW48I`jTj2bQkaciy
zeh_4x8Ju4PS;qtCgWAoos}Mngpm988K4@G8ncoLl4+c^S#=9Zw1Ho(%0bM^1VuG;*
zntP$^z`=4L0(34qviYEM&XM_rkoA!urC<zQKM7`o2wybwq5CaBQeX_~HzJz{x~~A4
z4>}(nnLi87K2SdvS$-p0c!KVKK$eH@>j2vgBB1MPKuj?Hgce?gkaa&`IS{cOEq<<{
z`42R2foxwJn*4J#{h)DcWc4P{G!C*0gx90_cQ$1G97qa`1<=wLbR85}4n!<MlfR9|
zZ$dNgJDPu?`xih)fiZL)7?=$r>d@4Sqw%5Z%RoxO7*wny`!@*9J+5f^LkW#vhZdgR
zX!^IJ*$=u;1KGY%H2;F`b3m5ggQouo8owCLzG^gnB3k@{=2?)<uSd(D$I$pI(DXCJ
z$48m?7o_F|dHWfaSy(z2rI+TW=9Lt?f@DBKhK3%Ac_}%m!O8grsm_M3WiScL(7cq?
zw9LHJ6oi;ra7j^SUb?YgYPoBGcXB3Nt!qVcYC%b6ex7AWWkITIQBi)8t6y-u8N_T)
z5EG)+)fHj0Nk~RfemPt#ng-Lb#GKMpWcA1{H8gTAN=+<Dg;?Mk;1?Wkk(pPLT9lWV
zW9FZfm6}|Fun1YB3(Sk&Mr9TdJ1j!-p^k%l9_mrc(2_I@usfU$@j4I5FwbJB^$^35
zWJ2<B$QT-U7Q2<^C4&MG64-g=xeW2Sskz0eB@FS!B}K^vm9Vge`p(!rwS-6~nTO<i
z=9L&5L5%i8xX91|EDrV{k|fmgh6W(t`=sWjmt;U>^AdBxt^k<;Rb&}nlv$DrQs^3x
zoEear33hHyY95%*OHM3KP0lTV>w*WkUukYqY7xX(WEUAiB+#7%(PtTw@06dPlbV=^
zsnG~3gQU~QARw`*I5i+Au_P_ODAymHK#L(c!PF-|IWY&EFrkqGO_+v;eu;U`i8(n*
ziOJc{My?R$h=gnqZvl@gke1T2_>|PN#L}FS_?-NFuum;qJ^kZBnJ&Pxv@E_nzbHGt
z7!(4A#vlpDw35^!4B67M_`=fE(p0c=kYZ5YgoQCEc)|XHCf@kslEmcf_~eZ2`1I1m
zq7;~VOL$%~B{B;l=M0OW#B%4H{NhyC0KD1BD9pmp*d?>LAip@(JtsdYF$a%^l$-!a
zJ}@e?F!#(WNli~J0v8{d4DqF9@wufXsTJ{=d6^|3KNy<911GpNIXShsI5PkxK7tM6
zgAL+AN<qP6?wp@jl3Gz>XyBe&;#^u(l$uupO&B2Cpt5FAH$t4@jbffDD5B$CL53m6
zFf@y~y1Hft_yrrrd-??%#6yxGq&z~3fV9NS9FT)d!5IOPTF{GGP=0}EH}@<CXE~@d
zP4e<nQq7!7)6!ClKm~EJXI^nhVqS78nv)DsY>xuF7m{p^&D~Q=Jo8dgD^gPeit-Cm
zi%K$6i(M-qC81+cQDUV_Vo4&@KBF=VsNYOL<p*JX$hjY6D=6+QAOV_Ll^T?qmRghw
zaxShE1CQdI{N!v<Fj<1K063`7GlvOC1|0vG(r{x+^PmRBCl(i{7L~*omE?hpH3cVJ
ztf3FK5iE_{Mr_h1KAFWOSWN`yZ;&jyfr$K#MHUo%rr-#HrT=)8hy>NCkTi;jCF5Y+
zg?zAaykBs<p*b|xD;-NpiZYW*OH$$W9yF@KhGc=NU`S;ND)b<!5t5jr{DO;3;)7BP
zj11y~<5P1BN-E=vQVZgXOY(~n)1k&el^7bt`^KlF7MB#|SGopy2Pb+agRL`l%PB3+
zz#3ZM@CQqy2Nxp7u}OoRjnzPNP(le#EkQTV2qX?pK$w!IE=7r%*c(A$_kpF+4MeyP
zQyNxe`GK>rWpHYVZ)!<Keu^h3nh|A*VLUVvTtT2LBtF19Il#>?*a%dnAm!>HZ%{dd
zRBnJn)z8o@IJGD<F{dEEs3agiCnvSY#4|6m1g&&1K(Yjs8Ng0}v}i2-Qp<xYbCdFO
zP}*yTX0SReBsI4nC$S_IoF+joLvFLdQwhj<@yM<NCq8h&7;hPznVy$eQd)%4R>QEs
z(9k`#1ZFEnaRe%jT(iKA2M4I3k#AylDyVb@Rl|7v3ko)H@r+z6V=uLf;XxUno1ape
zlgi)|uUA}B1f>k2v=NjxhSDZb+7wEgL1`11gb7T>1TJL`Q)2;Tzyx4?OQ^V^0gM5&
z-VkQLA<O}WFpCULK>_4rXjBerb3xh*#W4LayA5Gh8G`JJk54PjOOB7%i;se&RA^;m
z0<ILm2?bs#ASFkrp(ZeAnu45(%Pcc!B|*qELzrnsAk#o0Zv^wS5zMbfFuxkX0@VoS
zF(a7Aj6fa(Ylj(V3^ULeW}q=F6pdjf8^cUChM8;(GuaqsvN6nLW0=V%Fq2JSCY!)a
SHZf*!^@vX^O3Y0)U;qHhh}b6p

diff --git a/input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport_poller.o b/input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport_poller.o
deleted file mode 100644
index dde7edb278a7ff2c5c95936ddfe48f964c5d70ca..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 120596
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
R$%MhxBR&mu_bq6>Eda$49!LNH

diff --git a/input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport_unix.o b/input_devices/mag/node_modules/serialport/build/Release/obj.target/serialport/src/serialport_unix.o
deleted file mode 100644
index 1ca5cff599053c799ce756a230f614ccf3e089e1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 119268
zcmX^A>+L^w1_nlE1_lO31_lNY9l*xGz@WeY29gX63@=#0OsvGgX&_w;3<V%P3=9kn
zP(C{Y0|N*PL3PE)m!wvdKsgKy4Ds<Ht`Q*!K8)oG)c`Z^!yHD2NgzoUh6WG?!}0Mc
zsY#{j@tJvP`5>|Qc$aX;AU6;bjA7=~%>Z*5wn{+ghJ}m_%OFf92n8Ww<|QU26{VJe
z+=pu3;Z+cI>`;FiZ-nrXNbKenCFZ547Bir`@6-l}P6r6ZV6`2>*szR|0csGGf{4T1
zmz$Uj_A<J8Txjm8f|>`>4JNUgmy?;73X;WTo+t-MmVp6g-hpL|;B>;k0COfp9_GHB
z{A92Ix_R<D!NLs5f)KiYKZHK9jFG_%l7z6juehWLtPtJ2rc+>HhFkL?^rs6D8i~Ye
z9yB^I;v*&t;)n?lis4KFgi*19kwFP!D4Kc6`MJ6Ic@QaZdT|VKgz*sh07(d(w_qwD
zro(t3{mI28MVWc&P$BgE@g^Ih!y7^|#1ugpQ1vK|1Lv>gG-Lzg<6ThP=a380zW}O#
zLop)*3j+f~$3{j5E~pqX6(66RpI3~?!07IK05y*XswtoZo{pg+s8oD>VnIPpYJ6T|
zZfY^uy{P%^4b;30X!?sOfw=d^Mn;AS5Tj7M3^Ol3DGQtc(bG#v8AQJdL@&dU8VDcC
z1yNYd1G}#vF&W*w3aEK6KsrHXB-Ff!ZHx?j5HYOgl~fjB^>0Es#62dm5X~2AA^a2D
z7#Ti6m}usuX2hozCFX*2FDU(>mZvkOKs3F8Pz)Ti8Nul<;us@?7y|<XHv>Zk#3l#{
zG8|MyavW!502Rv~XBZjgu!7Yw1VEH9h%hjKF)srHgCYY1gE3T`6e`rC^QmLFW0+$|
zut)P71<%g^KE0&}d^*2_19Cse8DN%2=i#*D%nS^^-Rd5_wjdk!{r~^}KUmJE^SMXo
zF)-7k^Ee9K!R*^@k43|OoEn@NVU~Mz-tcHXq7dyE;~3`{AA1<))ZhTm&hws~*E~8u
zd$isz5%uV{_GtZI!V0zcKA84x{a+&L*=>)I@#%!P*0=RriM(gG9kR@KkLDvB(O_#{
zg8YWyf^BX5|G$};fxmwi0|P_j|NjRW8Tk7_<y_<c{|^`#`1_YY#HWJTD<Nzz5PKb%
zU9SpaZw9mX3xU`>!0dQV5PKV#&CU*DZvnH{vw+x}!0d1)5F1oCHU8IT1hGM8Hvc!|
z?_bZrz|i`izZK-*mms3?KSK*M1Aoh11_p+gm%-W@4ly$Dw;l%xfQZKb3=bI?_*+4C
zz624C{~4x%1eStSfQZKb4BjAtDIft5(fGds<owoVkN}8i{C_}*fuXeQb!FrK1WpEq
z(wx`%jsH2=85l~FUZ*zx-@wAaP#W<%y77Mm69Yr3-|N7}|2m8e45cow-5dXdTv5-{
z{NJlyu=&4HsljXG#{VZ67#K>`UTZf0&#h-~{_kBX^;)*qeNyuejdB5xos6J%5F-PF
z2mj)OMXdWliLUbpBr!A}|K0qbshr;<`M5_fC=)PrvoyvY-T}&35EbB*9STX?89v>r
zpt$wyW>N9zbiLryZSUDV-+_gJ!L@t63JU{+W8+^)G%sg>aKQ1r2Fd|PG^kPsDFeqe
zC;&kma8&PxD1*fH0SE^Y*+(H9NNj^@Nyo;&kmx=Sk%7cFsJ?V;{0oWja}XIwjGqB<
zn*SQ|_n&28U~p}H%ik)?$iVPYjuGrkNTdsbMA)Dr;8_0&im_iHy^Vh%(f%AH0?HkZ
zjejBWeibBg4XOql@rOYoM<61Qm<Rd!B`7sIHvR=gJ%1}G>AwV3RE~{*K}mqWwHKtT
z526d46zX4sT8EB}f5FM2@O7zU<6m%kNPC^-*!UNmAfjK#J2w6WrwAdB&YM1+j~$!;
zdesX$HvctxE$Z0#7o0FmUt2mh|IMxEb8P<W?b&(9qw{pB;%imMURO{Gfe2uv6E?@a
zpoHSs-LApHz|ef)x8pugqG<lXRL<)$1DaTTl1&=-wJ|U;8Xka^4b4CP^S69rU|{g*
zoLlk#|9_9((vHsKovkIXqRz4T@Bb26&*Zy4y{R4Ga_=4}KpBvj9>-lfKsC3=@q_>W
z{QvKv>^sAU^P@-S2@lo(|Ns2==yaXo*s$LKq@;w;qwyrDjqlOvI|HNws@1V!zadC|
z7l_!&!URhFE~h*?eLEZ*_8Wl&OSnNgSwIf;?eORZS5ly`=$;C4wqwJ7V}vRWh$_eK
zehW}w{A4LHZT`tzYT=>!|NQ^|9=r?!3=FR=J$v_ifXwR^1!a<bpvDI%Tz-PR_fi^^
z19=$?7#LpjH~(bhZ+!#`B-Q`#|3f^~-ERXno4J(3gBPS1s%$kx*>A8tCqNEyo#AoZ
z72IO*IPMBcL=0U_9j-gNoESS?ckTn#j@@%X!QBZd$31#OI}E=;IiS!l4f0HG2W3}}
zPS*yH-q419Od%W%h6kWZnt%K+HSq1-4)P1w>D?A!%A@n3Pd7*ds`nt(oMY#F1r`Q|
z*A||Q$3YrBAc63j50wuO6i7wVy%*$8u<773#oF~kDZfYakql6c6$`FR4ufSu6<2V8
zM>o4icSON)X9G|GgC#&|pMk-nJ6OP@yI7*z+C%e`2Xiq8SgzCAp!vuD5?+tw4<5|L
z5+0q!60eoOGR+psC5mvCIF!XwDgrVDY?$Sz@=f3>EcUQR^I;RP3Pd<SeFyc8N9TQr
zQcxAb0CK8hSg=R8e77}NTkC-m*5)6arL578aj}P8x{W=W4-0^0T)G)hO>*h{=+Su}
zqz+*esAT~ze;eQYPyj{$Z;x(p@71H50aOS#*n;vYL#Z&djQ}?J7%NDS(W9H$qqDW*
zJ}4W4TO43XkIuuOT3^hg*YrUOBghFqK@>Flp{93RbnYzxYn*xnM0G-P>9N)e_y7NA
zINo{yL@_WhbngX8gUxm9JZg9wRJgV%vVr0R>`I^Br63)yhW}j+zk!|Hy5Ro*|F5My
zy64Wg|NlQ!-luzO$Nm5RU!G-UU~t?4O2aOl?>%}=K@siID|#cDk-?+87o-zx6~qht
zE%O)|7+gBnPPqU7|1MCT*~!4jz~Rw(->35#Se<X@Q^$@Y9#F5jwmji)DQ09~*e@W#
zzyMYNG6<yn9fa4r8)S+{=iY|<|NkFr2Dc48jyE%a+K~(l42Iu!G4jB4_JYH}qqCVq
zf`P%e^}lE5of0n3&UqlkzMX$OI_H9X^dF)M(%^$yf)o|42VA<r&iCnj%-^z>1r(s*
zVDCKU(L43TeQ5iz^#FhC1W?)12@bUGy>J=F&Lgg^Pkef}Uikh0KYvRHs0M+C-*ZIx
z%}Bx)ekE>bf%XmTK;O>qjvdDkf%eU}^IwUuPv>`!-mRdx1S@JiP-5rO`5er~a1MVf
zs0?*AeDYe=r}OvA56lb<KApdPJKsP(`|=($$fIyiAQ|A=`UILX_*>>NBN79WXI>{_
z^NdgL-V5LV|1U8|^V2`D6I%|Hh<S9kf?~v@cL%7v_UVMk!2AhIbx0O1!fFw5Hi&?{
zjB10&@zx#CT;p-Pbp@1p+(jiIk%58XxQmL1284D1<(%U#Di-Pxz5%HFdfY_?Bn?uh
z;13a(0JS%dyQm0Uf$%v%BN4}0R6va<@L<HgxeN>pyFg{+PSD_q;|_3>V&^<i?+%=^
zIuC=a2MsrYtapMK<8TZ@TRef#2B6*&vh`5wBql=S(XF4uz`y{p{t(D|7X}7~ouEi?
z+z|mvojV0!*1LduJ@-614|(+Vf<nfpw{;70iof~$|9_wEtsp7i)^GeRCx8F{@7c}f
z(H+47ayF@<<_dAHL^p&+clKwvvtvNcZUi~I9pvC0;D#k~s6l#Ypd10proEu3{C~Og
zut)b^kXt>v+5ZPfwBF`#l>pV+-C%i-)|2pb%>fo>^z1z6)A`+}^WXmopjy23fJZmD
z$S76l?gb^~ecYfT=YU5yxHN*+6rg})@a$#-S>C(#-2MOm{|98W9w=4x=-ti0!N9=3
zy%!|74>VF~cmS)WGhj^xtp`d~Kvh@caRwf+K9D#TeIDI=K^}zo3YO)eenGBtphY;e
zKzHeU4|XbQ{ovaA*0b|If2-uL|NoI>Ji5V!s7tqjYwI_U?yaC2i@y)l(f4RR#^KQk
z764^%P)!7_{hAL*cyzXc%E~kk{=5Te{5c2G`0HB}KuRE`<StN2?9=(*16p_Ow}2%)
z&(0&BumlZafJcTw3~)IQVt~>p1Bd}0tnoa~0v=`Y>~&EQ@aP2BU?4V!M`tUj?g6ni
zJUUxJwT5qRj*3DWe?HhHpB?$@SyVuzi;4h*QUED7@aTk;McrT@cy_v|7{FT4KAq2f
zI{$fe9s-A-NAKJVk3mgDNMp{Y^SwtWD9gYlpCcq;DFs!*YZL{b640l6EhvQ13<5Vq
zA+~sQ?*(}aO~GdrgFtmLl7ju9paVO~r!zsoqw}~=C$vuOZUxoz9^ErQ(c#g0+k@Zb
z25gYS@&7sgR^NaB|3h0Hpaue{5h&!*cm&ki!PO3w@3savbio#OItxJBU*M4jP%}}!
z+uEZy^vk}i5*7!;17JlvZvOlKU)l9br|Xx7-6G(oJzMh$7BE*7##I1w#b8_}FjpMR
z<=_Pk5`zUKKmy&?CG7jEOBfVhv+k=ZVNfu<1hoiib#4hu15^a7`@oJu$W+aMjXraL
z8b1sy4ECS`nt_2K3ObDe<}!imcTn?zkx`J788$P)?7_gm@Rfmqfu)H#n1O-eDQMP1
zjyaBjfdSO>Wh!I=4U0H1`LRw0jd*|ty8W4y85mg?F)%RnfVcrn${dUgY%>`c7+5*j
zK@$udpf0L80~@IO!N$l58b4uSWdeo49*~0=g*cfHKqp4HK)p;*SDMw7kxhV+fq{dO
zTaA%{Ardt3ptTW1g8c;Y0mwKI%^1eBVlD#%qgL^B5SM|0cLRv4&6UT%z%<c;Z`Cvg
z21ec5=?o0~jAaa<UK3aus4f9981?wClp==fV8Rj?d8RirFz6p!V8*~;#=yWJ;KU2!
z-eP88sD~N_sx?4Hl!6G5SM<R~r9inbVHBexF^pmm+{VbjAe0C49Gi`BJ0k-F*rOJV
zj4&@MLOsnG##1+mfq~Hi<cb;w1_qugkmoEecQY`^Gcqvnw8OcfAnqJEw;MEEl~lvP
z02)#NxertkfoMick#a1;lKHHntu+h`j0YJR7{p#7sW=VN#lXNIS->hXp@xA0#)law
zS;#7O6q~p!D6R8@+yELA1DWy)M1aE03hV}SVYnNfz}x^+0ZNr1y)ZYx_%H)uZom*n
zxZyiUKPa8Ug4P=B26SP#8`znk;Q&+dA8G*14KO|n)IgXUFvP)bU=TmV$iQ$76z6uJ
z$Yf-M#qkc%C@&~b!Welrg5nP>uLTli17#gn7V)Qy3=DrkTFW3>VOnm16hXD_0%--y
zr+`F-1(+BZ)R`C<7@HUwVd_#qH9J^6Pw8}!lvo!7Lnjjh11~s3t-8_8z`#7Qqh3M>
zl<1~`ENg4*;E)8T!Ra9GHzo!KNw6#1K-`(k3=Dh|g&7zan|r1+F!22XIidxW_4vT<
z=?5v|U&hS9zzv#8Wnf^CfYOX@NS<8-axwoyW(I~Qpftn4!0;PNGxqa<4FY@YB1oCk
zTIif3E7UVmo6!WMw}FZSTgI{;kZ&65rB0$Lkh+Q{fUW}^(=rC2ksnY9x-&8|!h((;
zT&XiKFowy3gV3E36o!A985rci;o!+=*2};E8qbj519FB3qakQ`P9}(nfguZISUMvk
zBg~K}G{e%thJ~>(Fvx=q%V3;1oq<9A1jwK~#%ZA9PNsy3fuS2@P%{%FBg}vtQ0pBW
zu@F}^Gl5)H$-=-O_j?`#17knal?n!i&m1s=dzl1hFffR$EoWeu2X%upKiJnGwbIP<
z85kHJGWt$uU|^YeWPiPMI>?YmjBS-5feZWVrE4V_7#OvgKmyDYFXT&if%wh{z8J`a
zASSUHAPqbA*GpT01cI4(Cx8UD?5~&Z1{oQ~^ayOniv9JNmSVVq8Umm~o$);*C|$Bl
zJg~oB8bbiX>0}6Cc#d=dIR{XPy<h}YnU_EjDFq6!2aJr>3=DFt3=DGKAo*vETP89v
zOa}2IK>T-%pomstV_=Z;1gZbbs6B&$0hDFrz}4bUuz43i^0^@Otl)(46~xyAsh4N!
zsA6Ea#m>M0QLn`Wvj0Dv?*!(na4;~))qwPeFfmPFVDRK%U=TS~g-A?qp^1v|38TV`
zDh3A7AUlKN`$}jMlV?(5tO6y33;XMp)xoS2`|Fi6sz4d`LOGHULXr+F1>PzKhFo?A
z1{KLF(3%h9Dh7rL><kPFB~=UzTS3K*;*3g2gMu-eNp({t14AAM1B3FuO0c{0l}~~5
z$GQFW%GbcGGyCfil5kaU20}SD7QzTDEQLpv3=B)ap)3W<xvtPcKq?lRm0<#M>zf%E
z7$<|HIzxbg0Yia&11K)1GJ$f1d=r8VS7-w@S{j^4rZHUy=h_SV>*d-&s%J2LGi6{n
z&j%_5LHspftF8+$Fer+ZF)$Q>N~Rf1YK!MGFn|;?{^ez0P&X)JU;y=9*(M(4Vqg%p
zD`Q|_RN!M^(C{o{U;s5P*d{8*m4UP}Fz^U-C~gL|<v@)bVGh}I^B5R-SQ#gpF)&=?
zXJAl#P{zQJ0Fq;4RQ*xL!0-ne0t^fy304dY9^ft+14A5?W}FFe%wJF?c#D^TL9-T%
zDxSZL@!SjyqU}};42;`(85qRoA*l+0n#Hq-nSntHW^y%D6hi>)j#Q{DOcmoCBzL$9
zFfhp80D0^WBd86!g%j#7bX`1u8Nb8br6j<>pgPftfgzQXfk6c1K$!AesAW8hn8C*K
zF*5p_Gcbs8LNXzP6wDQKpb9Yrz;14W%EDAJ&PQ_d27XjGFXV!{8C@68U&hruu(0gn
zhq^h43+iT=@-C=lXl`Z(4Pt?uEd_JM5vW280kE4FLuFyA7#AVAc_Ugl_i;nrjIIk5
z|GY3acf-Qjo*U|BnDW(7%h25X0q$m)E1p6XN}&sY-FzA<3sc3o6v@pgXyIJV19daH
zE}p-P!hA3{+rh$FhX?9rnDWa|%h23>7c^=F4riDvxS<(e3S9u~<~LAdV5%5bAh}rr
z&CMCGe1@)z=P%=NxSK!mLDPmLFVxL2<zJwdp}F}KY>kabiUk7$%q412cQdYHlD#vJ
zfkE&$laK`i!x}yY29fhv)CvA!Qhjg1z|aX&z+s6nNCaw-U?+>Jj3om@8c2bJ6+(dk
zOu-RG5nXKJwv1Xc=QA*HgsnFNO{O!56k0Mcz;wZlKhCH+!IFW&8M;~q6bTG6Q<xYS
zKy72j-As&(ur^*d)IwMbbT_!I_e%iQw%fyG4(f!<Y-3_zI0I@Z9%N!<glW=-E+~X)
zJ_yz<E6BhgJr`7R9|6|^OcP7cxRCbfAtsv{3=C2Spe{HMrKL_n8887f%?u1uFqwN$
zl~OmL4443>7MRR?s7k5lPzFo@Lkok<6($CTHy}ShW@2Q7`4zVK5$5N|U_Uzu!UF6G
zlOrg=v_X9volkn8$eGTl%PY>nz@*H;r01Z-z)-Ekz#w>tk;8(4fsv6(pBF?MfD#k~
zSE)V&Ll;PT6C)R>a+?5RFJd&D4We%_f&f&#3}_6It5br3VUI8agWy`In#Uj|j8HXd
z77PqvgAKr{jlib72dRK6FajB(w?K)3VL3MggP<6b4ahBwF#TX@<FiT(443&B7zCA>
z7~xWIqZ#xVlo=S-f!turv{n%0B}RQmkTDE;=E@8VS3w55F{KJYWWb(f;F@Z{z;K;|
zfkALNqn^JiRFywdH&hiwKi6$T28R7y3=D!R81<H@GBA7tnH7O%mfm@oOd^_oz2B+~
z3}QSC41!rqPoXA5?SE*<z>p7;S;eTAqy|-0%)|}qd@{n^&-L7pf#C&6)k;Ra3u+7u
zJiH7Hf;DJn>HUGpw4&+P(^O|*xDL|O$E08m@jt|8dg1B}47wnh$xNV-1cfV9rbV5B
z;Tj7AgWwD_8RM<$3=G*IJ<HJJp%avr^`5CSFbHcfFbJ+=x(xLP)VHFN3=A8X85jhY
zGU`ccKvivH`UzD9v6)Ljl7ZnXNYye%J$DTThGLLe`_RnNtANRzLep=&RD*%x4oJ^k
zB=>=nwefQe1_lXD1_r^m2q^|*B~1o~?VyD98zBl#t_;TEnhXr>APrp1ps<1XLvMm6
z149@;1B0L>GfH|g0P&zYZ^G1QAap|HK>-a>q^GRK!0-=bPzV--81&L$(wSJK!G<vy
zuhC*)$ONVODkOVA*@waSwiW}!Ay7nhBcvFNIkXuV0<;+z1m__{!DbmibcMs@H(`?p
zt7I@<1XFYdry{7z584b2N;(V-f{&3@mYai?7HaA+Foc7o{v)IqjN^0|82Uh>(k$>G
zhdOPF4g&+53<HCpF+z&L_^=KG!+VehTV&BMIt&aZx(p10Ni2xM4H5Ll?z#*N%^>+&
z?DCUz85kac<eQM>!SM?x7>wWPGB8-_F)#?Wqbq`>Hy1qyhAxnNKbky)@nk&)h8rNM
znMhLL7%%}9xIU~53?`sbwGuS-sRLS{EFdVwX!?tZfk922fkDuc5mb(wCCGzHc6~<O
z1W3uwXc{5Uz%XB*fkDs+q=L~1q(aaHT-e?QWqyMPpulI~dLzNW;4aU=AgIl#mo3l0
zunfeuVO$4N!^oun3Pdv)Z;}V~85tM^9T-8u2o^N}sbSFLQD9&QRA68bbZ2}IQq0H*
z)ufjWlksK*Sq6&6FCY~RdTSLJ7(RmZ_%ps2hm=GR87@vq1_n7r1_nW0Mm=3cXh|N-
zC@O)X3KSyXdd7v(C>x|Y4D2z8v;KiRW>f|ejz$PG7&j?0Fzf`0#v_X!Qe<HG0TN9@
z62%hs=4sLl42;~Nx_=D8btj`m3TVx23dmPAU|&H5(%=FHjUb0u<bjmsz(pD0X0!Cj
zfJ{s@0oAhYG7JpNP6iANj`9o)+(`^9tcnmxP$~dRg8U4XWX>>$l%U)(%%D63DkiyO
zErdZ@vltl};U?;XU1o3*<PZktFi8f6GD!vo0UMoUNd^WE{>#jk<;)BWwPp+qJOUu^
zgBHhtFmtCa14Akc0|QTm=>%2=hKZ643_K#Bgv4yNkd=XfgNK<>*IXA85T>BT!=T<O
z4+lsEqY+324=cz#{WqXyp#ezJ;1OuvfkAH_D+9xRRt5$hac~cpk&#*dBS;a0-f@_W
zG+gF4NCvE(LGK1DWP1vaJR<`ryx|&I8aWskBzR`&Zk2{O$V!6^>Zvu1jEq($Yzz!b
zL0()7;yJJ}FbJ44Fz{?-WMs4sWrOTz;n^Y$Hj~k&mW_d7CL03-&pucksSc81uvyK<
zz;GNSaR^ny_6i#V!v~PWF;FBMf>qo8V`E^DVP|0AIfW#s!_L4E3KBdA7c>Ax2!l-l
zI|D-}NahA8tl+W?HdELc7&d_<?x0A3LlaCe*z96wV7LiV@&pntj9@b%1US%bAG0$s
zFmW(2@H~f`4AE=L%fY~)1CsfKCSzmH!N3pzlKF~aF@sGs2LnR|Na8<=1lT~Zr3?%#
za%`X&nauj06_Vn3rh=!{e!{rZK+|fhtZWPnte~iv&ZI2B$e`E8!N4#RWU?wFD=2Hg
zW0<+a1kyg^sndJF!NBklq(~D@k?~Is1_n+}1_mBoMo_8(ryT}8K~4q+HIS$YBPggr
zGT`(EcB%nrEP}yUpOb;X7o^4ptP@Edqy?f#FP4*mp#Y@F1)D)2g$#O?oD2*TL27&$
zA&CT<xFJRu&*fxb*aVUe1=#~m*I*g2TNsRYaWXKR2T8|amA=l&!0-kn4H{)<hUf-a
zYXEBCGZ=s4WMDAk0?nc!bc2G?07NhtyKq6J>k!iEvJ4CcAcBFp&jix8<!LZJ2UFRE
zPzj1^u#F7HuVB(`2x(9-f_=iE$HC3OAj{3bz|#dDhh}7C2Kx?7Fc@oaGceeIWT${M
z>x1J6EQKH#jNP~y7-B$*rXv(F*ky7<v+68HNM2<&ss|}r1}<p8CNUU-ML@Zpkr8S*
zI0ryfZbqmyFas5d5aC^D!bnbmC^(E$0XWe!KvbPaQUwkVaNHnSe+^v$lH6S+Ij}xZ
zoI*|S0r~O`LIH!`EN(~-iRTNWHK@3Odlu{~y^S#GKWNe*XEEsQg-NqBq3Q<N$)I<f
z8`A&b5oQ9V98kFc30%F~Fc~=}P@)0JfU^pN-YafMZ-_??UC%F=j3K%nb{<GShsTQP
zvpl4BhuFisS{KqA;%U-rfGKijl2Cvsf>_DCQ5Vt~;%U_T&jaZT@%W&bq$kJ=l?g@D
zt|!k6>GANyGJ(Py$uCB{3=E)o6P{#r8BbnFUx+6IO~yEy7t$BvDFb&M!2W<FBXF1+
z7s2E~^IEW!39^?#uaTF5VKT^>-ROqS;bmZ01Cm*QW+;R47G6k`o(IzR0^7%+cY+tv
zzvEd8@83ZJOYbf(1H%iDQG1wDK<x@fMo6U#b|VAx6kSMHi>F%eGfd@Kraq`ju<1~h
z^K~H&51uML&^R|I9|Hr=BWz~s@$fM)fTh1;Ge}RIkAXo2q??5qH4#FRus%$h7fl+H
zgsoxHVrbIf;MQ~HV_*me8LosT4KX|pCT)mC8thRp!Jt<JQ)q>z5abG|niiNECoF0h
z^rph31JR^Gu@5b|m-0b6o;<1G4iF@~AwD_C2N~?(DM8Z?@yRWibTbxdumiyagWfxs
z!pUd~k$l3y54CGP7Bvidf-vdzXwpbNQRIj8h<PCWL5NR4r3ly=5bx@NW^h2=W}esB
z41##90A>&)3u^KJTLw}CF%iUN&})UMmcXVO$%`{!3bk-4WYAj$Q{#wD4ah>MKX$_u
z2C;y=2r5F5JPe7y_xzBaJx>-c!x;2f1fXiFu$aT3X9kn*!y*l--1V{r7#JD^7#Mg~
z;<5%(;puh26z<2X5IJz?!?aw-sRb#7x4=}t!mFA=?*vRCBP*5|1_v{kfP~|1m}+4(
z)u50E2LjZCVuH|+P{pYb$+dwn)mC^_Gw6Yan85+;k5eI%YmdN;Eyk%D(V)^}6oNXr
z7N=^klR*T7o*hhe2Ts-SFk#TEhN+%}Q#Gh6hcp894hk_a+z|pLBdBU-Xd?>jHv|ER
zlh;BF44lFY3_NRbss=e3oR%2$B!w9m%t5Meu!8&!Zx@2hf;4pWT!a}ILP1Jiu!8IY
zWhij{1#WnPjR6x3#!<qM!7iRppk5}_ji6M-pqD4iz)%Y^;}0vya<~}`dd<QN44{Q4
zJZx-eGSh@1;|x5!Y_%FFjSNs17c|bmQ?7Sfn1SIg$Y2>ZRL6k~1G@`MFz7vkDbz$$
z2rso5^uEB<n4_tI8^)l=Dgw3815FJ$#6WIf&=V11U{DufVBiTwQ-freE=)}dni{xW
zP=`Cf6c*xA$e<SlQ`3Z|2FX!LA`A?5AV>A1sX=m74@}KGG&SgsS^-nI8ka%_y~8jy
z`_R-NIqHrG1H*Taqt2kIL2?v}C{)dDG&Sgsl7}gLflDESo+V7pZ!|SXjtUfIU?>!2
zVBq0o2gN5mv4YDoXsk5D)JUMIL3h+*m_jvN3K{ec!PJ<esX=noeNhI6e;`M>ps7I$
zDSk1inh-QK=#J8ZDNMwrkU`G}rltr@4U(fW#26SV#TXcP8reakScs4Ug&Q=a8pIeF
zrhwE;W(TeHK&SyZoI!66OnM`lG~5Vqurugwf+;+SS0UI|Fu|aA3Z~^Ynif!aFzDTd
zNq<6<Mpz9|_z9+vn*-Ggs0tyrnt;NGL!5!ZWV<c{L$o9Vg9)g-0*@4%H?V?+59@WE
zj3HxUkikjtXyskdpc(^206ba=7J!t&NTZctQ3kLjAS0P~nL&mGxg(fYnL+vs+_B8F
z%^)2D?idDpSsn%kM*9gMlEo9WW{&TLEx$OVQOWm_k&)5B!JL7?z!lW>W(GOlNSuLz
z@0E>>I0Hiri1`&VXu=3q0wx%2;>8&l>Oqn}u}C(FL!zATFEqFeK&wC?1jxM%dMm^s
zy*WNcMvwr=5g;WDdMCvp#Va2xc;yI8!T_WSVzu5|aRvr{2?ho}PR0;OH`@S2BO5Ow
z0jaY1cyTH*lYoYRAgU6uMK^RA7#Q>-Bp4VPKo*HIf&@Tri3A4{$XC4}iPw75Bp4X>
zf|$~bfAzqX6x5X`B^Ve!gCyjkV@`|)AkAQc!S25V1B0|A0|TEjOq-s(Bm;vZNJtGP
z1W^l)YEXJ&V9AnUV2}_@)&)%<fJg2?BetNCXu(v_P#t^-n}H=t1~l>D&Dtc*z|d{Z
zz#!-gR^J8V`hiCJY$r)WDr~_(kl!YNQUQoyumug--jQZt5DWoj*QuaTHkbvH1`!Ol
zPo<$VJrQte23tNE1_nLQ^bcrsUmu}|!PZ!Yfgu<q0~$bs$bcFhpwR{HP~9me7+K*A
z$U@|-02Y9Zmm_5buqXp~R2?)S!@#1a%D})OSilOJWC8nn6Uf&VDas5Cg4H0Wx`Ah$
z9l!$h;Gr9^hyh43gH5qA1H(d)+LpHl;HcF12CIjU>kC%etX5`VxCv6zA!vxA=A$VC
z!wS&6Xobxakh}^5gJ4f6NIxT^KG+rpX3%`L3`nBLMhQfL@MKe{IbbygprplM<FCTN
zPy>>kjcS5TJ4|8`Hf>u}7#N;`w5@_>N{9yxqCgY)HXl_O7?f2(Grw455oyP<RuxoU
zXsUt8i6GKx_FM)AJwpa(CT0c(_J!tdpeYv)Qwttu1_llnP`Exa1uZjy2)Mxo44#Ab
z!&*pzlzGEN8EiC}85q(*f__m(kT6UJMYut#5d#AQGb|uEtl;6!VPkVj5~?S#4@J*R
zu%29V28QP#6RqJBFC4ZuoKg%7pk47CVK95Z?lb@`iZQqjn)k4EmttU;&%(gKkpOp}
z0Z1`e4TDXm6l7?LBL$=fqy+3z2HT@j3=I6N3=ABgc^!R-v0#0mc^?K_PH6@P7m#!w
zNDo39G0VhY9ssHeP(rZ@QUid46&#9S0fTmsOOZkmEXrV00}sUo#*k2)2GVb^8gwWO
zGpI2SN{$>>@VbD*#%32xPv8|4J@>(SK$RUd6k$~fhpi1O3oI02_JAD#4k2hL=CdG&
zB19Ub7_5fDW)%y1D1u$eV0#~Q?g=QEz@dnw4`e-qtt2aQC?cdGwI4Xk+b`w-CDT?e
z1_nm+hjI)Ij3^;GAC#^bkkTbsz+efe6h{hCuqcDgb{S|I^ZR513DM0U{RV$cK<N@R
ztqKj%9ng6`4jUU*S*V^sHBcU4WYmY~F$5)j=Dmn?dE6XQIdj<Bgvi1|6lM?D0pQSr
zhUg+$<Pe2OgA{|+FxY&NMGsN1tqisfa>(ftNgv312HPoe$RUc5Mk+)hnca**5Hz9c
z^2U^b!4<?31XnY^O&J(ic1toaSg=iG&1Ys{@Rnp?V4DmoWm!SX^TFIHpt^+>v^pQm
zoeHX&Sf@)u6;ESQmSAL^3*$~_QdVGOT><0HU{cm#WZekk&SX+HU~~gn2rjI(LF;uH
z7+gWkE<sQe%B9DQfx#8T0_`ne5Cm~uKus7y(9EJMh~)xe!COfj7R*P@7#QMM7#O(Z
zm@k+yF!-@BFmT4Ofey1^=McPO#=zh%2x_mnJO>#KVhMt#Sp~m=xS&R^Aec~=Vqjnf
z71n}m3=F)g;3l#MXb&2L3rLD>85;uw6QiJxIRk?$NI(!oxPT0C0qJ)EH7H!XK(Zi~
zAc!RhV!6bD#6V36K~UJcfP=jVBnD!+fLMZ{DQA~9kQj(12x<+ufCw<l6;ziAf+|&)
zl^`V`mLO;<TM)!`0kaN)BtR?|5K9m=zwL4jBnDy$f)+5iJOyz<s}=-7i_%=cte+q;
zFqheafx#6t`7c;2$iN`zBgnwuA`TJ*tub;@1hGJiytqJ(DbRei;A%z}bC4)lC5R9N
zaRosYqF?|>0>p9w)oCvAATEgInI*!&z~}{9!42Bt$LNi;sFJ~Fx)1{cLXN?AuK@#t
zjy_b(Z3Y7aqaRp(Jt#aN(m6P#{g;R_Fx&)H)(9iLpMchIwzGg1lt8R*X92Ank$(>o
z?_>cj%wzD66J%fzvc%%fLyTa>4?v2KfLHM`_#TvCU|0ilgg3~I5V4bJV%kOw49{R<
zJYaSH|BV<Js^J!a1^qyVb7X<)9lx*hK$Q`=_VKwY4h@C?uvTAfNd^Wf0|rPY2Q69v
zdlGDa0CyI66#`gIFab3zMhpx+22iuXE@1H4jcS*FjyMB@5@_){*bXMJ13Ya&MI%@s
z6eQq>SeqKa5eBY^ed<i1=0<^3FnAh+T8CgQ;05#ENQ=}N{Iir97{Dv!(G|>R2GwB<
zp7x-oI9LyK1v-QC0RsjGp&;|ldIkm#p>?K*4Hy_A@);O}m_Umom@OU~GcX8&W+L?k
zOF(TI2e7~naIpgxF#xG%uwkiZU=TE6U=X?pYeb2G)!S;;GceeKBtY|tP(y6I>mjX0
zp&KCGptb-+wM|w%q^T)%3su4-$(n(o6;$8o{HtSNU=(U()m>-}X&~#psAFI_0&-_F
z>&;?F1;qrm+z6yrsFf8oi_QZUVbIwP)?UD>TVn&&{<@Zd0aVco6|pL0gS8ugjA77Y
zsAFJIs$*afDuzo;1nr;DGpd8?D1l3WbQoL)oxq?M0@GFsmj!8q$~MCsTgG}E>e$a9
znn7=N9RtHG8wLiUa@NX1h&w_-))|4EEK~{h#b2;e<HL0f45#cF7=)@oq6T1P3_1sD
zK_QdGs>@^x^;%giG-Og(4}f$sGU`78(F}UMFi)qlu6Kf122#PGx3CuKiZs^#e24_t
zcq5SMLKz_Y^xuKaFg{)jbwwsf6y}N?uq)m(>xx2M!Jq?*97ds3X5AP^sKd@0FfhCV
zrMzrrSb9kU*~Xyv&47V{*N}lhs1RL7#E^kO8zfVPE@NcKz~BXvsYaIxGGt)L2FWy{
z%aj;0FiZf+w4uw)He_Jf43g<am)UK|z;Fd5GXY)Zt|0@%caY3fbQwk?1_mi31_q&7
z=rYPi3=H-lnfd54UPcTINg$ae=rUPG3=GX6nU&}=Jw^-+i$OB$&}CK`F)*A4$!tcK
zxoyP2@Eatv16_v8n1MkHl%@8f%UBvSFhqc44x!7W88a}{gJh1Q%XAnsFf0PeoMf(W
z1g9x|Xly?*VPF6?BZW>eLz5v)=CLUQ!yi)y2BFi;3!G8(>~LUUxZ%LSAan*@<~iuh
zT1N&3p|i}Ny-@UguV7#htYlyiI>!vn<1l;TDj68cK{Dr=(;>MZCR1I-z%aRrfkEg3
z^Yk1P({5EUF#G_?TtnBxTFt<qT+P5BbOSvM45}Fzd_gidnL!y1ROUg$AfcLpp$;T-
ziy2lTKxGzIGcfD}$=qfJl^{rZPE|87JOjzxVFr~vNHRaG85rbi7#M`^qq@N0eGq8u
zMy-Z{As8h60IPID4Ff|HNcu5Uni&=vlWQ0lHh^TFpv&y3VPLool6i_Q^RkA4fvc8*
zLFgH}j8rWHgBeKXIl7EvEdxV5Nah8a41>-I(CC8@1CtSmA;iQ4D%NAcr3Qn}MH5i{
z#mlI>A6mp1%?4FE{NReJ3#>?Qp$W9u)@FnzLj#a%29r!DXyszw4mJi-4d!622CKnl
zAy<Q75d)BF2AfyL=+$5YSiP;J334?E*1}-pYyztWLApVa2vKd5VgjoMQ6&&A)d3yU
zz$o;M8By4;F@_fQKcFGUs9y-ST<?@I)Z;&yK^_JTYJo~!1_qsrrqE#f<^(C3k%Mh9
zME4?7sBUdWXdX2Hsb(+%)u7-y*}NZY3?$e<wFYMEVG7tR<X{7f7=TnW*sz(R2ir`r
zdRrY+<X{79VX*Nxg#{Z(Hz?R3s%`R3VZnwffpDqLG6$%KpF3lExVQk+#L+8vfO{BP
z^ca9tGnh<tfu)laurUx1ufUp4Qov>*dl)QY08-6hbK4%>!<k_9wu}zQ9tLY+uu*Y<
zc^IS{<Y9<v8y5$dhfyUEF4ehW4{8)JuprV2s~H1>tQiA?5El!mqXsf=EjYCGRLmF{
z96>Sy=rTTL3=D-J83`6p%0bf8V#dHQA0%Uss>fh^J_7@I*bYH3=<PLQV7LcT?SiHn
zG%kZs2xc+py)<KB;527o5c0&S`W(y_20LMM1_n)#>OdA~wCU-?go0o~&{i0;CA97h
zNB56{B?E(#B?E&{47yB^B?AL!UzpG)mhYhOVr0|@hns;MsFfD@%awuQw<Rcb#jymf
zvt(fSlMhK@jKTLo<|VK&G6^s+GBSb`>hpu6+X$pVC>gw#9wHJVX2rk&8eSF32B~La
zWMslnpU(m+`M~N8L_l^Mds#tN*a;P&OEHA5vtnRi5n^Hqs{wUC!g{S37#PClg9I7$
zwp%eUJhozB5ZcM23~~_6OAKJ&6kCIQQ_Z3aasg;8Bls^!Z4=00Adj4IV_?wN0O?~0
z7qx~=R|~bX=oT<AFfj>$76*Y<m_t-JTSKNcgnC#&-Crgq0no+=Bo#&=`-C8S4j`s7
z=yh2$FzmKwU=Z5R;s`PZ)q(LgAP3Gxa^NkH+9fatX1X&l=zD|oF@%4IIdB;Zs4oO{
zAXr5JM1__O)PXCI9f+jD2xOnoDsXH;Ol8okwt+U653xYAAfz3vH{S+Yh@6EdJ&?W7
zl)VimdjT#B3O1<hSsMn1SD>E2Ww<Po-Y+%`46?Qi3_>^IvY_G#Qby^i*fKE0fn=Y+
zWkFHPpqFLKz_1h~@gAPAqd*=vfJkqG>H7iK7Y|BXdLLo>SXg0MAEFN;ZD_~95M;-|
zAjF9(&7hZL$H34AlHp;6=11_FTc{tW!DI#CvWO5c-et$YAOq^)M1Z;$(0m5Ubq13_
zHz^p~+A}b8g5;x+<iQ>>US<#Nl|+N2AhE%qGYvF|A@rNeF3=nrFB06K?iwQ_qg|Rg
z14A>Y;E;m}8TXkpFdP60X>x<gx*MSUZt%#Hfq{YRZaxFU9gvg;xA8B~6p{r4gODjg
z8G|us#77q-YKJUpWC6|CF36(677PrzAhn(dQG@5;eq^Zy14AE3%AXq~0Cxw25y&$_
zLENBH0PHfTNH9Xg;04GCqj@0hAqZgxz2z3rk|LD*6UbAH%=%y>AR6@cSuikM1ZfI`
z+Q|%_VPr7AXTiYm86*)7G7aoPhzx_y(+W^7<Ym;g@`e<6$Zd#Da92@pTLm=KwHcu;
za|4iS29qb=uqt&i*ceEaT2X*)1fmLT7IKve7BK*+X0VY0HSs}hKKKYkJy^Z1Lj`h`
z3f974lUxC-QbD>wVGB`h(_8_oQc)!kF4d861y!kMS>ZigJx)gk247Ie<2*bQ)PnOC
zsL>5>c^m8io#>?};{;WB8BHOmeGgX1pcm`Jz_84TfkEgVni_P&K&`QxAcc=uZv{g-
zC<t2_^kkeF7{Jm`(4;|jG3XgMGce>jGcX9fW(Bzo6a>h+o1GaL)`6toqqzc9)-dR8
za%Nz70FwTQRT`v7%7uYJ=qs8u$PWy9YA#U2zoSV*oMz<$HT)-5=|C3-hQA=gf1^o*
zY&B2}VPG(L03twk8N30pKpte!Q*~otaCc*15aM9t3q=Yq2EDWH3=E&#85o54(Ph{?
z7#LJM7#M`a*igclLC?^Gfgu$nBg+OW7m>rS$b*655J*~?4VvQhA<|32K>aX*BnAf4
zBnAc{Z8m7(2$5#c^Gsr3$OOq4qT5)J#K15IBx8oIXMGX_LtqqW#FY)!qyt;Vpm#Zm
zf#EAik2R`kkW$!~Et!GAKAC|*$d(O}06<1S(_%m}14AuH-hmBP27wKRYM+_Rz;FyC
z?ToG+q?$qRK{5k_cnSl9kQ-VUfnth5Pc4OkAsHm?j#auMg@IuKNZJEU8j?!3r!X-5
z0ZDtJNka^mOl4q5OJ!gX@<;PIM7lebf#C#5IvlI?-Bbn!jx+`ap(s?t8T6FW7#RFP
zGO=hf#@T5M41FM(6hvq+=q*TNU^oa8%|(x!i)joDlIaW#LZzrCfopPT1Zbo)FvNq@
zlwoxy=vI~$An9@}Mlk5@N@rlW1d?t*m1fYpmCnHM0VLCgnmifwzNIrTh-WY`2z9gN
zq$1}M<8Orw44Op@3_?>7{xirbhBosV^a6_*7@9!xQ_*c(RK&n=5hOE>4Wu5P)EM;M
z7cnrX6f-agO-BnIV~=76hFKt)1xU7ml9j=OEVz}kOBfiglrS&|EkU>PPYDBqaVZ0X
z&{EWt%b*uo%D^xMB(sbSWD=5N_LVX){07M^M{|sxdKm+Qa~T7J&^mN`{K^;@CV*tN
zphXa<egkI{gZx5Jj-Ow~z;Fwsa4(udaCQT$v3pYnttJn^VnvUk9NNG<$Of&DAWa%0
zP%R{MgbmaP0B1=CWBGDu%jYOa6rxPextxI^r<{R7=or*mW=KH;b{d0TOF09>R*>{@
zXfUBlUoB@~V5k6%sA1F1V1CUJRQE$FZO||=X2-t?R1Y#BSK43^i0f<u9nt&2?O^q`
zWsb;|HdqUT%?w9ar46zR6mbyMHrpLxl{Tt`31|!&G(=$m>aYtPVPs?kca3M)Gcf3b
z4F%^l28K{BCr~eG3TxO4(7i}uZ$ZP9Vc$SwNn!sT85md?bhw>CUgc%f1yw7c-Vky#
zXEE5-dUu_m@u$rQtt}wg814=Rt`!9g3<q2p7=+fa>d3o-jQq-O%IV6$a2(X;`OnUz
z%)o2}k`VgN4)WnekjVxhNd`R~R|bXvklvr{(6+1oHIOueUbHI%19(*I7dzBqm`sH$
z1H)91p5N@SdI+j#mMa6pPLRwWG#LhGevoj9Jt&DW+Jjn~jP`3LfW}6+ZWk~xoCnEn
zU=0;_1BKZk*06h^BbmdVftp2OpIsRkn8FxAQVcqK+(91XWz-D~#cUdifF?N@^!nW4
zVFs<04M3_HO#X+$nuaxCV<4&QBPf_KCZ|}zW+A6Cu!sRjHG|D}H}q7-1y*k><Bpul
zz*-n=?A&3g45S+r2N2aZvF@-`hAM$@sm?h!P}A@Vn=Ytb3rZw<5pK}YmTPRFY71oC
zH%Of2yD>2Iftn+CV3}Q?0pu(LkU9pvxo*&Kc?4^dK(p)yH)x6QgbnHrNM<quSuXSp
zl=mS9F&JNQgO&)-L81_44CbE`L9qe}PRT-SE$#nBpvXoJPOyjpNHv3vT_SpLvOrqe
z`H9HE3D&}3GdB?yoFLsG|3g&UoJfQPC#r;rUpO@4b(Y40g7X50u6HCP{pkJigoesx
zj`%2W?PRblih%)~%?y6Wg9_S=AO?mBL7*{s4)YkW68#&XaAh!_6U4yq86<O`1LO{{
zC_+1f9#b#_gMKgrgV19RlSCAqLNN>sE-|2yY$TnKmYh!v149)^>J7T4o)`v(Ga#8S
zNSeT{596CL3=ABxprGeOxCGRUWH6SFWnl0GNpT>g81$lJ85m}QMEN*D$`G1Br4fS>
zD4>J{IYE^H*jEh3+hQ3QX2&rw2niuX!G#^p2C@ODCC6aAJ&u84emnz%kR+1EEh!8P
z1_waI84z&;L_7fzVC#+d$1^ZYN?>3Rl1I|>0VEG<pc!zaGB6m3fCvQ;0nxK1fq_9b
zk%2)-6-f^~E*ThfK6`>9{{TCD*3kIA2ekKe7+f^UfnpWnr>&6;43I9C@lj8xqN7NP
zz{4jXMGQtDV}*{hgMtcd00V>h7EeTmP{x`eG(c9N)M8)}1CVM48)HxO4515FZyWB3
zoFTwk7;Gv$VHpCX8x)fe)i%>SVHpBd!UQyJ3aZ5zbf$TMT*}L+3rc&S@&&mPG6!3#
z7vlxZBHE0wECN!^fXG)|HiZlf(t!*NLd+aGf`JSS5<*wlBQ|+4Foc18{{R#?3=s!l
z{D&ZZeZ*-P{}G5^7jXl|e+=T+nm+Y{R${Nfm6+)l82>dplQIXh=^rl!22fi^=nXrQ
zvH-Iwi#G!UC@l-UWoJ?rVb&A(hLx1?W#`cl9~pT=_Jaythu3ak8EAp%;myF1><!BB
z?63?EmS)h)4}eyFH{n$rRHh>UTKU~VmsuRZz;GgffkEgtJIHmQ_<`!V0g?etTHir+
z27}(m0BFU07hW+#^caCcSLhiifb=(jJOi%DAp|Ha3_w;eFz7@FK;yM822#)=$Lng4
zMg~2t0C>DYy=eea&0wMt3oS3rMZv~EO7;X$RAN+=bHHXHm+W8>1CVM4n-+icguD=}
z-gb>YazX}cVX(RA4@<}(-JpPisJ8j+4@=0X5(t;-g!+Rr_d7&I8JXn`O@6$fe5+UI
z&A>1Z6saHJwPPySEqbe9G9OW8z^MV+*nZ^Az@Y5Iz##Mq+HPgkF9GQWk2)bKG}iE8
zV2A`M{0i=6Koo(?XuU)q28J4t)HgOzi3Rc>)CDa*3=AtkGXKzJcK9$bJOIhCz|$~P
z&levC2035QI4Qb}i7x{~2uOyD9nGEuUj~L2kPJ8bia1Dp1U1dXAKC`sVTT4Wq;fX`
zg{zPNIK6@W!eAWd4{ZYof<z(87<7vKK)K$5$#jY@0|UrfAzvm?)6;aZF9Sm$sQC9|
z0_WN&KPcay36yJ%KpKUdz+1d~!66FLYyi>$CK&YU{TLXQ`hg~Gm_SmXV4DO|$e_2$
zkAdMHNXCl^q#jA;qaOo<ygvhjkT;qPgSnd@C}%*DG-z22W)GtdY&vq128$SgR5RG@
z^hHn7&0zJm4}6i6G*}CR4T~QvNrQBQTnJHZqv{7s(x?(9pjAlVve`T+2;tJLSTo;A
zu+7LW1&bJfR5RG@4Mcb8Ik0-$XMxBr1#4lj;R%Ad6r>yEQiy6B{UDf2Q6)^4CP0e`
zoy~!u%y)_tUbE`y1wzY~Gn{V|z$wiDRA)eP%6?G))d-|X=pwkTJ_2?ZgU-A_kdJv8
zbwLd;^x9|_Sdm^1%w%mwn8_g33`oxT5e+q_IuWz*`vq=_>K%xNI#8Pt+B7o&sb(-y
zO@jK$d@0x%NJ_bjHT++L%|Z@;u!sRjHG|EMDD?3E09J3S9*rFSU@Z(b!O^hr2k8cd
zKSZ@nO*Ab0Q6&&A)ma5<xe6I`!ke{r4#80GnQ=nBrxzOxEdVV!VI8+e;2<?_4u+0@
zMu1z0U{Odj2-nyrv}rdll!2ipjDbO@2uUM>rrn<~28N^I3=Be@NO}k~?E)hh7&b&O
zFbGXU(t~K)8J~<`VE6`-Ux<)rFy@S8V3-jJ8e>6-8t8x;j0qqDRG2`jOFfk+=y2zD
zPEaKZ3Vd)NFc_yqF)&O44TSDRG6STB!3Y%SLI=R<7ou2iXB0Hh4?+W-8Jy@D7|a_&
zK`9cFl%8WvN*}>dft-}UA_gGU3^vC@(328q?2M7Y_GbukQUYsXu+a#GB_)t<kZ&NW
zZ9+m}NeNZLq#y;F=ykS+fU@#Uq^ukk0`=8x&UGn>tju5pQYv&08~|^?u4k~H0n!Z~
zl9&QY7MvVh3`GnKD?n^P4lb!828KN#wiE}Keh~x1c@SHfgUh9ef#C^=t;N9=QpCV;
zACx={Ik+;57#O~S*p?hz%|#3h+@L6S;^3N5#K52cVtYaKnuFMZ99(OQ7#O~RB0Pm7
z^mQa?EFqjDYy;?$j<DU4pkw`yfqH#m7b6)Mn8WUa6fkg|DPmyY0Yz{ghtA_dP%QB>
z>TXWOEH^-R88b5IZ7zg{hBhN~G}8d2n!zMC4H|^z^TEbIBAX91;E2&^3Ilg<ks}){
zVgORjU?WtB9@)`g^|qFU$dL`!!eA3y2#aixZct=HRNH`RAkZ!=p<AdD2$$-B$03B=
z`1I5>7#Qq9W3&-`u(ClIY^SkX1_MJXNG6UCWHwZ^D1(7v6-YD-Aqs8^G3f2gfCf+<
zpLqr(xwwOdbU~%70VvNg*xkrwVECHLz#!DZ2Mt3zhCJw$X**m<Hjjb9DvyCds1GJ&
z?3%~GPzMs4f@Ce&OymAM28Nv=sp$wQ2EB`U3=CgDqO<rw%8-1(n$N%>2%3LfgrweB
zCZB-;Jkz=YNmS1$pMfC;v?ymaAE<eaFvYGUpMe3iG)QP2OvV_rbO<~FyA@#s#NT=+
z@}U#3+xTFEYS8d}2r?Zs5Oowu6UZ(GJ;MS9hBT1WX_yuIP)(f$3=H=`GMA7vft#8P
zI@5ANN!bA@Da&MnrcJ=h*CfDEtEZj`jj3`*SWJPFvT<xCbY>Z{bq}K4xFeH+;Vj6I
zc7!32dE4Yn&^eYiISdSwvltkJx)AaV#+f+`4Cg_jlaWOA=H@Uk2xNl_bl9d%eOrj5
zF61yU_=03+qRTMmGB7lOWagmB80+LRFzf}%EJD~}um?0@t(TO`z`&Tpz#z1O5hTFK
z$OyFvkqek*iy0WyKx(>l1ahFk21+g91_)BH=|Nn04H0a4nUDkyQq5q@m4y;)5aq_k
zSt!8<7DW!Wj4YI31IsfQ&&@&!Hi)R+{Va@NGln=yE*m4*pfZu!7{LaSG49Mp2{y1D
z&|o_cTDb}e5=5{;G$96_bq?k-FbD{l^O>&8h4#a3`M@pyUAYVlKA>{Xjt|u0Hv%aX
zvIM8mK#*%8jX;nJ28Phi5>Pokn>FkZNGj}VF#`ir*oR_J3C#kM3R5UyU|<b1Dq&z?
z3-c*qU|<hRC}CjW2rDgNVBloX@va2L7%!tPs0RR!F{E{xeIPR#^rS1H30<2Jx>y&|
zwLrABbuz1<#;nW6Ec&-WjIpYM8v|Y0YXDNsU=oo7EBZkfS-^HZOa=u3M$x|<Y!-6S
z4;C>1sb;X5SBYNquK}yKJyMBW^n<l9*gUU<75yOHptKE9ZNpv#tLITA5H8i3UJ0t_
zdysZLG*m*Dd-kz{28=<*%>Y|&1X3$B0krx>e-T)OLFXhaymnY&hSzSeBE8v&@Pe*)
zHUOz+K-zoppbZr44oFKqkn)=q=*lVvy;m*JU@vF92U#`^scDSmTT${GM7gnND@uL?
ziz4T@-d2?S29{?q-r0(h-youTZ(1?(n?1x)a%~v-4JzZ;hLPVOGR75cDESR+2Q<H}
zZNn(0AexX?iQMXEU{Da+$7s5~pMgQVfq_BjEqF_f>5hKrIN3W!P<}H#4CB9N1of~@
z&x16A78reIWKx!3HUb$WbO2mb$~1t+<&B>8GcX7pLK3n2+|R%uH32kF2R+7+QBP|E
z149x>=n^An_6W4-_Y8PJS3XSQ3S2@FbfGB3qMP7D48ax|sDXryw@-jB8M=iorFVG(
zbh*%N#^;dLM36;6#;+$pmkZqi>4C&2Xw@HsG3!JI2E~b>WhWpReXvCgdg>Dy7@|R<
zU!ZPchRA?N${0ZBAzL#r2!h5z1=I6Ed+cl(7z9Dfwgt;TTrdl?v{|qf#09fJOS}a^
zOOypctCa=kfh52z(6Sjp&{AH(O&~Ea3sl)KAJ1oC*kZ=OAS}-Y+8oKwBnav`2+jbF
z?t+O&`3wwEplUwa<t<1nNYDjD2!d8f3NjWjFvM_yCde!q7^1*>LE<iw1q=+XAeJC#
z@tPoL$s>d?0!e_Z7PJAez!GjC7HH9-AeaDg1wpfz5Ep~RKy3!WJdipt3$%Vj5H#Ne
zAwZRzU=K(Z#A2RPz`zjV#K0gT&*tvLz`)KT2x`j+t}S3-hy^Jy0BJYa3rZO-hd{b?
zL46lcN)bE@Vu86J3Bd;i3=DA)<sc&<dIUkUbb`M@8o?|u0h+%P<S%4ka0RnK(|UrS
zNgYAZG!7&dL1XcPMj$0%7HFVa(6JEaCLhp<gG(StdQ%hwgDW^JL0m!5Sf^kXNCM0P
z`2ZpY8ix@CRVsoVAXzXAG-xI`9mEB*K%=FC%RpQ(3p9u-2r^y}G%_Lx8l4aX4SGPh
zpg{`3%OJ&I7TEcqu?9gf0qTGWf(g*1iQsRLIxvg12<8WHxFQ9VJV*xQEJzT7LtM}V
zBnV2b$bz0AK~Ts+gE$hz2l*5{GYA#TLls1_r~@Pewg^-&K$Xu034$#`65Iq51f^#K
zP%pv&Y=#A>uMJ``2!d8@#3H1@8j++yJp{q8MGOqCU>0cH0up|l#S9Ft;E)7$vIM~d
zsKqL%R18W%pjH^TL|_mEF$FC^%E2rr5DTnwRu%(;AZXG?5X=I#a|IJXvS1dd7b2Js
zYIK0EtONy@sJtL(y@g;4NDY_;@{u5@`5*|Y?gi(9B)}{%0cr>cZUl*eS)lfTAgIz~
zi>zi~VBuiCRLsCIvzmcHOpdL)8g!W^cu(`kY6b>zIl-48ec+M>O#A?G!O0Iyu$M3}
zxPrDT3W5nx6)GqV5(BY()U2WVIpe|mIeljYGce4pXMpT204+-ZZ`}l~24VDDG@pS%
z=m;o}Gl11yAgs<O&jo6J3fTO3wgv_U*9Ha#i3`_38z3ReA3)=kCZNz|ZeU>WTRtBo
z4dOC5r-77;uoQsm83_&WS_zP1@J6c+kemhsi*geK1Ea)T-D4$?riAsx21t!BF%Mz~
zqs?xZ$b6^>(#l_(7cj{MFiFJ1UmMXzs96hPk{du*dD=L^#23TF!K;03I$`2VVB)*L
z>c7Fnm&3$QmBLmH!M(-6;Ig%pfx#8DA75~PDFXvDsC>QJ$iN`!C3qer14?9`Y^9)G
z(}){M{Xplf>K_9YN(?@rVLEV}Wr73Te}y*#12<?tK3FghbgLCZLXH^&gE=VJz=EJ1
z>x>M7phE)^K{EbL3=H5aw~%BLWaJna(&1Xbn|&D)L4t)%3=BDN3m_7{`ML}Y)lJZ-
z&jY&zEY^W0R%pz?Fcl_N3|5!0S(1TaC)}nVAQyWhUFzk11#}M<D<k;$-$an&n@tQ1
z@8B-LufaD`mx19Y%to-w{6GeBr-9A$jW%Xr;B1CE9PFR~4ma@09=;yB3=D=aDX>lk
zu$Ud1n3pjFgEveJYy^YPGbyN%;4{V<k~rlU7<}TS7#R3Kd&7Blf?6vK$@$F;3~iwM
z*zSR^>SJV-N4nTg9_flhd8A7h<&iG?lSjH3P#%1{<6E#v@<<l|%7ao1^qNC?q>BLM
zkuCw0N4fw|J|A@X9~;vp&~=mGJKi7{0m`odT?(Ycv<D;()~f}+08k!uzy$RENBP4b
zHC9M!AeRKngHD}bgxm=!F9uQrxernv=_*Khq)P<lk?u%j5WHEzz`*>Zf`Q>MD6EQ8
zwlp&^2uLvIvx2gOEU05r0P4xHg08lk4B{3tD>oQ0vVuGg+MmN%#H`$5z{rrYs2OzY
zC}SGyTu{J+RHlP9f=;~vU0=zV!K~cC0Xg;p%+F+2ZV-T+djaNWF)KGnFoKWN0Q0k%
zl^YZo!DniK`8mwW4H}FLpkomjQbDIq{AXqm1i3uzN;3n4a0>$i<55ONMsIKsA7umu
zu{YSOM;SqvU&?O)1^o%e$cYRL^1DIo^NcAV_7M>K8iWl_BFDjZKQbh1wlFZ*f{dNW
z2)eA1k<nWfq;w)9Xg`zu7tm#)QyJHQVhkLUlfkOe)8!w7WM+VG^@OCknP3Cc)8$P;
z`saYJl9aavvFC!XiA;wiorR2`=uc0FB*<mpTR<TRX(?D4_^v9@sVtz4t4mrK7-SYQ
z&#Pi!m;qwWWL{atz|hmez#whNyrqhPp}d8GLCTeRe-#5mEQsj>ZY_GXFfec$CGTiq
zU^oTxS_9Z=jEvr3M>jBffV>0tS~J9J;1Fp7tAd>UakYhkLDpS|t(}2^Lo$KY^l=LV
z1E?=3Ihz$U;*jyZje)_lhJitH4ycm~a<dUgtz;7Td`v%Zm(36?0@`oR$fyq%G63yc
zWiS$IXJC-bM^b4l-_F1g0}?Gkh(Z+WWwb-q0!db~f|`4vPI3g;c)iYcNY`Dm9=?bi
zDzmg5GIuQ5$_i?9!S#T<v5>(KQ2orH_Zp^fBAP-_%>bQ<mg`_(NbO)?kX!;)!>kXs
z2Hh|QK~Mk*y3{Z*xPn-&pw^ZkPc;LB3#i2^7z>gBaTAiN85puVU?*#UZl7jkNCXKs
zbTBZqf;<PVMj#TIQ#%+KE`#iM2JN<jcTc@RQ6lNW(hj=E)@QOew6v@M*9iX7xeN^F
z;U+bKY6J$KgD^#qI?cbzn}OjAToFVti$!i{*cZ^{=3&g8pb>noPSE&}XeVfVNUoEC
zfhA0<6Er?#)(ILPvgrhk54m)L#)pDCLE}SNEOLEe$(;-g^<jCPpp9xJU}LJm#&m#<
znFKaw4%nDgU}JWJjX4cA<~qojum_zC3|wI^I~f?b!+v%$Fz|$Nb}=yUhKYAEFz|(`
zcQG*VhZ%M;FbIS>b}=vrhIw@{FbIW(bTKdphsAd>Fo=X@b}=xBhLv_PFo=aUb}=xB
zhfU~WV2}u#)y2Rd8Md^Gfk7&4eHR0Rbl9#g1_qh1BV7y(vSH`C7#QTkZgnv*D1<%h
zVqj1V``E?6pcMAIi-AEojJ2DAK_!f@n}I<!Oro2CK`l(Xn}I<+%(9z-K_kqqn}I<y
zEU24-K`Sh^n}I<mthk$jK{u?an}I<utiPLqK|gF}Hv@w~*rIL*2E(vT-3$yyVY|B-
z7>vV?bTcrRgq`hXU@#54)y=?Q7WSl@fx$fNbvFZpMc9{a1_sNpf87iWR$&}H3=Gy`
zqCE@@Heqr-3=Fnmx;+dGc3~Dh3=H;RPCX0^2N=S<dl(oFGK7WpFfbfqV8~*T+Ypuv
zx?eu5v<DQabv>X+Z3kWH95%TJ6shxiK#{tl2NbCrdO(r7uLl&V$9fnTIKwXXfMVlL
z4=6UC^?+jIZ4W3mzV(1&<8KcrHduN=vBB31iVd+|1_mL9>^Z#*3@mIsVVb=lOC5Sa
zmWKC&Qc@mBCak5Gfq|7F`xl7ACK9$5tn4UQ*&~oLh8!08<;-EceIV`HeGCjt3|TA+
z$ziU2poA6Q$H36Q6;{{Bz|hDNHWNgNh3x<d@`RlSQA}YkKvYx10fw-DeGCl$#lvL#
z85kOv!c0I^Q$qt|m@kC2fH5o$!g|0ERtsSrU<{iEVLf1E5WEcPN^|8gFbLiZVPJ64
z2DQpTT$cQap!1MabV1k9gX=<2eFJKBGOB^OnG+cpz+81EWkyB@v!rPZ3<+{8SWQ7^
z1A|&Iaw|b)Dx+!hL<WXi4GaumJ_n=el!*)sPhorkM$>&085m?5L3atWf{vCl<(kI8
z@UN4BL2flG=xixd^=S+YYF!Kra%)&YhfA5dO=Dni2JzRjGAUayGBE$IVPNQ($iN_X
zfcZlM1H&fJI1V?<vWW}~0*bt>3nwx#h&M7YD1ye68Np2fFqa>6=oNz?$R&b`jSLLT
zI*kkr4AU4G<c{Qio65kT!7O)*9pRZXprvDsriUjoFsx{1V30cpS~|vP`fDNs185*a
z?gD7(7^5lYB&g>uvV)GzG8KdIFR_C?qcjPs{t7$D@uoVH7#Ki@TFG5yXHs@xG&Pz8
z83G6MJs3@GVfsPx0gR^J$ovFG)5u8-3@<?L0m&CInl6Ny58_uanyyCX*D#uHK<H;y
zZeV0I-8_kb!Ipu6LGCI$v+@K+M$<i$7#LQzKm{%^GMc(iW?(35g$it7Vl)k(%)p@A
z1{K)B#Aup68R}_}87G(+P0Nu5ZZI*Lwjv9>U}7|#ge>rbiP3byWCjLHn4ulajHXv6
zGcX)%g4%L}nbE9q3IhX&+*NkdN0S*Crb3j0QX+$C&lCoR>+Mjb511KECr)8tcnK4D
z!OUnne+mP`CrB_cD}P{SG~GCbf#EAm#Re8eQ}L<rfM-@-!OCc=I2Fmz4Xli&`coMg
z%t7fA<jWnbjHWxLGBAJ>I!NFEE2HT?WPuZ`jHbt?A_eXRRz}nFQyCauz|5Gy#%TI_
zDpJtRU}I!p-rUT<@DY@nkD9%h2=eh3M$<DB85r(@oWBh;P|Ij~7nG$yx5@8dWKw2f
zWMFovWnj1n(lk-<Z8HOdAjq%Gf14Q?W=vvWU~y;ZpTxl6z~af8G>L(su7!bt#S0X2
ztgzI@;tk3Stgytz;sZ*%tohKi!{Q4{x~%0et{;=K4kK$FG^MimgK{NnBa9osq-?^-
z+JVFc<<ZU-28L9STU-SDT0mnh^II4g3_$Hb15oy15Cr8uL6D1?x3n-Y*i2?%kh^GR
zI2lx?Y-2G!I*EZH4wMGBvw$3q$d({J2T~aV;tN2^90pJl0r4e}vL%SGzzEKEptg`4
zh;P7XdUp~ujf40WjHY~(85p=h`ggE^v!yaDxq|o}jHa5Cp{WJLk6>ir%4%g`U;;V1
zhfy%U734usmSGUAZe?I#Zfj*=_%?}wLGGB@D^Ntp{a{4+=qDsf;iV>skL)85AK6DB
zKC+KMd}JSi_{cs2@j)?grH+B&9LN#dxy0KT7{o!2oxmt4(*|;^MjLDhLJ*Yq*+Hcu
z2dJCEz`$~9G6O>ZOE@^~<hL;}utb2OfOYp|NS0!W1gD*2&=6sXVp8^CWMHmpV_;Y}
znSp^NSg;;!1vtVdfb4-pI4H9V&T3;|Fe{tFz|bIf8Yz~~pv5wXj~pf-K603V_{d=b
z;v<I%h>sj5Aif2o>Fdc149cKF;4C<n^AzOHvY38@l`bGb21e8W$b1e)Q_d;S(g!3j
zz-THm1)3B<d<jMdQ@JS&469(KCNP@X!Ad8Pf(%B}G-Q4OqiHTOzk-p0Yg;=5gV7WQ
z2Dv^)!QJhk=sDgFkDfE_3=GVmU{eRFILrK~oq-{C3Il_ZJe%7T1_pKx@FGrd+%YmR
zGjuR8a8Cu5jAs9*Ffdfe-D5+fy!&jRh(zQi5Fa^|L44#;2Jw+Y8N^2pWe^`ZltFw8
zM$`RM7#IXVW!?iea9+9w3$TZ5prithg_Ru)404ayn3Mw;^AzMBv4La32&4%l2#p0e
z9~ujAK5{I8)PrK-?i6T63lb<`G<}22FJWZhlIdh%I0*{F)r^9QouE+G?SzLisA>=d
z1s=0gCj-NpsSFG(jm*BC3=E5=GB7C1F-LSVF!WDlU|=c}jO}D#NU5C)y4H~?opmw;
z14AnV0|QeAC~R3Rr!p{10d)~F!I@+c0|Uct5H|~S#3qB_Oi+&@VJZWI1d}DJ=TruU
z^B_qpu-0H`Wx`|))*1;j$p)hJ3fRe@>W2X_sPJB%f%$VM1H&VbgImD;>uXaP7*ra$
zxVjh^WI&CZ>5PK>T_E3zb%AEDq`Mdxm=i#AfFQ~HTt;0C45lFF3`Rk7xH@p(l7S_1
z8Uup{ODwDZGzNx_E(QjcIIv4YrZF(g1aafRE(NvcK$)E-0pwCvSc`)t5mc!#2=;<a
zodUKU)Ql6H2N!@?lOi^qfx&}=&5<={8Uq7p^n}eBY)|1d1_n^)k<A4%7*hq~yD}?x
za4@pA!}xB@$`d#kS?9p`?##+FI2c($LsOtapUs0=c>xC_>&9u2oXh6Pth|JSk#!f0
z@5QXVf`gIuFpTfbth|PUk@eg($hH7BA7<qZ9E_}2VSHa^<&7MStT$nNKW61k9E_~@
zV0?dO<;@(7tdC**0A}Sa9E_~5rZF&p&KqP4WLDn6!N~e?8UsU7Jp%(<5VP_g4o22r
z(-;^wGBPl*1v4uj;9z9snhp()5N72Q9E=R$PPkbvD6~|$8BG<YGcW}8Ffgd{Kx!02
z7@rq3o6Bfw3FGsDW^)-$9btTa&}=TFspoVChB%OZ0Y-2;Ja{?-Lm7xK$Ovw#roi|@
zjG%nXzy)fzYD{NfP-SOi&jR(TKoy2C0~cuO!w)3R!3b6p17dSBvTT^nz)-=K%vw5~
zfdQ26*iymK3TmJm_A)TAr7<ZdKpN;^ZaR~41|w_bbOr`9kZcB%asi_S$P6~{;lq1D
zy($I^(5MqzA!sNBB4B%RI^=>}wo)X)$I}@YSZ6RWu+_o^4M3JK*np0q1>NP$)&iPO
zg3B^62sZUFFbG=rGBBhpozB2u!NL{}Z}YH4f?Zxeoq+)~oW>RfPWWBZ85lrQ$!yW!
zgg+g|jR7Tm)_Kz*LrrY4pwMN7C+0YC;|iWO<H4;dcvL5VT2m0Wq-f1xU=Uzo>q0oA
z2kZ>EQN3Vi!1eZloWYP{JA;8if`x4k!peDIZKg9A7(fTRvdu@;wgBW@h7@;*w#5kB
zmV&jxZCeJ`26y;!kZp)Gx`Ihrgpna7Z3Y8_0t?$}gehxLO<9L(%6e2&Hh@fF4FVZr
z&cML7ky&{P2P113jK7Ilc`64ZE9eALQ0%d7W>%iY!N?j1li$LuJe`A)H3`Pw3N8p3
zQt}~w+lg@1Zd6z8L3Pz$R9Ec-xr)KD3N$9gvUVl|gM*qGYwHY1Z$Ql)Y*haY28I{?
z3=AMH2P3QTOa=zKi4d*;Bda?SSAvn%e<lM1sC%tu0ZtonNL(dG*7TVS44~dPNLGW9
zb<s=)h9e-OEWk-+#Y_f<dr+<gBZJ`Eeg=kErU?uT;F(MV2@p$fB5355cLD>$(isd4
z>O$Z-!+A3p7+9;Al_xMTsLo_yP#0y^o4~*zIg^1wLor`KLx6Sd3<d_}i3|)Hf?yx*
zgmHyH9e&pRFs?9@G7}@~Q5aW*Ntv0E^)!qt3hJP+UW9SQn3P!=S+B#m;!MhHjI4KI
zTnQ#+c1G66Fs>vx7GA=*QcTL6jI8frTxlj{E=JaGFs=-fGB+dZUl>=GNtuU{m1QQ>
z3vx`#yo{{eFs?k4G9M$W5R9w9q|DFAzziz5HiJT?SkQPP0|PUtcGUp|jfkN0L<WXf
zzlqRLWncyk#5;ndgux@zRx=qGSS!KnG{Qm5Qo$0ChCY}EgP9=K77(!?92bn$3=Fw5
z85lHmnU_ptU}&Amz@W8NaOFe>2G?~H85kVPW->4^GK0p-r_N+xkXa-Miaf!SI1FVF
ze2gN)U{*Vqf#HSrGG<d)veaJA42nflSh@uBIT%f02@}j0U^IoLOfX-9(e(IC28OGX
z85p#;GK12lDd#K(2G%JI4BGpcK?Rqo@+<}hQ4s$OGblNlTFzo%&<F9aGJ|UkpIMOP
zsr`r<RBM<<!T4{O!L7f{Squ#JAobswL9IX23K*Y>g-JPr(X<Q3=Vbv^52kZwF)&1e
z)Jw2{>Ic&`FupPisDd!v3*+mtFez6snqHa3z)%cQZ^;4~@c1^1fnf$nz=efbxr33>
zRB$%b1%51$5fBBKKqL#Z@(e~sQ>)ofEom&w$_p47O+98aFl+*uQN+Tmyn>O@RA3I&
zj9M0E<qeFCriybI7%HYRFlcwPFe~q1WHdFJ!@$rB5}3iltbBlx(KLGwG+<V;Fe{&6
zWHc?G!@%$hq+$mPvodJl<>DL$hH29n7_?8ZFe~3+WHkLchk@ZbNZ=X^v+@H*Mh3xK
zlNlId5vlAIsQD@Qeli0C^RLMa4BuulFzAR1f_gBHPe2JukZTHP5y)g%G8U8q@e%s9
zrhwXnplKOF6Oasu1ujMy1YJOUgvt=GN>J$_7>6p82bKYqW`Y%{G96%<-YE<W%pmEf
zvltk3?+VUERkRkY2$a19x1-8{EHgL*mcBRzbllYx28Iu_85ndknFJq!1l~<yV7Lqt
z$Y3%9(OkN5Or~kGAtiurJZKjgqiG(DpTGnv#!TyGLyBJAL?%!<X4(ytPhtX<T&A;N
z{A4Cj(Pg?0#!q1am0hNLVf<7kP~l~I3dT<Z?NVc85CnA%kfI3W3kJbSQ&Hk=`BVl5
zgYBR`gdnJ|0q)ef%wb?)T_?C_Dgy)8iKz?>aUi}tBlG2{3=DxF_H-5y#lbq6)q4&D
z11Q8;r+~6Js~?Oz732d3!T+e1@lOLqvdA<B1}=qZ3=9Y7Ffi!OXU>z*oz869ItLnB
zGa#kKWEg)YGdQ&7%z=j1EM{<MEr#)DGlT3hT?OOMVFriJra6#GQFksgs4O?#0d<=0
zJZ4ap${;v<8cINb+-9(K8Z3Qs9h}C%@MI1HgS-T*;IU~83~}JpXaG-#41#x14FI*F
z4M6jN41(W4K4hBCzz{l@fkD@gC67bblf{&GF4PBJkTC{X7~h)(>>~ph--iY4BWD=j
zmj&b_20`EH3=H6cIe#t#gUkZwe$Z7bmIZp&Zw(n33iNDlf$ot2FZXe&n9ji93SRDG
z(7*thM{@y9p$V=6&FvflO$98R&cJYcE(3#s95blfcxo;K17|t&c90$O7#Os63xa9`
zt`pN47^3GfFc?-b3Z4ZS8r09gAb1_53N*`I1DcJ^6?{IOfkE)ibOr{lcM};HX3t|_
z(7wR}xeEbwg8}$n0PxBG;F}@@e}bkoq-QWN2rA5AU|@~_HCE;`FsNB_fev_2p3lHw
zSivZ0(8s_aSOy|^Kz4#o{RdxXAPBl!0DNl!_?iOnLL%_eKky1a@P!QE3m?F%pBNYg
z8CCg&S(*6+*rfR$*7FE5GB7ZiFfj9Z3fuEoaa(gUaWOD3i!pc#GxLGC3=Ay7jLdx8
z+z<{cFIXvvW5H#_&A`B>!obXD$IZ>nz`)MP=qb#=z@f<CDXh=Uz`zNT;^wyFW?<lg
z8_3GQz^%vF?!X5z9%QQ#w;-bsqXX!oZ&n7FFcau*2#~u#R(T48T*ZgrGBEJVG8zhl
z^hIz-ax*XpAau&`GB618Gk}~TB+P(tx-gQp_B;qnMUYHlWnd6xWiS*r;Q`q%Cd&Y~
zgO!0n9LWG=cPnr+Fi0TW2C`og!37y4#mxwEDg%QwRGby!BN>E=tjJE1h581hjE#Xo
z4oMdq1A{z*%fO&u!eA&2vO^K%jZn4-?nqV!1|^UuKw+i~mgZt$PysPy_!$^f!BT7t
z3~C@tJfU7yhwJ7}5oTb}KyVotG(jAY`$1-dWVJv#A@Kq-QQMM{nU8@%hY6NWSQ!{}
zWf(k#At^);$&;SKHasAYGBD_~GJx!6U@!nN7#Ixo7{O7`3Q>^E!@yvKD#XBGjARl-
z83TifJ~*i|FqpzqCM(2VGkCgXWneIeJC2)y!2)V9H_Q-AgkF0d8y+KW8FmH+E4Uyx
zM38~OT8{xK<-&B^Ae_aG@SrV{C`_dtLO&})r9Be^GoK9)1A_yqyFg*!2ui^qIVVeK
z)?i?828A~$_!$^n1i<OsRSitJf%Mz(m_UQrU5$Z(!2^^V85lhE7~O?I3DpY}caV_x
z1~IL;tyw`?#RsH-fx#C<wL9=JF!(`bxk0l2AmJ3S0RgNGAiF`LflQ3D!q5!H%D@l=
z2{2IToA59&1cO`yGTw*VmkSaCvce1uA&78cMU@F<K}tYj8Vt;QpsW;*q~22)RYwHG
zMvx_tC<1ASL>FXWh!O>dPc%OR149g`XaJ?xSW$3s6(`Ebzz~nHgd38z85j~ker|W*
z1BF^5lnn`jBs~UqVFrd|geF!`VIyvk!W3|#V+Dl}14Ak(?Dbh07}AhbLe!;mGcqt_
zpu1Ftje#K(Ni8U=fK1I|VT2XH+3-N(W?;yHinB5><iagxWnjn?hNx#{V919uxfvJ=
ztiUlRA<V$QU;`Q%1+A)K;9&Uw|NsAnX^dbV=wvG}14_6GK^bV2AO~o!JRWop7vpa}
zUeHm$AOjc~7#Q{R^oxs<8T3nwi}W+|l5<K^QuT`~i}m9RN-~O46H^%ULyJ?3iuKD=
zlhRXDv-S1z@>5cE(<=+~4fG5R^o-5)Q&J0x^-Ig(x=YJ+3yLz!5=&B1Ohw`7Cu?i#
zo9G$o8R8JuPpv3HmC7`>FhdmqJF}#+Ahj4(9B#ILQf5gpksc_sfO!Dbuy}|CdV2aG
zkH_ccr<CTT7VGCF=Ao)9t}JHI53VdONzK*w$xJFrEUMIZD@x2wEzd8?F4p(-_s%TQ
zOM?mMd!#0&q!yt$JU1~pLm%Q#5(6Ed)z0}vsc!kDc`1n{nfZCdxB;JOI6R_XTAYL$
zAc$B<NlhwEXJ9B!Ey_&HDabD>i7(B|tk6p?C}03(<^o7Ug9Nl*1_KiV11#~y=a!bF
zR>YS;L`%zb!5T9dm>C#+6O%(gQLmT5z=CYHUIxg}<l>T)oXjK!Q0_`Ck5A0W$xlu!
z$uH8&U|?flfLq1Rzz|=YS(OU5frEhoSsf<>LsDXKW^#OSNl|8Ax?TnYCj&!bNq%l-
za(sDyQ3^yLIU}(szN9EIv!oazfTE`)IT@r2VnSLuR8Mh9PJB*gG00b(3=Cx!dKnB{
z3=Hw5nRz9KW?-jqL%GIAC|nCTFEg*i%mmEiU|@*P%qxMa<X~XPOU#SUOD)&SVBi6B
zAPl&dc^MeuLFp_W91$Qla4;}<`oqGKkAWdOwJ0yXD7B=tC{HhgfuDh)v`jC9K>(!6
zJF~<mGf6LlfscW~*)13rFoFyWdFd6pg{7&bse0hp0ec4OLXc<RaSVw`umivuOD}^#
zh=HLbwJ0|;9~6STAZwi60&+^zJweukErRfz{eAT^7z9B!hlYB(K-ixCK`@tsmAYgm
zgHm~7Q6)@1G}sB^W?_)dpwc{_{QLrlWN5IHUIv3O0|PjP>SZv9fI}=kGq)foH8(Y{
z1e{~y3yM<X4UOV6^KzhJS&W=!oZXxfi$UHN1QoiROdt}3nKc=?I3iE62r;i_Ji(&R
zoNvRz$o#yHLx@F)c@-naE|}1ZIu0R@(;QV?9QrIm%rh7xn9s{Mu`n{vjE`t$5n`SW
z7nlVRm<AV^9UsA=xQ@%4S%s;enUPu8i_4p1vk@1^Q`<7;o%JQm7Z{i>F*7n}lrT$j
zq-}0t7Ur;FRy>i;p~%d+hMD(?x814vw^}$NedlwmpTB`wkVA;MyZ##UI|e2tM&?Qm
zp<HGmul;|SdD9lQwM24=ovcXbh}_L&AkG{&fw}k-$8KhQ4lfQnF7HU6(hbb~94DBI
zPH;Fd^UpiUTv);^$fVE6<(*eCDV({FiAjf%i%C^%((ZER@3l4@kx?A6%=Z~MPE;)5
zXk$tc;h4rD)^ej|ZN+sCnf+yL9AeqbKk9bv<}l>&e#xXF!hD6nhIvi>wP&w5#9Np-
zIp#5^H8IOGIWjUoW>~`!$sBCMtXskn#}T)YIl_xs^IGdo=H2x+%tskYIO1MyWOnpo
zKEQCTwROWfrs+(g9F<IS7{yL8Kd$4r#-X^5<HcuY3omA`5{@aKnT@=d1LiSTUaMxF
z!WeOyc}@Kj=Iab49LCH)>YA9l8962}i>_go<e0$1!+fWPLxF{nc><_+&#{h$hxuI%
zQywD=ACnFr3lH-GR!{`~s=da-$Na3O1TOLyEb<shq@j*OfrXFx0g_O29Y+%jAM;%#
zp*D!BTW}!`=AD%sY0Lr<EP~AQIlNdHnU~aXC~$}~Cq*!;a5QmbaCt{PE#vZz=E%sH
zm<fh$rMeu-(H!1oT;5Uhnb;W^K@9*<ItArFFwMvi3Tr;3fCWH16G7+iK{*f#blCui
z<qjekKuSWPEI5@7WmQ0FMg|NetD#cIpfoc>=wz1DP|js24Hmos<vf7WV8N$Q&RZxA
z7W@R|{DRV8!T(SWJJh>iK`AIl5lVvvp$g#?%!&J;B8&_nFec1Rj0~V7z@hRG3Z`o}
zgv-Fl5C~)PL2YAXh=WSPDVVMuP!UFkAQ%(oD@F#4s5lH&eE~{ian4<+)GH{B#gy+*
zDHhz$gN2hSR0%k|456I$&=L<U2sH~%?SM+|htgOT-GWL=FhlfVNiW<`DVP#whS<q0
z5Y-6s2~^}clxAiKz*NM?3elhirNN3|oFj0-vM+U4p&U*&hz@3kvM+VoP>vIn1`E1D
zIWwU&SP;hHV~1%Ep3DN{=)eWbzSKeF5u`EHVuWjAC$nI>CU!ClrfXs+v%p-l8SWY^
zVU+@PKsS`e66S?ashd!mks<g2l=%coV@YxR91xF4Luo7qM?s|up)?~yD2%xUE`*V@
zU{ZXX5DT!_{T8a*o(rOci9vt?#ufwhCc)h(0Y(@*2V7-?x<&#J4M-#wvshtfh4DfZ
zg3O1p<Dg>T^z?@hq5x(QNFj`kWGOVBA!<P+57ckwP#T=f1EHLDC=C{baonI@Wnn0r
zu)iM0ljH`O#=rnpY60aSTo^l<1?ECIXt01)LNp;rSWt^YZDwQ$J^*FPLG5K^2!=6X
zma;IEb?mQ4w-q7^vz8xfEkqQ?g9Q<m60#g>?`9~CCH5CVrC>^!8Db_w%P54G2Fm?5
z(C|uu(u@oN2uDF!FsU4<5^zd_NFm7UP|2rInwcRE)055^F&=|i5H5u(S_!2=)?ow}
zI}gNaZYYga5f?PI%R^~qhG0zV)S!|!P@0h;2*%t47s99*J)ly-P#R=EOEZ+y4yD0@
zJD?nxVPHXs;}N6<G}%pp(pXYaEL18LS|qSAl-<}@591X>MHv}_VN6$OAp%i|unWQ(
z8pbt2y~V;%c41#Vj5h@;%E%B5V<LI>!oGTl7ZD`PvoHe&r*Vs+-eO@WJF%}G#@hoG
zWn>73F_Aob0=H*j1`JN)PD8!L!ccZ#Up<U>7b?og5Da4?dG-Kq&%z8CoW{L@dW(gj
zY{$NO81Elcl#wAA#zgY$4&0uF88Env+XgM5V18g^h(Y8)2y0XcxMPYDE+5c>j)kFY
z!G4TVj5t+)FwL5PX%=y+IG`yM7Nsl<Weu2S5vNK7)2t7eNt`@Yj0~}m1co4C2JM7e
zi$#epw1PB&(pV~8d#Dsr0CZpm0C}pgSO;r@mqV?^(nslrN=<{(Sd?f(M@!70G!`X}
z1qC^&3O+tzz6xcjMa7x<c?xEF1_~O<If;4cx@HCjdIox?CYlNwNr}a&DGK>{5Vgj7
zrp0A>nhcP+8GUR6=V-Gs0Y&*)smUe9;7JNyga-Yj(#)I`2GD3TWGtN_KE60JogpVb
zFI^!suY@5!KEEKbur!qcG?2{z7J&$$55Y6U$EPF~m1pK*NWjK+p=0$7rDYJS;!7BE
z@{_YY^D;{^6LT_)Q&Sj9^NKUm^HNh3z_vN%=jWs*<}t)a85sm578R!k<Rq4)<rn4p
z7l6iai-WxVjLIxbee#nNb3FZm<IVh&K%R7Ub!EV&oWZ{!HP0!rBtH+$9ESKPLo>&;
zlGGxQir~`Z<kaHg%m70}zr;M}#GIU@#N_N?gZN;Bcm{M;Agv}L`A&(YDbD$M#U+V(
zC7BGUe2@~0kbIZKl0>J>l44|K=wb}<Q5LSA{_!AZ1Xz}qf#wmi<BJ(!Vhr(7mLPU`
zQD#Xhx&p8uOoek!eldm$uprD1pUmPCbR$4wFcaKzN{chl6@Ud9;-kz#t_V)WFd#U!
z1g77mC^0h+T|Zcmp|~W4A>J1}ip~%ppPpA5pIlMFkcT`E!%&CHjgRv4wuGxSG)9s2
z3@|hSIXx(~xHPB4vm`aw)jTmJr6{$y*fl8FD4qezVMxx;^-Ii6WymYYFJ{1RWHOQw
z$qWVgnRz9tMGQr$X{kl2dC93H==M%#NCqX1c$gs&9*R-8y_W210iAS8b<GX%E`v=$
zr9!eOJi~x<CM*X+rXLtksLBGcqw(2fXpoW$w=5tzmjS^g=wFN6#0v0KnQIvXj0w_&
z&pu0VNEDSOm$(Kb2f@M##3!WFJSDZbq$t1AH6WP*%4CQSDL_p_HlRYp4i;efMGSRN
z&*c{}#5;m!{19?bwei03DTyVC1v#a~pcGmFRTrO;nUY!ra+G&)u{l(cYZ*uhNI6IX
zNjxAKB;XxfY!>euUzAz^QCO5(08*cmnwMUZ0b(U579=KTmQ;e+MX71Y`K6%Z))6s*
z$PgctS`ZH^`5EGa;}L-x91orj%S+4wiKpfklvIMOi7zh6FG@@Y$8vD72}rY{QG9Sb
zTmi@(NL;8RVG4cYGmGPMQWLXNQ$PxlxC}}8`8n8B7iT0EA*qINK?-5k8^`;`7pIn>
z7>nQ|t2BkG1euYTl#>c^0!S@P1WC0KC}2Tykid*j%u9)fDRa#Qg(nV4Br^;Rz>$*%
zia&^DMX6v8k{VD<rxztAxdwR$CweBkf{K!O-*}J^k}Avi;P~XC)Wnih*W6sFN>Ic=
z#E=w%txU-*F32xVg&7HQEK~?XB{Ye{jr5I&C-o>lSP(<Kk(^&p3HJtwgJhaTyl;GR
zPJSNTQg9G~MZif6q|`gO*b-DEC#9xm=0Oa~1hX09<MZ;1auajnGfPs7KvU%4tfHW$
zqflIuVr7Lqoeh?;Q?O%zDTSI03dhXUJXpF)%}W7EKynNy#X;-?u|VS9!Np(~XQU=)
zgNnRlP#7hHcu-kGP+|cK#6uE*Yi@3UH$oXy6sj6zR!(MaW{GPq*xz6_RL;;4l$SG$
zvr6+oWe~)S6eu602I59gc)A882Y4rgO#pEblDYY1sYsF_E<_R(o{7bv_Ka&laxU0;
z5H3X8&={0%@(U{CLB&+DYe2FeQdwz^5$vA9@xjHekTe(^4{`%UBblZJcqfC6Gl|C*
z!=U;K+y=uR&*1VKo-lB^Bse}e9+w=*8HO-f18|7s79<vdvJyBC<%4+;-Jk%?EiHj$
zG;mBnco11bqj+C%K@*>mSOiUKpd<z6!j&MEf39UH>o*wckdrb*Lt-!}pB6LZ7eJD}
zEnFC!-axr9G1wJc+y@t%g7XW=R8SrQsq{t?j0Y(;hGYV02Jj9ph6;cs&5B?KKo|@~
zsh~bVDm;8`;O!qPD~#j;&U<)cOTiAqM5rT?Y$nZ0;*yDi9kc<2?jex%!Nn#;kWc|p
zAQ5kb5U7b3Tx<er$GDb(n=?=aX3&gZ#sFbJg^?Q}&@fE}YtBt(C<3!U3WJNyARJI#
z5#<LeZ(wz?YZ(KK2~lZYlv<oxRF>+R3o-!2f{2?Y=cFbUfs})2kQgYk!Bwqm83UMx
z3T9Tg=E4(DbSy|TxEL%5@tsj(iEA!HBB<T$7hDYCf!$u<gPQoXp{cLH#}%IX3VdLx
z&n&T^02Gcv-oeET5H`drWC>6S2ug=AF-VDqCW5LBRB(Y5SQeBPXT*bgLaxaSa5hXW
zq?m))4Q69XAnXP!0Qn&oRTbP<W{`5y6=t_tW?pe>QHd*o0x|$xqU9ztK$Jrbhj3g$
zH8Z%)A6yJG4lD$B7EB#dm>>zE8Ag`NVC6(=QDQN;fCDoiCYyrU#QBhP9pHuwC>G6&
zQVVhtlR>tFBMZufn206`3mGI~MA)DTV(5p34_p~hQ5S3!4|Wwe`ID>_i{ps36`t})
zwv=p-1{=l)!zw<KZ3Weupo$wMN{RJsuu(i_dLUM_U$8;EC&+qGQ^XWjahrhK(%_U8
zpIBPqnwtv>7jWkXl-fXIkR$?bx<M0Nd~sqLC?P`P4WSq$3{?&4zJS{ppgy5%ZZf<n
z3~B)76_<d7K}tbY2B<{@YG~y$fLI_=P|Z=ESl}8IT+C2ho>%}91C`R?6`P=<8?<s0
zDrf@j2Y@K3kfCvUY6)UxsB0Mm3LnvT1TUS0YBEX7%u4~6ZMh5}CW<g9af8b|kb6P0
zV1+13KrKvgm1J53RshigW<%9MB|xDDGYd%wRT11YLt~I>@oAYw#U=6iY2b<l;y}0<
zR42MhWP7m5;n0S#*$8ZNP9lcIP$8HBsOnIx#gxLX31O)@*iwjh^YXEK86pld35yOC
zH{g)RqaEQIGq7vG{)JeI9R5hcFvBp_qc{b-G;YmshnN+YCKZ<yfjUAE7F3UUGNhRe
zb{1%m4AcTgmjm~0!8Iso3<RbFA_}Q0kj0@TDzXr?lLk)Ra2vsbxeW2n8Hq(9AS;7Q
z3=KgYBIufF&tz9vYaj?RL<C+>4IRwFRBV)5=o;jm3@YGK3$dGLlv4szk^^aVVOR-w
z9;l=<iU;R2OuJx>P^e!q6(9<OAXr(CVU-D}!wBm?g4oy{Z2~IPV9G%CBZfh+V1o2D
zqx>+PV`x;85AHL93oO?l?@R_{0np$+SO&Wb3=K>2K?}*jN<aY!(wv!B0_Nk=l3IwY
zB@+@Ya3Sovj8pT|KyB#!H0<)`pgaUp1M&cr4W6BVCK+%~$c`aC1ia`TrH==df-JXZ
z$W6>EO-oEJDJ@DZf^I(WE6q(xEn+ChEAUJKO-_K<cYCHVl%?jS<QI9SFccK!r<5j_
zc&0F*4mg9HO6CByHz-u%qmXN0g2UTrW5OirMjhu3h9+>5oR8MiLK?Xs=yv2$Ur3A3
z2;7b!#SFywFDUR(CIf6xBSt|BX#^OHT)c059%w63yf0`Oe;FtqgG&re<3XmxgLm|R
z24GD<?FZMOVDKCeB>SN&u_!4@%qvbyEpiQjD1-5F7-<ge4ZD`Xy5%?&nq=hXXM+r7
z05NbVGAqpk$-0&?Ko|^Y9zfz_3xtpYLx!T%q|Ce&8}O(eLN}&r1v`)%@T8XD5<>%o
z0azwykfv6GA<bASndS{O4tG)_>^4%e7GcxSvYH8`E}_V~L}xw1u0zR+CZNt2BswSw
zKcuW_5|1_^LrmI&&(RQ-67x$kKoc{5`6;Q8raH7b@&)HzXsQQo*8!zjM1X+uG-kpK
zPV@{mjCXYf4-11D`=I;}8JvdkNH(URv;^!F*8qg=AY;Kcfkw7r3P>^82sCaDauUMd
zppkimQ&Gi1MtdWy$M1POW`mk;@Vt%R6hqKpEy#r-1(0|_bsw@Qtl$BaxQH2CP`Mos
zQwEJxQtZd*yg^DNkgFN$kl2vI99mw1WN{}8&`bhs*bh9Vl9~vf6C^fd!P6jlnI({D
z%FN3wfu>K8wHW0rbbbYq9WcTNQV<81n1EJq;C8klsCN#TjDn=ZAa8JM)E7Ey1r}t8
z2PGMXvc#OyR7hxp3<V_|g62a8$&JBvI6=j*Rw`)h4Kn=UO;8VJM;sh!1iTF&j)z1x
z>XcN8p$V!mX7IVDfF>bfBmY{UpaA6|!ukq85e(C(3$84KiLtK$G*JxGr>)HpADo&4
zYXTEtYk_Mf$c;o<m7D8Y1|O5w)g?tA*b?Fb0^Ah?wa;LlvIUP|6Q>z6TWJ&zcc!8(
zG`GNF5+lcegPL%1LQ5Fn@g>9@3q~%31P+13hM318Y(GLR!IY0@Vg{)y#T_7!5`wUk
zh_i=KNI`5P=qcEI4|w{6P~k<AVpH(E3#fPn*AxWe3^uJqlsnKGT?9P|pJ4(QwV>WO
z0oRzO73JrFN)9j$N_2#y4X%fn^3Vi4cLSR9OwK0Gc$f}iOgA(D&k2DY4;n@?jE77T
zfdxR;5ezZQg8YJbuyWTj1~{8Yt?;=iXx&CcfLnm<fQAW-NtA7{=_4#9EvWTKybA~z
zgs373h8=YF2#1S^@)dp~f}unG1hXr&pG;(H06vRKOcFCIF38DDPIblM%b;N6cm{|P
zqC8B5am4zXIHQO*ttb^V4hYRf5DsxZD$UC*ECsb%APk~3ndYVzrKh@rLl4X(N*B`L
z1u;=)Qk-7|D%(I5QRW+h+S+NEIXUs5W^!g?PG(gqcnTNPX7r6mlOfJXP%{{;5jMLF
z&8bl1Afm(>1?qmmhIeqK$6(WVaE$wch9$uRLqwSk>Ni2>opB{}So0mCj3`q<!3mjR
z#$hO^Ckj?TlyOFg6<Dc-rHMI+E*@yXEhzK*#zPipp-Y2Tnq#!wi0|tV(QbD(1oySk
z$LAm(BSyawZvBZ^`Ux(EkQPTUR!Jj>B<>Lv%(crdP(4@;bT;%v^fw^`2?p`5uAtH)
z(K96873@uHE^#&@tdSH~I)hwUW&!Fl#xsBxvV&~)2Cc^r19c(|4LyrP^HNgNGV{Po
zM3H!?3e7x={YrCkT+0|B3=G+jB5;}JSqx&J%9?u?yCvongNi&T3sv62vlwy)4cK%D
z6IF$wfoHKBX!T!aK4{q^f`h8e+_TuRs3;M%#1hIvmACLLhVDH8c>}^kRblB_>;&1)
z0Co$MjjF~16at_L2(S|9Tm-0jiU?H$&tlh#lGLKSL`aCiIH(4hdlq|wj{E_e17@Mh
zTX+_Sg3km3D}XRjRhW4eyMPwjfxH7^pvoGW!hHkrE7%;UpCBS=8cbkbgUEu_Lp%r(
zz*G*2Er={wIkEtna%0b8zr>QvvQ*ciqI}S*EEGPfVhhjWpwx8N3Q%tw#za+N8Ilk6
zifb8YF9#&rU~0^va;D&9?pnqGra`hsWfm|=W53jL*CYnN)N%%o#JrRo@S<!`<}ibB
zLAzC8YF%B;J&RpItGL151hb&VVO4GF3|eyLTE+mTK`L<?3?7PrCLpY4fyX#Ppl-A&
zv#_#)`p%94ysHLeIw<jhIjD{Xdl9th2I?bF+t(GM3)LW~{gCjo2+4;;J2+?|OpqmL
zUND2mpae~P6lk{(k~iRr;2{FF3Y!`nK>;@d91;+(fSnI<0C-3NB>><W2>Bn$0FdY4
z-iIV(u=gQMxc4DkGav8{0oO7H2m?*p&>*xV%>p9jTE>9jpsTa+O{{dz&nrpH%=637
zb1Y8I%ycbdz!XH&XA0g%<Qh<tnVHD|W+OIb6=&oZl`z1LAw$z>XaH6Xu_z!Jt{p6Z
zrq&Xy6y$c-faJ^om`xx7kV>O63o}Syn1XYIYZ(KW#wr)!7aVWyS)88(Dz2a^V0>^K
zf#>u<c@wJ0(7-*l#JRMnC>7k_MsUzH8<_{EmN+Km7nS(uh2|wEmZoQvxK<>mg7==e
z2Dl}axia8U!H@{j8lRsRUkcS6p9<3*4_<eG<R(*B(DovbKS4B_Lrh#Nz=Osh3Qfw~
z1-hM}i~-6*R}h?90;-%{1Ij>-1u@Z8xI<NxF+f=i(12p7gE1gk4;HGB0bc{~fG?6C
z^2(7Gx+>(QmZMpelH(dshFA)#kdm5{T7oDTArTI$k70Ehq~!$4JkZnts&-(K;A90U
zFroD!SOjDzk`5zF_tX-Y7KjZ&sm1xFMaik4L)lydK<n8oT=SCiQ!?|?T|ps$TQx&`
zSwTsW3O)t#WhF^D@dYJCkTLW+JZkYsL4q6VX(Kb-Dv_d}Xg!eFGmK{l_4D@g5BH0A
z^>g-j@$_?N2nqL(cZv*gMTj^CJ9~N}xUg_S4`frEf$R!SRM<VhfFpF!O*g`>9kyZ*
zR^~%u*9eDd*jk-32JEJxS!xU_BVa1Q2@7I8Eb*ZF3yT7T=deklx!D|#O*p)XPYb4B
zakv3d&YCzU7MFl>Lp-FOa%BJsfC2@f23(j1cqfBr05F70(1b1hQp<xYbCdFOK#LqR
zK}{hD7u8TR=ls0n#1dEJh6JcT1DZB~NTI4XGz7J*pgA7oV1syEQSJ(|6Be>)rWpAq
zW~ajB2pNN{7R?+iuE7^G;NBS`=nSzrgB1Oy&WU-*t^+j+QAN<)YwDL;4(gSaq$Zbu
zx7mT?6HSn?9!O*(m9xf1VW~x#X_c@bMa?aUq849a=89Gp6EYFxOe7~5S>V$^D30;z
z1zCiMG)rgDRy0ud0GWx%FECLCh~Gh)z^;R|DM4*#Xn{_kQ47)T>WZ&X3sZxuQ45nt
zZ`4A>u{3HS60WY`JdT_fLCYbK8ubu$U;{v&gA^8qCL#GQsU?Y-IS^@Z+ZI^>78VfY
z79siYULA}HQUMBLh=g%)DoTmq7Yqw#SJz<Uc)#FyL-T+l(5zxfrDI7+QD#zUNh-K8
z1~LcaFr*#;#8Ui$4pW0C%wbA!1UXC^J;cGCLpuh){Jd0#pwz?^|Gb<^1{cswPhM#*
znBf9x24VOI<Q23a$wG=5<S;?B&_TPvLG5$UX}_ojSh(dEC8v@XurRHtCK`ikeOxYb
z2Ok6g>aZb>XMlwfp+p7^GiZwjnj}D$WuZF2$k08t1S8yvk?RtaP{OJj)ktHHM0EY|
zT<gl<kqBP@jEEI8NaUf}h@=A|k7|dZAvioCQfOLXLFCGSqy|+x*okN%0dohMu%RKS
ze*!+uBEJaDCWIpc-28$K<3R-!+;&i~LAw0GM)9DrMNpPAa)g@XnU|LD>Kfoy7Hl5x
z7i<>q8Eg{o>Kg1A?;30h&YZ>&m7v~dQGO1{VqEzZqA<URA+adEI3BbD89cPb0Eu)4
zm^8>nP$+=1wjqi;z@0g0HwDrtgL1GdHvx5k5d8{NvrIxVGK)clS4Ji{o-u7R^T^Lh
zNd*lsK^Slcx~G<aj)#D`HyFZoadmSH^$B5c^zn&zcJzx6a&>fpbHal>LtGgGg8V%^
zojgN=<Nd>2gFs@SmN>*5X!wDAf=F_PW=P2xbeILm#ppsHEg;vMf(I=TBMOi#1raqg
zaR%=Rha6<>SmK(+fGPko1T^#kHUpezVNE=U0hnz@uu2qdI4Vn6`xj9+LX0F(N`uYE
zTQkCp!Bt8_O+YWD!NTBL4dh`+$_M2EusGpb5v&ZR9eN0jA*ko+U!DgmpOB&oT@)H(
zFpWl#*euBhoqrBV(*Z^K5H7k>&=D*!IZ!^sQtyH5MH~hgS-559rFeqRtw~Px1UVLB
zk8?(1W*(Y>hGwvV@{rWr0`PE)t1AOO1E8+8fT_n)uOo^fSRn+-qOKszv6dQ`X$PtU
zX%rQb&XEEGssvB{4po68;Xq~4(+#LJfyFzjF9W=jQL9F%39byVz<>r0W~hR*8mLf?
zNAdu?Xb$rB3y!yREJ`m0oj(uSg$HU7LCSB-;LP;AM9_W)&=E+GKtNQ#m^Kkk+2}ED
z$B+#zUp@0uQY#p;K_LKTf=)_GO@(qG<s*axT7H|EoLLeNDdfRx42$ETJGbK*GK=HE
zD~mvz`Qnokb8^4~OQ7Nl;Z2kx3{@(#0<!Q8Rn!dP8gPdwCnq(PA=@W2FV#OStvI#B
zFTVtQ-32HHK)Nhoz65tJVY$Jz4Ag&w@d&8R1dT#si!P8pqcRJ)6(%5efzmdTVra&9
zb#(<91Bps_d^3PFpqm03nFJLm=mtUC->%?14^jZqh~h<a_tX-Q1f*O6u`rYvf`)TE
z^U_j_ic(WRDj;f+MKJYPx~G-|Cl_TFlz_q+GWHG8hc1et7u<}4sB+HFDb3Bp)Qv2T
zq2CbH420<S1fBZ;cZnzXm=P53gZ&0k>tB?a4nFDxt{x%++UE}*AdJsT%uS6)aC0*A
zQseW%DF~iIkz&!@Gp{5yJ+%mb9fnYarz}D!!ciO{6rh(#P)C4{dVmab#wUZr6z*_j
z&%=V!&<I)7&<Hll1&w@UE)FdgFg2jqhvYKXG6qaR?AnbCU@9RIjbQ+?FvtkB9ECP?
z1<TIpDv554z;i49xI|KhCo+*#;fPHn73k3k^9rnzL6qi5n!ptXQf-4i6Nh35C_5m^
zRalc3TB#x=5G`E{DbOf9_z*i#fek91z@zXeBA}2*vj|jCAR68Xi_jYI@QRJWGp`JE
zB~NBP{0KgfsYYcMh*}Qa<Dgy&wnj>30BCI(dVPp6hj2XzuUPFE;7pKnK%PV@1CWix
z*Bn7shbQSEE5ng?kd>e(9=J<ksRy$K04_UW=>t+;!+0R?8I@UJ(PI*vS^|o9Nb9}G
zm87-`Xch`dGj3bVU{x=y!30WX(3UDp2&UTv(qDuLgVP0U+RqS861|d#BnwPcgSqPr
zYbzU?Lwbt&Mew*rwEVD0f&&Jrq`;M7kVgD4EU<%jdf|40q5&-@V6hy3VTx4)p1gro
zJ&sI*RV{jM!QxTuNy7-#jR94SDX_jB!HfXvOTv4Vh%OJfEsr_|0UB2cHjWQAi}wpQ
ziT4B#zXV&xgYy`qWr(QzU4zZy(d3}3H(XsY<zQW7SCAG^c^C|738MRg0mW<3fejQf
z=;#KDSYT;tQ6;KY$N*Ons-SCLX)fd}El{EXl`m-7)5tV9wFKO6NJV!UI1sRQin4Hr
zBxuYOT5CcA(+o#oW(A|lAc7K21`&{E@u1;oP>F`!!3=1^(7;3!g$5^@C?r791Ytpn
zCQLX`VMVqhe6btBGz$(=L_G~2c?WqFRCr?;gCjBxEqoJ;vK_$-0pU|lphYO?f;jYp
zvl=90LT6ndhw&DJmS3P|Do73B3K}<n<P&%g3RK7$Knww0Vh0+e1ZfX8jt50-uxUJU
zFA6-AnFR7DL<g$1435suuED|a?yey)W-x;3;TQ}Pb#e7^4RM9>yj>%Mp`|9s1&|yO
zoSIx(lvz><3Qy2B1XyCh5XW8$8Crmv`k-}yZkee$DbAqNL%}s9WN{!u5LeKG#)h#N
zkqPoUrZ{v&7FNUJFqG)}1=^@YYC54;zyxXwv{D1_pdhBvxatWEQ_(94NGgMc0<2vH
zEnh$h4Z{TVAVF`OV>c1A)n)FPmyueOi83!144NrtfJ(rk1fu~A9z}x;>%koETE+k$
z5rm21)^7xA@8u*G7lTTC<jewUNuUflIKx!oHq0V8wZtPcB_$Ox*ysw*Z)k$JO)!Ve
zqrtrZ?rK8j*5G2e^&5I57Q@<>Xug4$8K9{im>LFHi<n?Y8JRn#z(-SIjRQzIG6?5i
z2s9$`cm-$J8iNWIP%6O)1%lNLYH1EnRp44^z?(?0qyURksBdtG1E`4zt)y}29sG?M
z91h3rX;3)<(*&y3Fj@(?{S1y~ER7Ak#(`Xd-tE9B{Rq?}Sk&X|bYM}At1iK!6umY<
zFIZsp33Nc%&=OKPfXlRyd}y91gI2{TqM)Eanj<s;EoucF&I%f$0WXM06+lyNfhr5i
zz>u*3_@GXH5l9eS8)h>BGQxx863}cViZa(s&>~9|Av9ynz#RajW{hhlsG@=7Ih1K?
zjHU{zNk*W-?f}Ti{cc71xhR%G+<{9L%^*;p1gg|C56u|J!dmRIsKywYcqA4hP5z-(
zK8SuHsP;iphiZzEfk$F-P-<chC`RC2B)n!}s75o<2x=m<#DbM_u2~?5fHb2?plP>&
zY6m+Al<`5$S-2snafj+jkl9#uq1s>!N=0zBFp~*PS0dTuo?1dsH>!<Bp!J^^dT<9a
zHXG1PH1$XXH=t5{^7FGx3&5!ew3r;6J#osR8Db7@yQHL6q~bCL8dVsUpc-Uo9#UGA
z=br~@oPawypoI_UVrZJc6GJJfc_o=8l^%)38IVH46G;S31E|{xY1e_*^xzCXSW^Vi
z{(`p>!5Yzxb%(Vf!Lm4w1(h^N)}xtX4(UxJDZp(IhEi0s%sq=;GK)$e+rz*tRC!a#
z$_mhyo&3C1R5?RaXVB#VpmFZ}ypq%k&^}o-5vT@p(1MWEiV`#Toctv4{x1jvP1?{1
zwDvAJ10v~K#(>O4S8EcKnpjej2v?1kTOkz?XiO1R9hx!VP7Y`a6tWgK4|I`{bADc0
zW_oE6_y|3;kj3ngx%vegqpm?>2moD(R9un@x)lSw^~cZvAq1)iVBvvl_#WDE#;FTq
z^*nA1EI_Ml!&4KpT?5Jj+{!>JRY5L*r`KTPcvl9P8ff64n+8)14lJZ_hV%%rI~Jyg
zpi^NA(Hsgo>lfrS{H9xicanj<2TG!;iA5kb0dE+Zg2r}0#SQ4(amZd8G!c*qpavSQ
zkT5g`?NdxiMHqm>C#c=fv)C^+vB)Jgu>@2WA@K-lHS;V6c@Z>V0%m~Jg9anf(h4k8
z4M7v`;YFZh)r-J=T+bBO5>V>{RSaYbUjLe)s&_48Kovkr^WaTr;Ns1W0p!#m*v&(*
z3KnD;7AGSz1xl=9PXGwT*kThpNP`}GNSZL>kFXZBI3uV55mN-cfHjf`T40D7DTrbQ
z91GB5*Ny?aAOL(%Pdu1i91q@2f?3=_;|3N|;5kn44lnRlXwXtt&^E7B@cIPM4l1Y(
zV0DO{X%G*i7y^oX&_*Tjwi+l0-7--788(O*lAoQ5zK#o)sKJXwP!yt>WMmv#oa&OA
zmROoof}#$z?-08TnhD^=is)KF>n)&TpJ3;q=`jTd6uct=^FC}79BQB#fmXx%mzMaa
z`KIRP7gZwm=aqrluGnPIth4mYgN8n+Fo3bq6oFC}cmf-#*ai()fb%D)c0_d*sNVrr
z4x597dBWJhF()U#+&Mob)jc&2G!K%Qp9kuiK>BvYu1O5|6`;Ax*u=9Kr(s}|zzL49
zA~bVNK;swSz0|&`#l?x~sc!j2IPF2J+mYJcpw;G}4cSB(!T^l~kV8O4DALF<Eb#F6
z<Poay^xqMRaP-;{3efxNQ1`*Q=!hX-gcj@-J9yp?wH$$@7HBUYJZ1)}Ml0YGUYV)I
zA^8EB6{$JkR1}Z_9h3*R`=Q+*R5jpDxfbwkrEsGW-35d;&pd?D;9P=XIg$!cd?32>
z;O&$c%8`w8N1wdQOf81XqZ(!m?oNP~5h8mWt{A?>8LyELRcHoVf=3WALJPJz3A|hv
z60&8WF?+<0E6@=SpcxuhTmg<@1Vc7V$f>d<6>Ks>C=_~|B^Ie*&{k?3%CX6L=9S=3
zjVa@nlb?vL+9kg<DF@ws;IM`m3-bk-2MPl8AjO`NP_%)A6jzGEP>E&%sLaGjSs0q2
zJx=sQgP{)9a1+o9LBfWEyiKeHAhl?gfcC=>wgi%3iM0lz8r34u7HLq`58l5AI-di^
zK~n}^YKj<xMJ}en6Gylfn<BKJ8E6i&$PsdZDRf{FWCqq5dGNAT6t$>^fy+u*^$0Dl
zFgFyS6qLA^?;#aX#^AAx)D&=`fii~3fI|k&U53Fq`Q@M$__)Un38+9d(8x424}267
zRyX040~vx=4?;r;e>DhKgr^pStHDtT!sXHHK*(qSW)%q60FG6pHWH+3i>LvS3;=l!
z(h{`{$p;OFftJpKj$47UK>>iW83VEIg^(>!6Tt37SYr{A4>{-tG|&ZQf-C{4FoVcI
z+yiRef)B@m%OZxJp$ZAa0mL-CbJB2waK!=44D>jFh=cux5<GAN355=l0U)nK{A>=6
z17pyUPEZ!e^C%XWg3l4cHP(WNW3V!?`w+$(8inM8YZh?%2#x>*7i1H%Qs}}PNZY!M
z0hx=Y)DW^#9HtV9$B+W9@6gm6K~n}y12PwKoi6;^>&(0oGZRRA3dwDTkidiKN8+K`
zWB?8Ym^uUpw8IUyHxps5nJefJHI$8q;1ZevB93OZ5va3}Tmq59DAmE+k72TCI?V!0
zGn2ECPU3PcV?Y-|(_#pfhaS;|#6weP43z>oE-xKnFoch$*wn2wCkNFXXd-AD3?R}_
zS0FfO%8Vc~5IbGV7?8OP0Y#u&Kr_q0<FBB=haTkv$pP>VCsY)ijbI&gs2FAi1xa!s
zSAgmu2oG;P1uMnC#>4j0!2}IK+w(!)L0H4lH4C%{1z7}Y6-)=j7|_To>~I#?5d$z4
zSj@yw4hjsIdbH4h31fO4nt9M1gxm8VOCV(k+zN2M02u(1L+bHCl;JOAVQTQyb1)@1
ziddL5dI<}5l^sJc$YG#ZMU?(fhr2o(f(CyP9bNEna7er>EbNiJ0x1JrosDp5aWr6v
zk23R1%=1ev_XKU2hM61So$Tso>6Zwda5Q&IOfJbUsstVKXHk?|Qd*Q3U*Z~K5YGV7
z3+`e<QofD?ctaKR0#`eb0#Ixf<uO3b03FDHq#m?e1Y#b@&seNPb{6D}0C3ZdD3#z7
zCO{X|VEP2p*Z^<H(Go<N47wYQXa@)Q1smZxDuieUf{j7+7(vHsK>{7Ng~b&V+^`Ob
ze_kr6^M|T}csF}zWWu5hCA#9H{LpW_cZQxqi6IWE(?Msn7Q<8o7lV&(1c`wzwMII=
zGT9Y&^d#<sAQ5VUiw%t+*Qi6TM|U;^-{KCwDI4TP40$6od64bSMxc``!TYK3*$Ghw
zI{Y=t4{QP4Gf+by=@EWGt|8hjM9HpDKl?z3B#SZ=b6ir(GLut_!DFexsYoKAGc8L~
z845tBogqswfNu(dXak)S?^%+X%TQc`CJ-OxV`S)BQBstcToPKG1lqe^lnb5(3otZ7
zHZCB*(A?8MG}sAZKrrMwL##R(;-h>FK^ucZi<2O#1Cl|rn{X~ee0)k`QF&%wJa_|W
zVh*V70u#zjOwNc0`3AD3tpuSMAydMD%+Ab@&rixqO)iNqVaUvnFG@|%EG{Xkj8Dx2
zk)YGdd<+dhTYr7?Q&Mw_1G2#TfFT@)?9`&XcvuO=kO4pc5X)=@ft~}T|A#&S0oO!u
zRt&BZZCVUmU?UIUg6HoD*ha*B3fw*trc)4lh@DMA=pb$~1+JdZTnbzv_W3RxQz-~t
z1ZPrU{l9F`NCIe;2)I80DllOJ40V2qC>y>E4Uq)E2U@^ZO}PengDVht{cI4Av?&fe
zy8%-QDvrF-Oma^xfk{K!ey9piw{M}!fk#$c(JhCE17aJm0pi>mOea80$qYa@2iD2}
zw<b_6HU$M!JgGK=HG%9$2?1ESk17bMEsPBO67!%33L+-MAgvQf9J;!e1%YxAO5OxF
zfw1WWS6&c}b_}6m@uAS8=Ym`VL0l;1?C<C2>Kp<R0Ud<l3StC%goe2Ihx>upp)LXO
z!LEKTAhugDhz$1+@&?iFt|5*tE<v7tZvG%{kZWLkNMwL(ysu*fh!3?6#PkQNclCDz
zaa@r#xq{dBLxkNOJ;63Y6@&(Z-2&$M`G+`$IePj)6uSBO2Zsg(_y>Vq?ds?QI^rV|
zEa&9t0<pv?G#DZR@}HxVe^7`k*bA;8evqqMXfO&Nw4oq0EZ)_{H5lwEXy8DP5&_A0
z_y>oC`USZ<I(vX^^7IP{f-=G!ArA8l1{n?(^mX&}fjHkc*ge=Y3c~htg$JvvpDT)S
zesB$b{!XEgfOhrs_jUCJo9E{r;^GOlFBr!1^Y?Rw1c9G_2;6Ev|BzsRXGn;H*r5SX
z6I}gZii0D;5$PJ>831uuK#+e3I1*jKEY$D?3xQ%5Y)*)$ud9oHD8wjd562)_&^da#
zIr^gNbo2~%4GQyghFIe0333<QAml{m>Kfr03^6h|2pYhCj=ruT{{BAxe(qq416+e3
zVd3NN5Ajlji)$EI%FjQ<)i)pn65)RS!2!--VNZycg8bpZ3DXb^_qns9pR=nEG%dI}
zc|z>+^9Os{KLFyUkcbc`XmSd2^mB)J$1ehEzORp`A2_&u9V6mhgM$2nz@ZCG|M4D<
zelC!-;20d~2X>jWhbtt4+=Am>!=Ulv791bo?*mRr2rZsat)RegiHErwrY<1JHNY_l
z?3{ogf6yiwkiUaNf?OTJK^5W*4k%ERfzwV1B#1&?z{0_v?tYMz3rl+tdl9)f*fq%0
z(Fc^#;sYFmJVPSmK}n7QQ`pxr$Qz3=$ZuGL{aswJhz18ZI)myDP?Inqzo;Z25wuYU
zSz&O9e*omv9zR!H;_+^tVb~=@!u=T_4MC9U!6o?xPMIae4B4LkLC}VlX9;L>I5h|~
zPhOl^mYP$EMK&N2bcAg&L$<RUq=NxFpVK!nIVe9jF%MHFJTosPzr5Hdu_QCk5L4PS
z*dLdaUus23a7k(bSRPX+_@q!w;n2Ly<ouLWED|AZ7MP-b`FTG1#l@AlObc-{G{e*t
z3KDj5#UbH?UBcK1t9oN290nO1`M5G<LXH`ZXDBF2Ed$>h3T5VihL#{lndIabr>4Y1
zkJJuM&M!!1sDm_7ARK5b(-29_&=fLq<evr+1Rd#wCIYIyLG5Q0ZARdAf~gQq;L`{#
zGC>PV@)C1kjS&W9C8Qc+XyB2WSOBTFT^SH;Z010Ym4zP)Y>4bo@X5ef{0%)37>kUl
zPikUWD)<cSM96?0y5}u|63d-IVeJ|K8qdP?I82_QEH^Wcp{yh`H<ckYFS8;bC$S_g
zzbMxqe2#N51L%|`hSIY5qSQjjp}mR8pp)d|3rkZ$eZZpBGKReL3J5p87>QlNkdvQZ
zzyQ9#JGH2Y0i4iF%i>duisHfS;>uzWCoex9WIjl^7{(}JfZ77-9Th`+Nf29Laz&|y
z#SFzIplgwG64M#dauU;v89=S()V!4Vv=j!=vboH>bf~8C#FFHU)FM<~F+*|^$j<o8
z{P^S~hJw_x)Vz{n1}K%5!cYWW&csj-p-Ri*K`Oz{1Tjh&@}R~RGvuYE6f=|;GL#p_
z=a!bFR)83Z#g%!<49TEq02yCe77y_cBp^Y(<#>=}W?nkT5l}g>=}>kFNF1aj6{H_*
z9Eed`77u4b;~_N<bV4&oIYb6*3WQk#b^$0PAf^_BZfQ<VEiQ(-2E<PVU1<*IgD2$R
zyv&rGR5%A>B+MWP4;ls_%MtF%%#VkOm#3v5<QPCHtq5*jQBp>HQGR|2LrGC;Dy09+
zP?VG!pOcza0%jCtre{D{ASdQQn92D$`9)BZATbCr6&zj=W^xi(KED){4)f9#z*85c
z&=m&?u!A7MlNd#*1*wT848<jhMJ4f>V7Efd00&|`m|YAujiDHHf>cg?L1sZ}S_+JZ
z<kjSi%$yXs$DyhrE<|uZtkPTt$dT#sAYNilF+)mbaRE4uroe?t%b?77uuC8+<4YJ)
zbJH?&QbB1P?6!Dt>P#(SNKT6{$tX%qOks$R2i?S(S6UEXT#^X7&@8?vzqBM1w75Dx
zu_&D(9$Y#j2098L`r;uGTNGcEn#>TNUyxW>ni>z2LmC%B2q9RdWl+oGOF#}uP6CnO
zA|N>pnkACc;)_8;LaDil1sVB8sqx_WDo)LXXo2_->{XCHh^N7<5{B~pqHJi=2Q$Gs
z!K~yYhQzdz)S`G850pDl1i%tSsfA!e7*aq>%t1LBBn(QIAUeL7p&+p&g8_8D7N`he
zNJ%V71a%A{oXq0n{Jgx><dW1BxL_)1=@y(<lv-SxQ^JsxSeg=)Sdt3X4{o(2m8PYo
z76oTkr7{$i6epJyGgRc~F;wKIr7=__=2bGJ6c?qG6fqP)+EAe446F@wfE;o$47Lr@
zjA8IENX>IfEXmJfNRH106?+UN$sh_8it+g%7DIA8ScD-tJ_p86W=Kv3tH>-aNKH*)
z0Fz*Wd@z%tB(*3vGryPt6jDiG;~{Pbty^J$Frn)$Ag4S*#UQsJK-?1usuWVdw-+$f
zA#*?@vW7?kW{`WkAR`Ng$TEh8nR&&jMJ4f|19QRGdL!{cH7km0_?3p>x(?z9NK_Pq
zZ=i>WxaE`<XF!-mCB+P&NC1U-N^ucGQc*TTaB2xe(xoUd6B@Gd@vv4SLwr$cacWUn
zY6=7R&;jsNL0V#RDnl@MDulr!$Tb*rjAc?~NvZ)usApb@1p|m}2quldq%oK@0h6X+
z(hN+RgGq>bOEBBe075}@8$z@jLi8I#3@|ihaCQp~^>hJ^ofk6%xw?6Jx-j?zg!y~A
zFgT{91f`~dondUm5DM;;1*PVsCKjhMl!3Mk<mZ7U4b4FJs%L_>B7inKC#5ogn%AId
z4hE3lT{4qPGV}8iiz*qM-4Gm*(V6-2pzz2{2Ib#iP@%~HYNIoF`a8P?<dmjEw}63y
z2s&m9X=FhLW*tFwqARGL4F(@02DUAzG|wkLzW^%Y?1sVz+3B7N9Y)5`j$t;a&j1?x
zMY0Yo1RqESWgiAO51eoi>cPv`5!~R?Bs3B5zQW}E9E6&%)V!4ZA_PC6C_kk%xdb5q
z4Sq<I6(Q`Hl2VjfT#RrEOaSg#r_$np{PNTy$FjuC9MF0ugyvvy9tNFOR|>ij$v+Kc
zKS?o2A!yA3C=NYcKs*$Am(*hLVRZRL0VPEYNziPagb)U=-zpEuFG<XSN&1ySb_jyv
zwU{9Z#XRsV9z!OI7(-Gn{P5{w2H(UAuvZwsBl;)`5w_x$1i2Kl5fia*29$MC%mVq;
zskGRwC^0t`8s4A`X=cKZlh2Tm$pD)<4$n+UWpGR?&d(_=NeuzDeS=bqVQGv3l5~Pn
z3rkarOBj-Jp)7EqBtbb0<q%JoL&j*!p}|xDE-gVk7f?L|_N_~58B7z3$>6li;OP&h
zVKs>%v`YdnW*~jt{33=VxDX^sBKYuBiV%V)(<H|n@H(#&(Bal4pr$6+O`ypMxOp(w
zW#+>#`i(DvL<Ypc(0mM;KT1hWDh0J5Aan`nG~j$_XQ3F}pMz8<;D#x*E+|5@G>VHe
zt3U+@jLrqMc{20TgHwyZ(@hM?phFTsD|~%HG7QdczNO%^_)!ZX&?E}vHgs^s4caBi
zkOH2tVt^J-P%h*s%cSCzfW(pv$6|P?4r72y7pN>qCw$(Ep|}Jx1_22HsA=#ZLk=B;
zU=H+1HcuCZGH|Kj>B3L|DGoecz+nJtL?trB#}_li$5$}K#}|NbesLx!qcX(Dm*j#3
z$`W&+_7y|j1S-Mc384VBki}N;G88B07o{@ff~KD!ApmAV0~y>YgZj(a4V0`wp#TX!
z_{3dNYB575=oC`W5s#%gCE(e-WXQchp!Op}5@=ASBqOl|bUL*GLvCVTX<A}3=y=s4
zq;M_<&m2PXB9gEH7Xui~g3>FXv>!KE7=tk5g9x=l={_jE2TC7<(hs0CL^XoU=ZCN-
zL1`HQ2;T!rLwE>sq^U<51#nKx%gZlO$S+9EQ&24i9W<DjlbNCbX`w0<r<Q<95e3y0
zxD2S#ssKt2$dcgg5ells3ZN!+W?s5NW`1%>j)sDso}P|^r+;v;r+;vOtE-ESf@)5R
zf+hoo`tqX8l2i>nJv~i^&^%D(r%;lw0PYJbq@^gRrsyc778T{?TY+8T4@=pe{-A<1
zzZBYB09CFEkP2D>Tt<WjJ1Ic&wE`qfG8j~-8dy|-DU%B1Y|Y>aGBq<X$0^vwIVTge
z(Go)hly~6jf=h~06LS%12*x_W4r4)RXcB~Q7#J8xl^2BTgfP(ci$a9qB)U9G7GY#y
zU|?ck@CbJF05Me<7#KVl7#Mh<x<O)$3~XQ?h|R>nz`(-502bk7U|`^7U|;}cArS@!
z29UjC3=9na|Ns9l$-uxM#lXNI&A`AQ%fP@O2NhRfU|>*WU|;~*qsG9%puxbvpvl0%
zpu@nxpa)fB$iTp0#K6E{!oa{_#lXN|&A`B5%fP^3&%nUo%)r3l&cML1hG|k|XP4Y;
zE<cmHu-gxEkH6C8J{@Xvz(bj*s%Bqn@rIfz4pr`#Cq=n8uxPFmUukIkF#XlLLv>Aa
zCsc|VAK#sPC}n#0_k+vUAFna2_cQk1@{mvEYUgIAQwIOe-kQj7Vz=PNYnus|LY7`x
zw^ONWmfxhe&w_++|G3TZ@$$wTon_HcWgmmMP5+%`W-75M7qpDJBh}Db5N;&<_4~V+
zy<&Ho{5lpo=<{@NYqtewHjAyiHsjURM-k%3lVokpGks;htzNs*wOH73%S?#|(Z?Qb
za<gAX)@E>CG|;^|VM@W>WTS|WvLah<&Ns@)YG#_AZ|)b>T#_FZz`ZBq!!_2UC%3FV
z;5c(aWvts?i@%cJZ?k1jlK!=F?#Dj%P0Lofw|;8xSkC$Z6j96!3=+%?3>wS~3>M4`
z3^B|M3^~jU3^mLQ3{#jH7}hW|FzjJwV0ggH!0>??60rg-3=9e^3=9@53=9D*3=9b@
z3=AbK3=AzS3=C6P7#LQtFfi<3VPH7H!oYBcg@NG%C^4`yFbJ?RFetDxFc`2hFgUO>
zFa)qNFr=_DFqE(|Fto5TFic@(U|7P+z;J?<f#C)#1H%he1_mBB1_lK-1_lE*1_lQ<
z28IAO28I+i28I$g28J1I3=AvS7#Mc2F)*BAV_<l~#=yYA&cGnU&cL9<&cNWp&cG1D
z&cKku&cIN@&cM*Z&cHB*oq=HqI|IWOb_Rwc><kQ7*cljJuro0HU}s?9;9y{o;9y|T
z;b340;9y`7U}9hZrDsu)`xzJ*8afylKtW)@#K5qH2@+nQL~qOjQP&C0v?Wk|Z&^XI
z3=B@Zki3w|&A`CL!@#hQhk>Dpmw`czkAdM9G^4dMLd@6)vXFs+AzL28FNB)uZ2_^n
ziHU)MjhTU=3*-<61_nVBh<Fea1H&~Y28Jl8xRoA6zdls|3UR`2xB_)I7qsvInF(?Z
zC{92=$!~_3X$i^d424Y){w-*|ELDNsEmNW4mc_)t@Q#Urp$O{69W4<3Z5$xe85nj;
zf{Pi3Ia~}3+n{FJLe;E*s(Ggi(F60>Ax4OvWy}l=3!w324s{pE9FWPHXlDF{>Uqe_
zz;GO@=cY2m94STyhE$NJ85kJ0LBm4~RCqBkFl<DNqoYy~x2%VTu{u;eEWNa$g_j3Z
zJ{+1Z7P3O@e8$DVzyxj6_(R<e^S^@<#Et-{9iT7-IS&>mYEU<w2YD2P`62P_%+0`X
zo11~5pNE0LnU{g#J1+ynYG_(phL*ObK;3l{YR7VJh#9in3=B)T85kmY7#MhY85j=o
zGBA`v&A4w2al0WS149kSK@1EGr=Z~si%%s@h}+qr=I(_04dh>tQ+GFDngPmiAmf&S
z6fiI_2(?4pBFV(S0LpiBp?OacT3&&aoq@U^7Ec`v5PQ`@k_-$C$rTWLkmEKRnkGT!
zg3JV&2U5O~2){qYl76=HLF|P2^)l3aP<$b$`AD?*x(N*vSp4&|Ld=1ssW(u+!Sdu9
zC?6JA!q70!2352S3=AQ%5dE;Ss2VN(q(kjH56xfo+>o#V@nQM68)^rv`~rnLC{AGM
z_6jsz!|c2U4G-izc$p6pZ}`%od@H29Krho^?F^8epg2KqXMoxcFg2iN69}WL0qFzj
z2W4+ib_3~wVI$-7yW$fnZxyWW;NDyr$#CjnLuGJqRGgBoNlys_149b~1H%*s28JaJ
z3=CU9Z7&7}h8qkF3~3FJu-y+*1Zom7L-=1ojS&V0hHubtbBC6n2Mi$c8$k^e1_p-N
zb0J~<){ueWmMO@E3=I8qA!;I~L-_oz5dN_c2p{Ip8U_Z2p9~BPpf(gp22_NC+FZ;G
ztPCs+kir96oil*^3rY^4D2DkNqym(6K}DGm0|Nu74JHn4e}UA1+Fqb`mlCvn1rk$c
zU|>*XU|;~{BW-BgOP_&(0pwkf^Ua}ZEuif$2WZ>N4cb2RW?*3Og{tvmU|<MfU|<Mj
zU|<MhU|<MiU|<MmU|@)b%EvM=FvLUINuWH-z`&3K<)<?+Fl2)2L<R<i90mr4JO&1a
zLIwr~P&AY>FfddwFfddyFfddzFff3^sh)v>p^<@sp_PGwp`C$&p_74up_hSyp^t%q
zVFEO6r!g=v%w%9-n8U!pFb^8nOQH5HXJBAh0ct-oFfgoRU|?7e72m+Xz_1z0-p;_l
zu!DhtVGjcX!vO{chQkaD3`d}H#~2tGPBJhsoMvEPIK#leaF&6A;Q|8#!$k%LhAYst
zbQ7xf9s>izeFg@GhYSo1j~N&ko<qf7LFqRP3=D4>7#Q9&Ffe>%U|{$HN@olV3<d%w
zGglNpI@f4$*6-Dkp3AG4j7-!ST@UU5Yj^lLv!p<Dbj=e1p0X{H0=v3?yw0D|v4Z2~
zogI3|TVHy)oSkg5DM;d2r_iGRvpz4CW3WHo$k{Fzx`zAy<2O4NY22N-c}mUIsgGqu
zXTBHBsxIy3I{b+5(U}b4S4#0UG6o?=2EALSnojun;OuYRT&}C<ulB|(&MN%HCGK@n
z{+ir};HYfFtut@$?>*yvQvTZMsdlU0?E9`QBPnyRB-HI*?>jH$XIG`x^u6;^W)IFP
zeZ1PtDw^?JX?h;3sLvhYN(rlVS0%01UA-LcT{izgkf68YyX|*Q`5$lKZ(4H0Rqu>~
z^qYQzh7RtD3!YBcTVwkBWKPDeSG;TPKay9>2ztYw{8~2WAN!i%whB}2;3bQv&-dui
zdv(<*jrZv0<Lf}}@hNpWM|L>aiDoj)WVy#RwPw5Dv<&SzFTGDsoK(YY_)vU9lDFE{
z2WsyXr8<iWdGihT@@n%*`32_xYW!7m;B3hbhuKPNr=CdR{dlGJcA&^{o9T<2dosRp
z7`y7(wr76hF!t1!IBKr^=A`kYHDV7=1p2Btf0ug6rF`R;$|9C!rvBaPSsE)I?>l+#
zb$RpB4u65v0L~TKE?e&(cHMgaa9;RRzOJJ?-qr0@HQ+ui`&okTmfD&lJ(qcv&O0_8
zvlm=s+wE0!N1|o1ZMWBY`)}p~_PfRI>^OJs#Rt#%cYMwY^v?61fAgZ6iI$cQUmj1$
zvHo|-n;w77V9H;1{1>PXb7%Iuizj!8xNw?Xw*U0SN9U1>G|Rux$7;V~*J>Ku|KC^t
z!h6x1i054mFT5A=1U_5uyUR@B;>)d9AF>vvP1{<?on-QEfj0m9$?`L=t?qyNe%j+*
zdv6<y$gP|F>4J2O?48K9)mMMtl(Lh&eV*(0nnk}o&fHtJSjV$GZ;rlDm}C64b6*_{
ze8gg|*}KOlcK_vwOA?ic(mvX*RQ>48{zt!>pK1Scm>IS1dt#qLwC&H>7r}yC^}KdZ
zEUh$7J+#^F&}`{=rAbd?zSY~WW||f%sDEtXpJaupHP<KA_pq$H&U3Qx_!7f|+)R_7
z{8+^P;OI4Xw=XUxA3n|gvwpJ7)-FTNd)|KC{zrQ*KYxAy-Qlv+)mt2=D{lOD;`K!?
z`(1NGPsj-+{*_a5_u^|xw>`coKFOpy&2-fRnPaO(oJE%}nZ3cJCe3t}N>JUNZO$L2
z>W55yWv{NaCgowTu7kSPn!ok#hax`)31zw)Jv({JQ16+KM#H@8{xxbTti~TSh4g!Z
zb}m-aytvzcX+oSmYfH_S*`Es+EI<9zvR3?DYK80biH}coORX-R_w6Xxob6sW=BmFE
zz5ZV7tJ(uj28Pd^3=C{s3=EQ73=BG43=H;M3=BbB3=FAU3=H*L3=EUF7#NmvF)-}l
zVqiGU#lUcni-F-I7Xt$eHv@w>Hv@wfHv@w$Hv>ZeHv>a5Hv>Z%Hv>Z_Hv_{QZU%<+
z+zbpSxfvMla5FHx2ekuu7#Ku(7#Q?<7#N&*7#Ko%7#K2m7#ON~7#R9^7#J4vFfeT4
zVPH7U!@zKhhk@ZOsM6(SU=RlNWq27FEO{9ie0Uic;&~zcn^s;1h8duCCocoTK3)cf
zi@XdBPoQm4E<OeZSw02^13m@@XFdjoFg^x`Og;vN8a@Vwem(|<MSKhlTlp9mPVg}>
z+~#9ocn4}<@iQ=p@G~%|^D{75@iQ>^@-r|b@G~$J^D{8C@iQ>Y<Y!=5!_UC5pPzx@
z5<dgOQ+@`9AN&jq+yV>?asmtth5`%>E&>b;;Q|Z{Spp0UwE_$b69gC-77H*iY!hH$
zI4Quua7TcF;k^I@1Ct;FgQy?_gN7gjgS8+7gP$M+L!ux9Lx~^*L%SdY!z@7thP8qW
z3<m@m7%mGkFgz1vVE8G>z`!HKz#uQgz~CUnzz{6Nz>p@yz)&f~z|bSaz%XBkfnk#n
z1H(}v28J6#3=FS@7#RKuF)#=UGcc$KGccG7Gcb4wGcd#oGcXhgGcYs@Gce2*W?<MZ
z%)oF;n1SK0FayH}VFm_f5e5b^5e5cL5e5bu5e5c-5e9}N5e9}*5e9}15eA0YA`A@c
zL>L$jiZC!-5n*6>F2ca@ON4>JT$F*qOO$~jR+NFEK$L-@S(JfcnkWOqN>K)eJ)#T@
z=S3M99*HtAd=+J2;1^?HP!eNcFco89@DO8Qh!$gD$P;5=XcS{$m?Fl&uw0CRVV4*K
z!&xx~h6iE{44=gq7}&%a81%#$7#zhJ7(&Du7}CWV7^=h>7<$DS7#4^#Fl-iQU^phu
zz;IKXf#Hof1H*rD1_mJs1_o6L1_lcW1_o~l28K8Z28Kcj28I?128QVp3=FFz7#Q|S
zFfd$@U|@JG!NBlMf`Nfkl7T@+l7T^Al7YcVl7S&ql7S&Zl7XRGl7XR5l7V5NBm=`1
zNd|`Fk_-&DBpDdqLI;|Jr5G60q!<`1r5G4|q!<|Dr5G5Bq!<`lr5G4aN-;3pkz!zY
zFU7#XB+bAeD$T&4A<e*GEzQ8-C(Xc+D9yl7BF(_iF3rF&OPYaUtuzC}0ci$?Tha^+
zZ$SfCG7JogG7Jo!G7JncG7Jp)G7Jn&G7Jn;Wf&M%$S^P*l3`%DD#O6=LWY6iw+sUV
zpDY7|qAUYLybYwim+1~_8-iMJ4D)6{gm@=FnrWbx%uI;T%!zOzE2vN;LWrvnqAE5G
zZWgN|MCgYE1A{PV43B{!N(Le{Umq^yC=b%W!0<)_Y&<A@LG43m^B2^Nj$?o;?yiRD
zzf=qvp<`fR$cHv!eW!!<gW9JZ6CtW@HNb^(r$dBpbi>W6g=%~^5iTUh22r(D8ZPAS
z1QD830JpIr6e4si8RT+su&Gx;gw|!lg?86Lgce%Eg?>asgiI3QLZD$NkRP4EU0SeN
zJW&u;38`?`uYwAxCc!l>gF02g9PY0DpsqXv14FkESYx^@m;wceEi_ht_QL&@ItgM+
zT?<@Q7qq)pD+m{AoB~mGunDd)p9kay28O2)TRzLf6<?bQQT(|RE~E_Y@jWhq>+gYf
z8s}BPRVB}dXw;qo7n)uP5sJtG*#-_5Vd%(#lL1`lNf<=clN7kd7tpxh+zhv|0otuK
z*M)0b3r)Zg{cu%+fe^DcMZr~lgqpRY8E*VHsK)n`;X>=IAQ~sRF)*+|l6fAqqrHt0
zZak<h4vOetX#a<Sf#DT23ffxXs%}Hm<TONL{svW5-3qsHX)MG>zi_xympMR$7C6I&
z-25Oyf$?ymEuIjet&wmcX{fiCMZt~lhuZiT5ri|KLZ1*JAsPTNt1bp^))q5}(4Ks_
zS-1KjLR@)pRT9u%<`ZwY&{Al|s77QARcJs<APOQ-mkAVvpsp2Yc%FfQ0n{r33Eg6b
z=K?Qi`r403UpCM&(hFvARh=aecRk30N7^+<h|v2WxVu83(eZ5>+(Xe&Z<`~$y~iD*
zkuMakvDg|SbixfTB<=<gdJ_V-Q63r+x*>2?r=T`2L?nQJ(1IihQIPC`ru#F9bPpQO
z1BJvyNqA!VFdJgy#VK&t-!X>>J@SML)k1S^Y$sf!AGEN{>Vd0@g@)=DM5u=PL(I~M
zg}c6y10tj>1vjezI&N_cQ39-+3{jQe1~=Xh8be3T;6mIH5LFzAVo)5aksG0LGqhw=
zM$|-8pn<am5jft^(nJAKJoi9rqT7hdX$y2{=}86L^^2fFvXyY51ZXj&CJq-mZwYZK
zV*vvLbhxn`8eS_A;k67}ntW)0YfOW>zN`-}v<a%}DWdLD%Yhi5oCyycJynR%R0Fui
zxH%A^JyYST7D1!d2~i-YK+B2eh;o7n8me)K0_I>Y#H?9a@Tgq@4b=mPP~8J+4l+QR
zqGAjTqL2!_Rs(MT0ciSG41o)YL6g?1F1W*I&x2U@29e|ypm8sPi2I~z5LF3?&=Z0R
zNq51Gmr;SJGBtz?Z4H446{NuZG7nnjy-k1%F+&}(2H}VfXv)1_0yirhS}3I;Qd_$T
z#Q6P=aI=2(LWGLy;W@nwT93|ZgM0fTG@|b!id1!|sx$3y8?SSKjAdX*h19mJGH{s}
z(0Z6#7%U{A0H#2-y&$w{z-kT``Uq_|-7JO+orE@7rXy<DnNU^75vn#o<EyC$?r=wF
zAow8y;Xp0K$2B$}*Me(n0cfJl%Y+L}fVM9>5$%if&=m3jkwQQdF`$C%w<+AlEA|lM
zC%VAR(tx@v2vJ0Rg3dbm2*Op(hc-$#r^1Dzp%J|Y5z#qN*E89|Refb<U;vHm{)7as
zf+RTDQWU||6kRYi(+Es~CL_cc7z|CpJW%-SKm*7a5kUW;G0V^a_tYt9wzEVe32tb9
z{fdbH8fe`Til|%6p_xMgkvSrvIl&o`t3E@kdT&HkKg|LXj59pp{`?Isxqi9Ag#zb*
zm<$XjAmzyAsc;tu1wr)xMl>i6LJJ)cL<RY@0;1}(7swoNTF8QywWWwwe;l;H--Rgf
z&q3Q542aU*4H|5Z+Tj)V>qv<47OC*e<qj=H4G^X1MQE<9K;%kEXsjqB8Wc;R8krD6
zHPGa79g#dzSwJ>1FqA<OK_?{k*FzkxW&w}(uh5wv&`JPk4@L$WFaHn)uqjkX4N++2
zLS5E}NH6ZtN+v-ZZhQhXam+;2(+toI#VZaE>Z^^A;Mrda*SH3%(H!B3X<iUj@rbr=
zBsA|IK=iCapk1Gd1#q)2nnE<LcY@pa7@Eg&5P9tBEQqRJM8l&W>Ih$iBZ{Ey(-m=W
zv+jpOG=4x-GO^Gka2=5+zCn|K4k81rhKBtN=*kTS28L<SI?Ox+Zu~iD6YM`CGsQs5
zkupR%;wcGn#CBbH%9n%oWZxsA<1n;kaI*p)IQh`z#DnNm7(rdX3gLQCG6I!v-jL)3
zDln3vHim)cput&&3mW!2f<cK7EaU>sYoPdqrmw5eRt94=+!1r2m5(=~@=241c&JkX
z9ug;^?h-&mM<%pBNJq4h+@Ko&7{WC^g$6We2@cc|M~orHiy{@D(0KfVh{vVSzQOT)
zcvk)fO%pne@PM8Q%?eu(Sz!Y+0|RLO{W7E|7KH>`AEYRr56O&g4Z!|Sg_OvvjlsOX
zCSVE_z((Q_C*FW42MIAi^PyrRT-9P|$z_G;m^_q&Xq;jK4}s5#5TPYua3MozQNE=G
z?vbU?bY+d`aoa#utwi*=JL@54?XZHIwFDZa9f*eGgEok&dx)Bv+ZiHsD;TbE22|r@
zgvQIWL9z@Ck0AN*-4wX<)Sx|X1w@bAvj}2jKBDq}&J39&?Sq8t6-c<MA!@o6%%IfC
zz#s@|Zbd=VEr6)|gb05vXwEo<2#pia`N<eW34I>g#Jqt>H3HC%^a(`1ege$~TM<=`
z9CQvCG#@6$z>tY3oO&f7p8Bf?kL7%5yUPI4knD$+YTpnVH$$6<OA$@PN6_T@0+DCf
z+9AgCRD%K<oJ&Dz3pP*6SQW&;SRueDz{Aclff2HXOooAh;Q?rZ^Z)<<pi&E@p23k%
zppD6ym(9DGt%tRbr5`lG3iYuMsFw>>Uj|mpzyMe8)(ln+>I{SCBRin#ri02CkXo3z
zAU4!I(41oeR2^u(6)c6O4z$({G@obzRo4ZY$Ob8dsq<}S?_ui&+YJ&1*$<i<<bbNj
z@Rw6F*he6BGK>ri5B@<Eg63#J`r-a@Zf5CYhJ=#~BLl+@s5&9ggfd7W%>DpO`%4%Z
z7&@Tp<w0se7^WV{{yB^c3<*$m3qWc>7>l|ij0_AGP<5bnf*@sZcS6lG7h+)WVPMde
z1&z5gFz9ka=|zGJ3=Rwox}bqHUj_!<3_<WZL0u2fcs>Jzt%V?Xt)Q;7AOnLb1A{J)
zAOnLr1A{JT+~0(OLHC0I1A{jMgYH8C@ESwi^HBZ)D1SMWKLg5dgYwIv{7fi63d;9^
z@<Ho5K=v%<XJBw)V9+h%XJ9a9V6e642d{I~RRzs&Ffiy!LHR8F;Q4ah|9lJ#@(c{J
zANe5a?(l)vIO<;K1Fx@?T>|CLhw}5G{4753I!)QHyx_Tf-M75pvR^j{G-t!Wplb%@
zZ|8xCtMV{_nl!qyJPZt;3=F!=JPZuV3=F!@xWQ{Mb#HNl%@e&0TFb`3AbXe_qJB3w
zMEyc;i27Qn`a-DsEU0=fZixHsxxwoSbUC5)KQ4&)Cob^XQr+8J5OdFRLCo901+jk#
z7sUR#Tnr3c3=FbWTo7{-xEL6;7#MUdxEL6;85nepxfnpJB4j~xW`PV0y6Rkz@B_`K
zxiT>59_NI(cPA%!y{PUoPKbRoI3e~Ga6;@$;e^;1%L%bhij#rCk%7UMl@ns`OAd&=
zmpB+0oER8vPji6RuIe7<fau!;rPp#m+yz?4#>v1SJB@>ZL4koGcLHdwAp?VMHwVOh
zpy3;kcnJr1O{;Af2PB>yIKWk~tQiLbgCzrlt_%kQgB>WnL*>7*gL_M|Z`c_aycigC
zpRz;L9fs07q4atvJ(Zn-A((+dw-U-vV29)nCw7Rr=IjuAHQ2%Hcw{Bm89?hwWEr92
zpV+|Fjx1=+CCI+JY!LfE>o7t2ZY3K7gFgd<?i@Do8W3G2Hi&t`Y~cD#_BboVe}1gs
zb-TLGtPBh`3=F#3tPBi(3=FzltPBip3=F#8SwO`)gDhwbl{Eu{?I|V*Ux<-`!Hj`H
z7qnhXkAXq=9Rq~_46;r|7qrd-Bo7+%1<8Y!*XS}Z==MO?ujqo-_!u!T=z`XZ=rb_r
zg4UB5FfizX)|xOfFvx<|r5G|W=z_+ILFz!|BuE`-jSEPf8MrWFkOh^ep!^IfpL7@)
zbQJ`_)e)Nnlm?X}j0_BHF9aas_o4K4D7_a-Z-vrpp!5<b-36tapmZgaE`-uLP+A2_
zzvqY8^BhX=fzn%`^fV~l2c_$vbQzS6h0>u=+6GFSKxxqYE66`QQ2uk!yetC)+kGg#
z14?gz(oImh3QFff=~O5k1EoWtv@w*{hSDrh`VTL}U+19oF(|zgN^gYHE1>iOC|wVw
z%b|1tl=gtqQczk5O0z=gzdR88zCh_WQ2I2KJ`APjK<Oz^It@z4LFqs!?FpqFptJ>)
z7KhUOQ2GTo#NG!`dJ~jh1*PXg>8Vh<2THd<Y0&&WD1P#we9*i<i0=XAgVqCp_)1WI
zG8e?YXeez3rH!C8Xx#xwy&#m&0i{8OFGzecWVo3PRDOZ@Zjga5HajTI45fcVCV<#>
zLFr9UIu}Z(LTM`~Z3Lw?p|m2D=77?m!U$v^sC)p??;(R3Y*(Q487RFLN-u@dT2NXE
zO8<ha;bZ#*rT0VW?NE9;lm@j2LH5)``Q=bL9ZJVTX;&z13#Ij-v>KEahSJ<n`Zr|F
zAlqjs{TNE$hSCS2^iC+f3Q8}6(*01n9ZHu&>3k?152eGQv@Mi2h0<zJS`JEIhP3wC
zPDANVDBTF9i=cECl(vJ?W>8ukO3Op(7m&^>+XE;KT2INvz`zDtKM0~hYYsu-3R;&4
z;^#o)7t~Gzi90~cQB^1{3#CErG?4r+Xt{@8uI_}2Z-mm5p>#KtE`ZV*P}&ztyFzI#
zD6IsgS)lYEXt{R}N?(K0JD~IiC=J>}26A5)l%E5oQ=qgPl(vJ?3Q$@CO8<hEd!L{*
zsGSEg?>v;h1xl}h(i5R{CzQ^E(rHlI8%l%L+JMZ_fbtcfG%J+;3oZX1LFrpidOwuj
z4y9*8>4{Lf4NBKR=>jO70j0g5G-xjb$bNGuUmr><LTO1T{To^yeumPZp>~kI2T=Yc
zD18b_uYuA_p!7^AJrPPbLut@jCXhL?P(Eml6Nv8x<%8Bef%qm+z7CY;gVJnJ`Zu)v
z{0ya^Lg~9udOwuj4yD&X=_OEl8kFvX(gjdD14_q2=};)`4y8fuW{~?7p?paw%?G8~
zp!5%DIsE}jUxL!7pfqTq0?3^0Q2t6Ny%0(_L+NTLT>zyspmY?J2CYQ{nPURwgWB65
zz9N(lt3SA*d}b*9loL|#+=bGYp!6vyy$4Effzs2UbRU#%hSJqgIu}Z(LTPs>Z4aeQ
zptKH@mV?q_Q2IBt9{UWXuR-Z^Q2HR0-U+4GK<On=x)Vx++V3F$mqGb?P&yDwdqQc@
z9wU%C6)2w_O8;kvgv%o+eG5wOh0<H0^b9CH0ZNxb>0Brs1f{*8v<;LtfzoPFS`JDJ
zKxxqaDUiGVLhJ3XQ2GXxz5u1SLg}?odJ>fGg3>im8njOfWL_GS9|xsD`?x^j9#Fn5
zls1LZT2LC)Zvd%dh4TMG>xU0e8nj0YB!3&qzYL|1Lg~FwdIOYR0i|a{>B&&K97^Xy
z>0~G!4W&W-6p%e`P(FG)MGY!02c?;y^e<>T;~kWK2BmL7=}S<0JCt4zr9u1XK=$=O
z`HfJz5=uiSZ`i`1d}}BT-HXPi0p)}C>4D5)h4TMG+Z~|&d?4`~Q2uEseHcn_gVO7u
z^g<{-6H0^j2ZHpMK>6tHpdhHY7nFvzhfJY-(0)UZeg!BWy<PMV+8%-KsbISa<zIx-
zp#66s{m}g|Y!jj4olrUlN~b_+cPMQSrH!Dp7L?|P((F+B4Yd981WKQT(g&gRGAKO{
zN>7H;-B7v!N@qanSSTF|rLCZ}5tK%6H!(rQe?i+#pgjN}|3U}<*+BbIKzz`?0uT+_
ze*mI)L)C-!Er9r-eN-SCx^RbWB2*sK{{@MI`oADL5h@-DrR|_JsGkdx2Q6^~(ZW!1
z&~yNZ59$Vk=nANN(fyqO6$fn`2B~v^@-3jW0hE@2($LXnHV!Bs)V~MmLvKf-`yaFy
z1EdbR8i@_Ge*?q^jW2>|=$<gP2B`Z%dqzOw1yFtjlm_il0f~bqS3oqVzYn58dt5-Y
z0aTp?lm@k1LE`A)0orFG#K6D@vd@Bnfe&PlAOizm0s{jBh!3(yfPsMzWIl)wGMAr$
zfe+Lk2Ju1W@-Z-gw(Nk_gZ6>(F))NcX_gmEV95|D&GH1whtez$pnNFJatF$X(kwTi
zd??KV+WQGIA4;=afXYK@7SJ9$kUW%TIRTZ2(kw@yd??Lw0Lq8bEPJ4QD9y41%7@Y{
zp!^InA4;=qfXYK@7EnG1$wO(D6;OF7&9Vf_htezypnNFJG6%|s(kwHed??KV+5-tP
zA4;=KfXYK@mL4b{O0#r8`B0jr1<HrgEDcaTlxC@c@}V?K1(Xk^SwMS+LH0vwmIA0e
zlx6{yXCQef&5{9?hte#dat<U9rCAc7@=%&32Fi!hED=yXlx7Km@}V?K0F)1<S$v>;
zD9r-e%L=j&O0&2?<)Ji-1C$S?S!|$uD9vI4<wI!}6DS`_vw-#-g3O1~EILqmD9xe)
z<wI!}6(}D{vnW9MP?|*s%7@Y{5>P&rW)Xq%p)?C<?>ESPD9yqHm50(S98f-#W?_Ny
zp)`0ADo8(QF)AMe1Ir&qNPdOVEI*)pD9!Q(%7@Y{AE10F%>t^AK;}VdmKRWYD9r+@
zr$F*hn&kmh9!j&^f%2g=%MB<WO0!&n@}V@#1t=d%vw+Gk0S1N;D9r-ehX>+AX_gGg
z84n>)ngz6X4<rwzSwQ6;h!3S%Vxa1wGz+Nw1<6BcmOGpb41x>{AyAs-29yt_S*}3&
zP@3feln<p@&OrH4n&kwP52aa-K>1Lb<p7iqrCC7z50L#(nq>!69!j%-`XwNFD9y3~
zDi5Vu)<F4Cnq>u)52aa_K>1LbWdW2ArCH`c`B0h#G%o?N4@$F4fyzT^mI+WklxFFH
z@}V?K2b2$`Sz4fcD9zFU<wI$f8Ymx1vs6I&P@1I#%7@Y{p!pJz`=B&S4pbgWvt&T|
zP?`lauL4pJrCAc7@=%&32Fi!hED=yXlx7Km@}V?K0F)1<S$v>;D9z#l<wI!}7bqV}
zvp7KcP@2UC%7@Y{7EnHvW&!mlLGFjrECx_{D9r-uXM*IRG>ZmQ9!j&QK>1LbMFGl(
z(kwDiK9pvWfbyX<iwKktrC9`^d??Mr1LZ?$77i#MO0%#)`B0jL0m_HcEPps4`4397
z{DAVIG|Lw#A4;=)fbyX<%Nr;kO0&Fx@}V@#6DS`_vpj(Ep)|`KC?86*+<@|-G|Lqz
zA4;=afbyX<%NZyiO0%4R@}V@#5hx!@vmAi(p)?C<-VPLhP?}{2R31vRY=QEjG|L7k
zA4;=;#s@(9p)?C<-Velw(k!5H0}vldvn+t>hte!_pnNFJG6Two(kxS;d??KVnnwhg
z2c=nhpz=_fr31=`(kv}dK9pu@fbyX<OAV9{rCBPVd??KVnx6#O2c=mGpz=_fB?rof
z(kvNJK9pujf%2g=O9GS+rCDO2d??Kl0p&w!mJlc(O0$5@YXP|jO0)Pt<)Ji-2b2$`
zSzMreD9r+zUj^xh(kwPmc___d0p&w!7858RO0yV1`B0h#G`<5e4@$FWK;@w{3uxR2
zBoC!o6rl1@nguk!3zCP@ED}(8D9s`Q<wI!}0Vp3zv+zLqP?`mFwhhQUD9yqGm50(S
zp!HoKc__{DhaH;#Av6o<d>oKGlxFz?5f6dVEFYkJD9r+zhX$#K(k!4ec0hb6&GH1Q
z9!j%3fbyX<%N-~mO0(R6@}V>f=-eKVc~F|=0#qJKvz&qQp)?EVd@GQ8D9r*o`v=5_
z(kus{>Y+5t9w;A5v+RKKp)?EV{2-8iD9y3~Di5Vu)<F4Cnq>u)52aZ^XApt(Lur-;
zP<bfLG6%|s(k!6yK9G7S%>p{d2*iidETC~f5Fbjj^g#7PX_gKsA4;=;&O!pIhtez!
zP<bfLQUm2fX_g8oA4;=;&Qk*EhtezsP<bfLk^|*KX_gEqA4;=;&SV1Vhte#d^#>q6
zlxB&6s)y1n5l}vqW&xe+1X2&BSpuN)P@2UD%7@Y{9#B4%W&xcI1=0_tSsbA9P?`la
zUJ8<j(kvEGc__^S8b<}mLunQRs63Qr(Sh=zGz(}Q1xP)VW>JC4LunQTC?86*fX=W2
zsfW@mp!F9ZK9pt=fvShnETHjQkUW%T;epCSX%^79E=V3qv#>zrp)?C<sXa&@O0)c7
zgXVt-&GG|6hd^nTFHk;|X88c+Lur;bP(GAqc>(1^X%^7B5s-aQn&kmh9!j&^f%2g=
z3uycqq#jDMT!G3%X%^79G)Nvwvw+s2fcQ|F<pfkclx8^s<wI$f15iGcX4wPfLunS!
z8Dk*xpft-Cs63Qr*#PB3X_hrmK9ptwol^$V52aa_K;@w{%K|7LO0$60&4AQHX%^5~
zXCOY5W|;z252aZqK>1Lbr3cD~(kvZNK9pu@f%2g=O9PY-rCC7Z_aOVAG)o0k9!j%-
z#`Qt+P@1IxDi5Vua-e)D&5{A-LunS!8Ezo`P?{wHDi5VuVxW8|%@P6SLur-}C?86*
zfaViG=0Rx|AE-Q(W&zDJfaIYxiwjg9O0$5@mIKK{X%-u(Jd|d!fbyX<iwTqurCAK1
zd??ML1LZ?$77ZvLO0%dy`B0h#bjBUXekjc%1C@u;ED}&Ylx7iu@}V?~0F)1<SwQFJ
zfy{%_EF4gID9yqG<wI!}&|!@r^-!AS4=XhPLui&0;BB-FaUdGBeSHCx527U)82CWr
zzrqX*aUfcjfq@S+-V5S`Xi3nxCRDuwBlx^Wz8~NX<qUBkT8@E%545@%q#i^|F);9f
z#%)1-5G@8WAF3WSZY#pTzy}&X1<8YGQIPpidC>T&I0FOU3l;_j(46R-Y{)`f(E1P%
z|09$SS~tSS%fRp;7b4Hb3Q_+ZD$fVy+vY&z#h`ozC?7P>12T^d$_LH=fcUvkz8+M4
zCzNjn<ugF-vxo9mLFL_{{4Y>GXj3}Kyk}5;Bvk$_l%E9UZ-Mf&q5LCIKIlwEkp3%B
zel1j92x@;Dl&=Bh_k;LC3=A`-K>X{?$iTqQ$iSco;eyX40`Xz%ib3Q0AU<gP7CHw2
zRu5u>a4!o)e>e0jtVkvZKMFKZ4mz(1YW^+gifzz1A;>&_sQePBer?cURiLw;p!^)D
zd7yDUka|%20c0QO3^9H#28M=d5C<26?Bil!H~{5?#*ra1Ak_>EA&_||2#0}z!2yjw
zAC3PAjSpQX1lRuyGH(RugVs<Z+b55vA2be+EDt(^4w(;HAA`(42bphxn-5z5h%65}
zQWlvXil%-e8XvSv2U$HkWPT8Cz7-nZ7me=>nV*5H2c7SQY~C?6^`LQ0WO+Wc@S2Eb
z-c~d|=$uDn{m^+jxczx(_Ps^Z&xIEL$I$GDuHS;22VExy=jWs8UxH@-c{F|-ntJH`
zDBL{I8I;KWF+y|yUNrtqH1k)X@gJe_`_TLcU9SeW{~Mb7EYZ|6#K%V&83ZI26{iNE
z-u48!GSn1wb3hLGLT>2gR-mi9<D)<~aiUyY1-WH7J}R#~7i1<#9(p@B_~LcQ)z%Pw
z&<nSW-BU|k{et7MTmkM1HUf0jIpl^<^N@V-{TiS<LgJ(R5E6z4U~%yA`%p>r+pi#(
zcg9B<nmK}Qf&tz55L}uJy7MSAz!3Sy)L?`7V9=#p5Jwt?Sr{5a@AY)g$xlkm!F799
ze0)?&PCyyR$%ZB&`A&(YDbD$M#U+V(pbNU=qYN!V@<BHNfbMcZk+5*}^p6L*C&03_
z402@+=qPx|H9hgk8QJmarHMr;pv!ks^BCewlG9U55=%;o7~+%Dic?FVceg+|(0g0r
zi}MPKGV@B(K+4lVSDk<u#V~!~bGI4d<3V?A<rgu;7nc-)FOy*a-#wKIk^$cl1hzaa
zF*66`DNB$u!S}eJxD$LPH(VZkbq0!jd=%J!pfluA#B=hKvpw@NOEMF4GK*7F7~*p>
zi%X!F0>zh>L0Ivbd6^{)@!&JIL018Q&;JKqSP+kV14(dd2{`5%;<G*deG`jIQj0)`
z<GZA$C4w&CL1=eRErFQ;Jsi9kWH{^;eb9w{4Ds2{ZjL$NQ~UFakc@!cGw2Gs&p9|X
zu_!si*)5<bzaX`!q>=%CH4NxF3h13Y@y>40Yd#p_a}z;Ef<rpFppqdzH#N67wS)oT
zQBZI|q(R61d-_9i8C*Z)au<-{&?E)A>m@w1B*Uq)Bo*ul$fYM}m#w(v7ePG=av?~M
zduj=Yf@*_@b7>yL0iY|+i%sH#QVWa>;)CN;a|=o;<BL*3cShwGC8npkf}IZbLUBn^
z4k$f>wU{LqgRW|F4e(Be<on<fL(_Orq{rvwr=-RwB^IZeWaQ^(gRk$2Pb*3VrLrh+
zngU<NgOWDlqs&2xEjYCVO&F{md?gQxL`iZA=$al-x^;Gg<t<1ofbYc!N=-{GO3h17
zW$=mDD=sO5QicpU@x|qtCCM3j;Oiuy!p2bA3`(0qX%i@I4y7%iv>}XP2@`;+FobC}
hgqdY%08?WKW5BF4glRW2WN`I}PXpao0$L`(007QnX)yo*

diff --git a/input_devices/mag/node_modules/serialport/build/action_after_build.target.mk b/input_devices/mag/node_modules/serialport/build/action_after_build.target.mk
deleted file mode 100644
index 337e6f18..00000000
--- a/input_devices/mag/node_modules/serialport/build/action_after_build.target.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := action_after_build
-### Generated for copy rule.
-/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node: TOOLSET := $(TOOLSET)
-/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node: $(builddir)/serialport.node FORCE_DO_CMD
-	$(call do_cmd,copy)
-
-all_deps += /Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node
-binding_gyp_action_after_build_target_copies = /Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64/serialport.node
-
-### Rules for final target.
-# Build our special outputs first.
-$(obj).target/action_after_build.stamp: | $(binding_gyp_action_after_build_target_copies)
-
-# Preserve order dependency of special output on deps.
-$(binding_gyp_action_after_build_target_copies): | $(builddir)/serialport.node
-
-$(obj).target/action_after_build.stamp: TOOLSET := $(TOOLSET)
-$(obj).target/action_after_build.stamp: $(builddir)/serialport.node FORCE_DO_CMD
-	$(call do_cmd,touch)
-
-all_deps += $(obj).target/action_after_build.stamp
-# Add target alias
-.PHONY: action_after_build
-action_after_build: $(obj).target/action_after_build.stamp
-
-# Add target alias to "all" target.
-.PHONY: all
-all: action_after_build
-
diff --git a/input_devices/mag/node_modules/serialport/build/binding.Makefile b/input_devices/mag/node_modules/serialport/build/binding.Makefile
deleted file mode 100644
index 043866b0..00000000
--- a/input_devices/mag/node_modules/serialport/build/binding.Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-export builddir_name ?= ./build/.
-.PHONY: all
-all:
-	$(MAKE) serialport action_after_build
diff --git a/input_devices/mag/node_modules/serialport/build/config.gypi b/input_devices/mag/node_modules/serialport/build/config.gypi
deleted file mode 100644
index 1db53a88..00000000
--- a/input_devices/mag/node_modules/serialport/build/config.gypi
+++ /dev/null
@@ -1,140 +0,0 @@
-# Do not edit. File was generated by node-gyp's "configure" step
-{
-  "target_defaults": {
-    "cflags": [],
-    "default_configuration": "Release",
-    "defines": [],
-    "include_dirs": [],
-    "libraries": []
-  },
-  "variables": {
-    "clang": 1,
-    "host_arch": "x64",
-    "node_install_npm": "false",
-    "node_prefix": "/usr/local/Cellar/node/0.10.36",
-    "node_shared_cares": "false",
-    "node_shared_http_parser": "false",
-    "node_shared_libuv": "false",
-    "node_shared_openssl": "false",
-    "node_shared_v8": "false",
-    "node_shared_zlib": "false",
-    "node_tag": "",
-    "node_unsafe_optimizations": 0,
-    "node_use_dtrace": "true",
-    "node_use_etw": "false",
-    "node_use_openssl": "true",
-    "node_use_perfctr": "false",
-    "openssl_no_asm": 0,
-    "python": "/usr/local/opt/python/bin/python2.7",
-    "target_arch": "x64",
-    "v8_enable_gdbjit": 0,
-    "v8_no_strict_aliasing": 1,
-    "v8_use_snapshot": "true",
-    "want_separate_host_toolset": 0,
-    "nodedir": "/Users/webgeek/.node-gyp/0.10.36",
-    "copy_dev_lib": "true",
-    "standalone_static_library": 1,
-    "name": "serialport",
-    "configuration": "Release",
-    "module_name": "serialport",
-    "version": "",
-    "major": "1",
-    "minor": "6",
-    "patch": "3",
-    "runtime": "node",
-    "node_abi": "node-v11",
-    "platform": "darwin",
-    "target_platform": "darwin",
-    "module_main": "./serialport",
-    "host": "https://node-serialport.s3.amazonaws.com/",
-    "module_path": "/Users/webgeek/Projects/node-serialport/build/serialport/v1.6.3/Release/node-v11-darwin-x64",
-    "remote_path": "./serialport/v1.6.3/Release/",
-    "package_name": "node-v11-darwin-x64.tar.gz",
-    "staged_tarball": "build/stage/serialport/v1.6.3/Release/node-v11-darwin-x64.tar.gz",
-    "hosted_path": "https://node-serialport.s3.amazonaws.com/serialport/v1.6.3/Release/",
-    "hosted_tarball": "https://node-serialport.s3.amazonaws.com/serialport/v1.6.3/Release/node-v11-darwin-x64.tar.gz",
-    "save_dev": "",
-    "viewer": "man",
-    "browser": "",
-    "rollback": "true",
-    "usage": "",
-    "globalignorefile": "/usr/local/etc/npmignore",
-    "shell": "/bin/bash",
-    "init_author_url": "",
-    "shrinkwrap": "true",
-    "parseable": "",
-    "init_license": "ISC",
-    "email": "voodootikigod@gmail.com",
-    "sign_git_tag": "",
-    "init_author_email": "",
-    "cache_max": "Infinity",
-    "long": "",
-    "local_address": "",
-    "git_tag_version": "true",
-    "cert": "",
-    "registry": "https://registry.npmjs.org/",
-    "npat": "",
-    "fetch_retries": "2",
-    "versions": "",
-    "message": "%s",
-    "key": "",
-    "globalconfig": "/usr/local/etc/npmrc",
-    "always_auth": "",
-    "spin": "true",
-    "cache_lock_retries": "10",
-    "cafile": "",
-    "heading": "npm",
-    "proprietary_attribs": "true",
-    "fetch_retry_mintimeout": "10000",
-    "json": "",
-    "access": "",
-    "https_proxy": "",
-    "engine_strict": "",
-    "description": "true",
-    "userconfig": "/Users/webgeek/.npmrc",
-    "init_module": "/Users/webgeek/.npm-init.js",
-    "user": "501",
-    "node_version": "0.10.36",
-    "save": "",
-    "editor": "/usr/local/bin/subl -w",
-    "tag": "latest",
-    "global": "",
-    "optional": "true",
-    "force": "",
-    "bin_links": "true",
-    "searchopts": "",
-    "depth": "Infinity",
-    "searchsort": "name",
-    "rebuild_bundle": "true",
-    "unicode": "true",
-    "fetch_retry_maxtimeout": "60000",
-    "strict_ssl": "true",
-    "save_prefix": "^",
-    "ca": "",
-    "save_exact": "",
-    "group": "20",
-    "fetch_retry_factor": "10",
-    "dev": "",
-    "cache_lock_stale": "60000",
-    "cache_min": "10",
-    "searchexclude": "",
-    "cache": "/Users/webgeek/.npm",
-    "color": "true",
-    "save_optional": "",
-    "ignore_scripts": "",
-    "user_agent": "npm/2.5.1 node/v0.10.36 darwin x64",
-    "cache_lock_wait": "10000",
-    "production": "",
-    "save_bundle": "",
-    "umask": "0022",
-    "init_version": "1.0.0",
-    "scope": "",
-    "init_author_name": "",
-    "git": "git",
-    "unsafe_perm": "true",
-    "tmp": "/var/folders/dt/m043hkss4tv3mt5tfqf05jd00000gn/T",
-    "onload_script": "",
-    "link": "",
-    "prefix": "/usr/local"
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/build/gyp-mac-tool b/input_devices/mag/node_modules/serialport/build/gyp-mac-tool
deleted file mode 100755
index 7abfed5f..00000000
--- a/input_devices/mag/node_modules/serialport/build/gyp-mac-tool
+++ /dev/null
@@ -1,512 +0,0 @@
-#!/usr/bin/env python
-# Generated by gyp. Do not edit.
-# Copyright (c) 2012 Google Inc. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Utility functions to perform Xcode-style build steps.
-
-These functions are executed via gyp-mac-tool when using the Makefile generator.
-"""
-
-import fcntl
-import fnmatch
-import glob
-import json
-import os
-import plistlib
-import re
-import shutil
-import string
-import subprocess
-import sys
-import tempfile
-
-
-def main(args):
-  executor = MacTool()
-  exit_code = executor.Dispatch(args)
-  if exit_code is not None:
-    sys.exit(exit_code)
-
-
-class MacTool(object):
-  """This class performs all the Mac tooling steps. The methods can either be
-  executed directly, or dispatched from an argument list."""
-
-  def Dispatch(self, args):
-    """Dispatches a string command to a method."""
-    if len(args) < 1:
-      raise Exception("Not enough arguments")
-
-    method = "Exec%s" % self._CommandifyName(args[0])
-    return getattr(self, method)(*args[1:])
-
-  def _CommandifyName(self, name_string):
-    """Transforms a tool name like copy-info-plist to CopyInfoPlist"""
-    return name_string.title().replace('-', '')
-
-  def ExecCopyBundleResource(self, source, dest):
-    """Copies a resource file to the bundle/Resources directory, performing any
-    necessary compilation on each resource."""
-    extension = os.path.splitext(source)[1].lower()
-    if os.path.isdir(source):
-      # Copy tree.
-      # TODO(thakis): This copies file attributes like mtime, while the
-      # single-file branch below doesn't. This should probably be changed to
-      # be consistent with the single-file branch.
-      if os.path.exists(dest):
-        shutil.rmtree(dest)
-      shutil.copytree(source, dest)
-    elif extension == '.xib':
-      return self._CopyXIBFile(source, dest)
-    elif extension == '.storyboard':
-      return self._CopyXIBFile(source, dest)
-    elif extension == '.strings':
-      self._CopyStringsFile(source, dest)
-    else:
-      shutil.copy(source, dest)
-
-  def _CopyXIBFile(self, source, dest):
-    """Compiles a XIB file with ibtool into a binary plist in the bundle."""
-
-    # ibtool sometimes crashes with relative paths. See crbug.com/314728.
-    base = os.path.dirname(os.path.realpath(__file__))
-    if os.path.relpath(source):
-      source = os.path.join(base, source)
-    if os.path.relpath(dest):
-      dest = os.path.join(base, dest)
-
-    args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices',
-        '--output-format', 'human-readable-text', '--compile', dest, source]
-    ibtool_section_re = re.compile(r'/\*.*\*/')
-    ibtool_re = re.compile(r'.*note:.*is clipping its content')
-    ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE)
-    current_section_header = None
-    for line in ibtoolout.stdout:
-      if ibtool_section_re.match(line):
-        current_section_header = line
-      elif not ibtool_re.match(line):
-        if current_section_header:
-          sys.stdout.write(current_section_header)
-          current_section_header = None
-        sys.stdout.write(line)
-    return ibtoolout.returncode
-
-  def _CopyStringsFile(self, source, dest):
-    """Copies a .strings file using iconv to reconvert the input into UTF-16."""
-    input_code = self._DetectInputEncoding(source) or "UTF-8"
-
-    # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call
-    # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints
-    #     CFPropertyListCreateFromXMLData(): Old-style plist parser: missing
-    #     semicolon in dictionary.
-    # on invalid files. Do the same kind of validation.
-    import CoreFoundation
-    s = open(source, 'rb').read()
-    d = CoreFoundation.CFDataCreate(None, s, len(s))
-    _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None)
-    if error:
-      return
-
-    fp = open(dest, 'wb')
-    fp.write(s.decode(input_code).encode('UTF-16'))
-    fp.close()
-
-  def _DetectInputEncoding(self, file_name):
-    """Reads the first few bytes from file_name and tries to guess the text
-    encoding. Returns None as a guess if it can't detect it."""
-    fp = open(file_name, 'rb')
-    try:
-      header = fp.read(3)
-    except e:
-      fp.close()
-      return None
-    fp.close()
-    if header.startswith("\xFE\xFF"):
-      return "UTF-16"
-    elif header.startswith("\xFF\xFE"):
-      return "UTF-16"
-    elif header.startswith("\xEF\xBB\xBF"):
-      return "UTF-8"
-    else:
-      return None
-
-  def ExecCopyInfoPlist(self, source, dest, *keys):
-    """Copies the |source| Info.plist to the destination directory |dest|."""
-    # Read the source Info.plist into memory.
-    fd = open(source, 'r')
-    lines = fd.read()
-    fd.close()
-
-    # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild).
-    plist = plistlib.readPlistFromString(lines)
-    if keys:
-      plist = dict(plist.items() + json.loads(keys[0]).items())
-    lines = plistlib.writePlistToString(plist)
-
-    # Go through all the environment variables and replace them as variables in
-    # the file.
-    IDENT_RE = re.compile('[/\s]')
-    for key in os.environ:
-      if key.startswith('_'):
-        continue
-      evar = '${%s}' % key
-      evalue = os.environ[key]
-      lines = string.replace(lines, evar, evalue)
-
-      # Xcode supports various suffices on environment variables, which are
-      # all undocumented. :rfc1034identifier is used in the standard project
-      # template these days, and :identifier was used earlier. They are used to
-      # convert non-url characters into things that look like valid urls --
-      # except that the replacement character for :identifier, '_' isn't valid
-      # in a URL either -- oops, hence :rfc1034identifier was born.
-      evar = '${%s:identifier}' % key
-      evalue = IDENT_RE.sub('_', os.environ[key])
-      lines = string.replace(lines, evar, evalue)
-
-      evar = '${%s:rfc1034identifier}' % key
-      evalue = IDENT_RE.sub('-', os.environ[key])
-      lines = string.replace(lines, evar, evalue)
-
-    # Remove any keys with values that haven't been replaced.
-    lines = lines.split('\n')
-    for i in range(len(lines)):
-      if lines[i].strip().startswith("<string>${"):
-        lines[i] = None
-        lines[i - 1] = None
-    lines = '\n'.join(filter(lambda x: x is not None, lines))
-
-    # Write out the file with variables replaced.
-    fd = open(dest, 'w')
-    fd.write(lines)
-    fd.close()
-
-    # Now write out PkgInfo file now that the Info.plist file has been
-    # "compiled".
-    self._WritePkgInfo(dest)
-
-  def _WritePkgInfo(self, info_plist):
-    """This writes the PkgInfo file from the data stored in Info.plist."""
-    plist = plistlib.readPlist(info_plist)
-    if not plist:
-      return
-
-    # Only create PkgInfo for executable types.
-    package_type = plist['CFBundlePackageType']
-    if package_type != 'APPL':
-      return
-
-    # The format of PkgInfo is eight characters, representing the bundle type
-    # and bundle signature, each four characters. If that is missing, four
-    # '?' characters are used instead.
-    signature_code = plist.get('CFBundleSignature', '????')
-    if len(signature_code) != 4:  # Wrong length resets everything, too.
-      signature_code = '?' * 4
-
-    dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo')
-    fp = open(dest, 'w')
-    fp.write('%s%s' % (package_type, signature_code))
-    fp.close()
-
-  def ExecFlock(self, lockfile, *cmd_list):
-    """Emulates the most basic behavior of Linux's flock(1)."""
-    # Rely on exception handling to report errors.
-    fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666)
-    fcntl.flock(fd, fcntl.LOCK_EX)
-    return subprocess.call(cmd_list)
-
-  def ExecFilterLibtool(self, *cmd_list):
-    """Calls libtool and filters out '/path/to/libtool: file: foo.o has no
-    symbols'."""
-    libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$')
-    libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE)
-    _, err = libtoolout.communicate()
-    for line in err.splitlines():
-      if not libtool_re.match(line):
-        print >>sys.stderr, line
-    return libtoolout.returncode
-
-  def ExecPackageFramework(self, framework, version):
-    """Takes a path to Something.framework and the Current version of that and
-    sets up all the symlinks."""
-    # Find the name of the binary based on the part before the ".framework".
-    binary = os.path.basename(framework).split('.')[0]
-
-    CURRENT = 'Current'
-    RESOURCES = 'Resources'
-    VERSIONS = 'Versions'
-
-    if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)):
-      # Binary-less frameworks don't seem to contain symlinks (see e.g.
-      # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle).
-      return
-
-    # Move into the framework directory to set the symlinks correctly.
-    pwd = os.getcwd()
-    os.chdir(framework)
-
-    # Set up the Current version.
-    self._Relink(version, os.path.join(VERSIONS, CURRENT))
-
-    # Set up the root symlinks.
-    self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary)
-    self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES)
-
-    # Back to where we were before!
-    os.chdir(pwd)
-
-  def _Relink(self, dest, link):
-    """Creates a symlink to |dest| named |link|. If |link| already exists,
-    it is overwritten."""
-    if os.path.lexists(link):
-      os.remove(link)
-    os.symlink(dest, link)
-
-  def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning):
-    """Code sign a bundle.
-
-    This function tries to code sign an iOS bundle, following the same
-    algorithm as Xcode:
-      1. copy ResourceRules.plist from the user or the SDK into the bundle,
-      2. pick the provisioning profile that best match the bundle identifier,
-         and copy it into the bundle as embedded.mobileprovision,
-      3. copy Entitlements.plist from user or SDK next to the bundle,
-      4. code sign the bundle.
-    """
-    resource_rules_path = self._InstallResourceRules(resource_rules)
-    substitutions, overrides = self._InstallProvisioningProfile(
-        provisioning, self._GetCFBundleIdentifier())
-    entitlements_path = self._InstallEntitlements(
-        entitlements, substitutions, overrides)
-    subprocess.check_call([
-        'codesign', '--force', '--sign', key, '--resource-rules',
-        resource_rules_path, '--entitlements', entitlements_path,
-        os.path.join(
-            os.environ['TARGET_BUILD_DIR'],
-            os.environ['FULL_PRODUCT_NAME'])])
-
-  def _InstallResourceRules(self, resource_rules):
-    """Installs ResourceRules.plist from user or SDK into the bundle.
-
-    Args:
-      resource_rules: string, optional, path to the ResourceRules.plist file
-        to use, default to "${SDKROOT}/ResourceRules.plist"
-
-    Returns:
-      Path to the copy of ResourceRules.plist into the bundle.
-    """
-    source_path = resource_rules
-    target_path = os.path.join(
-        os.environ['BUILT_PRODUCTS_DIR'],
-        os.environ['CONTENTS_FOLDER_PATH'],
-        'ResourceRules.plist')
-    if not source_path:
-      source_path = os.path.join(
-          os.environ['SDKROOT'], 'ResourceRules.plist')
-    shutil.copy2(source_path, target_path)
-    return target_path
-
-  def _InstallProvisioningProfile(self, profile, bundle_identifier):
-    """Installs embedded.mobileprovision into the bundle.
-
-    Args:
-      profile: string, optional, short name of the .mobileprovision file
-        to use, if empty or the file is missing, the best file installed
-        will be used
-      bundle_identifier: string, value of CFBundleIdentifier from Info.plist
-
-    Returns:
-      A tuple containing two dictionary: variables substitutions and values
-      to overrides when generating the entitlements file.
-    """
-    source_path, provisioning_data, team_id = self._FindProvisioningProfile(
-        profile, bundle_identifier)
-    target_path = os.path.join(
-        os.environ['BUILT_PRODUCTS_DIR'],
-        os.environ['CONTENTS_FOLDER_PATH'],
-        'embedded.mobileprovision')
-    shutil.copy2(source_path, target_path)
-    substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.')
-    return substitutions, provisioning_data['Entitlements']
-
-  def _FindProvisioningProfile(self, profile, bundle_identifier):
-    """Finds the .mobileprovision file to use for signing the bundle.
-
-    Checks all the installed provisioning profiles (or if the user specified
-    the PROVISIONING_PROFILE variable, only consult it) and select the most
-    specific that correspond to the bundle identifier.
-
-    Args:
-      profile: string, optional, short name of the .mobileprovision file
-        to use, if empty or the file is missing, the best file installed
-        will be used
-      bundle_identifier: string, value of CFBundleIdentifier from Info.plist
-
-    Returns:
-      A tuple of the path to the selected provisioning profile, the data of
-      the embedded plist in the provisioning profile and the team identifier
-      to use for code signing.
-
-    Raises:
-      SystemExit: if no .mobileprovision can be used to sign the bundle.
-    """
-    profiles_dir = os.path.join(
-        os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles')
-    if not os.path.isdir(profiles_dir):
-      print >>sys.stderr, (
-          'cannot find mobile provisioning for %s' % bundle_identifier)
-      sys.exit(1)
-    provisioning_profiles = None
-    if profile:
-      profile_path = os.path.join(profiles_dir, profile + '.mobileprovision')
-      if os.path.exists(profile_path):
-        provisioning_profiles = [profile_path]
-    if not provisioning_profiles:
-      provisioning_profiles = glob.glob(
-          os.path.join(profiles_dir, '*.mobileprovision'))
-    valid_provisioning_profiles = {}
-    for profile_path in provisioning_profiles:
-      profile_data = self._LoadProvisioningProfile(profile_path)
-      app_id_pattern = profile_data.get(
-          'Entitlements', {}).get('application-identifier', '')
-      for team_identifier in profile_data.get('TeamIdentifier', []):
-        app_id = '%s.%s' % (team_identifier, bundle_identifier)
-        if fnmatch.fnmatch(app_id, app_id_pattern):
-          valid_provisioning_profiles[app_id_pattern] = (
-              profile_path, profile_data, team_identifier)
-    if not valid_provisioning_profiles:
-      print >>sys.stderr, (
-          'cannot find mobile provisioning for %s' % bundle_identifier)
-      sys.exit(1)
-    # If the user has multiple provisioning profiles installed that can be
-    # used for ${bundle_identifier}, pick the most specific one (ie. the
-    # provisioning profile whose pattern is the longest).
-    selected_key = max(valid_provisioning_profiles, key=lambda v: len(v))
-    return valid_provisioning_profiles[selected_key]
-
-  def _LoadProvisioningProfile(self, profile_path):
-    """Extracts the plist embedded in a provisioning profile.
-
-    Args:
-      profile_path: string, path to the .mobileprovision file
-
-    Returns:
-      Content of the plist embedded in the provisioning profile as a dictionary.
-    """
-    with tempfile.NamedTemporaryFile() as temp:
-      subprocess.check_call([
-          'security', 'cms', '-D', '-i', profile_path, '-o', temp.name])
-      return self._LoadPlistMaybeBinary(temp.name)
-
-  def _LoadPlistMaybeBinary(self, plist_path):
-    """Loads into a memory a plist possibly encoded in binary format.
-
-    This is a wrapper around plistlib.readPlist that tries to convert the
-    plist to the XML format if it can't be parsed (assuming that it is in
-    the binary format).
-
-    Args:
-      plist_path: string, path to a plist file, in XML or binary format
-
-    Returns:
-      Content of the plist as a dictionary.
-    """
-    try:
-      # First, try to read the file using plistlib that only supports XML,
-      # and if an exception is raised, convert a temporary copy to XML and
-      # load that copy.
-      return plistlib.readPlist(plist_path)
-    except:
-      pass
-    with tempfile.NamedTemporaryFile() as temp:
-      shutil.copy2(plist_path, temp.name)
-      subprocess.check_call(['plutil', '-convert', 'xml1', temp.name])
-      return plistlib.readPlist(temp.name)
-
-  def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix):
-    """Constructs a dictionary of variable substitutions for Entitlements.plist.
-
-    Args:
-      bundle_identifier: string, value of CFBundleIdentifier from Info.plist
-      app_identifier_prefix: string, value for AppIdentifierPrefix
-
-    Returns:
-      Dictionary of substitutions to apply when generating Entitlements.plist.
-    """
-    return {
-      'CFBundleIdentifier': bundle_identifier,
-      'AppIdentifierPrefix': app_identifier_prefix,
-    }
-
-  def _GetCFBundleIdentifier(self):
-    """Extracts CFBundleIdentifier value from Info.plist in the bundle.
-
-    Returns:
-      Value of CFBundleIdentifier in the Info.plist located in the bundle.
-    """
-    info_plist_path = os.path.join(
-        os.environ['TARGET_BUILD_DIR'],
-        os.environ['INFOPLIST_PATH'])
-    info_plist_data = self._LoadPlistMaybeBinary(info_plist_path)
-    return info_plist_data['CFBundleIdentifier']
-
-  def _InstallEntitlements(self, entitlements, substitutions, overrides):
-    """Generates and install the ${BundleName}.xcent entitlements file.
-
-    Expands variables "$(variable)" pattern in the source entitlements file,
-    add extra entitlements defined in the .mobileprovision file and the copy
-    the generated plist to "${BundlePath}.xcent".
-
-    Args:
-      entitlements: string, optional, path to the Entitlements.plist template
-        to use, defaults to "${SDKROOT}/Entitlements.plist"
-      substitutions: dictionary, variable substitutions
-      overrides: dictionary, values to add to the entitlements
-
-    Returns:
-      Path to the generated entitlements file.
-    """
-    source_path = entitlements
-    target_path = os.path.join(
-        os.environ['BUILT_PRODUCTS_DIR'],
-        os.environ['PRODUCT_NAME'] + '.xcent')
-    if not source_path:
-      source_path = os.path.join(
-          os.environ['SDKROOT'],
-          'Entitlements.plist')
-    shutil.copy2(source_path, target_path)
-    data = self._LoadPlistMaybeBinary(target_path)
-    data = self._ExpandVariables(data, substitutions)
-    if overrides:
-      for key in overrides:
-        if key not in data:
-          data[key] = overrides[key]
-    plistlib.writePlist(data, target_path)
-    return target_path
-
-  def _ExpandVariables(self, data, substitutions):
-    """Expands variables "$(variable)" in data.
-
-    Args:
-      data: object, can be either string, list or dictionary
-      substitutions: dictionary, variable substitutions to perform
-
-    Returns:
-      Copy of data where each references to "$(variable)" has been replaced
-      by the corresponding value found in substitutions, or left intact if
-      the key was not found.
-    """
-    if isinstance(data, str):
-      for key, value in substitutions.iteritems():
-        data = data.replace('$(%s)' % key, value)
-      return data
-    if isinstance(data, list):
-      return [self._ExpandVariables(v, substitutions) for v in data]
-    if isinstance(data, dict):
-      return dict((k, self._ExpandVariables(data[k],
-                                            substitutions)) for k in data)
-    return data
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv[1:]))
diff --git a/input_devices/mag/node_modules/serialport/build/serialport.target.mk b/input_devices/mag/node_modules/serialport/build/serialport.target.mk
deleted file mode 100644
index 9d24f218..00000000
--- a/input_devices/mag/node_modules/serialport/build/serialport.target.mk
+++ /dev/null
@@ -1,162 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := serialport
-DEFS_Debug := \
-	'-D_DARWIN_USE_64_BIT_INODE=1' \
-	'-D_LARGEFILE_SOURCE' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DBUILDING_NODE_EXTENSION' \
-	'-DDEBUG' \
-	'-D_DEBUG'
-
-# Flags passed to all source files.
-CFLAGS_Debug := \
-	-O0 \
-	-gdwarf-2 \
-	-mmacosx-version-min=10.5 \
-	-arch x86_64 \
-	-Wall \
-	-Wendif-labels \
-	-W \
-	-Wno-unused-parameter
-
-# Flags passed to only C files.
-CFLAGS_C_Debug := \
-	-fno-strict-aliasing
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Debug := \
-	-fno-rtti \
-	-fno-exceptions \
-	-fno-threadsafe-statics \
-	-fno-strict-aliasing
-
-# Flags passed to only ObjC files.
-CFLAGS_OBJC_Debug :=
-
-# Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Debug :=
-
-INCS_Debug := \
-	-I/Users/webgeek/.node-gyp/0.10.36/src \
-	-I/Users/webgeek/.node-gyp/0.10.36/deps/uv/include \
-	-I/Users/webgeek/.node-gyp/0.10.36/deps/v8/include \
-	-I$(srcdir)/node_modules/nan
-
-DEFS_Release := \
-	'-D_DARWIN_USE_64_BIT_INODE=1' \
-	'-D_LARGEFILE_SOURCE' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DBUILDING_NODE_EXTENSION'
-
-# Flags passed to all source files.
-CFLAGS_Release := \
-	-Os \
-	-gdwarf-2 \
-	-mmacosx-version-min=10.5 \
-	-arch x86_64 \
-	-Wall \
-	-Wendif-labels \
-	-W \
-	-Wno-unused-parameter
-
-# Flags passed to only C files.
-CFLAGS_C_Release := \
-	-fno-strict-aliasing
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Release := \
-	-fno-rtti \
-	-fno-exceptions \
-	-fno-threadsafe-statics \
-	-fno-strict-aliasing
-
-# Flags passed to only ObjC files.
-CFLAGS_OBJC_Release :=
-
-# Flags passed to only ObjC++ files.
-CFLAGS_OBJCC_Release :=
-
-INCS_Release := \
-	-I/Users/webgeek/.node-gyp/0.10.36/src \
-	-I/Users/webgeek/.node-gyp/0.10.36/deps/uv/include \
-	-I/Users/webgeek/.node-gyp/0.10.36/deps/v8/include \
-	-I$(srcdir)/node_modules/nan
-
-OBJS := \
-	$(obj).target/$(TARGET)/src/serialport.o \
-	$(obj).target/$(TARGET)/src/serialport_unix.o \
-	$(obj).target/$(TARGET)/src/serialport_poller.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
-$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Debug := \
-	-framework CoreFoundation -framework IOKit \
-	-Wl,-search_paths_first \
-	-mmacosx-version-min=10.5 \
-	-arch x86_64 \
-	-L$(builddir)
-
-LIBTOOLFLAGS_Debug := \
-	-framework CoreFoundation -framework IOKit \
-	-Wl,-search_paths_first
-
-LDFLAGS_Release := \
-	-framework CoreFoundation -framework IOKit \
-	-Wl,-search_paths_first \
-	-mmacosx-version-min=10.5 \
-	-arch x86_64 \
-	-L$(builddir)
-
-LIBTOOLFLAGS_Release := \
-	-framework CoreFoundation -framework IOKit \
-	-Wl,-search_paths_first
-
-LIBS := \
-	-undefined dynamic_lookup
-
-$(builddir)/serialport.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(builddir)/serialport.node: LIBS := $(LIBS)
-$(builddir)/serialport.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))
-$(builddir)/serialport.node: TOOLSET := $(TOOLSET)
-$(builddir)/serialport.node: $(OBJS) FORCE_DO_CMD
-	$(call do_cmd,solink_module)
-
-all_deps += $(builddir)/serialport.node
-# Add target alias
-.PHONY: serialport
-serialport: $(builddir)/serialport.node
-
-# Short alias for building this executable.
-.PHONY: serialport.node
-serialport.node: $(builddir)/serialport.node
-
-# Add executable to "all" target.
-.PHONY: all
-all: $(builddir)/serialport.node
-
diff --git a/input_devices/mag/node_modules/serialport/build/serialport/v1.6.3/Release/node-v11-linux-x64/serialport.node b/input_devices/mag/node_modules/serialport/build/serialport/v1.6.3/Release/node-v11-linux-x64/serialport.node
deleted file mode 100755
index 3fa370262696ae358df90d3c89463483bfa9bc92..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 55065
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
Z^(;ozrJ%eFEiw^(S4j4OlrR_(0|4ijY=Zy*

diff --git a/input_devices/mag/node_modules/serialport/changelog.md b/input_devices/mag/node_modules/serialport/changelog.md
deleted file mode 100644
index ae2b0b3f..00000000
--- a/input_devices/mag/node_modules/serialport/changelog.md
+++ /dev/null
@@ -1,146 +0,0 @@
-Version 1.6.1
--------------
-- Upgraded to NAN 1.7.0
-- #476 adding break signal
-
-Version 1.6.0
--------------
-- Long standing issue resolved thanks to @jacobrosenthal for adding control signals into the serialport. YAY!
-- Fix for #426
-- Ability to return from inside loop #453
-- Emits for close/disconnect. #452
-
-Version 1.5.0
--------------
-- Fixed to work with io.js and node 0.11.x by upgrading to recent nan 1.6.2
-
-
-Version 1.4.8
--------------
-- Simple bump for the binary.
-
-Version 1.4.7
--------------
- - Fix for Issue #398 - Dropped sent characters on OSX and Linux
- - Fix for Issue #387 - added isOpen
- - removed a residual comment
- - Added osx control signalling
- - Fix for Issue #401
- - Fix for double write callbacks.
- - detect a serialport disconnect on linux.
-
-Version 1.4.6
--------------
- - Emit error on serialport when explicit handler present. Fixes gh-369
- - Fix for windows and Node 0.11.13 (atom-shell)
- - Fix for broken Travis-CI build.
-
-Version 1.4.5
--------------
- - Identified and report issue to node.js core about recent 0.11.x system.
- - Removed support for 0.8.x
- - Updated dependencies
-
- Version 1.4.4
- -------------
- - Fix for delete error.
-
-Version 1.3.0
--------------
-- Merged NAN integration for Node 0.8->0.11+ compatibility (#270)
-
-Version 1.2.5
--------------
-- Fixed an issue with pool handlers being global instead of instance isolation (Issue #252 and #255 thanks: foobarth !!! )
-
-
-Version 1.2.4
--------------
-- Resolved parity error under linux as reported here: https://github.com/voodootikigod/node-serialport/issues/219
-
-
-Version 1.1.3
--------------
-- Remove ATL dependency on Windows (added Visual Studio Pro requirement)
-- Update build instructions
-- Four small bugfixes
-
-Version 1.0.7
--------------
-- Guaranteed in-order delivery of messages thanks to Jay Beavers and bnoordhuis
-
-Version 1.0.6
--------------
-- Support higher baud rates in Mac OS X
-
-Version 1.0.5
--------------
-- Added flush support.
-
-Version 1.0.4
--------------
-- Fix for arduino firmata support on windows thanks to @jgautier.
-
-Version 1.0.3
--------------
-- Fixed issue 65 - https://github.com/voodootikigod/node-serialport/issues/65
-- Added note in readme about what is required for the system to be able to compile module, should solve 90% of issues.
-
-Version 1.0.2
--------------
-- Fixed issue 59 - https://github.com/voodootikigod/node-serialport/issues/59
-
-Version 1.0.1
--------------
-- Fixed items from Firmata
-- Added flexibility for options (camelcase or all lower)
-
-Version 1.0.0
--------------
-- Added Windows support thanks to Joe Ferner.
-- Merged in the various underlying changes from node-serialport2 complete thanks to Joe Ferner for that!
-- Verified against known installations.
-
-
-Version 0.6.5
--------------
-- Added SetBaudRate, SetDTR; Custom Baud Rates
-- New "close" listener when device being disconnected
-
-Version 0.2.8
--------------
-- BufferSize fix for readstream (thanks jgautier, you rock)
-
-Version 0.2.7
--------------
-- Make no port available be an exception not error emitted - Ticket #12.
-
-Version 0.2.5 - Version 0.2.6
------------------------------
-- Debugging issue with IOWatcher not holding in the event loop in node.js.
-- Converted to ReadStream instead of IOWatcher.
-
-Version 0.2.4
--------------
-- Integrated arduino tests (rwaldron)
-- Integrated options bug fix (w1nk)
-- Integrated hardware flow control for crazier serial port action (w1nk)
-
-Version 0.2.3
--------------
-- Something amazing that has since been lost and forgotten.
-
-Version 0.2.2
--------------
-- Integrated enhanced version of arduino/readline that actually buffers the data (epeli)
-
-Version 0.2.1
--------------
-- Refactored the parsing code upon data receipt, now allows for dynamic specification of how incoming data is handled.
-- Revised creation interface to use named parameters as an object versions positional parameters.
-
-Version: 0.2
-------------
-- Upgraded to node v. 0.4.X compatibility
-
-All other version are not recorded.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/examples/break.js b/input_devices/mag/node_modules/serialport/examples/break.js
deleted file mode 100644
index d5d3e09c..00000000
--- a/input_devices/mag/node_modules/serialport/examples/break.js
+++ /dev/null
@@ -1,39 +0,0 @@
-////////////////////////////////////////////////////////
-// Use the cool library                               //
-// git://github.com/voodootikigod/node-serialport.git //
-// to send break condition.                           //
-////////////////////////////////////////////////////////               
-var com = require("serialport");
-
-var serialPort = new com.SerialPort("/dev/tty.usbserial-A700eTSd", {
-    baudrate: 115200,
-    parser: com.parsers.readline('\r\n')
-  }, false);
-
-serialPort.on('open',function() {
-  console.log('Port open');
-});
-
-serialPort.on('data', function(data) {
-  console.log(data);
-});
-
-function asserting() {
-  console.log('asserting');
-  serialPort.set({brk:true}, function(err, something) {
-    console.log('asserted');
-    setTimeout(clear, 5000);
-  });
-}
-
-function clear() {
-  console.log('clearing');
-  serialPort.set({brk:false}, function(err, something) {
-    console.log('clear');
-    setTimeout(done, 5000);
-  });
-}
-
-function done() {
-  console.log("done breaking");
-}
diff --git a/input_devices/mag/node_modules/serialport/examples/drain.js b/input_devices/mag/node_modules/serialport/examples/drain.js
deleted file mode 100644
index 4e621ca8..00000000
--- a/input_devices/mag/node_modules/serialport/examples/drain.js
+++ /dev/null
@@ -1,45 +0,0 @@
-var SerialPort = require("serialport").SerialPort;
-
-var sp = new SerialPort("/dev/cu.Cubelet-RGB", {
-  baudrate: 38400
-});
-
-sp.on('open',function() {
-  sp.on('data', function(data) {
-    console.log('>>>>>', data);
-  });
-
-  var message = new Buffer('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
-
-  function writeThenDrainThenWait(duration) {
-    console.log('Calling write...');
-    sp.write(message, function() {
-      console.log('...Write callback returned...');
-      // At this point, data may still be buffered and not sent out from the port yet (write function returns asynchrounously).
-      console.log('...Calling drain...');
-      sp.drain(function() {
-        // Now data has "left the pipe" (tcdrain[1]/FlushFileBuffers[2] finished blocking).
-        // [1] http://linux.die.net/man/3/tcdrain
-        // [2] http://msdn.microsoft.com/en-us/library/windows/desktop/aa364439(v=vs.85).aspx
-        console.log('...Drain callback returned...');
-        console.log('...Waiting', duration, 'milliseconds...');
-        setInterval(writeThenDrainThenWait, duration);
-      });
-    });
-  };
-
-  function writeThenWait(duration) {
-    console.log('Calling write...');
-    sp.write(message, function() {
-      console.log('...Write callback returned...'); // Write function call immediately returned (asynchrounous).
-      console.log('...Waiting', duration, 'milliseconds...');
-      // Even though write returned, the data may still be in the pipe, and hasn't reached your robot yet.
-      setInterval(writeThenWait, duration);
-    });
-  };
-
-  // Stuff starts happening here
-  writeThenDrainThenWait(1000);
-  //writeThenWait(1000);
-
-});
diff --git a/input_devices/mag/node_modules/serialport/examples/logger.js b/input_devices/mag/node_modules/serialport/examples/logger.js
deleted file mode 100644
index a523a858..00000000
--- a/input_devices/mag/node_modules/serialport/examples/logger.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-  Simple example that takes a command line provided serial port destination and routes the output to a file of the same name with .log appended to the port name.
-  
-  usage: node logger.js /dev/tty.usbserial <baudrate>
-  
-*/
-
-var SerialPort = require("serialport");
-var fs = require("fs");
-var port = process.argv[2];
-var baudrate = process.argv[3];
-var active = false;
-
-function attemptLogging(fd, port, baudrate) {
-  if (!active) {
-    fs.stat(port,  function (err, stats) {
-      if (!err) {
-        active = true;
-        
-        var serialPort = new SerialPort.SerialPort(port, {
-          baudrate: baudrate
-        });
-        fs.write(fd, "\n------------------------------------------------------------\nOpening SerialPort: "+target+" at "+Date.now()+"\n------------------------------------------------------------\n");  
-        serialPort.on("data", function (data) {
-          fs.write(fd, data.toString());
-        });
-        serialPort.on("close", function (data) {
-          active = false;
-          fs.write(fd, "\n------------------------------------------------------------\nClosing SerialPort: "+target+" at "+Date.now()+"\n------------------------------------------------------------\n");  
-        });
-      }
-    });
-  }
-}
-
-if (!port) {
-  console.log("You must specify a serial port location.");
-} else {
-  var target = port.split("/");
-  target = target[target.length-1]+".log";
-  if (!baudrate) {
-    baudrate = 115200;
-  }
-  fs.open("./"+target, 'w', function (err, fd) {
-    setInterval(function () {
-      if (!active) {
-        try {
-          attemptLogging(fd, port, baudrate);  
-        } catch (e) {
-          // Error means port is not available for listening.
-          active = false;
-        }
-      }
-    }, 1000);
-  });
-}
-
-
diff --git a/input_devices/mag/node_modules/serialport/examples/readdata.js b/input_devices/mag/node_modules/serialport/examples/readdata.js
deleted file mode 100644
index 7c1c44dd..00000000
--- a/input_devices/mag/node_modules/serialport/examples/readdata.js
+++ /dev/null
@@ -1,19 +0,0 @@
-////////////////////////////////////////////////////////
-// Use the cool library                               //
-// git://github.com/voodootikigod/node-serialport.git //
-// to read the serial port where arduino is sitting.  //
-////////////////////////////////////////////////////////               
-var com = require("serialport");
-
-var serialPort = new com.SerialPort("/dev/cu.usbmodemfd121", {
-    baudrate: 9600,
-    parser: com.parsers.readline('\r\n')
-  });
-
-serialPort.on('open',function() {
-  console.log('Port open');
-});
-
-serialPort.on('data', function(data) {
-  console.log(data);
-});
diff --git a/input_devices/mag/node_modules/serialport/examples/reset.js b/input_devices/mag/node_modules/serialport/examples/reset.js
deleted file mode 100644
index 535837c0..00000000
--- a/input_devices/mag/node_modules/serialport/examples/reset.js
+++ /dev/null
@@ -1,43 +0,0 @@
-////////////////////////////////////////////////////////
-// Use the cool library                               //
-// git://github.com/voodootikigod/node-serialport.git //
-// to reset an arduino.                               //
-////////////////////////////////////////////////////////               
-var com = require("serialport");
-
-var serialPort = new com.SerialPort("/dev/tty.usbmodem1411", {
-    baudrate: 115200,
-    parser: com.parsers.readline('\r\n')
-  });
-
-serialPort.on('open',function() {
-  console.log('Port open');
-  // note you get a dtr for free on port open so lets wait 5 seconds
-  // to make sure ours is seperate from that one
-  setTimeout(asserting, 5000);
-});
-
-serialPort.on('data', function(data) {
-  console.log(data);
-});
-
-function asserting() {
-  console.log('asserting');
-    //NOTE: you actually de-assert rts and dtr to toggle!
-    serialPort.set({rts:false, dtr:false}, function(err, something) {
-      console.log('asserted');
-        setTimeout(clear, 5000);
-    });
-}
-
-function clear() {
-    console.log('clearing');
-    serialPort.set({rts:true, dtr:true}, function(err, something) {
-      console.log('clear');
-        setTimeout(done, 5000);
-    });
-}
-
-function done() {
-    console.log("done resetting");
-}
diff --git a/input_devices/mag/node_modules/serialport/hwtest/package.json b/input_devices/mag/node_modules/serialport/hwtest/package.json
deleted file mode 100644
index 59bf0359..00000000
--- a/input_devices/mag/node_modules/serialport/hwtest/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "name": "node-sptest",
-  "version": "0.0.0",
-  "main": "index.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
-  },
-  "author": "",
-  "license": "ISC",
-  "dependencies": {
-    "serialport": "^1.4.6"
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/hwtest/test1.js b/input_devices/mag/node_modules/serialport/hwtest/test1.js
deleted file mode 100644
index 8386ae9a..00000000
--- a/input_devices/mag/node_modules/serialport/hwtest/test1.js
+++ /dev/null
@@ -1,40 +0,0 @@
-var serialport = require("serialport");
-var SerialPort = serialport.SerialPort; // localize object constructor
-
-serialport.list(function(err, ports) {
-    console.log(ports);
-
-});
-
-var sp = new SerialPort("/dev/tty.usbmodem1421", {
-    baudrate: 9600,
-    parser: serialport.parsers.readline("\n")
-});
-
-var i = 1;
-
-sp.on("open", function() {
-    console.log('open');
-    sp.on('data', function(data) {
-        console.log('count : ' + (i++));
-        console.log('data received: ' + data);
-    });
-
-    sp.on('disconnect', function(err) {
-        console.log('on.disconnect');
-    });
-
-    sp.on('error', function(err) {
-        console.log("Erreur ?? " + err);
-    });
-
-    sp.on('close', function() {
-        console.log("Someone close the port ...");
-    });
-});
-
-setTimeout(function() {
-    sp.close(function() {
-        console.log("We're closing");
-    });
-}, 10000);
diff --git a/input_devices/mag/node_modules/serialport/hwtest/test2.js b/input_devices/mag/node_modules/serialport/hwtest/test2.js
deleted file mode 100644
index 2b2cf6e4..00000000
--- a/input_devices/mag/node_modules/serialport/hwtest/test2.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var SerialPort = require('serialport').SerialPort;
-
-process.stdin.on('data', function() {});
-
-process.stdin.on('end', function() {
-  var sp = new SerialPort('/dev/tty.usbmodemfd121');
-  sp.on('open', function() {
-    console.log('SerialPort FD:', sp.fd);
-
-    sp.write('this will not get sent');
-
-    setTimeout(process.exit, 100);
-  });
-});
diff --git a/input_devices/mag/node_modules/serialport/lib/index.js b/input_devices/mag/node_modules/serialport/lib/index.js
new file mode 100644
index 00000000..e40447c2
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/lib/index.js
@@ -0,0 +1,15 @@
+const SerialPort = require('@serialport/stream')
+const Binding = require('@serialport/bindings')
+const parsers = require('./parsers')
+
+/**
+ * @type {AbstractBinding}
+ */
+SerialPort.Binding = Binding
+
+/**
+ * @type {Parsers}
+ */
+SerialPort.parsers = parsers
+
+module.exports = SerialPort
diff --git a/input_devices/mag/node_modules/serialport/lib/parsers.js b/input_devices/mag/node_modules/serialport/lib/parsers.js
new file mode 100644
index 00000000..f7cd3643
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/lib/parsers.js
@@ -0,0 +1,35 @@
+/**
+ * Parsers are collection of transform streams to processes incoming data
+ * @summary The default `Parsers` are [Transform streams](https://nodejs.org/api/stream.html#stream_class_stream_transform) that process incoming data. To use the parsers, you must create them and then pipe the Serialport to the parser. Be careful to only write to the SerialPort object and not the parser.
+ * @typedef {Object} Parsers
+ * @property {Transform} ByteLength
+ * @property {Transform} CCtalk
+ * @property {Transform} Delimiter
+ * @property {Transform} Readline
+ * @property {Transform} Ready
+ * @property {Transform} Regex
+
+ * @since 5.0.0
+ * @example
+```js
+const SerialPort = require('serialport');
+const Readline = SerialPort.parsers.Readline;
+const port = new SerialPort('/dev/tty-usbserial1');
+const parser = new Readline();
+port.pipe(parser);
+parser.on('data', console.log);
+port.write('ROBOT PLEASE RESPOND\n');
+
+// Creating the parser and piping can be shortened to
+// const parser = port.pipe(new Readline());
+```
+ */
+
+module.exports = {
+  ByteLength: require('@serialport/parser-byte-length'),
+  CCTalk: require('@serialport/parser-cctalk'),
+  Delimiter: require('@serialport/parser-delimiter'),
+  Readline: require('@serialport/parser-readline'),
+  Ready: require('@serialport/parser-ready'),
+  Regex: require('@serialport/parser-regex'),
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/.bin/node-pre-gyp b/input_devices/mag/node_modules/serialport/node_modules/.bin/node-pre-gyp
deleted file mode 120000
index 47a90a51..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/.bin/node-pre-gyp
+++ /dev/null
@@ -1 +0,0 @@
-../node-pre-gyp/bin/node-pre-gyp
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/async/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/async/LICENSE
deleted file mode 100644
index 8f296985..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/async/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2010-2014 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/input_devices/mag/node_modules/serialport/node_modules/async/README.md b/input_devices/mag/node_modules/serialport/node_modules/async/README.md
deleted file mode 100644
index 0bea5311..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/async/README.md
+++ /dev/null
@@ -1,1646 +0,0 @@
-# Async.js
-
-[![Build Status via Travis CI](https://travis-ci.org/caolan/async.svg?branch=master)](https://travis-ci.org/caolan/async)
-
-
-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
-<script type="text/javascript" src="async.js"></script>
-<script type="text/javascript">
-
-    async.map(data, asyncProcess, function(err, results){
-        alert(results);
-    });
-
-</script>
-```
-
-## 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`](#seriestasks-callback)
-* [`parallel`](#parallel)
-* [`parallelLimit`](#parallellimittasks-limit-callback)
-* [`whilst`](#whilst)
-* [`doWhilst`](#doWhilst)
-* [`until`](#until)
-* [`doUntil`](#doUntil)
-* [`forever`](#forever)
-* [`waterfall`](#waterfall)
-* [`compose`](#compose)
-* [`seq`](#seq)
-* [`applyEach`](#applyEach)
-* [`applyEachSeries`](#applyEachSeries)
-* [`queue`](#queue)
-* [`priorityQueue`](#priorityQueue)
-* [`cargo`](#cargo)
-* [`auto`](#auto)
-* [`retry`](#retry)
-* [`iterator`](#iterator)
-* [`apply`](#apply)
-* [`nextTick`](#nextTick)
-* [`times`](#times)
-* [`timesSeries`](#timesSeries)
-
-### Utils
-
-* [`memoize`](#memoize)
-* [`unmemoize`](#unmemoize)
-* [`log`](#log)
-* [`dir`](#dir)
-* [`noConflict`](#noConflict)
-
-
-## Collections
-
-<a name="forEach" />
-<a name="each" />
-### each(arr, iterator, callback)
-
-Applies the function `iterator` to each item in `arr`, 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 its `callback`, the main
-`callback` (for the `each` function) is immediately called with the error.
-
-Note, that since this function applies `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 `arr`.
-  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 when all `iterator` functions
-  have finished, or an error occurs.
-
-__Examples__
-
-
-```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
-});
-```
-
-```js
-// assuming openFiles is an array of file names 
-
-async.each(openFiles, function( file, callback) {
-  
-  // Perform operation on file here.
-  console.log('Processing file ' + file);
-  
-  if( file.length > 32 ) {
-    console.log('This file name is too long');
-    callback('File name too long');
-  } else {
-    // Do work to process file here
-    console.log('File processed');
-    callback();
-  }
-}, function(err){
-    // if any of the file processing produced an error, err would equal that error
-    if( err ) {
-      // One of the iterations produced an error.
-      // All processing will now stop.
-      console.log('A file failed to process');
-    } else {
-      console.log('All files have been processed successfully');
-    }
-});
-```
-
----------------------------------------
-
-<a name="forEachSeries" />
-<a name="eachSeries" />
-### eachSeries(arr, iterator, callback)
-
-The same as [`each`](#each), only `iterator` is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-This means the `iterator` functions will complete in order.
-
-
----------------------------------------
-
-<a name="forEachLimit" />
-<a name="eachLimit" />
-### eachLimit(arr, limit, iterator, callback)
-
-The same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously 
-running at any time.
-
-Note that the items in `arr` 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 `iterator`s to run at any time.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  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 when all `iterator` functions
-  have finished, or an error occurs.
-
-__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
-});
-```
-
----------------------------------------
-
-<a name="map" />
-### map(arr, iterator, callback)
-
-Produces a new array of values by mapping each value in `arr` through
-the `iterator` function. The `iterator` is called with an item from `arr` and a
-callback for when it has finished processing. Each of these callback takes 2 arguments: 
-an `error`, and the transformed item from `arr`. If `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 `arr`.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  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 when all `iterator`
-  functions have finished, or an error occurs. Results is an array of the
-  transformed items from the `arr`.
-
-__Example__
-
-```js
-async.map(['file1','file2','file3'], fs.stat, function(err, results){
-    // results is now an array of stats for each file
-});
-```
-
----------------------------------------
-
-<a name="mapSeries" />
-### mapSeries(arr, iterator, callback)
-
-The same as [`map`](#map), only the `iterator` is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-The results array will be in the same order as the original.
-
-
----------------------------------------
-
-<a name="mapLimit" />
-### mapLimit(arr, limit, iterator, callback)
-
-The same as [`map`](#map), only no more than `limit` `iterator`s 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 `iterator`s to run at any time.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  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 when all `iterator`
-  calls have finished, or an error occurs. The result is an array of the
-  transformed items from the original `arr`.
-
-__Example__
-
-```js
-async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){
-    // results is now an array of stats for each file
-});
-```
-
----------------------------------------
-
-<a name="select" />
-<a name="filter" />
-### filter(arr, iterator, callback)
-
-__Alias:__ `select`
-
-Returns a new array of all the values in `arr` 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 `arr`.
-  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
-});
-```
-
----------------------------------------
-
-<a name="selectSeries" />
-<a name="filterSeries" />
-### filterSeries(arr, iterator, callback)
-
-__Alias:__ `selectSeries`
-
-The same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-The results array will be in the same order as the original.
-
----------------------------------------
-
-<a name="reject" />
-### reject(arr, iterator, callback)
-
-The opposite of [`filter`](#filter). Removes values that pass an `async` truth test.
-
----------------------------------------
-
-<a name="rejectSeries" />
-### rejectSeries(arr, iterator, callback)
-
-The same as [`reject`](#reject), only the `iterator` is applied to each item in `arr`
-in series.
-
-
----------------------------------------
-
-<a name="reduce" />
-### reduce(arr, memo, iterator, callback)
-
-__Aliases:__ `inject`, `foldl`
-
-Reduces `arr` 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, and 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
-});
-```
-
----------------------------------------
-
-<a name="reduceRight" />
-### reduceRight(arr, memo, iterator, callback)
-
-__Alias:__ `foldr`
-
-Same as [`reduce`](#reduce), only operates on `arr` in reverse order.
-
-
----------------------------------------
-
-<a name="detect" />
-### detect(arr, iterator, callback)
-
-Returns the first value in `arr` 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 `arr` (in terms of order) that passes the test.
-
-If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries).
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A truth test to apply to each item in `arr`.
-  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
-});
-```
-
----------------------------------------
-
-<a name="detectSeries" />
-### detectSeries(arr, iterator, callback)
-
-The same as [`detect`](#detect), only the `iterator` is applied to each item in `arr`
-in series. This means the result is always the first in the original `arr` (in
-terms of array order) that passes the truth test.
-
-
----------------------------------------
-
-<a name="sortBy" />
-### sortBy(arr, iterator, callback)
-
-Sorts a list by the results of running each `arr` value through an async `iterator`.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  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 occurs. Results is the items from
-  the original `arr` 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
-});
-```
-
-__Sort Order__
-
-By modifying the callback parameter the sorting order can be influenced:
-
-```js
-//ascending order
-async.sortBy([1,9,3,5], function(x, callback){
-    callback(err, x);
-}, function(err,result){
-    //result callback
-} );
-
-//descending order
-async.sortBy([1,9,3,5], function(x, callback){
-    callback(err, x*-1);    //<- x*-1 instead of x, turns the order around
-}, function(err,result){
-    //result callback
-} );
-```
-
----------------------------------------
-
-<a name="some" />
-### some(arr, iterator, callback)
-
-__Alias:__ `any`
-
-Returns `true` if at least one element in the `arr` 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
-  in parallel. 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
-});
-```
-
----------------------------------------
-
-<a name="every" />
-### every(arr, iterator, callback)
-
-__Alias:__ `all`
-
-Returns `true` if every element in `arr` 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
-  in parallel. 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
-});
-```
-
----------------------------------------
-
-<a name="concat" />
-### concat(arr, iterator, callback)
-
-Applies `iterator` to each item in `arr`, concatenating the results. Returns the
-concatenated list. The `iterator`s 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 `arr` passed to the `iterator` function.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  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 occurs. 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
-});
-```
-
----------------------------------------
-
-<a name="concatSeries" />
-### concatSeries(arr, iterator, callback)
-
-Same as [`concat`](#concat), but executes in series instead of parallel.
-
-
-## Control Flow
-
-<a name="series" />
-### series(tasks, [callback])
-
-Run the functions in the `tasks` array 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 `callback` is immediately called with the value of the error. 
-Otherwise, `callback` receives an array of results when `tasks` have completed.
-
-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
-[`series`](#series).
-
-**Note** that while many implementations preserve the order of object properties, the
-[ECMAScript Language Specifcation](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) 
-explicitly states that
-
-> The mechanics and order of enumerating the properties is not specified.
-
-So if you rely on the order in which your series of functions are executed, and want
-this to work on all platforms, consider using an array. 
-
-__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 `err` (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}
-});
-```
-
----------------------------------------
-
-<a name="parallel" />
-### parallel(tasks, [callback])
-
-Run the `tasks` 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
-[`parallel`](#parallel).
-
-
-__Arguments__
-
-* `tasks` - An array or object containing functions to run. Each function is passed 
-  a `callback(err, result)` which it must call on completion with an error `err` 
-  (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}
-});
-```
-
----------------------------------------
-
-<a name="parallelLimit" />
-### parallelLimit(tasks, limit, [callback])
-
-The same as [`parallel`](#parallel), only `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 `err` (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.
-
----------------------------------------
-
-<a name="whilst" />
-### whilst(test, fn, callback)
-
-Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped,
-or an error occurs.
-
-__Arguments__
-
-* `test()` - synchronous truth test to perform before each execution of `fn`.
-* `fn(callback)` - A function which is called each time `test` passes. The function is
-  passed a `callback(err)`, which must be called once it has completed with an 
-  optional `err` 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
-    }
-);
-```
-
----------------------------------------
-
-<a name="doWhilst" />
-### doWhilst(fn, test, callback)
-
-The post-check version of [`whilst`](#whilst). To reflect the difference in 
-the order of operations, the arguments `test` and `fn` are switched. 
-
-`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
-
----------------------------------------
-
-<a name="until" />
-### until(test, fn, callback)
-
-Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped,
-or an error occurs.
-
-The inverse of [`whilst`](#whilst).
-
----------------------------------------
-
-<a name="doUntil" />
-### doUntil(fn, test, callback)
-
-Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`.
-
----------------------------------------
-
-<a name="forever" />
-### forever(fn, errback)
-
-Calls the asynchronous function `fn` with a callback parameter that allows it to
-call itself again, in series, indefinitely.
-
-If an error is passed to the callback then `errback` is called with the
-error, and execution stops, otherwise it will never be called.
-
-```js
-async.forever(
-    function(next) {
-        // next is suitable for passing to things that need a callback(err [, whatever]);
-        // it will result in this function being called again.
-    },
-    function(err) {
-        // if next is called with a value in its first parameter, it will appear
-        // in here as 'err', and execution will stop.
-    }
-);
-```
-
----------------------------------------
-
-<a name="waterfall" />
-### waterfall(tasks, [callback])
-
-Runs the `tasks` array of functions in series, each passing their results to the next in
-the array. However, if any of the `tasks` pass an error to their own 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){
-      // arg1 now equals 'one' and arg2 now equals 'two'
-        callback(null, 'three');
-    },
-    function(arg1, callback){
-        // arg1 now equals 'three'
-        callback(null, 'done');
-    }
-], function (err, result) {
-   // result now equals 'done'    
-});
-```
-
----------------------------------------
-<a name="compose" />
-### 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
-});
-```
-
----------------------------------------
-<a name="seq" />
-### seq(fn1, fn2...)
-
-Version of the compose function that is more natural to read.
-Each following function consumes the return value of the latter function. 
-
-Each function is executed with the `this` binding of the composed function.
-
-__Arguments__
-
-* functions... - the asynchronous functions to compose
-
-
-__Example__
-
-```js
-// Requires lodash (or underscore), express3 and dresende's orm2.
-// Part of an app, that fetches cats of the logged user.
-// This example uses `seq` function to avoid overnesting and error 
-// handling clutter.
-app.get('/cats', function(request, response) {
-  function handleError(err, data, callback) {
-    if (err) {
-      console.error(err);
-      response.json({ status: 'error', message: err.message });
-    }
-    else {
-      callback(data);
-    }
-  }
-  var User = request.models.User;
-  async.seq(
-    _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
-    handleError,
-    function(user, fn) {
-      user.getCats(fn);      // 'getCats' has signature (callback(err, data))
-    },
-    handleError,
-    function(cats) {
-      response.json({ status: 'ok', message: 'Cats found', data: cats });
-    }
-  )(req.session.user_id);
-  }
-});
-```
-
----------------------------------------
-<a name="applyEach" />
-### applyEach(fns, args..., callback)
-
-Applies the provided arguments to each function in the array, calling 
-`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
-);
-```
-
----------------------------------------
-
-<a name="applyEachSeries" />
-### applyEachSeries(arr, iterator, callback)
-
-The same as [`applyEach`](#applyEach) only the functions are applied in series.
-
----------------------------------------
-
-<a name="queue" />
-### queue(worker, concurrency)
-
-Creates a `queue` object with the specified `concurrency`. Tasks added to the
-`queue` are processed in parallel (up to the `concurrency` limit). If all
-`worker`s are in progress, the task is queued until one becomes available. 
-Once a `worker` completes a `task`, that `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.
-* `started` - a function returning whether or not any items have been pushed and processed by the queue
-* `running()` - a function returning the number of items currently being processed.
-* `idle()` - a function returning false if there are items waiting or being processed, or true if not.
-* `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`. Calls `callback` once 
-  the `worker` has finished processing the task. Instead of a single task, a `tasks` array
-  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` limit, 
-   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`.
-* `paused` - a boolean for determining whether the queue is in a paused state
-* `pause()` - a function that pauses the processing of tasks until `resume()` is called.
-* `resume()` - a function that resumes the processing of queued tasks when the queue is paused.
-* `kill()` - a function that empties remaining tasks from the queue forcing it to go idle.
-
-__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');
-});
-```
-
-
----------------------------------------
-
-<a name="priorityQueue" />
-### priorityQueue(worker, concurrency)
-
-The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects:
-
-* `push(task, priority, [callback])` - `priority` should be a number. If an array of
-  `tasks` is given, all tasks will be assigned the same priority.
-* The `unshift` method was removed.
-
----------------------------------------
-
-<a name="cargo" />
-### 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 becomes available. Once
-the `worker` has completed some tasks, each callback of those tasks is called.
-Check out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work.
-
-While [queue](#queue) passes only one task to one of a group of workers
-at a time, cargo passes an array of tasks to a single worker, repeating
-when the worker is finished.
-
-__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 `err` 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])` - Adds `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<tasks.length; i++){
-      console.log('hello ' + tasks[i].name);
-    }
-    callback();
-}, 2);
-
-
-// add some items
-
-cargo.push({name: 'foo'}, function (err) {
-    console.log('finished processing foo');
-});
-cargo.push({name: 'bar'}, function (err) {
-    console.log('finished processing bar');
-});
-cargo.push({name: 'baz'}, function (err) {
-    console.log('finished processing baz');
-});
-```
-
----------------------------------------
-
-<a name="auto" />
-### auto(tasks, [callback])
-
-Determines the best order for running the functions in `tasks`, 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, it will not 
-complete (so any other functions depending on it will not run), and the main 
-`callback` is immediately called 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. Each of its properties is either a function or an array of
-  requirements, with the function itself the last item in the array. The object's key
-  of a property serves as the name of the task defined by that property,
-  i.e. can be used when specifying requirements for other tasks.
-  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. It receives the `err` argument if any `tasks` 
-  pass an error to their callback. Results are always returned; however, if 
-  an error occurs, no further `tasks` will be performed, and the results
-  object will only contain partial results.
-
-
-__Example__
-
-```js
-async.auto({
-    get_data: function(callback){
-        console.log('in get_data');
-        // async code to get some data
-        callback(null, 'data', 'converted to array');
-    },
-    make_folder: function(callback){
-        console.log('in make_folder');
-        // async code to create a directory to store a file in
-        // this is run at the same time as getting the data
-        callback(null, 'folder');
-    },
-    write_file: ['get_data', 'make_folder', function(callback, results){
-        console.log('in write_file', JSON.stringify(results));
-        // 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){
-        console.log('in email_link', JSON.stringify(results));
-        // once the file is written let's email a link to it...
-        // results.write_file contains the filename returned by write_file.
-        callback(null, {'file':results.write_file, 'email':'user@example.com'});
-    }]
-}, function(err, results) {
-    console.log('err = ', err);
-    console.log('results = ', results);
-});
-```
-
-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){
-        console.log('in get_data');
-        // async code to get some data
-        callback(null, 'data', 'converted to array');
-    },
-    function(callback){
-        console.log('in make_folder');
-        // async code to create a directory to store a file in
-        // this is run at the same time as getting the data
-        callback(null, 'folder');
-    }
-],
-function(err, results){
-    async.series([
-        function(callback){
-            console.log('in write_file', JSON.stringify(results));
-            // once there is some data and the directory exists,
-            // write the data to a file in the directory
-            results.push('filename');
-            callback(null);
-        },
-        function(callback){
-            console.log('in email_link', JSON.stringify(results));
-            // once the file is written let's email a link to it...
-            callback(null, {'file':results.pop(), 'email':'user@example.com'});
-        }
-    ]);
-});
-```
-
-For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding
-new tasks much easier (and the code more readable).
-
-
----------------------------------------
-
-<a name="retry" />
-### retry([times = 5], task, [callback])
-
-Attempts to get a successful response from `task` no more than `times` times before
-returning an error. If the task is successful, the `callback` will be passed the result
-of the successfull task. If all attemps fail, the callback will be passed the error and
-result (if any) of the final attempt.
-
-__Arguments__
-
-* `times` - An integer indicating how many times to attempt the `task` before giving up. Defaults to 5.
-* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)`
-  which must be called when finished, passing `err` (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 (if nested inside another control flow).
-* `callback(err, results)` - An optional callback which is called when the
-  task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`.
-
-The [`retry`](#retry) function can be used as a stand-alone control flow by passing a
-callback, as shown below:
-
-```js
-async.retry(3, apiMethod, function(err, result) {
-    // do something with the result
-});
-```
-
-It can also be embeded within other control flow functions to retry individual methods
-that are not as reliable, like this:
-
-```js
-async.auto({
-    users: api.getUsers.bind(api),
-    payments: async.retry(3, api.getPayments.bind(api))
-}, function(err, results) {
-  // do something with the results
-});
-```
-
-
----------------------------------------
-
-<a name="iterator" />
-### iterator(tasks)
-
-Creates an iterator function which calls the next function in the `tasks` array,
-returning a continuation to call the next one after that. It's also possible to
-“peek” at the next iterator with `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'
-```
-
----------------------------------------
-
-<a name="apply" />
-### apply(function, arguments..)
-
-Creates a continuation function with some arguments already applied. 
-
-Useful as a 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
-```
-
----------------------------------------
-
-<a name="nextTick" />
-### nextTick(callback)
-
-Calls `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 `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')
-```
-
-<a name="times" />
-### times(n, callback)
-
-Calls the `callback` function `n` times, and accumulates results in the same manner
-you would use with [`map`](#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
-});
-```
-
-<a name="timesSeries" />
-### timesSeries(n, callback)
-
-The same as [`times`](#times), only the iterator is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-The results array will be in the same order as the original.
-
-
-## Utils
-
-<a name="memoize" />
-### 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 to proxy and cache results from.
-* `hasher` - Tn 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
-});
-```
-
-<a name="unmemoize" />
-### unmemoize(fn)
-
-Undoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized
-form. Handy for testing.
-
-__Arguments__
-
-* `fn` - the memoized function
-
-<a name="log" />
-### 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'
-```
-
----------------------------------------
-
-<a name="dir" />
-### 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'}
-```
-
----------------------------------------
-
-<a name="noConflict" />
-### noConflict()
-
-Changes the value of `async` back to its original value, returning a reference to the
-`async` object.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/async/component.json b/input_devices/mag/node_modules/serialport/node_modules/async/component.json
deleted file mode 100644
index bbb01154..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/async/lib/async.js b/input_devices/mag/node_modules/serialport/node_modules/async/lib/async.js
deleted file mode 100755
index 01e8afcc..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/async/lib/async.js
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*!
- * async
- * https://github.com/caolan/async
- *
- * Copyright 2010-2014 Caolan McMahon
- * Released under the MIT license
- */
-/*jshint onevar: false, indent:4 */
-/*global setImmediate: false, setTimeout: false, console: false */
-(function () {
-
-    var async = {};
-
-    // global on the server, window in the browser
-    var root, previous_async;
-
-    root = this;
-    if (root != null) {
-      previous_async = root.async;
-    }
-
-    async.noConflict = function () {
-        root.async = previous_async;
-        return async;
-    };
-
-    function only_once(fn) {
-        var called = false;
-        return function() {
-            if (called) throw new Error("Callback was already called.");
-            called = true;
-            fn.apply(root, arguments);
-        }
-    }
-
-    //// cross-browser compatiblity functions ////
-
-    var _toString = Object.prototype.toString;
-
-    var _isArray = Array.isArray || function (obj) {
-        return _toString.call(obj) === '[object Array]';
-    };
-
-    var _each = function (arr, iterator) {
-        if (arr.forEach) {
-            return arr.forEach(iterator);
-        }
-        for (var i = 0; i < arr.length; i += 1) {
-            iterator(arr[i], i, arr);
-        }
-    };
-
-    var _map = function (arr, iterator) {
-        if (arr.map) {
-            return arr.map(iterator);
-        }
-        var results = [];
-        _each(arr, function (x, i, a) {
-            results.push(iterator(x, i, a));
-        });
-        return results;
-    };
-
-    var _reduce = function (arr, iterator, memo) {
-        if (arr.reduce) {
-            return arr.reduce(iterator, memo);
-        }
-        _each(arr, function (x, i, a) {
-            memo = iterator(memo, x, i, a);
-        });
-        return memo;
-    };
-
-    var _keys = function (obj) {
-        if (Object.keys) {
-            return Object.keys(obj);
-        }
-        var keys = [];
-        for (var k in obj) {
-            if (obj.hasOwnProperty(k)) {
-                keys.push(k);
-            }
-        }
-        return keys;
-    };
-
-    //// exported async module functions ////
-
-    //// nextTick implementation with browser-compatible fallback ////
-    if (typeof process === 'undefined' || !(process.nextTick)) {
-        if (typeof setImmediate === 'function') {
-            async.nextTick = function (fn) {
-                // not a direct alias for IE10 compatibility
-                setImmediate(fn);
-            };
-            async.setImmediate = async.nextTick;
-        }
-        else {
-            async.nextTick = function (fn) {
-                setTimeout(fn, 0);
-            };
-            async.setImmediate = async.nextTick;
-        }
-    }
-    else {
-        async.nextTick = process.nextTick;
-        if (typeof setImmediate !== 'undefined') {
-            async.setImmediate = function (fn) {
-              // not a direct alias for IE10 compatibility
-              setImmediate(fn);
-            };
-        }
-        else {
-            async.setImmediate = async.nextTick;
-        }
-    }
-
-    async.each = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        _each(arr, function (x) {
-            iterator(x, only_once(done) );
-        });
-        function done(err) {
-          if (err) {
-              callback(err);
-              callback = function () {};
-          }
-          else {
-              completed += 1;
-              if (completed >= arr.length) {
-                  callback();
-              }
-          }
-        }
-    };
-    async.forEach = async.each;
-
-    async.eachSeries = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        var iterate = function () {
-            iterator(arr[completed], function (err) {
-                if (err) {
-                    callback(err);
-                    callback = function () {};
-                }
-                else {
-                    completed += 1;
-                    if (completed >= arr.length) {
-                        callback();
-                    }
-                    else {
-                        iterate();
-                    }
-                }
-            });
-        };
-        iterate();
-    };
-    async.forEachSeries = async.eachSeries;
-
-    async.eachLimit = function (arr, limit, iterator, callback) {
-        var fn = _eachLimit(limit);
-        fn.apply(null, [arr, iterator, callback]);
-    };
-    async.forEachLimit = async.eachLimit;
-
-    var _eachLimit = function (limit) {
-
-        return function (arr, iterator, callback) {
-            callback = callback || function () {};
-            if (!arr.length || limit <= 0) {
-                return callback();
-            }
-            var completed = 0;
-            var started = 0;
-            var running = 0;
-
-            (function replenish () {
-                if (completed >= arr.length) {
-                    return callback();
-                }
-
-                while (running < limit && started < arr.length) {
-                    started += 1;
-                    running += 1;
-                    iterator(arr[started - 1], function (err) {
-                        if (err) {
-                            callback(err);
-                            callback = function () {};
-                        }
-                        else {
-                            completed += 1;
-                            running -= 1;
-                            if (completed >= arr.length) {
-                                callback();
-                            }
-                            else {
-                                replenish();
-                            }
-                        }
-                    });
-                }
-            })();
-        };
-    };
-
-
-    var doParallel = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.each].concat(args));
-        };
-    };
-    var doParallelLimit = function(limit, fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [_eachLimit(limit)].concat(args));
-        };
-    };
-    var doSeries = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.eachSeries].concat(args));
-        };
-    };
-
-
-    var _asyncMap = function (eachfn, arr, iterator, callback) {
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        if (!callback) {
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err) {
-                    callback(err);
-                });
-            });
-        } else {
-            var results = [];
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err, v) {
-                    results[x.index] = v;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-    async.map = doParallel(_asyncMap);
-    async.mapSeries = doSeries(_asyncMap);
-    async.mapLimit = function (arr, limit, iterator, callback) {
-        return _mapLimit(limit)(arr, iterator, callback);
-    };
-
-    var _mapLimit = function(limit) {
-        return doParallelLimit(limit, _asyncMap);
-    };
-
-    // reduce only has a series version, as doing reduce in parallel won't
-    // work in many situations.
-    async.reduce = function (arr, memo, iterator, callback) {
-        async.eachSeries(arr, function (x, callback) {
-            iterator(memo, x, function (err, v) {
-                memo = v;
-                callback(err);
-            });
-        }, function (err) {
-            callback(err, memo);
-        });
-    };
-    // inject alias
-    async.inject = async.reduce;
-    // foldl alias
-    async.foldl = async.reduce;
-
-    async.reduceRight = function (arr, memo, iterator, callback) {
-        var reversed = _map(arr, function (x) {
-            return x;
-        }).reverse();
-        async.reduce(reversed, memo, iterator, callback);
-    };
-    // foldr alias
-    async.foldr = async.reduceRight;
-
-    var _filter = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.filter = doParallel(_filter);
-    async.filterSeries = doSeries(_filter);
-    // select alias
-    async.select = async.filter;
-    async.selectSeries = async.filterSeries;
-
-    var _reject = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (!v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.reject = doParallel(_reject);
-    async.rejectSeries = doSeries(_reject);
-
-    var _detect = function (eachfn, arr, iterator, main_callback) {
-        eachfn(arr, function (x, callback) {
-            iterator(x, function (result) {
-                if (result) {
-                    main_callback(x);
-                    main_callback = function () {};
-                }
-                else {
-                    callback();
-                }
-            });
-        }, function (err) {
-            main_callback();
-        });
-    };
-    async.detect = doParallel(_detect);
-    async.detectSeries = doSeries(_detect);
-
-    async.some = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (v) {
-                    main_callback(true);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(false);
-        });
-    };
-    // any alias
-    async.any = async.some;
-
-    async.every = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (!v) {
-                    main_callback(false);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(true);
-        });
-    };
-    // all alias
-    async.all = async.every;
-
-    async.sortBy = function (arr, iterator, callback) {
-        async.map(arr, function (x, callback) {
-            iterator(x, function (err, criteria) {
-                if (err) {
-                    callback(err);
-                }
-                else {
-                    callback(null, {value: x, criteria: criteria});
-                }
-            });
-        }, function (err, results) {
-            if (err) {
-                return callback(err);
-            }
-            else {
-                var fn = function (left, right) {
-                    var a = left.criteria, b = right.criteria;
-                    return a < b ? -1 : a > b ? 1 : 0;
-                };
-                callback(null, _map(results.sort(fn), function (x) {
-                    return x.value;
-                }));
-            }
-        });
-    };
-
-    async.auto = function (tasks, callback) {
-        callback = callback || function () {};
-        var keys = _keys(tasks);
-        var remainingTasks = keys.length
-        if (!remainingTasks) {
-            return callback();
-        }
-
-        var results = {};
-
-        var listeners = [];
-        var addListener = function (fn) {
-            listeners.unshift(fn);
-        };
-        var removeListener = function (fn) {
-            for (var i = 0; i < listeners.length; i += 1) {
-                if (listeners[i] === fn) {
-                    listeners.splice(i, 1);
-                    return;
-                }
-            }
-        };
-        var taskComplete = function () {
-            remainingTasks--
-            _each(listeners.slice(0), function (fn) {
-                fn();
-            });
-        };
-
-        addListener(function () {
-            if (!remainingTasks) {
-                var theCallback = callback;
-                // prevent final callback from calling itself if it errors
-                callback = function () {};
-
-                theCallback(null, results);
-            }
-        });
-
-        _each(keys, function (k) {
-            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
-            var taskCallback = function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (args.length <= 1) {
-                    args = args[0];
-                }
-                if (err) {
-                    var safeResults = {};
-                    _each(_keys(results), function(rkey) {
-                        safeResults[rkey] = results[rkey];
-                    });
-                    safeResults[k] = args;
-                    callback(err, safeResults);
-                    // stop subsequent errors hitting callback multiple times
-                    callback = function () {};
-                }
-                else {
-                    results[k] = args;
-                    async.setImmediate(taskComplete);
-                }
-            };
-            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
-            var ready = function () {
-                return _reduce(requires, function (a, x) {
-                    return (a && results.hasOwnProperty(x));
-                }, true) && !results.hasOwnProperty(k);
-            };
-            if (ready()) {
-                task[task.length - 1](taskCallback, results);
-            }
-            else {
-                var listener = function () {
-                    if (ready()) {
-                        removeListener(listener);
-                        task[task.length - 1](taskCallback, results);
-                    }
-                };
-                addListener(listener);
-            }
-        });
-    };
-
-    async.retry = function(times, task, callback) {
-        var DEFAULT_TIMES = 5;
-        var attempts = [];
-        // Use defaults if times not passed
-        if (typeof times === 'function') {
-            callback = task;
-            task = times;
-            times = DEFAULT_TIMES;
-        }
-        // Make sure times is a number
-        times = parseInt(times, 10) || DEFAULT_TIMES;
-        var wrappedTask = function(wrappedCallback, wrappedResults) {
-            var retryAttempt = function(task, finalAttempt) {
-                return function(seriesCallback) {
-                    task(function(err, result){
-                        seriesCallback(!err || finalAttempt, {err: err, result: result});
-                    }, wrappedResults);
-                };
-            };
-            while (times) {
-                attempts.push(retryAttempt(task, !(times-=1)));
-            }
-            async.series(attempts, function(done, data){
-                data = data[data.length - 1];
-                (wrappedCallback || callback)(data.err, data.result);
-            });
-        }
-        // If a callback is passed, run this as a controll flow
-        return callback ? wrappedTask() : wrappedTask
-    };
-
-    async.waterfall = function (tasks, callback) {
-        callback = callback || function () {};
-        if (!_isArray(tasks)) {
-          var err = new Error('First argument to waterfall must be an array of functions');
-          return callback(err);
-        }
-        if (!tasks.length) {
-            return callback();
-        }
-        var wrapIterator = function (iterator) {
-            return function (err) {
-                if (err) {
-                    callback.apply(null, arguments);
-                    callback = function () {};
-                }
-                else {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    var next = iterator.next();
-                    if (next) {
-                        args.push(wrapIterator(next));
-                    }
-                    else {
-                        args.push(callback);
-                    }
-                    async.setImmediate(function () {
-                        iterator.apply(null, args);
-                    });
-                }
-            };
-        };
-        wrapIterator(async.iterator(tasks))();
-    };
-
-    var _parallel = function(eachfn, tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            eachfn.map(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            eachfn.each(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-
-    async.parallel = function (tasks, callback) {
-        _parallel({ map: async.map, each: async.each }, tasks, callback);
-    };
-
-    async.parallelLimit = function(tasks, limit, callback) {
-        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
-    };
-
-    async.series = function (tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            async.mapSeries(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            async.eachSeries(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-
-    async.iterator = function (tasks) {
-        var makeCallback = function (index) {
-            var fn = function () {
-                if (tasks.length) {
-                    tasks[index].apply(null, arguments);
-                }
-                return fn.next();
-            };
-            fn.next = function () {
-                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
-            };
-            return fn;
-        };
-        return makeCallback(0);
-    };
-
-    async.apply = function (fn) {
-        var args = Array.prototype.slice.call(arguments, 1);
-        return function () {
-            return fn.apply(
-                null, args.concat(Array.prototype.slice.call(arguments))
-            );
-        };
-    };
-
-    var _concat = function (eachfn, arr, fn, callback) {
-        var r = [];
-        eachfn(arr, function (x, cb) {
-            fn(x, function (err, y) {
-                r = r.concat(y || []);
-                cb(err);
-            });
-        }, function (err) {
-            callback(err, r);
-        });
-    };
-    async.concat = doParallel(_concat);
-    async.concatSeries = doSeries(_concat);
-
-    async.whilst = function (test, iterator, callback) {
-        if (test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.whilst(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
-    };
-
-    async.doWhilst = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (test.apply(null, args)) {
-                async.doWhilst(iterator, test, callback);
-            }
-            else {
-                callback();
-            }
-        });
-    };
-
-    async.until = function (test, iterator, callback) {
-        if (!test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.until(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
-    };
-
-    async.doUntil = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (!test.apply(null, args)) {
-                async.doUntil(iterator, test, callback);
-            }
-            else {
-                callback();
-            }
-        });
-    };
-
-    async.queue = function (worker, concurrency) {
-        if (concurrency === undefined) {
-            concurrency = 1;
-        }
-        function _insert(q, data, pos, callback) {
-          if (!q.started){
-            q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-
-              if (pos) {
-                q.tasks.unshift(item);
-              } else {
-                q.tasks.push(item);
-              }
-
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
-        }
-
-        var workers = 0;
-        var q = {
-            tasks: [],
-            concurrency: concurrency,
-            saturated: null,
-            empty: null,
-            drain: null,
-            started: false,
-            paused: false,
-            push: function (data, callback) {
-              _insert(q, data, false, callback);
-            },
-            kill: function () {
-              q.drain = null;
-              q.tasks = [];
-            },
-            unshift: function (data, callback) {
-              _insert(q, data, true, callback);
-            },
-            process: function () {
-                if (!q.paused && workers < q.concurrency && q.tasks.length) {
-                    var task = q.tasks.shift();
-                    if (q.empty && q.tasks.length === 0) {
-                        q.empty();
-                    }
-                    workers += 1;
-                    var next = function () {
-                        workers -= 1;
-                        if (task.callback) {
-                            task.callback.apply(task, arguments);
-                        }
-                        if (q.drain && q.tasks.length + workers === 0) {
-                            q.drain();
-                        }
-                        q.process();
-                    };
-                    var cb = only_once(next);
-                    worker(task.data, cb);
-                }
-            },
-            length: function () {
-                return q.tasks.length;
-            },
-            running: function () {
-                return workers;
-            },
-            idle: function() {
-                return q.tasks.length + workers === 0;
-            },
-            pause: function () {
-                if (q.paused === true) { return; }
-                q.paused = true;
-                q.process();
-            },
-            resume: function () {
-                if (q.paused === false) { return; }
-                q.paused = false;
-                q.process();
-            }
-        };
-        return q;
-    };
-    
-    async.priorityQueue = function (worker, concurrency) {
-        
-        function _compareTasks(a, b){
-          return a.priority - b.priority;
-        };
-        
-        function _binarySearch(sequence, item, compare) {
-          var beg = -1,
-              end = sequence.length - 1;
-          while (beg < end) {
-            var mid = beg + ((end - beg + 1) >>> 1);
-            if (compare(item, sequence[mid]) >= 0) {
-              beg = mid;
-            } else {
-              end = mid - 1;
-            }
-          }
-          return beg;
-        }
-        
-        function _insert(q, data, priority, callback) {
-          if (!q.started){
-            q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  priority: priority,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-              
-              q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
-
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
-        }
-        
-        // Start with a normal queue
-        var q = async.queue(worker, concurrency);
-        
-        // Override push to accept second parameter representing priority
-        q.push = function (data, priority, callback) {
-          _insert(q, data, priority, callback);
-        };
-        
-        // Remove unshift function
-        delete q.unshift;
-
-        return q;
-    };
-
-    async.cargo = function (worker, payload) {
-        var working     = false,
-            tasks       = [];
-
-        var cargo = {
-            tasks: tasks,
-            payload: payload,
-            saturated: null,
-            empty: null,
-            drain: null,
-            drained: true,
-            push: function (data, callback) {
-                if (!_isArray(data)) {
-                    data = [data];
-                }
-                _each(data, function(task) {
-                    tasks.push({
-                        data: task,
-                        callback: typeof callback === 'function' ? callback : null
-                    });
-                    cargo.drained = false;
-                    if (cargo.saturated && tasks.length === payload) {
-                        cargo.saturated();
-                    }
-                });
-                async.setImmediate(cargo.process);
-            },
-            process: function process() {
-                if (working) return;
-                if (tasks.length === 0) {
-                    if(cargo.drain && !cargo.drained) cargo.drain();
-                    cargo.drained = true;
-                    return;
-                }
-
-                var ts = typeof payload === 'number'
-                            ? tasks.splice(0, payload)
-                            : tasks.splice(0, tasks.length);
-
-                var ds = _map(ts, function (task) {
-                    return task.data;
-                });
-
-                if(cargo.empty) cargo.empty();
-                working = true;
-                worker(ds, function () {
-                    working = false;
-
-                    var args = arguments;
-                    _each(ts, function (data) {
-                        if (data.callback) {
-                            data.callback.apply(null, args);
-                        }
-                    });
-
-                    process();
-                });
-            },
-            length: function () {
-                return tasks.length;
-            },
-            running: function () {
-                return working;
-            }
-        };
-        return cargo;
-    };
-
-    var _console_fn = function (name) {
-        return function (fn) {
-            var args = Array.prototype.slice.call(arguments, 1);
-            fn.apply(null, args.concat([function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (typeof console !== 'undefined') {
-                    if (err) {
-                        if (console.error) {
-                            console.error(err);
-                        }
-                    }
-                    else if (console[name]) {
-                        _each(args, function (x) {
-                            console[name](x);
-                        });
-                    }
-                }
-            }]));
-        };
-    };
-    async.log = _console_fn('log');
-    async.dir = _console_fn('dir');
-    /*async.info = _console_fn('info');
-    async.warn = _console_fn('warn');
-    async.error = _console_fn('error');*/
-
-    async.memoize = function (fn, hasher) {
-        var memo = {};
-        var queues = {};
-        hasher = hasher || function (x) {
-            return x;
-        };
-        var memoized = function () {
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            var key = hasher.apply(null, args);
-            if (key in memo) {
-                async.nextTick(function () {
-                    callback.apply(null, memo[key]);
-                });
-            }
-            else if (key in queues) {
-                queues[key].push(callback);
-            }
-            else {
-                queues[key] = [callback];
-                fn.apply(null, args.concat([function () {
-                    memo[key] = arguments;
-                    var q = queues[key];
-                    delete queues[key];
-                    for (var i = 0, l = q.length; i < l; i++) {
-                      q[i].apply(null, arguments);
-                    }
-                }]));
-            }
-        };
-        memoized.memo = memo;
-        memoized.unmemoized = fn;
-        return memoized;
-    };
-
-    async.unmemoize = function (fn) {
-      return function () {
-        return (fn.unmemoized || fn).apply(null, arguments);
-      };
-    };
-
-    async.times = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.map(counter, iterator, callback);
-    };
-
-    async.timesSeries = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.mapSeries(counter, iterator, callback);
-    };
-
-    async.seq = function (/* functions... */) {
-        var fns = arguments;
-        return function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            async.reduce(fns, args, function (newargs, fn, cb) {
-                fn.apply(that, newargs.concat([function () {
-                    var err = arguments[0];
-                    var nextargs = Array.prototype.slice.call(arguments, 1);
-                    cb(err, nextargs);
-                }]))
-            },
-            function (err, results) {
-                callback.apply(that, [err].concat(results));
-            });
-        };
-    };
-
-    async.compose = function (/* functions... */) {
-      return async.seq.apply(null, Array.prototype.reverse.call(arguments));
-    };
-
-    var _applyEach = function (eachfn, fns /*args...*/) {
-        var go = function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            return eachfn(fns, function (fn, cb) {
-                fn.apply(that, args.concat([cb]));
-            },
-            callback);
-        };
-        if (arguments.length > 2) {
-            var args = Array.prototype.slice.call(arguments, 2);
-            return go.apply(this, args);
-        }
-        else {
-            return go;
-        }
-    };
-    async.applyEach = doParallel(_applyEach);
-    async.applyEachSeries = doSeries(_applyEach);
-
-    async.forever = function (fn, callback) {
-        function next(err) {
-            if (err) {
-                if (callback) {
-                    return callback(err);
-                }
-                throw err;
-            }
-            fn(next);
-        }
-        next();
-    };
-
-    // Node.js
-    if (typeof module !== 'undefined' && module.exports) {
-        module.exports = async;
-    }
-    // AMD / RequireJS
-    else if (typeof define !== 'undefined' && define.amd) {
-        define([], function () {
-            return async;
-        });
-    }
-    // included directly via <script> tag
-    else {
-        root.async = async;
-    }
-
-}());
diff --git a/input_devices/mag/node_modules/serialport/node_modules/async/package.json b/input_devices/mag/node_modules/serialport/node_modules/async/package.json
deleted file mode 100644
index 7eba6c20..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/async/package.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "name": "async",
-  "description": "Higher-order functions and common patterns for asynchronous code",
-  "main": "./lib/async",
-  "author": {
-    "name": "Caolan McMahon"
-  },
-  "version": "0.9.0",
-  "repository": {
-    "type": "git",
-    "url": "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"
-  },
-  "readme": "# Async.js\n\n[![Build Status via Travis CI](https://travis-ci.org/caolan/async.svg?branch=master)](https://travis-ci.org/caolan/async)\n\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. \n\nUsage:\n\n```html\n<script type=\"text/javascript\" src=\"async.js\"></script>\n<script type=\"text/javascript\">\n\n    async.map(data, asyncProcess, function(err, results){\n        alert(results);\n    });\n\n</script>\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`](#seriestasks-callback)\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* [`seq`](#seq)\n* [`applyEach`](#applyEach)\n* [`applyEachSeries`](#applyEachSeries)\n* [`queue`](#queue)\n* [`priorityQueue`](#priorityQueue)\n* [`cargo`](#cargo)\n* [`auto`](#auto)\n* [`retry`](#retry)\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<a name=\"forEach\" />\n<a name=\"each\" />\n### each(arr, iterator, callback)\n\nApplies the function `iterator` to each item in `arr`, 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 its `callback`, the main\n`callback` (for the `each` function) is immediately called with the error.\n\nNote, that since this function applies `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 `arr`.\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 when all `iterator` functions\n  have finished, or an error occurs.\n\n__Examples__\n\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```js\n// assuming openFiles is an array of file names \n\nasync.each(openFiles, function( file, callback) {\n  \n  // Perform operation on file here.\n  console.log('Processing file ' + file);\n  \n  if( file.length > 32 ) {\n    console.log('This file name is too long');\n    callback('File name too long');\n  } else {\n    // Do work to process file here\n    console.log('File processed');\n    callback();\n  }\n}, function(err){\n    // if any of the file processing produced an error, err would equal that error\n    if( err ) {\n      // One of the iterations produced an error.\n      // All processing will now stop.\n      console.log('A file failed to process');\n    } else {\n      console.log('All files have been processed successfully');\n    }\n});\n```\n\n---------------------------------------\n\n<a name=\"forEachSeries\" />\n<a name=\"eachSeries\" />\n### eachSeries(arr, iterator, callback)\n\nThe same as [`each`](#each), only `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThis means the `iterator` functions will complete in order.\n\n\n---------------------------------------\n\n<a name=\"forEachLimit\" />\n<a name=\"eachLimit\" />\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously \nrunning at any time.\n\nNote that the items in `arr` are not processed in batches, so there is no guarantee that \nthe first `limit` `iterator` functions will complete before any others are started.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `limit` - The maximum number of `iterator`s to run at any time.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\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 when all `iterator` functions\n  have finished, or an error occurs.\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<a name=\"map\" />\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in `arr` through\nthe `iterator` function. The `iterator` is called with an item from `arr` and a\ncallback for when it has finished processing. Each of these callback takes 2 arguments: \nan `error`, and the transformed item from `arr`. If `iterator` passes an error to this \ncallback, the main `callback` (for the `map` 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. \nHowever, the results array will be in the same order as the original `arr`.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\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 when all `iterator`\n  functions have finished, or an error occurs. Results is an array of the\n  transformed items from the `arr`.\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<a name=\"mapSeries\" />\n### mapSeries(arr, iterator, callback)\n\nThe same as [`map`](#map), only the `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n\n---------------------------------------\n\n<a name=\"mapLimit\" />\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as [`map`](#map), only no more than `limit` `iterator`s will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that \nthe first `limit` `iterator` functions will complete before any others are started.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `limit` - The maximum number of `iterator`s to run at any time.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\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 when all `iterator`\n  calls have finished, or an error occurs. The result is an array of the\n  transformed items from the original `arr`.\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<a name=\"select\" />\n<a name=\"filter\" />\n### filter(arr, iterator, callback)\n\n__Alias:__ `select`\n\nReturns a new array of all the values in `arr` which pass an async truth test.\n_The callback for each `iterator` call only accepts a single argument of `true` or\n`false`; 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 `arr`.\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<a name=\"selectSeries\" />\n<a name=\"filterSeries\" />\n### filterSeries(arr, iterator, callback)\n\n__Alias:__ `selectSeries`\n\nThe same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n---------------------------------------\n\n<a name=\"reject\" />\n### reject(arr, iterator, callback)\n\nThe opposite of [`filter`](#filter). Removes values that pass an `async` truth test.\n\n---------------------------------------\n\n<a name=\"rejectSeries\" />\n### rejectSeries(arr, iterator, callback)\n\nThe same as [`reject`](#reject), only the `iterator` is applied to each item in `arr`\nin series.\n\n\n---------------------------------------\n\n<a name=\"reduce\" />\n### reduce(arr, memo, iterator, callback)\n\n__Aliases:__ `inject`, `foldl`\n\nReduces `arr` into a single value using an async `iterator` to return\neach successive step. `memo` is the initial state of the reduction. \nThis function only operates in series. \n\nFor performance reasons, it may make sense to split a call to this function into \na parallel map, and then use the normal `Array.prototype.reduce` on the results. \nThis function is for situations where each step in the reduction needs to be async; \nif you can get the data before reducing 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<a name=\"reduceRight\" />\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ `foldr`\n\nSame as [`reduce`](#reduce), only operates on `arr` in reverse order.\n\n\n---------------------------------------\n\n<a name=\"detect\" />\n### detect(arr, iterator, callback)\n\nReturns the first value in `arr` that passes an async truth test. The\n`iterator` 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 `arr` (in terms of order) that passes the test.\n\nIf order within the original `arr` is important, then look at [`detectSeries`](#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 `arr`.\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<a name=\"detectSeries\" />\n### detectSeries(arr, iterator, callback)\n\nThe same as [`detect`](#detect), only the `iterator` is applied to each item in `arr`\nin series. This means the result is always the first in the original `arr` (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n<a name=\"sortBy\" />\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each `arr` 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 `arr`.\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 occurs. Results is the items from\n  the original `arr` 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__Sort Order__\n\nBy modifying the callback parameter the sorting order can be influenced:\n\n```js\n//ascending order\nasync.sortBy([1,9,3,5], function(x, callback){\n    callback(err, x);\n}, function(err,result){\n    //result callback\n} );\n\n//descending order\nasync.sortBy([1,9,3,5], function(x, callback){\n    callback(err, x*-1);    //<- x*-1 instead of x, turns the order around\n}, function(err,result){\n    //result callback\n} );\n```\n\n---------------------------------------\n\n<a name=\"some\" />\n### some(arr, iterator, callback)\n\n__Alias:__ `any`\n\nReturns `true` if at least one element in the `arr` satisfies an async test.\n_The callback for each iterator call only accepts a single argument of `true` or\n`false`; 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  in parallel. The iterator is passed a callback(truthValue) which must be \n  called with a 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<a name=\"every\" />\n### every(arr, iterator, callback)\n\n__Alias:__ `all`\n\nReturns `true` if every element in `arr` satisfies an async test.\n_The callback for each `iterator` call only accepts a single argument of `true` or\n`false`; 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  in parallel. The iterator is passed a callback(truthValue) which must be \n  called with a  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<a name=\"concat\" />\n### concat(arr, iterator, callback)\n\nApplies `iterator` to each item in `arr`, concatenating the results. Returns the\nconcatenated list. The `iterator`s 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 `arr` 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 `arr`.\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 occurs. 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<a name=\"concatSeries\" />\n### concatSeries(arr, iterator, callback)\n\nSame as [`concat`](#concat), but executes in series instead of parallel.\n\n\n## Control Flow\n\n<a name=\"series\" />\n### series(tasks, [callback])\n\nRun the functions in the `tasks` array 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 `callback` is immediately called with the value of the error. \nOtherwise, `callback` receives an array of results when `tasks` have completed.\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\n[`series`](#series).\n\n**Note** that while many implementations preserve the order of object properties, the\n[ECMAScript Language Specifcation](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) \nexplicitly states that\n\n> The mechanics and order of enumerating the properties is not specified.\n\nSo if you rely on the order in which your series of functions are executed, and want\nthis to work on all platforms, consider using an array. \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 `err` (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<a name=\"parallel\" />\n### parallel(tasks, [callback])\n\nRun the `tasks` 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\n[`parallel`](#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)` which it must call on completion with an error `err` \n  (which can 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<a name=\"parallelLimit\" />\n### parallelLimit(tasks, limit, [callback])\n\nThe same as [`parallel`](#parallel), only `tasks` are executed in parallel \nwith a maximum of `limit` tasks 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 `err` (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<a name=\"whilst\" />\n### whilst(test, fn, callback)\n\nRepeatedly call `fn`, while `test` returns `true`. Calls `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 which is called each time `test` passes. The function is\n  passed a `callback(err)`, which must be called once it has completed with an \n  optional `err` 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<a name=\"doWhilst\" />\n### doWhilst(fn, test, callback)\n\nThe post-check version of [`whilst`](#whilst). To reflect the difference in \nthe order of operations, the arguments `test` and `fn` are switched. \n\n`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n<a name=\"until\" />\n### until(test, fn, callback)\n\nRepeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped,\nor an error occurs.\n\nThe inverse of [`whilst`](#whilst).\n\n---------------------------------------\n\n<a name=\"doUntil\" />\n### doUntil(fn, test, callback)\n\nLike [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n<a name=\"forever\" />\n### forever(fn, errback)\n\nCalls the asynchronous function `fn` with a callback parameter that allows it to\ncall itself again, in series, indefinitely.\n\nIf an error is passed to the callback then `errback` is called with the\nerror, and execution stops, otherwise it will never be called.\n\n```js\nasync.forever(\n    function(next) {\n        // next is suitable for passing to things that need a callback(err [, whatever]);\n        // it will result in this function being called again.\n    },\n    function(err) {\n        // if next is called with a value in its first parameter, it will appear\n        // in here as 'err', and execution will stop.\n    }\n);\n```\n\n---------------------------------------\n\n<a name=\"waterfall\" />\n### waterfall(tasks, [callback])\n\nRuns the `tasks` array of functions in series, each passing their results to the next in\nthe array. However, if any of the `tasks` pass an error to their own 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      // arg1 now equals 'one' and arg2 now equals 'two'\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<a name=\"compose\" />\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\n`f(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<a name=\"seq\" />\n### seq(fn1, fn2...)\n\nVersion of the compose function that is more natural to read.\nEach following function consumes the return value of the latter function. \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\n// Requires lodash (or underscore), express3 and dresende's orm2.\n// Part of an app, that fetches cats of the logged user.\n// This example uses `seq` function to avoid overnesting and error \n// handling clutter.\napp.get('/cats', function(request, response) {\n  function handleError(err, data, callback) {\n    if (err) {\n      console.error(err);\n      response.json({ status: 'error', message: err.message });\n    }\n    else {\n      callback(data);\n    }\n  }\n  var User = request.models.User;\n  async.seq(\n    _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))\n    handleError,\n    function(user, fn) {\n      user.getCats(fn);      // 'getCats' has signature (callback(err, data))\n    },\n    handleError,\n    function(cats) {\n      response.json({ status: 'ok', message: 'Cats found', data: cats });\n    }\n  )(req.session.user_id);\n  }\n});\n```\n\n---------------------------------------\n<a name=\"applyEach\" />\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling \n`callback` 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<a name=\"applyEachSeries\" />\n### applyEachSeries(arr, iterator, callback)\n\nThe same as [`applyEach`](#applyEach) only the functions are applied in series.\n\n---------------------------------------\n\n<a name=\"queue\" />\n### queue(worker, concurrency)\n\nCreates a `queue` object with the specified `concurrency`. Tasks added to the\n`queue` are processed in parallel (up to the `concurrency` limit). If all\n`worker`s are in progress, the task is queued until one becomes available. \nOnce a `worker` completes a `task`, that `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* `started` - a function returning whether or not any items have been pushed and processed by the queue\n* `running()` - a function returning the number of items currently being processed.\n* `idle()` - a function returning false if there are items waiting or being processed, or true if not.\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`. Calls `callback` once \n  the `worker` has finished processing the task. Instead of a single task, a `tasks` array\n  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` limit, \n   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* `paused` - a boolean for determining whether the queue is in a paused state\n* `pause()` - a function that pauses the processing of tasks until `resume()` is called.\n* `resume()` - a function that resumes the processing of queued tasks when the queue is paused.\n* `kill()` - a function that empties remaining tasks from the queue forcing it to go idle.\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<a name=\"priorityQueue\" />\n### priorityQueue(worker, concurrency)\n\nThe same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects:\n\n* `push(task, priority, [callback])` - `priority` should be a number. If an array of\n  `tasks` is given, all tasks will be assigned the same priority.\n* The `unshift` method was removed.\n\n---------------------------------------\n\n<a name=\"cargo\" />\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\n`worker` is in progress, the task is queued until it becomes available. Once\nthe `worker` has completed some tasks, each callback of those tasks is called.\nCheck out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work.\n\nWhile [queue](#queue) passes only one task to one of a group of workers\nat a time, cargo passes an array of tasks to a single worker, repeating\nwhen the worker is finished.\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 `err` 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])` - Adds `task` to the `queue`. The callback is called\n  once the `worker` has finished processing the task. Instead of a single task, an array of `tasks` \n  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<tasks.length; i++){\n      console.log('hello ' + tasks[i].name);\n    }\n    callback();\n}, 2);\n\n\n// add some items\n\ncargo.push({name: 'foo'}, function (err) {\n    console.log('finished processing foo');\n});\ncargo.push({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\ncargo.push({name: 'baz'}, function (err) {\n    console.log('finished processing baz');\n});\n```\n\n---------------------------------------\n\n<a name=\"auto\" />\n### auto(tasks, [callback])\n\nDetermines the best order for running the functions in `tasks`, based on their \nrequirements. Each function can optionally depend on other functions being completed \nfirst, and each function is run as soon as its requirements are satisfied. \n\nIf any of the functions pass an error to their callback, it will not \ncomplete (so any other functions depending on it will not run), and the main \n`callback` is immediately called with the error. Functions also receive an \nobject containing 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. \n\nFor 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 \n`results` 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. Each of its properties is either a function or an array of\n  requirements, with the function itself the last item in the array. The object's key\n  of a property serves as the name of the task defined by that property,\n  i.e. can be used when specifying requirements for other tasks.\n  The 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. It receives the `err` argument if any `tasks` \n  pass an error to their callback. Results are always returned; however, if \n  an error occurs, no further `tasks` will be performed, and the results\n  object will only contain partial results.\n\n\n__Example__\n\n```js\nasync.auto({\n    get_data: function(callback){\n        console.log('in get_data');\n        // async code to get some data\n        callback(null, 'data', 'converted to array');\n    },\n    make_folder: function(callback){\n        console.log('in make_folder');\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        callback(null, 'folder');\n    },\n    write_file: ['get_data', 'make_folder', function(callback, results){\n        console.log('in write_file', JSON.stringify(results));\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        console.log('in email_link', JSON.stringify(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        callback(null, {'file':results.write_file, 'email':'user@example.com'});\n    }]\n}, function(err, results) {\n    console.log('err = ', err);\n    console.log('results = ', results);\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        console.log('in get_data');\n        // async code to get some data\n        callback(null, 'data', 'converted to array');\n    },\n    function(callback){\n        console.log('in make_folder');\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        callback(null, 'folder');\n    }\n],\nfunction(err, results){\n    async.series([\n        function(callback){\n            console.log('in write_file', JSON.stringify(results));\n            // once there is some data and the directory exists,\n            // write the data to a file in the directory\n            results.push('filename');\n            callback(null);\n        },\n        function(callback){\n            console.log('in email_link', JSON.stringify(results));\n            // once the file is written let's email a link to it...\n            callback(null, {'file':results.pop(), 'email':'user@example.com'});\n        }\n    ]);\n});\n```\n\nFor a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding\nnew tasks much easier (and the code more readable).\n\n\n---------------------------------------\n\n<a name=\"retry\" />\n### retry([times = 5], task, [callback])\n\nAttempts to get a successful response from `task` no more than `times` times before\nreturning an error. If the task is successful, the `callback` will be passed the result\nof the successfull task. If all attemps fail, the callback will be passed the error and\nresult (if any) of the final attempt.\n\n__Arguments__\n\n* `times` - An integer indicating how many times to attempt the `task` before giving up. Defaults to 5.\n* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)`\n  which must be called when finished, passing `err` (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 (if nested inside another control flow).\n* `callback(err, results)` - An optional callback which is called when the\n  task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`.\n\nThe [`retry`](#retry) function can be used as a stand-alone control flow by passing a\ncallback, as shown below:\n\n```js\nasync.retry(3, apiMethod, function(err, result) {\n    // do something with the result\n});\n```\n\nIt can also be embeded within other control flow functions to retry individual methods\nthat are not as reliable, like this:\n\n```js\nasync.auto({\n    users: api.getUsers.bind(api),\n    payments: async.retry(3, api.getPayments.bind(api))\n}, function(err, results) {\n  // do something with the results\n});\n```\n\n\n---------------------------------------\n\n<a name=\"iterator\" />\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the `tasks` array,\nreturning a continuation to call the next one after that. It's also possible to\n“peek” at the next iterator with `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<a name=\"apply\" />\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied. \n\nUseful as a shorthand 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<a name=\"nextTick\" />\n### nextTick(callback)\n\nCalls `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 `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<a name=\"times\" />\n### times(n, callback)\n\nCalls the `callback` function `n` times, and accumulates results in the same manner\nyou would use with [`map`](#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<a name=\"timesSeries\" />\n### timesSeries(n, callback)\n\nThe same as [`times`](#times), only the iterator is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n\n## Utils\n\n<a name=\"memoize\" />\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 to proxy and cache results from.\n* `hasher` - Tn 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<a name=\"unmemoize\" />\n### unmemoize(fn)\n\nUndoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized\nform. Handy for testing.\n\n__Arguments__\n\n* `fn` - the memoized function\n\n<a name=\"log\" />\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<a name=\"dir\" />\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<a name=\"noConflict\" />\n### noConflict()\n\nChanges the value of `async` back to its original value, returning a reference to the\n`async` object.\n",
-  "readmeFilename": "README.md",
-  "_id": "async@0.9.0",
-  "dist": {
-    "shasum": "ac3613b1da9bed1b47510bb4651b8931e47146c7"
-  },
-  "_from": "async@0.9.0",
-  "_resolved": "http://registry.npmjs.org/async/-/async-0.9.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/bindings/README.md b/input_devices/mag/node_modules/serialport/node_modules/bindings/README.md
deleted file mode 100644
index 585cf512..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/bindings/README.md
+++ /dev/null
@@ -1,97 +0,0 @@
-node-bindings
-=============
-### Helper module for loading your native module's .node file
-
-This is a helper module for authors of Node.js native addon modules.
-It is basically the "swiss army knife" of `require()`ing your native module's
-`.node` file.
-
-Throughout the course of Node's native addon history, addons have ended up being
-compiled in a variety of different places, depending on which build tool and which
-version of node was used. To make matters worse, now the _gyp_ build tool can
-produce either a _Release_ or _Debug_ build, each being built into different
-locations.
-
-This module checks _all_ the possible locations that a native addon would be built
-at, and returns the first one that loads successfully.
-
-
-Installation
-------------
-
-Install with `npm`:
-
-``` bash
-$ npm install bindings
-```
-
-Or add it to the `"dependencies"` section of your _package.json_ file.
-
-
-Example
--------
-
-`require()`ing the proper bindings file for the current node version, platform
-and architecture is as simple as:
-
-``` js
-var bindings = require('bindings')('binding.node')
-
-// Use your bindings defined in your C files
-bindings.your_c_function()
-```
-
-
-Nice Error Output
------------------
-
-When the `.node` file could not be loaded, `node-bindings` throws an Error with
-a nice error message telling you exactly what was tried. You can also check the
-`err.tries` Array property.
-
-```
-Error: Could not load the bindings file. Tried:
- → /Users/nrajlich/ref/build/binding.node
- → /Users/nrajlich/ref/build/Debug/binding.node
- → /Users/nrajlich/ref/build/Release/binding.node
- → /Users/nrajlich/ref/out/Debug/binding.node
- → /Users/nrajlich/ref/Debug/binding.node
- → /Users/nrajlich/ref/out/Release/binding.node
- → /Users/nrajlich/ref/Release/binding.node
- → /Users/nrajlich/ref/build/default/binding.node
- → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node
-    at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)
-    at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)
-    at Module._compile (module.js:449:26)
-    at Object.Module._extensions..js (module.js:467:10)
-    at Module.load (module.js:356:32)
-    at Function.Module._load (module.js:312:12)
-    ...
-```
-
-
-License
--------
-
-(The MIT License)
-
-Copyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
-
-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/input_devices/mag/node_modules/serialport/node_modules/bindings/bindings.js b/input_devices/mag/node_modules/serialport/node_modules/bindings/bindings.js
deleted file mode 100644
index 93dcf85a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/bindings/bindings.js
+++ /dev/null
@@ -1,166 +0,0 @@
-
-/**
- * Module dependencies.
- */
-
-var fs = require('fs')
-  , path = require('path')
-  , join = path.join
-  , dirname = path.dirname
-  , exists = fs.existsSync || path.existsSync
-  , defaults = {
-        arrow: process.env.NODE_BINDINGS_ARROW || ' → '
-      , compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled'
-      , platform: process.platform
-      , arch: process.arch
-      , version: process.versions.node
-      , bindings: 'bindings.node'
-      , try: [
-          // node-gyp's linked version in the "build" dir
-          [ 'module_root', 'build', 'bindings' ]
-          // node-waf and gyp_addon (a.k.a node-gyp)
-        , [ 'module_root', 'build', 'Debug', 'bindings' ]
-        , [ 'module_root', 'build', 'Release', 'bindings' ]
-          // Debug files, for development (legacy behavior, remove for node v0.9)
-        , [ 'module_root', 'out', 'Debug', 'bindings' ]
-        , [ 'module_root', 'Debug', 'bindings' ]
-          // Release files, but manually compiled (legacy behavior, remove for node v0.9)
-        , [ 'module_root', 'out', 'Release', 'bindings' ]
-        , [ 'module_root', 'Release', 'bindings' ]
-          // Legacy from node-waf, node <= 0.4.x
-        , [ 'module_root', 'build', 'default', 'bindings' ]
-          // Production "Release" buildtype binary (meh...)
-        , [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ]
-        ]
-    }
-
-/**
- * The main `bindings()` function loads the compiled bindings for a given module.
- * It uses V8's Error API to determine the parent filename that this function is
- * being invoked from, which is then used to find the root directory.
- */
-
-function bindings (opts) {
-
-  // Argument surgery
-  if (typeof opts == 'string') {
-    opts = { bindings: opts }
-  } else if (!opts) {
-    opts = {}
-  }
-  opts.__proto__ = defaults
-
-  // Get the module root
-  if (!opts.module_root) {
-    opts.module_root = exports.getRoot(exports.getFileName())
-  }
-
-  // Ensure the given bindings name ends with .node
-  if (path.extname(opts.bindings) != '.node') {
-    opts.bindings += '.node'
-  }
-
-  var tries = []
-    , i = 0
-    , l = opts.try.length
-    , n
-    , b
-    , err
-
-  for (; i<l; i++) {
-    n = join.apply(null, opts.try[i].map(function (p) {
-      return opts[p] || p
-    }))
-    tries.push(n)
-    try {
-      b = opts.path ? require.resolve(n) : require(n)
-      if (!opts.path) {
-        b.path = n
-      }
-      return b
-    } catch (e) {
-      if (!/not find/i.test(e.message)) {
-        throw e
-      }
-    }
-  }
-
-  err = new Error('Could not locate the bindings file. Tried:\n'
-    + tries.map(function (a) { return opts.arrow + a }).join('\n'))
-  err.tries = tries
-  throw err
-}
-module.exports = exports = bindings
-
-
-/**
- * Gets the filename of the JavaScript file that invokes this function.
- * Used to help find the root directory of a module.
- * Optionally accepts an filename argument to skip when searching for the invoking filename
- */
-
-exports.getFileName = function getFileName (calling_file) {
-  var origPST = Error.prepareStackTrace
-    , origSTL = Error.stackTraceLimit
-    , dummy = {}
-    , fileName
-
-  Error.stackTraceLimit = 10
-
-  Error.prepareStackTrace = function (e, st) {
-    for (var i=0, l=st.length; i<l; i++) {
-      fileName = st[i].getFileName()
-      if (fileName !== __filename) {
-        if (calling_file) {
-            if (fileName !== calling_file) {
-              return
-            }
-        } else {
-          return
-        }
-      }
-    }
-  }
-
-  // run the 'prepareStackTrace' function above
-  Error.captureStackTrace(dummy)
-  dummy.stack
-
-  // cleanup
-  Error.prepareStackTrace = origPST
-  Error.stackTraceLimit = origSTL
-
-  return fileName
-}
-
-/**
- * Gets the root directory of a module, given an arbitrary filename
- * somewhere in the module tree. The "root directory" is the directory
- * containing the `package.json` file.
- *
- *   In:  /home/nate/node-native-module/lib/index.js
- *   Out: /home/nate/node-native-module
- */
-
-exports.getRoot = function getRoot (file) {
-  var dir = dirname(file)
-    , prev
-  while (true) {
-    if (dir === '.') {
-      // Avoids an infinite loop in rare cases, like the REPL
-      dir = process.cwd()
-    }
-    if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
-      // Found the 'package.json' file or 'node_modules' dir; we're done
-      return dir
-    }
-    if (prev === dir) {
-      // Got to the top
-      throw new Error('Could not find module root given file: "' + file
-                    + '". Do you have a `package.json` file? ')
-    }
-    // Try the parent dir next
-    prev = dir
-    dir = join(dir, '..')
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/bindings/package.json b/input_devices/mag/node_modules/serialport/node_modules/bindings/package.json
deleted file mode 100644
index f00b0fc9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/bindings/package.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "name": "bindings",
-  "description": "Helper module for loading your native module's .node file",
-  "keywords": [
-    "native",
-    "addon",
-    "bindings",
-    "gyp",
-    "waf",
-    "c",
-    "c++"
-  ],
-  "version": "1.2.1",
-  "author": {
-    "name": "Nathan Rajlich",
-    "email": "nathan@tootallnate.net",
-    "url": "http://tootallnate.net"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/TooTallNate/node-bindings.git"
-  },
-  "main": "./bindings.js",
-  "bugs": {
-    "url": "https://github.com/TooTallNate/node-bindings/issues"
-  },
-  "homepage": "https://github.com/TooTallNate/node-bindings",
-  "license": "MIT",
-  "readme": "node-bindings\n=============\n### Helper module for loading your native module's .node file\n\nThis is a helper module for authors of Node.js native addon modules.\nIt is basically the \"swiss army knife\" of `require()`ing your native module's\n`.node` file.\n\nThroughout the course of Node's native addon history, addons have ended up being\ncompiled in a variety of different places, depending on which build tool and which\nversion of node was used. To make matters worse, now the _gyp_ build tool can\nproduce either a _Release_ or _Debug_ build, each being built into different\nlocations.\n\nThis module checks _all_ the possible locations that a native addon would be built\nat, and returns the first one that loads successfully.\n\n\nInstallation\n------------\n\nInstall with `npm`:\n\n``` bash\n$ npm install bindings\n```\n\nOr add it to the `\"dependencies\"` section of your _package.json_ file.\n\n\nExample\n-------\n\n`require()`ing the proper bindings file for the current node version, platform\nand architecture is as simple as:\n\n``` js\nvar bindings = require('bindings')('binding.node')\n\n// Use your bindings defined in your C files\nbindings.your_c_function()\n```\n\n\nNice Error Output\n-----------------\n\nWhen the `.node` file could not be loaded, `node-bindings` throws an Error with\na nice error message telling you exactly what was tried. You can also check the\n`err.tries` Array property.\n\n```\nError: Could not load the bindings file. Tried:\n → /Users/nrajlich/ref/build/binding.node\n → /Users/nrajlich/ref/build/Debug/binding.node\n → /Users/nrajlich/ref/build/Release/binding.node\n → /Users/nrajlich/ref/out/Debug/binding.node\n → /Users/nrajlich/ref/Debug/binding.node\n → /Users/nrajlich/ref/out/Release/binding.node\n → /Users/nrajlich/ref/Release/binding.node\n → /Users/nrajlich/ref/build/default/binding.node\n → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node\n    at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)\n    at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)\n    at Module._compile (module.js:449:26)\n    at Object.Module._extensions..js (module.js:467:10)\n    at Module.load (module.js:356:32)\n    at Function.Module._load (module.js:312:12)\n    ...\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
-  "readmeFilename": "README.md",
-  "_id": "bindings@1.2.1",
-  "dist": {
-    "shasum": "66dd71d2b079b1aa1433f3e25b7c9362bba14d8b"
-  },
-  "_from": "bindings@1.2.1",
-  "_resolved": "http://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/.jshintrc b/input_devices/mag/node_modules/serialport/node_modules/debug/.jshintrc
deleted file mode 100644
index 299877f2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/.jshintrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "laxbreak": true
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/debug/.npmignore
deleted file mode 100644
index 7e6163db..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/.npmignore
+++ /dev/null
@@ -1,6 +0,0 @@
-support
-test
-examples
-example
-*.sock
-dist
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/History.md b/input_devices/mag/node_modules/serialport/node_modules/debug/History.md
deleted file mode 100644
index 770e4832..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/History.md
+++ /dev/null
@@ -1,186 +0,0 @@
-
-2.1.3 / 2015-03-13
-==================
-
-  * Updated stdout/stderr example (#186)
-  * Updated example/stdout.js to match debug current behaviour
-  * Renamed example/stderr.js to stdout.js
-  * Update Readme.md (#184)
-  * replace high intensity foreground color for bold (#182, #183)
-
-2.1.2 / 2015-03-01
-==================
-
-  * dist: recompile
-  * update "ms" to v0.7.0
-  * package: update "browserify" to v9.0.3
-  * component: fix "ms.js" repo location
-  * changed bower package name
-  * updated documentation about using debug in a browser
-  * fix: security error on safari (#167, #168, @yields)
-
-2.1.1 / 2014-12-29
-==================
-
-  * browser: use `typeof` to check for `console` existence
-  * browser: check for `console.log` truthiness (fix IE 8/9)
-  * browser: add support for Chrome apps
-  * Readme: added Windows usage remarks
-  * Add `bower.json` to properly support bower install
-
-2.1.0 / 2014-10-15
-==================
-
-  * node: implement `DEBUG_FD` env variable support
-  * package: update "browserify" to v6.1.0
-  * package: add "license" field to package.json (#135, @panuhorsmalahti)
-
-2.0.0 / 2014-09-01
-==================
-
-  * package: update "browserify" to v5.11.0
-  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
-
-1.0.4 / 2014-07-15
-==================
-
-  * dist: recompile
-  * example: remove `console.info()` log usage
-  * example: add "Content-Type" UTF-8 header to browser example
-  * browser: place %c marker after the space character
-  * browser: reset the "content" color via `color: inherit`
-  * browser: add colors support for Firefox >= v31
-  * debug: prefer an instance `log()` function over the global one (#119)
-  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
-
-1.0.3 / 2014-07-09
-==================
-
-  * Add support for multiple wildcards in namespaces (#122, @seegno)
-  * browser: fix lint
-
-1.0.2 / 2014-06-10
-==================
-
-  * browser: update color palette (#113, @gscottolson)
-  * common: make console logging function configurable (#108, @timoxley)
-  * node: fix %o colors on old node <= 0.8.x
-  * Makefile: find node path using shell/which (#109, @timoxley)
-
-1.0.1 / 2014-06-06
-==================
-
-  * browser: use `removeItem()` to clear localStorage
-  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
-  * package: add "contributors" section
-  * node: fix comment typo
-  * README: list authors
-
-1.0.0 / 2014-06-04
-==================
-
-  * make ms diff be global, not be scope
-  * debug: ignore empty strings in enable()
-  * node: make DEBUG_COLORS able to disable coloring
-  * *: export the `colors` array
-  * npmignore: don't publish the `dist` dir
-  * Makefile: refactor to use browserify
-  * package: add "browserify" as a dev dependency
-  * Readme: add Web Inspector Colors section
-  * node: reset terminal color for the debug content
-  * node: map "%o" to `util.inspect()`
-  * browser: map "%j" to `JSON.stringify()`
-  * debug: add custom "formatters"
-  * debug: use "ms" module for humanizing the diff
-  * Readme: add "bash" syntax highlighting
-  * browser: add Firebug color support
-  * browser: add colors for WebKit browsers
-  * node: apply log to `console`
-  * rewrite: abstract common logic for Node & browsers
-  * add .jshintrc file
-
-0.8.1 / 2014-04-14
-==================
-
-  * package: re-add the "component" section
-
-0.8.0 / 2014-03-30
-==================
-
-  * add `enable()` method for nodejs. Closes #27
-  * change from stderr to stdout
-  * remove unnecessary index.js file
-
-0.7.4 / 2013-11-13
-==================
-
-  * remove "browserify" key from package.json (fixes something in browserify)
-
-0.7.3 / 2013-10-30
-==================
-
-  * fix: catch localStorage security error when cookies are blocked (Chrome)
-  * add debug(err) support. Closes #46
-  * add .browser prop to package.json. Closes #42
-
-0.7.2 / 2013-02-06
-==================
-
-  * fix package.json
-  * fix: Mobile Safari (private mode) is broken with debug
-  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
-
-0.7.1 / 2013-02-05
-==================
-
-  * add repository URL to package.json
-  * add DEBUG_COLORED to force colored output
-  * add browserify support
-  * fix component. Closes #24
-
-0.7.0 / 2012-05-04
-==================
-
-  * Added .component to package.json
-  * Added debug.component.js build
-
-0.6.0 / 2012-03-16
-==================
-
-  * Added support for "-" prefix in DEBUG [Vinay Pulim]
-  * Added `.enabled` flag to the node version [TooTallNate]
-
-0.5.0 / 2012-02-02
-==================
-
-  * Added: humanize diffs. Closes #8
-  * Added `debug.disable()` to the CS variant
-  * Removed padding. Closes #10
-  * Fixed: persist client-side variant again. Closes #9
-
-0.4.0 / 2012-02-01
-==================
-
-  * Added browser variant support for older browsers [TooTallNate]
-  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
-  * Added padding to diff (moved it to the right)
-
-0.3.0 / 2012-01-26
-==================
-
-  * Added millisecond diff when isatty, otherwise UTC string
-
-0.2.0 / 2012-01-22
-==================
-
-  * Added wildcard support
-
-0.1.0 / 2011-12-02
-==================
-
-  * Added: remove colors unless stderr isatty [TooTallNate]
-
-0.0.1 / 2010-01-03
-==================
-
-  * Initial release
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/Makefile b/input_devices/mag/node_modules/serialport/node_modules/debug/Makefile
deleted file mode 100644
index b0bde6e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-
-# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
-THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
-THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
-
-# BIN directory
-BIN := $(THIS_DIR)/node_modules/.bin
-
-# applications
-NODE ?= $(shell which node)
-NPM ?= $(NODE) $(shell which npm)
-BROWSERIFY ?= $(NODE) $(BIN)/browserify
-
-all: dist/debug.js
-
-install: node_modules
-
-clean:
-	@rm -rf node_modules dist
-
-dist:
-	@mkdir -p $@
-
-dist/debug.js: node_modules browser.js debug.js dist
-	@$(BROWSERIFY) \
-		--standalone debug \
-		. > $@
-
-node_modules: package.json
-	@NODE_ENV= $(NPM) install
-	@touch node_modules
-
-.PHONY: all install clean
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/Readme.md b/input_devices/mag/node_modules/serialport/node_modules/debug/Readme.md
deleted file mode 100644
index 14222e0c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/Readme.md
+++ /dev/null
@@ -1,178 +0,0 @@
-# debug
-
-  tiny node.js debugging utility modelled after node core's debugging technique.
-
-## Installation
-
-```bash
-$ npm install debug
-```
-
-## Usage
-
- With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.
-
-Example _app.js_:
-
-```js
-var debug = require('debug')('http')
-  , http = require('http')
-  , name = 'My App';
-
-// fake app
-
-debug('booting %s', name);
-
-http.createServer(function(req, res){
-  debug(req.method + ' ' + req.url);
-  res.end('hello\n');
-}).listen(3000, function(){
-  debug('listening');
-});
-
-// fake worker of some kind
-
-require('./worker');
-```
-
-Example _worker.js_:
-
-```js
-var debug = require('debug')('worker');
-
-setInterval(function(){
-  debug('doing some work');
-}, 1000);
-```
-
- The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
-
-  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
-
-  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
-
-#### Windows note
-
- On Windows the environment variable is set using the `set` command. 
- 
- ```cmd
- set DEBUG=*,-not_this
- ```
-
-Then, run the program to be debugged as usual.
-
-## Millisecond diff
-
-  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
-
-  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
-
-  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
-
-  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
-
-## Conventions
-
- If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
-
-## Wildcards
-
-  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
-
-  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
-
-## Browser support
-
-  Debug works in the browser as well, currently persisted by `localStorage`. Consider the situation shown below where you have `worker:a` and `worker:b`, and wish to debug both. Somewhere in the code on your page, include:
-
-```js
-window.myDebug = require("debug");
-```
-
-  ("debug" is a global object in the browser so we give this object a different name.) When your page is open in the browser, type the following in the console:
-
-```js
-myDebug.enable("worker:*")
-```
-
-  Refresh the page. Debug output will continue to be sent to the console until it is disabled by typing `myDebug.disable()` in the console.
-
-```js
-a = debug('worker:a');
-b = debug('worker:b');
-
-setInterval(function(){
-  a('doing some work');
-}, 1000);
-
-setInterval(function(){
-  b('doing some work');
-}, 1200);
-```
-
-#### Web Inspector Colors
-
-  Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
-  option. These are WebKit web inspectors, Firefox ([since version
-  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
-  and the Firebug plugin for Firefox (any version).
-
-  Colored output looks something like:
-
-  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
-
-### stderr vs stdout
-
-You can set an alternative logging method per-namespace by overriding the `log` method on a per-namespace or globally:
-
-Example _stdout.js_:
-
-```js
-var debug = require('debug');
-var error = debug('app:error');
-
-// by default stderr is used
-error('goes to stderr!');
-
-var log = debug('app:log');
-// set this namespace to log via console.log
-log.log = console.log.bind(console); // don't forget to bind to console!
-log('goes to stdout');
-error('still goes to stderr!');
-
-// set all output to go via console.info
-// overrides all per-namespace log settings
-debug.log = console.info.bind(console);
-error('now goes to stdout via console.info');
-log('still goes to stdout, but via console.info now');
-```
-
-## Authors
-
- - TJ Holowaychuk
- - Nathan Rajlich
-
-## License
-
-(The MIT License)
-
-Copyright (c) 2014 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
-
-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/input_devices/mag/node_modules/serialport/node_modules/debug/bower.json b/input_devices/mag/node_modules/serialport/node_modules/debug/bower.json
deleted file mode 100644
index f7d3f6dc..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/bower.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "name": "visionmedia-debug",
-  "main": "dist/debug.js",
-  "version": "2.1.3",
-  "homepage": "https://github.com/visionmedia/debug",
-  "authors": [
-    "TJ Holowaychuk <tj@vision-media.ca>"
-  ],
-  "description": "visionmedia-debug",
-  "moduleType": [
-    "amd",
-    "es6",
-    "globals",
-    "node"
-  ],
-  "keywords": [
-    "visionmedia",
-    "debug"
-  ],
-  "license": "MIT",
-  "ignore": [
-    "**/.*",
-    "node_modules",
-    "bower_components",
-    "test",
-    "tests"
-  ]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/browser.js b/input_devices/mag/node_modules/serialport/node_modules/debug/browser.js
deleted file mode 100644
index 55f4cf92..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/browser.js
+++ /dev/null
@@ -1,175 +0,0 @@
-
-/**
- * This is the web browser implementation of `debug()`.
- *
- * Expose `debug()` as the module.
- */
-
-exports = module.exports = require('./debug');
-exports.log = log;
-exports.formatArgs = formatArgs;
-exports.save = save;
-exports.load = load;
-exports.useColors = useColors;
-
-/**
- * Use chrome.storage.local if we are in an app
- */
-
-var storage;
-
-if (typeof chrome !== 'undefined' && typeof chrome.storage !== 'undefined')
-  storage = chrome.storage.local;
-else
-  storage = localstorage();
-
-/**
- * Colors.
- */
-
-exports.colors = [
-  'lightseagreen',
-  'forestgreen',
-  'goldenrod',
-  'dodgerblue',
-  'darkorchid',
-  'crimson'
-];
-
-/**
- * Currently only WebKit-based Web Inspectors, Firefox >= v31,
- * and the Firebug extension (any Firefox version) are known
- * to support "%c" CSS customizations.
- *
- * TODO: add a `localStorage` variable to explicitly enable/disable colors
- */
-
-function useColors() {
-  // is webkit? http://stackoverflow.com/a/16459606/376773
-  return ('WebkitAppearance' in document.documentElement.style) ||
-    // is firebug? http://stackoverflow.com/a/398120/376773
-    (window.console && (console.firebug || (console.exception && console.table))) ||
-    // is firefox >= v31?
-    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
-    (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
-}
-
-/**
- * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
- */
-
-exports.formatters.j = function(v) {
-  return JSON.stringify(v);
-};
-
-
-/**
- * Colorize log arguments if enabled.
- *
- * @api public
- */
-
-function formatArgs() {
-  var args = arguments;
-  var useColors = this.useColors;
-
-  args[0] = (useColors ? '%c' : '')
-    + this.namespace
-    + (useColors ? ' %c' : ' ')
-    + args[0]
-    + (useColors ? '%c ' : ' ')
-    + '+' + exports.humanize(this.diff);
-
-  if (!useColors) return args;
-
-  var c = 'color: ' + this.color;
-  args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
-
-  // the final "%c" is somewhat tricky, because there could be other
-  // arguments passed either before or after the %c, so we need to
-  // figure out the correct index to insert the CSS into
-  var index = 0;
-  var lastC = 0;
-  args[0].replace(/%[a-z%]/g, function(match) {
-    if ('%%' === match) return;
-    index++;
-    if ('%c' === match) {
-      // we only are interested in the *last* %c
-      // (the user may have provided their own)
-      lastC = index;
-    }
-  });
-
-  args.splice(lastC, 0, c);
-  return args;
-}
-
-/**
- * Invokes `console.log()` when available.
- * No-op when `console.log` is not a "function".
- *
- * @api public
- */
-
-function log() {
-  // this hackery is required for IE8/9, where
-  // the `console.log` function doesn't have 'apply'
-  return 'object' === typeof console
-    && console.log
-    && Function.prototype.apply.call(console.log, console, arguments);
-}
-
-/**
- * Save `namespaces`.
- *
- * @param {String} namespaces
- * @api private
- */
-
-function save(namespaces) {
-  try {
-    if (null == namespaces) {
-      storage.removeItem('debug');
-    } else {
-      storage.debug = namespaces;
-    }
-  } catch(e) {}
-}
-
-/**
- * Load `namespaces`.
- *
- * @return {String} returns the previously persisted debug modes
- * @api private
- */
-
-function load() {
-  var r;
-  try {
-    r = storage.debug;
-  } catch(e) {}
-  return r;
-}
-
-/**
- * Enable namespaces listed in `localStorage.debug` initially.
- */
-
-exports.enable(load());
-
-/**
- * Localstorage attempts to return the localstorage.
- *
- * This is necessary because safari throws
- * when a user disables cookies/localstorage
- * and you attempt to access it.
- *
- * @return {LocalStorage}
- * @api private
- */
-
-function localstorage(){
-  try {
-    return window.localStorage;
-  } catch (e) {}
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/component.json b/input_devices/mag/node_modules/serialport/node_modules/debug/component.json
deleted file mode 100644
index 52ffd422..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/component.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "name": "debug",
-  "repo": "visionmedia/debug",
-  "description": "small debugging utility",
-  "version": "2.1.3",
-  "keywords": [
-    "debug",
-    "log",
-    "debugger"
-  ],
-  "main": "browser.js",
-  "scripts": [
-    "browser.js",
-    "debug.js"
-  ],
-  "dependencies": {
-    "rauchg/ms.js": "0.7.0"
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/debug.js b/input_devices/mag/node_modules/serialport/node_modules/debug/debug.js
deleted file mode 100644
index 7571a860..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/debug.js
+++ /dev/null
@@ -1,197 +0,0 @@
-
-/**
- * This is the common logic for both the Node.js and web browser
- * implementations of `debug()`.
- *
- * Expose `debug()` as the module.
- */
-
-exports = module.exports = debug;
-exports.coerce = coerce;
-exports.disable = disable;
-exports.enable = enable;
-exports.enabled = enabled;
-exports.humanize = require('ms');
-
-/**
- * The currently active debug mode names, and names to skip.
- */
-
-exports.names = [];
-exports.skips = [];
-
-/**
- * Map of special "%n" handling functions, for the debug "format" argument.
- *
- * Valid key names are a single, lowercased letter, i.e. "n".
- */
-
-exports.formatters = {};
-
-/**
- * Previously assigned color.
- */
-
-var prevColor = 0;
-
-/**
- * Previous log timestamp.
- */
-
-var prevTime;
-
-/**
- * Select a color.
- *
- * @return {Number}
- * @api private
- */
-
-function selectColor() {
-  return exports.colors[prevColor++ % exports.colors.length];
-}
-
-/**
- * Create a debugger with the given `namespace`.
- *
- * @param {String} namespace
- * @return {Function}
- * @api public
- */
-
-function debug(namespace) {
-
-  // define the `disabled` version
-  function disabled() {
-  }
-  disabled.enabled = false;
-
-  // define the `enabled` version
-  function enabled() {
-
-    var self = enabled;
-
-    // set `diff` timestamp
-    var curr = +new Date();
-    var ms = curr - (prevTime || curr);
-    self.diff = ms;
-    self.prev = prevTime;
-    self.curr = curr;
-    prevTime = curr;
-
-    // add the `color` if not set
-    if (null == self.useColors) self.useColors = exports.useColors();
-    if (null == self.color && self.useColors) self.color = selectColor();
-
-    var args = Array.prototype.slice.call(arguments);
-
-    args[0] = exports.coerce(args[0]);
-
-    if ('string' !== typeof args[0]) {
-      // anything else let's inspect with %o
-      args = ['%o'].concat(args);
-    }
-
-    // apply any `formatters` transformations
-    var index = 0;
-    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
-      // if we encounter an escaped % then don't increase the array index
-      if (match === '%%') return match;
-      index++;
-      var formatter = exports.formatters[format];
-      if ('function' === typeof formatter) {
-        var val = args[index];
-        match = formatter.call(self, val);
-
-        // now we need to remove `args[index]` since it's inlined in the `format`
-        args.splice(index, 1);
-        index--;
-      }
-      return match;
-    });
-
-    if ('function' === typeof exports.formatArgs) {
-      args = exports.formatArgs.apply(self, args);
-    }
-    var logFn = enabled.log || exports.log || console.log.bind(console);
-    logFn.apply(self, args);
-  }
-  enabled.enabled = true;
-
-  var fn = exports.enabled(namespace) ? enabled : disabled;
-
-  fn.namespace = namespace;
-
-  return fn;
-}
-
-/**
- * Enables a debug mode by namespaces. This can include modes
- * separated by a colon and wildcards.
- *
- * @param {String} namespaces
- * @api public
- */
-
-function enable(namespaces) {
-  exports.save(namespaces);
-
-  var split = (namespaces || '').split(/[\s,]+/);
-  var len = split.length;
-
-  for (var i = 0; i < len; i++) {
-    if (!split[i]) continue; // ignore empty strings
-    namespaces = split[i].replace(/\*/g, '.*?');
-    if (namespaces[0] === '-') {
-      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
-    } else {
-      exports.names.push(new RegExp('^' + namespaces + '$'));
-    }
-  }
-}
-
-/**
- * Disable debug output.
- *
- * @api public
- */
-
-function disable() {
-  exports.enable('');
-}
-
-/**
- * Returns true if the given mode name is enabled, false otherwise.
- *
- * @param {String} name
- * @return {Boolean}
- * @api public
- */
-
-function enabled(name) {
-  var i, len;
-  for (i = 0, len = exports.skips.length; i < len; i++) {
-    if (exports.skips[i].test(name)) {
-      return false;
-    }
-  }
-  for (i = 0, len = exports.names.length; i < len; i++) {
-    if (exports.names[i].test(name)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-/**
- * Coerce `val`.
- *
- * @param {Mixed} val
- * @return {Mixed}
- * @api private
- */
-
-function coerce(val) {
-  if (val instanceof Error) return val.stack || val.message;
-  return val;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/node.js b/input_devices/mag/node_modules/serialport/node_modules/debug/node.js
deleted file mode 100644
index 1d392a81..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/node.js
+++ /dev/null
@@ -1,209 +0,0 @@
-
-/**
- * Module dependencies.
- */
-
-var tty = require('tty');
-var util = require('util');
-
-/**
- * This is the Node.js implementation of `debug()`.
- *
- * Expose `debug()` as the module.
- */
-
-exports = module.exports = require('./debug');
-exports.log = log;
-exports.formatArgs = formatArgs;
-exports.save = save;
-exports.load = load;
-exports.useColors = useColors;
-
-/**
- * Colors.
- */
-
-exports.colors = [6, 2, 3, 4, 5, 1];
-
-/**
- * The file descriptor to write the `debug()` calls to.
- * Set the `DEBUG_FD` env variable to override with another value. i.e.:
- *
- *   $ DEBUG_FD=3 node script.js 3>debug.log
- */
-
-var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
-var stream = 1 === fd ? process.stdout :
-             2 === fd ? process.stderr :
-             createWritableStdioStream(fd);
-
-/**
- * Is stdout a TTY? Colored output is enabled when `true`.
- */
-
-function useColors() {
-  var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase();
-  if (0 === debugColors.length) {
-    return tty.isatty(fd);
-  } else {
-    return '0' !== debugColors
-        && 'no' !== debugColors
-        && 'false' !== debugColors
-        && 'disabled' !== debugColors;
-  }
-}
-
-/**
- * Map %o to `util.inspect()`, since Node doesn't do that out of the box.
- */
-
-var inspect = (4 === util.inspect.length ?
-  // node <= 0.8.x
-  function (v, colors) {
-    return util.inspect(v, void 0, void 0, colors);
-  } :
-  // node > 0.8.x
-  function (v, colors) {
-    return util.inspect(v, { colors: colors });
-  }
-);
-
-exports.formatters.o = function(v) {
-  return inspect(v, this.useColors)
-    .replace(/\s*\n\s*/g, ' ');
-};
-
-/**
- * Adds ANSI color escape codes if enabled.
- *
- * @api public
- */
-
-function formatArgs() {
-  var args = arguments;
-  var useColors = this.useColors;
-  var name = this.namespace;
-
-  if (useColors) {
-    var c = this.color;
-
-    args[0] = '  \u001b[3' + c + ';1m' + name + ' '
-      + '\u001b[0m'
-      + args[0] + '\u001b[3' + c + 'm'
-      + ' +' + exports.humanize(this.diff) + '\u001b[0m';
-  } else {
-    args[0] = new Date().toUTCString()
-      + ' ' + name + ' ' + args[0];
-  }
-  return args;
-}
-
-/**
- * Invokes `console.error()` with the specified arguments.
- */
-
-function log() {
-  return stream.write(util.format.apply(this, arguments) + '\n');
-}
-
-/**
- * Save `namespaces`.
- *
- * @param {String} namespaces
- * @api private
- */
-
-function save(namespaces) {
-  if (null == namespaces) {
-    // If you set a process.env field to null or undefined, it gets cast to the
-    // string 'null' or 'undefined'. Just delete instead.
-    delete process.env.DEBUG;
-  } else {
-    process.env.DEBUG = namespaces;
-  }
-}
-
-/**
- * Load `namespaces`.
- *
- * @return {String} returns the previously persisted debug modes
- * @api private
- */
-
-function load() {
-  return process.env.DEBUG;
-}
-
-/**
- * Copied from `node/src/node.js`.
- *
- * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
- * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
- */
-
-function createWritableStdioStream (fd) {
-  var stream;
-  var tty_wrap = process.binding('tty_wrap');
-
-  // Note stream._type is used for test-module-load-list.js
-
-  switch (tty_wrap.guessHandleType(fd)) {
-    case 'TTY':
-      stream = new tty.WriteStream(fd);
-      stream._type = 'tty';
-
-      // Hack to have stream not keep the event loop alive.
-      // See https://github.com/joyent/node/issues/1726
-      if (stream._handle && stream._handle.unref) {
-        stream._handle.unref();
-      }
-      break;
-
-    case 'FILE':
-      var fs = require('fs');
-      stream = new fs.SyncWriteStream(fd, { autoClose: false });
-      stream._type = 'fs';
-      break;
-
-    case 'PIPE':
-    case 'TCP':
-      var net = require('net');
-      stream = new net.Socket({
-        fd: fd,
-        readable: false,
-        writable: true
-      });
-
-      // FIXME Should probably have an option in net.Socket to create a
-      // stream from an existing fd which is writable only. But for now
-      // we'll just add this hack and set the `readable` member to false.
-      // Test: ./node test/fixtures/echo.js < /etc/passwd
-      stream.readable = false;
-      stream.read = null;
-      stream._type = 'pipe';
-
-      // FIXME Hack to have stream not keep the event loop alive.
-      // See https://github.com/joyent/node/issues/1726
-      if (stream._handle && stream._handle.unref) {
-        stream._handle.unref();
-      }
-      break;
-
-    default:
-      // Probably an error on in uv_guess_handle()
-      throw new Error('Implement me. Unknown stream file type!');
-  }
-
-  // For supporting legacy API we put the FD here.
-  stream.fd = fd;
-
-  stream._isStdio = true;
-
-  return stream;
-}
-
-/**
- * Enable namespaces listed in `process.env.DEBUG` initially.
- */
-
-exports.enable(load());
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/.npmignore
deleted file mode 100644
index d1aa0ce4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/.npmignore
+++ /dev/null
@@ -1,5 +0,0 @@
-node_modules
-test
-History.md
-Makefile
-component.json
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/LICENSE
deleted file mode 100644
index 6c07561b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-(The MIT License)
-
-Copyright (c) 2014 Guillermo Rauch <rauchg@gmail.com>
-
-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/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/README.md b/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/README.md
deleted file mode 100644
index 0fd54fdc..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# ms.js: miliseconds conversion utility
-
-```js
-ms('2 days')  // 172800000
-ms('1d')      // 86400000
-ms('10h')     // 36000000
-ms('2.5 hrs') // 9000000
-ms('2h')      // 7200000
-ms('1m')      // 60000
-ms('5s')      // 5000
-ms('100')     // 100
-```
-
-```js
-ms(60000)             // "1m"
-ms(2 * 60000)         // "2m"
-ms(ms('10 hours'))    // "10h"
-```
-
-```js
-ms(60000, { long: true })             // "1 minute"
-ms(2 * 60000, { long: true })         // "2 minutes"
-ms(ms('10 hours'), { long: true })    // "10 hours"
-```
-
-- Node/Browser compatible. Published as [`ms`](https://www.npmjs.org/package/ms) in [NPM](nodejs.org/download).
-- If a number is supplied to `ms`, a string with a unit is returned.
-- If a string that contains the number is supplied, it returns it as
-a number (e.g: it returns `100` for `'100'`).
-- If you pass a string with a number and a valid unit, the number of
-equivalent ms is returned.
-
-## License
-
-MIT
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/index.js b/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/index.js
deleted file mode 100644
index e79bfa18..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/index.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * Helpers.
- */
-
-var s = 1000;
-var m = s * 60;
-var h = m * 60;
-var d = h * 24;
-var y = d * 365.25;
-
-/**
- * Parse or format the given `val`.
- *
- * Options:
- *
- *  - `long` verbose formatting [false]
- *
- * @param {String|Number} val
- * @param {Object} options
- * @return {String|Number}
- * @api public
- */
-
-module.exports = function(val, options){
-  options = options || {};
-  if ('string' == typeof val) return parse(val);
-  return options.long
-    ? long(val)
-    : short(val);
-};
-
-/**
- * Parse the given `str` and return milliseconds.
- *
- * @param {String} str
- * @return {Number}
- * @api private
- */
-
-function parse(str) {
-  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
-  if (!match) return;
-  var n = parseFloat(match[1]);
-  var type = (match[2] || 'ms').toLowerCase();
-  switch (type) {
-    case 'years':
-    case 'year':
-    case 'yrs':
-    case 'yr':
-    case 'y':
-      return n * y;
-    case 'days':
-    case 'day':
-    case 'd':
-      return n * d;
-    case 'hours':
-    case 'hour':
-    case 'hrs':
-    case 'hr':
-    case 'h':
-      return n * h;
-    case 'minutes':
-    case 'minute':
-    case 'mins':
-    case 'min':
-    case 'm':
-      return n * m;
-    case 'seconds':
-    case 'second':
-    case 'secs':
-    case 'sec':
-    case 's':
-      return n * s;
-    case 'milliseconds':
-    case 'millisecond':
-    case 'msecs':
-    case 'msec':
-    case 'ms':
-      return n;
-  }
-}
-
-/**
- * Short format for `ms`.
- *
- * @param {Number} ms
- * @return {String}
- * @api private
- */
-
-function short(ms) {
-  if (ms >= d) return Math.round(ms / d) + 'd';
-  if (ms >= h) return Math.round(ms / h) + 'h';
-  if (ms >= m) return Math.round(ms / m) + 'm';
-  if (ms >= s) return Math.round(ms / s) + 's';
-  return ms + 'ms';
-}
-
-/**
- * Long format for `ms`.
- *
- * @param {Number} ms
- * @return {String}
- * @api private
- */
-
-function long(ms) {
-  return plural(ms, d, 'day')
-    || plural(ms, h, 'hour')
-    || plural(ms, m, 'minute')
-    || plural(ms, s, 'second')
-    || ms + ' ms';
-}
-
-/**
- * Pluralization helper.
- */
-
-function plural(ms, n, name) {
-  if (ms < n) return;
-  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
-  return Math.ceil(ms / n) + ' ' + name + 's';
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/package.json b/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/package.json
deleted file mode 100644
index fb0bd0d6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/node_modules/ms/package.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-  "name": "ms",
-  "version": "0.7.0",
-  "description": "Tiny ms conversion utility",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/guille/ms.js.git"
-  },
-  "main": "./index",
-  "devDependencies": {
-    "mocha": "*",
-    "expect.js": "*",
-    "serve": "*"
-  },
-  "component": {
-    "scripts": {
-      "ms/index.js": "index.js"
-    }
-  },
-  "readme": "# ms.js: miliseconds conversion utility\n\n```js\nms('2 days')  // 172800000\nms('1d')      // 86400000\nms('10h')     // 36000000\nms('2.5 hrs') // 9000000\nms('2h')      // 7200000\nms('1m')      // 60000\nms('5s')      // 5000\nms('100')     // 100\n```\n\n```js\nms(60000)             // \"1m\"\nms(2 * 60000)         // \"2m\"\nms(ms('10 hours'))    // \"10h\"\n```\n\n```js\nms(60000, { long: true })             // \"1 minute\"\nms(2 * 60000, { long: true })         // \"2 minutes\"\nms(ms('10 hours'), { long: true })    // \"10 hours\"\n```\n\n- Node/Browser compatible. Published as [`ms`](https://www.npmjs.org/package/ms) in [NPM](nodejs.org/download).\n- If a number is supplied to `ms`, a string with a unit is returned.\n- If a string that contains the number is supplied, it returns it as\na number (e.g: it returns `100` for `'100'`).\n- If you pass a string with a number and a valid unit, the number of\nequivalent ms is returned.\n\n## License\n\nMIT\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/guille/ms.js/issues"
-  },
-  "_id": "ms@0.7.0",
-  "dist": {
-    "shasum": "1755a148628019be8eae32f53f04881f0f8297ec"
-  },
-  "_from": "ms@0.7.0",
-  "_resolved": "http://registry.npmjs.org/ms/-/ms-0.7.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/debug/package.json b/input_devices/mag/node_modules/serialport/node_modules/debug/package.json
deleted file mode 100644
index b67d8838..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/debug/package.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-  "name": "debug",
-  "version": "2.1.3",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/visionmedia/debug.git"
-  },
-  "description": "small debugging utility",
-  "keywords": [
-    "debug",
-    "log",
-    "debugger"
-  ],
-  "author": {
-    "name": "TJ Holowaychuk",
-    "email": "tj@vision-media.ca"
-  },
-  "contributors": [
-    {
-      "name": "Nathan Rajlich",
-      "email": "nathan@tootallnate.net",
-      "url": "http://n8.io"
-    }
-  ],
-  "license": "MIT",
-  "dependencies": {
-    "ms": "0.7.0"
-  },
-  "devDependencies": {
-    "browserify": "9.0.3",
-    "mocha": "*"
-  },
-  "main": "./node.js",
-  "browser": "./browser.js",
-  "component": {
-    "scripts": {
-      "debug/index.js": "browser.js",
-      "debug/debug.js": "debug.js"
-    }
-  },
-  "readme": "# debug\n\n  tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```bash\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n\nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n  , http = require('http')\n  , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n  debug(req.method + ' ' + req.url);\n  res.end('hello\\n');\n}).listen(3000, function(){\n  debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n  debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n#### Windows note\n\n On Windows the environment variable is set using the `set` command. \n \n ```cmd\n set DEBUG=*,-not_this\n ```\n\nThen, run the program to be debugged as usual.\n\n## Millisecond diff\n\n  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n\n  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\".\n\n## Wildcards\n\n  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n  You can also exclude specific debuggers by prefixing them with a \"-\" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n  Debug works in the browser as well, currently persisted by `localStorage`. Consider the situation shown below where you have `worker:a` and `worker:b`, and wish to debug both. Somewhere in the code on your page, include:\n\n```js\nwindow.myDebug = require(\"debug\");\n```\n\n  (\"debug\" is a global object in the browser so we give this object a different name.) When your page is open in the browser, type the following in the console:\n\n```js\nmyDebug.enable(\"worker:*\")\n```\n\n  Refresh the page. Debug output will continue to be sent to the console until it is disabled by typing `myDebug.disable()` in the console.\n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n  a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n  b('doing some work');\n}, 1200);\n```\n\n#### Web Inspector Colors\n\n  Colors are also enabled on \"Web Inspectors\" that understand the `%c` formatting\n  option. These are WebKit web inspectors, Firefox ([since version\n  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))\n  and the Firebug plugin for Firefox (any version).\n\n  Colored output looks something like:\n\n  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)\n\n### stderr vs stdout\n\nYou can set an alternative logging method per-namespace by overriding the `log` method on a per-namespace or globally:\n\nExample _stdout.js_:\n\n```js\nvar debug = require('debug');\nvar error = debug('app:error');\n\n// by default stderr is used\nerror('goes to stderr!');\n\nvar log = debug('app:log');\n// set this namespace to log via console.log\nlog.log = console.log.bind(console); // don't forget to bind to console!\nlog('goes to stdout');\nerror('still goes to stderr!');\n\n// set all output to go via console.info\n// overrides all per-namespace log settings\ndebug.log = console.info.bind(console);\nerror('now goes to stdout via console.info');\nlog('still goes to stdout, but via console.info now');\n```\n\n## Authors\n\n - TJ Holowaychuk\n - Nathan Rajlich\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2014 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
-  "readmeFilename": "Readme.md",
-  "bugs": {
-    "url": "https://github.com/visionmedia/debug/issues"
-  },
-  "_id": "debug@2.1.3",
-  "dist": {
-    "shasum": "3ffaeaaa8a7e3632b916f853da7951c8c518e97f"
-  },
-  "_from": "debug@^2.1.1",
-  "_resolved": "http://registry.npmjs.org/debug/-/debug-2.1.3.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/.dntrc b/input_devices/mag/node_modules/serialport/node_modules/nan/.dntrc
deleted file mode 100644
index 47971da6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/.dntrc
+++ /dev/null
@@ -1,30 +0,0 @@
-## DNT config file
-## see https://github.com/rvagg/dnt
-
-NODE_VERSIONS="\
-  master   \
-  v0.11.13 \
-  v0.10.30 \
-  v0.10.29 \
-  v0.10.28 \
-  v0.10.26 \
-  v0.10.25 \
-  v0.10.24 \
-  v0.10.23 \
-  v0.10.22 \
-  v0.10.21 \
-  v0.10.20 \
-  v0.10.19 \
-  v0.8.28  \
-  v0.8.27  \
-  v0.8.26  \
-  v0.8.24  \
-"
-OUTPUT_PREFIX="nan-"
-TEST_CMD="                                                                        \
-  cd /dnt/ &&                                                                     \
-  npm install &&                                                                  \
-  node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \
-  node_modules/.bin/tap --gc test/js/*-test.js                                    \
-"
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/CHANGELOG.md b/input_devices/mag/node_modules/serialport/node_modules/nan/CHANGELOG.md
deleted file mode 100644
index 26e859de..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/CHANGELOG.md
+++ /dev/null
@@ -1,270 +0,0 @@
-# NAN ChangeLog
-
-**Version 1.7.0: current Node 12: 0.12.0, Node 10: 0.10.36, io.js: 1.4.1**
-
-### 1.7.0 Feb 28 2015
-
-  - Feature: Made NanCallback::Call accept optional target 8d54da7
-  - Feature: Support atom-shell 0.21 0b7f1bb
-
-### 1.6.2 Feb 6 2015
-
-  - Bugfix: NanEncode: fix argument type for node::Encode on io.js 2be8639
-
-### 1.6.1 Jan 23 2015
-
-  - Build: version bump
-
-### 1.5.3 Jan 23 2015
-
-  - Build: repackage
-
-### 1.6.0 Jan 23 2015
-
- - Deprecated `NanNewContextHandle` in favor of `NanNew<Context>` 49259af
- - Support utility functions moved in newer v8 versions (Node 0.11.15, io.js 1.0) a0aa179
- - Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite` 75e6fb9
-
-### 1.5.2 Jan 23 2015
-
-  - Bugfix: Fix non-inline definition build error with clang++ 21d96a1, 60fadd4
-  - Bugfix: Readded missing String constructors 18d828f
-  - Bugfix: Add overload handling NanNew<FunctionTemplate>(..) 5ef813b
-  - Bugfix: Fix uv_work_cb versioning 997e4ae
-  - Bugfix: Add function factory and test 4eca89c
-  - Bugfix: Add object template factory and test cdcb951
-  - Correctness: Lifted an io.js related typedef c9490be
-  - Correctness: Make explicit downcasts of String lengths 00074e6
-  - Windows: Limit the scope of disabled warning C4530 83d7deb
-
-### 1.5.1 Jan 15 2015
-
-  - Build: version bump
-
-### 1.4.3 Jan 15 2015
-
-  - Build: version bump
-
-### 1.4.2 Jan 15 2015
-
-  - Feature: Support io.js 0dbc5e8
-
-### 1.5.0 Jan 14 2015
-
- - Feature: Support io.js b003843
- - Correctness: Improved NanNew internals 9cd4f6a
- - Feature: Implement progress to NanAsyncWorker 8d6a160
-
-### 1.4.1 Nov 8 2014
-
- - Bugfix: Handle DEBUG definition correctly
- - Bugfix: Accept int as Boolean
-
-### 1.4.0 Nov 1 2014
-
- - Feature: Added NAN_GC_CALLBACK 6a5c245
- - Performance: Removed unnecessary local handle creation 18a7243, 41fe2f8
- - Correctness: Added constness to references in NanHasInstance 02c61cd
- - Warnings: Fixed spurious warnings from -Wundef and -Wshadow, 541b122, 99d8cb6
- - Windoze: Shut Visual Studio up when compiling 8d558c1
- - License: Switch to plain MIT from custom hacked MIT license 11de983
- - Build: Added test target to Makefile e232e46
- - Performance: Removed superfluous scope in NanAsyncWorker f4b7821
- - Sugar/Feature: Added NanReturnThis() and NanReturnHolder() shorthands 237a5ff, d697208
- - Feature: Added suitable overload of NanNew for v8::Integer::NewFromUnsigned b27b450
-
-### 1.3.0 Aug 2 2014
-
- - Added NanNew<v8::String, std::string>(std::string)
- - Added NanNew<v8::String, std::string&>(std::string&)
- - Added NanAsciiString helper class
- - Added NanUtf8String helper class
- - Added NanUcs2String helper class
- - Deprecated NanRawString()
- - Deprecated NanCString()
- - Added NanGetIsolateData(v8::Isolate *isolate)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value>* argv)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::String> symbol, int argc, v8::Handle<v8::Value>* argv)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, const char* method, int argc, v8::Handle<v8::Value>* argv)
- - Added NanSetTemplate(v8::Handle<v8::Template> templ, v8::Handle<v8::String> name , v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- - Added NanSetPrototypeTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, const char *name, v8::Handle<v8::Data> value)
- - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
-
-### 1.2.0 Jun 5 2014
-
- - Add NanSetPrototypeTemplate
- - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class,
-     introduced _NanWeakCallbackDispatcher
- - Removed -Wno-unused-local-typedefs from test builds
- - Made test builds Windows compatible ('Sleep()')
-
-### 1.1.2 May 28 2014
-
- - Release to fix more stuff-ups in 1.1.1
-
-### 1.1.1 May 28 2014
-
- - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0
-
-### 1.1.0 May 25 2014
-
- - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead
- - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]),
-     (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*,
-     v8::String::ExternalAsciiStringResource*
- - Deprecate NanSymbol()
- - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker
-
-### 1.0.0 May 4 2014
-
- - Heavy API changes for V8 3.25 / Node 0.11.13
- - Use cpplint.py
- - Removed NanInitPersistent
- - Removed NanPersistentToLocal
- - Removed NanFromV8String
- - Removed NanMakeWeak
- - Removed NanNewLocal
- - Removed NAN_WEAK_CALLBACK_OBJECT
- - Removed NAN_WEAK_CALLBACK_DATA
- - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions
- - Introduce NanUndefined, NanNull, NanTrue and NanFalse
- - Introduce NanEscapableScope and NanEscapeScope
- - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node)
- - Introduce NanMakeCallback for node::MakeCallback
- - Introduce NanSetTemplate
- - Introduce NanGetCurrentContext
- - Introduce NanCompileScript and NanRunScript
- - Introduce NanAdjustExternalMemory
- - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback
- - Introduce NanGetHeapStatistics
- - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent()
-
-### 0.8.0 Jan 9 2014
-
- - NanDispose -> NanDisposePersistent, deprecate NanDispose
- - Extract _NAN_*_RETURN_TYPE, pull up NAN_*()
-
-### 0.7.1 Jan 9 2014
-
- - Fixes to work against debug builds of Node
- - Safer NanPersistentToLocal (avoid reinterpret_cast)
- - Speed up common NanRawString case by only extracting flattened string when necessary
-
-### 0.7.0 Dec 17 2013
-
- - New no-arg form of NanCallback() constructor.
- - NanCallback#Call takes Handle rather than Local
- - Removed deprecated NanCallback#Run method, use NanCallback#Call instead
- - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS
- - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call()
- - Introduce NanRawString() for char* (or appropriate void*) from v8::String
-     (replacement for NanFromV8String)
- - Introduce NanCString() for null-terminated char* from v8::String
-
-### 0.6.0 Nov 21 2013
-
- - Introduce NanNewLocal<T>(v8::Handle<T> value) for use in place of
-     v8::Local<T>::New(...) since v8 started requiring isolate in Node 0.11.9
-
-### 0.5.2 Nov 16 2013
-
- - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public
-
-### 0.5.1 Nov 12 2013
-
- - Use node::MakeCallback() instead of direct v8::Function::Call()
-
-### 0.5.0 Nov 11 2013
-
- - Added @TooTallNate as collaborator
- - New, much simpler, "include_dirs" for binding.gyp
- - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros
-
-### 0.4.4 Nov 2 2013
-
- - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+
-
-### 0.4.3 Nov 2 2013
-
- - Include node_object_wrap.h, removed from node.h for Node 0.11.8.
-
-### 0.4.2 Nov 2 2013
-
- - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for
-     Node 0.11.8 release.
-
-### 0.4.1 Sep 16 2013
-
- - Added explicit `#include <uv.h>` as it was removed from node.h for v0.11.8
-
-### 0.4.0 Sep 2 2013
-
- - Added NAN_INLINE and NAN_DEPRECATED and made use of them
- - Added NanError, NanTypeError and NanRangeError
- - Cleaned up code
-
-### 0.3.2 Aug 30 2013
-
- - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent
-     in NanAsyncWorker
-
-### 0.3.1 Aug 20 2013
-
- - fix "not all control paths return a value" compile warning on some platforms
-
-### 0.3.0 Aug 19 2013
-
- - Made NAN work with NPM
- - Lots of fixes to NanFromV8String, pulling in features from new Node core
- - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API
- - Added optional error number argument for NanThrowError()
- - Added NanInitPersistent()
- - Added NanReturnNull() and NanReturnEmptyString()
- - Added NanLocker and NanUnlocker
- - Added missing scopes
- - Made sure to clear disposed Persistent handles
- - Changed NanAsyncWorker to allocate error messages on the heap
- - Changed NanThrowError(Local<Value>) to NanThrowError(Handle<Value>)
- - Fixed leak in NanAsyncWorker when errmsg is used
-
-### 0.2.2 Aug 5 2013
-
- - Fixed usage of undefined variable with node::BASE64 in NanFromV8String()
-
-### 0.2.1 Aug 5 2013
-
- - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for
-     NanFromV8String()
-
-### 0.2.0 Aug 5 2013
-
- - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR,
-     NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY
- - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS,
-     _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS,
-     _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS,
-     _NAN_PROPERTY_QUERY_ARGS
- - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer
- - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT,
-     NAN_WEAK_CALLBACK_DATA, NanMakeWeak
- - Renamed THROW_ERROR to _NAN_THROW_ERROR
- - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*)
- - Added NanBufferUse(char*, uint32_t)
- - Added NanNewContextHandle(v8::ExtensionConfiguration*,
-       v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
- - Fixed broken NanCallback#GetFunction()
- - Added optional encoding and size arguments to NanFromV8String()
- - Added NanGetPointerSafe() and NanSetPointerSafe()
- - Added initial test suite (to be expanded)
- - Allow NanUInt32OptionValue to convert any Number object
-
-### 0.1.0 Jul 21 2013
-
- - Added `NAN_GETTER`, `NAN_SETTER`
- - Added `NanThrowError` with single Local<Value> argument
- - Added `NanNewBufferHandle` with single uint32_t argument
- - Added `NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)`
- - Added `Local<Function> NanCallback#GetFunction()`
- - Added `NanCallback#Call(int, Local<Value>[])`
- - Deprecated `NanCallback#Run(int, Local<Value>[])` in favour of Call
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/LICENSE.md b/input_devices/mag/node_modules/serialport/node_modules/nan/LICENSE.md
deleted file mode 100644
index 95c2eb5f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/LICENSE.md
+++ /dev/null
@@ -1,13 +0,0 @@
-The MIT License (MIT)
-=====================
-
-Copyright (c) 2015 NAN contributors
------------------------------------
-
-*NAN contributors listed at <https://github.com/rvagg/nan#contributors>*
-
-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/input_devices/mag/node_modules/serialport/node_modules/nan/appveyor.yml b/input_devices/mag/node_modules/serialport/node_modules/nan/appveyor.yml
deleted file mode 100644
index 34294539..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/appveyor.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-# http://www.appveyor.com/docs/appveyor-yml
-
-# Test against these versions of Io.js and Node.js.
-environment:
-  matrix:
-  # node.js
-    - nodejs_version: "0.8"
-    - nodejs_version: "0.10"
-    - nodejs_version: "0.12"
-  # io.js
-    - nodejs_version: "1"
-
-# Install scripts. (runs after repo cloning)
-install:
-  # Get the latest stable version of Node 0.STABLE.latest
-  - ps: if($env:nodejs_version -eq "0.8") {Install-Product node $env:nodejs_version}
-  - ps: if($env:nodejs_version -ne "0.8") {Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)}
-  - IF NOT %nodejs_version% == 1 npm -g install npm
-  - IF NOT %nodejs_version% == 1 set PATH=%APPDATA%\npm;%PATH%
-  # Typical npm stuff.
-  - npm install
-  - IF %nodejs_version% == 0.8 node node_modules\node-gyp\bin\node-gyp.js rebuild --directory test
-  - IF NOT %nodejs_version% == 0.8 npm run rebuild-tests
-
-# Post-install test scripts.
-test_script:
-  # Output useful info for debugging.
-  - node --version
-  - npm --version
-  # run tests
-  - IF NOT %nodejs_version% == 1 npm test
-  - IF %nodejs_version% == 1 iojs node_modules\tap\bin\tap.js --gc test\js\*-test.js
-
-# Don't actually build.
-build: off
-
-# Set build version format here instead of in the admin panel.
-version: "{build}"
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/nan.h b/input_devices/mag/node_modules/serialport/node_modules/nan/nan.h
deleted file mode 100644
index 23c38e43..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/nan.h
+++ /dev/null
@@ -1,2212 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors:
- *   - Rod Vagg <https://github.com/rvagg>
- *   - Benjamin Byholm <https://github.com/kkoopa>
- *   - Trevor Norris <https://github.com/trevnorris>
- *   - Nathan Rajlich <https://github.com/TooTallNate>
- *   - Brett Lawson <https://github.com/brett19>
- *   - Ben Noordhuis <https://github.com/bnoordhuis>
- *   - David Siegel <https://github.com/agnat>
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- *
- * Version 1.7.0: current Node 12: 0.12.0, Node 10: 0.10.36, io.js: 1.4.1
- *
- * See https://github.com/rvagg/nan for the latest update to this file
- **********************************************************************************/
-
-#ifndef NAN_H_
-#define NAN_H_
-
-#include <uv.h>
-#include <node.h>
-#include <node_buffer.h>
-#include <node_version.h>
-#include <node_object_wrap.h>
-#include <cstring>
-#include <climits>
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-#if defined(__GNUC__) && !(defined(DEBUG) && DEBUG)
-# define NAN_INLINE inline __attribute__((always_inline))
-#elif defined(_MSC_VER) && !(defined(DEBUG) && DEBUG)
-# define NAN_INLINE __forceinline
-#else
-# define NAN_INLINE inline
-#endif
-
-#if defined(__GNUC__) && \
-    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
-# define NAN_DEPRECATED __attribute__((deprecated))
-#elif defined(_MSC_VER) && \
-    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
-# define NAN_DEPRECATED __declspec(deprecated)
-#else
-# define NAN_DEPRECATED
-#endif
-
-#define NODE_0_10_MODULE_VERSION 11
-#define NODE_0_12_MODULE_VERSION 12
-#define ATOM_0_21_MODULE_VERSION 41
-#define IOJS_1_0_MODULE_VERSION  42
-#define IOJS_1_1_MODULE_VERSION  43
-
-#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION)
-typedef v8::InvocationCallback NanFunctionCallback;
-typedef v8::Script             NanUnboundScript;
-typedef v8::Script             NanBoundScript;
-#else
-typedef v8::FunctionCallback   NanFunctionCallback;
-typedef v8::UnboundScript      NanUnboundScript;
-typedef v8::Script             NanBoundScript;
-#endif
-
-#if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION)
-typedef v8::String::ExternalAsciiStringResource
-    NanExternalOneByteStringResource;
-#else
-typedef v8::String::ExternalOneByteStringResource
-    NanExternalOneByteStringResource;
-#endif
-
-#include "nan_new.h"  // NOLINT(build/include)
-
-// uv helpers
-#ifdef UV_VERSION_MAJOR
-#ifndef UV_VERSION_PATCH
-#define UV_VERSION_PATCH 0
-#endif
-#define NAUV_UVVERSION  ((UV_VERSION_MAJOR << 16) | \
-                     (UV_VERSION_MINOR <<  8) | \
-                     (UV_VERSION_PATCH))
-#else
-#define NAUV_UVVERSION 0x000b00
-#endif
-
-
-#if NAUV_UVVERSION < 0x000b17
-#define NAUV_WORK_CB(func) \
-    void func(uv_async_t *async, int)
-#else
-#define NAUV_WORK_CB(func) \
-    void func(uv_async_t *async)
-#endif
-
-// some generic helpers
-
-template<typename T> NAN_INLINE bool NanSetPointerSafe(
-    T *var
-  , T val
-) {
-  if (var) {
-    *var = val;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-template<typename T> NAN_INLINE T NanGetPointerSafe(
-    T *var
-  , T fallback = reinterpret_cast<T>(0)
-) {
-  if (var) {
-    return *var;
-  } else {
-    return fallback;
-  }
-}
-
-NAN_INLINE bool NanBooleanOptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt, bool def
-) {
-  if (def) {
-    return optionsObj.IsEmpty()
-      || !optionsObj->Has(opt)
-      || optionsObj->Get(opt)->BooleanValue();
-  } else {
-    return !optionsObj.IsEmpty()
-      && optionsObj->Has(opt)
-      && optionsObj->Get(opt)->BooleanValue();
-  }
-}
-
-NAN_INLINE bool NanBooleanOptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt
-) {
-  return NanBooleanOptionValue(optionsObj, opt, false);
-}
-
-NAN_INLINE uint32_t NanUInt32OptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt
-  , uint32_t def
-) {
-  return !optionsObj.IsEmpty()
-    && optionsObj->Has(opt)
-    && optionsObj->Get(opt)->IsNumber()
-      ? optionsObj->Get(opt)->Uint32Value()
-      : def;
-}
-
-template<typename T>
-v8::Local<T> NanNew(v8::Handle<T>);
-
-template<typename T>
-NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
-  return NanNew(val);
-}
-
-template<typename T>
-NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
-  return val;
-}
-
-/* io.js 1.0  */
-#if NODE_MODULE_VERSION >= IOJS_1_0_MODULE_VERSION \
- || NODE_VERSION_AT_LEAST(0, 11, 15)
-  NAN_INLINE
-  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
-    v8::Isolate::GetCurrent()->SetCounterFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
-    v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
-    v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb);
-  }
-
-  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
-    return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
-  }
-
-  NAN_INLINE void NanLowMemoryNotification() {
-    v8::Isolate::GetCurrent()->LowMemoryNotification();
-  }
-
-  NAN_INLINE void NanContextDisposedNotification() {
-    v8::Isolate::GetCurrent()->ContextDisposedNotification();
-  }
-#else
-  NAN_INLINE
-  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
-    v8::V8::SetCounterFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
-    v8::V8::SetCreateHistogramFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
-    v8::V8::SetAddHistogramSampleFunction(cb);
-  }
-
-  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
-    return v8::V8::IdleNotification(idle_time_in_ms);
-  }
-
-  NAN_INLINE void NanLowMemoryNotification() {
-    v8::V8::LowMemoryNotification();
-  }
-
-  NAN_INLINE void NanContextDisposedNotification() {
-    v8::V8::ContextDisposedNotification();
-  }
-#endif
-
-#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-// Node 0.11+ (0.11.12 and below won't compile with these)
-
-# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo<v8::Value>&
-# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args
-# define _NAN_METHOD_RETURN_TYPE void
-
-# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args
-# define _NAN_GETTER_RETURN_TYPE void
-
-# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo<void>&
-# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args
-# define _NAN_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_GETTER_ARGS_TYPE                                        \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_GETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_SETTER_ARGS_TYPE                                        \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE                                    \
-    const v8::PropertyCallbackInfo<v8::Array>&
-# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args
-# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void
-
-# define _NAN_PROPERTY_DELETER_ARGS_TYPE                                       \
-    const v8::PropertyCallbackInfo<v8::Boolean>&
-# define _NAN_PROPERTY_DELETER_ARGS                                            \
-    _NAN_PROPERTY_DELETER_ARGS_TYPE args
-# define _NAN_PROPERTY_DELETER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_QUERY_ARGS_TYPE                                         \
-    const v8::PropertyCallbackInfo<v8::Integer>&
-# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args
-# define _NAN_PROPERTY_QUERY_RETURN_TYPE void
-
-# define _NAN_INDEX_GETTER_ARGS_TYPE                                           \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args
-# define _NAN_INDEX_GETTER_RETURN_TYPE void
-
-# define _NAN_INDEX_SETTER_ARGS_TYPE                                           \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args
-# define _NAN_INDEX_SETTER_RETURN_TYPE void
-
-# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE                                       \
-    const v8::PropertyCallbackInfo<v8::Array>&
-# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args
-# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void
-
-# define _NAN_INDEX_DELETER_ARGS_TYPE                                          \
-    const v8::PropertyCallbackInfo<v8::Boolean>&
-# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args
-# define _NAN_INDEX_DELETER_RETURN_TYPE void
-
-# define _NAN_INDEX_QUERY_ARGS_TYPE                                            \
-    const v8::PropertyCallbackInfo<v8::Integer>&
-# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
-# define _NAN_INDEX_QUERY_RETURN_TYPE void
-
-# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent())
-# define NanEscapableScope()                                                   \
-  v8::EscapableHandleScope scope(v8::Isolate::GetCurrent())
-
-# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
-# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent())
-# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent())
-# define NanReturnValue(value) return args.GetReturnValue().Set(value)
-# define NanReturnUndefined() return
-# define NanReturnHolder() NanReturnValue(args.Holder())
-# define NanReturnThis() NanReturnValue(args.This())
-# define NanReturnNull() return args.GetReturnValue().SetNull()
-# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString()
-
-# define NanObjectWrapHandle(obj) obj->handle()
-
-  NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Primitive> NanNull() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanTrue() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanFalse() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE int NanAdjustExternalMemory(int bc) {
-    return static_cast<int>(
-        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc));
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , const char *name
-    , v8::Handle<v8::Data> value) {
-    templ->Set(v8::Isolate::GetCurrent(), name, value);
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , v8::Handle<v8::String> name
-    , v8::Handle<v8::Data> value
-    , v8::PropertyAttribute attributes) {
-    templ->Set(name, value, attributes);
-  }
-
-  NAN_INLINE v8::Local<v8::Context> NanGetCurrentContext() {
-    return v8::Isolate::GetCurrent()->GetCurrentContext();
-  }
-
-  NAN_INLINE void* NanGetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index) {
-    return object->GetAlignedPointerFromInternalField(index);
-  }
-
-  NAN_INLINE void NanSetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index
-    , void* value) {
-    object->SetAlignedPointerInInternalField(index, value);
-  }
-
-# define NAN_GC_CALLBACK(name)                                                 \
-    void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags)
-
-  NAN_INLINE void NanAddGCEpilogueCallback(
-      v8::Isolate::GCEpilogueCallback callback
-    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter);
-  }
-
-  NAN_INLINE void NanRemoveGCEpilogueCallback(
-      v8::Isolate::GCEpilogueCallback callback) {
-    v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback);
-  }
-
-  NAN_INLINE void NanAddGCPrologueCallback(
-      v8::Isolate::GCPrologueCallback callback
-    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter);
-  }
-
-  NAN_INLINE void NanRemoveGCPrologueCallback(
-      v8::Isolate::GCPrologueCallback callback) {
-    v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback);
-  }
-
-  NAN_INLINE void NanGetHeapStatistics(
-      v8::HeapStatistics *heap_statistics) {
-    v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::String> NanSymbol(
-      const char* data, int length = -1) {
-    return NanNew<v8::String>(data, length);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , v8::Handle<T> obj) {
-      handle.Reset(v8::Isolate::GetCurrent(), obj);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , const v8::Persistent<T>& obj) {
-      handle.Reset(v8::Isolate::GetCurrent(), obj);
-  }
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData;
-
-  template<typename T, typename P>
-  struct _NanWeakCallbackInfo {
-    typedef void (*Callback)(const _NanWeakCallbackData<T, P>& data);
-    NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
-      : parameter(param), callback(cb) {
-       NanAssignPersistent(persistent, handle);
-    }
-
-    NAN_INLINE ~_NanWeakCallbackInfo() {
-      persistent.Reset();
-    }
-
-    P* const parameter;
-    Callback const callback;
-    v8::Persistent<T> persistent;
-  };
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData {
-   public:
-    NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
-      : info_(info) { }
-
-    NAN_INLINE v8::Local<T> GetValue() const {
-      return NanNew(info_->persistent);
-    }
-
-    NAN_INLINE P* GetParameter() const { return info_->parameter; }
-
-    NAN_INLINE bool IsNearDeath() const {
-      return info_->persistent.IsNearDeath();
-    }
-
-    NAN_INLINE void Revive() const;
-
-    NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
-      return info_;
-    }
-
-    NAN_DEPRECATED NAN_INLINE void Dispose() const {
-    }
-
-   private:
-    _NanWeakCallbackInfo<T, P>* info_;
-  };
-
-  template<typename T, typename P>
-  static void _NanWeakCallbackDispatcher(
-    const v8::WeakCallbackData<T, _NanWeakCallbackInfo<T, P> > &data) {
-      _NanWeakCallbackInfo<T, P> *info = data.GetParameter();
-      _NanWeakCallbackData<T, P> wcbd(info);
-      info->callback(wcbd);
-      if (wcbd.IsNearDeath()) {
-        delete wcbd.GetCallbackInfo();
-      }
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
-      info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher<T, P>);
-  }
-
-template<typename T, typename P>
-NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
-    v8::Handle<T> handle
-  , P* parameter
-  , typename _NanWeakCallbackInfo<T, P>::Callback callback) {
-    _NanWeakCallbackInfo<T, P> *cbinfo =
-     new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
-    cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher<T, P>);
-    return cbinfo;
-}
-
-# define NAN_WEAK_CALLBACK(name)                                               \
-    template<typename T, typename P>                                           \
-    static void name(const _NanWeakCallbackData<T, P> &data)
-
-# define _NAN_ERROR(fun, errmsg) fun(NanNew<v8::String>(errmsg))
-
-# define _NAN_THROW_ERROR(fun, errmsg)                                         \
-    do {                                                                       \
-      NanScope();                                                              \
-      v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg));      \
-    } while (0);
-
-  NAN_INLINE v8::Local<v8::Value> NanError(const char* errmsg) {
-    return  _NAN_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE void NanThrowError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE void NanThrowError(v8::Handle<v8::Value> error) {
-    NanScope();
-    v8::Isolate::GetCurrent()->ThrowException(error);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    v8::Local<v8::Value> err = v8::Exception::Error(NanNew<v8::String>(msg));
-    v8::Local<v8::Object> obj = err.As<v8::Object>();
-    obj->Set(NanNew<v8::String>("code"), NanNew<v8::Integer>(errorNumber));
-    return err;
-  }
-
-  NAN_INLINE void NanThrowError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    NanThrowError(NanError(msg, errorNumber));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanTypeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE void NanThrowTypeError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRangeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  NAN_INLINE void NanThrowRangeError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  template<typename T> NAN_INLINE void NanDisposePersistent(
-      v8::Persistent<T> &handle
-  ) {
-    handle.Reset();
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      char *data
-    , size_t length
-    , node::smalloc::FreeCallback callback
-    , void *hint
-  ) {
-    return node::Buffer::New(
-        v8::Isolate::GetCurrent(), data, length, callback, hint);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      const char *data
-    , uint32_t size
-  ) {
-    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
-    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanBufferUse(
-      char* data
-    , uint32_t size
-  ) {
-    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
-  }
-
-  NAN_INLINE bool NanHasInstance(
-      const v8::Persistent<v8::FunctionTemplate>& function_template
-    , v8::Handle<v8::Value> value
-  ) {
-    return NanNew(function_template)->HasInstance(value);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
-      v8::ExtensionConfiguration* extensions = NULL
-    , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-    , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
-  ) {
-    v8::Isolate* isolate = v8::Isolate::GetCurrent();
-    return v8::Local<v8::Context>::New(
-        isolate
-      , v8::Context::New(isolate, extensions, tmpl, obj)
-    );
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-    , const v8::ScriptOrigin& origin
-  ) {
-    v8::ScriptCompiler::Source source(s, origin);
-    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-  ) {
-    v8::ScriptCompiler::Source source(s);
-    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(
-      v8::Handle<NanUnboundScript> script
-  ) {
-    return script->BindToCurrentContext()->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(
-      v8::Handle<NanBoundScript> script
-  ) {
-    return script->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::Function> func
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, func, argc, argv));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::String> symbol
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, symbol, argc, argv));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , const char* method
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, method, argc, argv));
-  }
-
-  template<typename T>
-  NAN_INLINE void NanSetIsolateData(
-      v8::Isolate *isolate
-    , T *data
-  ) {
-      isolate->SetData(0, data);
-  }
-
-  template<typename T>
-  NAN_INLINE T *NanGetIsolateData(
-      v8::Isolate *isolate
-  ) {
-      return static_cast<T*>(isolate->GetData(0));
-  }
-
-  class NanAsciiString {
-   public:
-    NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new char[size + 1];
-      size = toStr->WriteOneByte(reinterpret_cast<unsigned char*>(buf));
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanAsciiString() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanAsciiString(const NanAsciiString&);
-    void operator=(const NanAsciiString&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUtf8String {
-   public:
-    NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Utf8Length();
-      buf = new char[size + 1];
-      toStr->WriteUtf8(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUtf8String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUtf8String(const NanUtf8String&);
-    void operator=(const NanUtf8String&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUcs2String {
-   public:
-    NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new uint16_t[size + 1];
-      toStr->Write(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE uint16_t* operator*() { return buf; }
-    NAN_INLINE const uint16_t* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUcs2String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUcs2String(const NanUcs2String&);
-    void operator=(const NanUcs2String&);
-
-    uint16_t *buf;
-    int size;
-  };
-
-#else
-// Node 0.8 and 0.10
-
-# define _NAN_METHOD_ARGS_TYPE const v8::Arguments&
-# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args
-# define _NAN_METHOD_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo &
-# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args
-# define _NAN_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo &
-# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args
-# define _NAN_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args
-# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle<v8::Array>
-
-# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args
-# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle<v8::Boolean>
-
-# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args
-# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle<v8::Integer>
-
-# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args
-# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args
-# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args
-# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle<v8::Array>
-
-# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args
-# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle<v8::Boolean>
-
-# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
-# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle<v8::Integer>
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::String> NanSymbol(
-      const char* data, int length = -1) {
-    return v8::String::NewSymbol(data, length);
-  }
-
-# define NanScope() v8::HandleScope scope
-# define NanEscapableScope() v8::HandleScope scope
-# define NanEscapeScope(val) scope.Close(val)
-# define NanLocker() v8::Locker locker
-# define NanUnlocker() v8::Unlocker unlocker
-# define NanReturnValue(value) return scope.Close(value)
-# define NanReturnHolder() NanReturnValue(args.Holder())
-# define NanReturnThis() NanReturnValue(args.This())
-# define NanReturnUndefined() return v8::Undefined()
-# define NanReturnNull() return v8::Null()
-# define NanReturnEmptyString() return v8::String::Empty()
-# define NanObjectWrapHandle(obj) v8::Local<v8::Object>::New(obj->handle_)
-
-  NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Undefined()));
-  }
-
-  NAN_INLINE v8::Local<v8::Primitive> NanNull() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Null()));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanTrue() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::True()));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanFalse() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::False()));
-  }
-
-  NAN_INLINE int NanAdjustExternalMemory(int bc) {
-    return static_cast<int>(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc));
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , const char *name
-    , v8::Handle<v8::Data> value) {
-    templ->Set(name, value);
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , v8::Handle<v8::String> name
-    , v8::Handle<v8::Data> value
-    , v8::PropertyAttribute attributes) {
-    templ->Set(name, value, attributes);
-  }
-
-  NAN_INLINE v8::Local<v8::Context> NanGetCurrentContext() {
-    return v8::Context::GetCurrent();
-  }
-
-  NAN_INLINE void* NanGetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index) {
-    return object->GetPointerFromInternalField(index);
-  }
-
-  NAN_INLINE void NanSetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index
-    , void* value) {
-    object->SetPointerInInternalField(index, value);
-  }
-
-# define NAN_GC_CALLBACK(name)                                                 \
-    void name(v8::GCType type, v8::GCCallbackFlags flags)
-
-  NAN_INLINE void NanAddGCEpilogueCallback(
-    v8::GCEpilogueCallback callback
-  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::V8::AddGCEpilogueCallback(callback, gc_type_filter);
-  }
-  NAN_INLINE void NanRemoveGCEpilogueCallback(
-    v8::GCEpilogueCallback callback) {
-    v8::V8::RemoveGCEpilogueCallback(callback);
-  }
-  NAN_INLINE void NanAddGCPrologueCallback(
-    v8::GCPrologueCallback callback
-  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::V8::AddGCPrologueCallback(callback, gc_type_filter);
-  }
-  NAN_INLINE void NanRemoveGCPrologueCallback(
-    v8::GCPrologueCallback callback) {
-    v8::V8::RemoveGCPrologueCallback(callback);
-  }
-  NAN_INLINE void NanGetHeapStatistics(
-    v8::HeapStatistics *heap_statistics) {
-    v8::V8::GetHeapStatistics(heap_statistics);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , v8::Handle<T> obj) {
-      handle.Dispose();
-      handle = v8::Persistent<T>::New(obj);
-  }
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData;
-
-  template<typename T, typename P>
-  struct _NanWeakCallbackInfo {
-    typedef void (*Callback)(const _NanWeakCallbackData<T, P> &data);
-    NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
-      : parameter(param)
-      , callback(cb)
-      , persistent(v8::Persistent<T>::New(handle)) { }
-
-    NAN_INLINE ~_NanWeakCallbackInfo() {
-      persistent.Dispose();
-      persistent.Clear();
-    }
-
-    P* const parameter;
-    Callback const callback;
-    v8::Persistent<T> persistent;
-  };
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData {
-   public:
-    NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
-      : info_(info) { }
-
-    NAN_INLINE v8::Local<T> GetValue() const {
-      return NanNew(info_->persistent);
-    }
-
-    NAN_INLINE P* GetParameter() const { return info_->parameter; }
-
-    NAN_INLINE bool IsNearDeath() const {
-      return info_->persistent.IsNearDeath();
-    }
-
-    NAN_INLINE void Revive() const;
-
-    NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
-      return info_;
-    }
-
-    NAN_DEPRECATED NAN_INLINE void Dispose() const {
-    }
-
-   private:
-    _NanWeakCallbackInfo<T, P>* info_;
-  };
-
-  template<typename T, typename P>
-  static void _NanWeakPersistentDispatcher(
-      v8::Persistent<v8::Value> object, void *data) {
-    _NanWeakCallbackInfo<T, P>* info =
-        static_cast<_NanWeakCallbackInfo<T, P>*>(data);
-    _NanWeakCallbackData<T, P> wcbd(info);
-    info->callback(wcbd);
-    if (wcbd.IsNearDeath()) {
-      delete wcbd.GetCallbackInfo();
-    }
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
-      info_->persistent.MakeWeak(
-          info_
-        , &_NanWeakPersistentDispatcher<T, P>);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
-    v8::Handle<T> handle
-  , P* parameter
-  , typename _NanWeakCallbackInfo<T, P>::Callback callback) {
-      _NanWeakCallbackInfo<T, P> *cbinfo =
-        new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
-      cbinfo->persistent.MakeWeak(
-          cbinfo
-        , &_NanWeakPersistentDispatcher<T, P>);
-      return cbinfo;
-  }
-
-# define NAN_WEAK_CALLBACK(name)                                               \
-    template<typename T, typename P>                                           \
-    static void name(const _NanWeakCallbackData<T, P> &data)
-
-# define _NAN_ERROR(fun, errmsg)                                               \
-    fun(v8::String::New(errmsg))
-
-# define _NAN_THROW_ERROR(fun, errmsg)                                         \
-    do {                                                                       \
-      NanScope();                                                              \
-      return v8::Local<v8::Value>::New(                                        \
-        v8::ThrowException(_NAN_ERROR(fun, errmsg)));                          \
-    } while (0);
-
-  NAN_INLINE v8::Local<v8::Value> NanError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(
-      v8::Handle<v8::Value> error
-  ) {
-    NanScope();
-    return v8::Local<v8::Value>::New(v8::ThrowException(error));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    v8::Local<v8::Value> err = v8::Exception::Error(v8::String::New(msg));
-    v8::Local<v8::Object> obj = err.As<v8::Object>();
-    obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber));
-    return err;
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    return NanThrowError(NanError(msg, errorNumber));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanTypeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowTypeError(
-      const char* errmsg
-  ) {
-    _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRangeError(
-      const char* errmsg
-  ) {
-    return _NAN_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowRangeError(
-      const char* errmsg
-  ) {
-    _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanDisposePersistent(
-      v8::Persistent<T> &handle) {  // NOLINT(runtime/references)
-    handle.Dispose();
-    handle.Clear();
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      char *data
-    , size_t length
-    , node::Buffer::free_callback callback
-    , void *hint
-  ) {
-    return NanNew(
-        node::Buffer::New(data, length, callback, hint)->handle_);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      const char *data
-    , uint32_t size
-  ) {
-#if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION
-    return NanNew(node::Buffer::New(data, size)->handle_);
-#else
-    return NanNew(
-      node::Buffer::New(const_cast<char*>(data), size)->handle_);
-#endif
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
-    return NanNew(node::Buffer::New(size)->handle_);
-  }
-
-  NAN_INLINE void FreeData(char *data, void *hint) {
-    delete[] data;
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanBufferUse(
-      char* data
-    , uint32_t size
-  ) {
-    return NanNew(
-        node::Buffer::New(data, size, FreeData, NULL)->handle_);
-  }
-
-  NAN_INLINE bool NanHasInstance(
-      const v8::Persistent<v8::FunctionTemplate>& function_template
-    , v8::Handle<v8::Value> value
-  ) {
-    return function_template->HasInstance(value);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
-      v8::ExtensionConfiguration* extensions = NULL
-    , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-    , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
-  ) {
-    v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
-    v8::Local<v8::Context> lctx = NanNew(ctx);
-    ctx.Dispose();
-    return lctx;
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-    , const v8::ScriptOrigin& origin
-  ) {
-    return v8::Script::Compile(s, const_cast<v8::ScriptOrigin *>(&origin));
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-    v8::Local<v8::String> s
-  ) {
-    return v8::Script::Compile(s);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(v8::Handle<v8::Script> script) {
-    return script->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::Function> func
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, func, argc, argv));
-# else
-    v8::TryCatch try_catch;
-    v8::Local<v8::Value> result = func->Call(target, argc, argv);
-    if (try_catch.HasCaught()) {
-        node::FatalException(try_catch);
-    }
-    return result;
-# endif
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::String> symbol
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, symbol, argc, argv));
-# else
-    v8::Local<v8::Function> callback = target->Get(symbol).As<v8::Function>();
-    return NanMakeCallback(target, callback, argc, argv);
-# endif
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , const char* method
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, method, argc, argv));
-# else
-    return NanMakeCallback(target, NanNew(method), argc, argv);
-# endif
-  }
-
-  template<typename T>
-  NAN_INLINE void NanSetIsolateData(
-      v8::Isolate *isolate
-    , T *data
-  ) {
-      isolate->SetData(data);
-  }
-
-  template<typename T>
-  NAN_INLINE T *NanGetIsolateData(
-      v8::Isolate *isolate
-  ) {
-      return static_cast<T*>(isolate->GetData());
-  }
-
-  class NanAsciiString {
-   public:
-    NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new char[size + 1];
-      size = toStr->WriteAscii(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanAsciiString() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanAsciiString(const NanAsciiString&);
-    void operator=(const NanAsciiString&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUtf8String {
-   public:
-    NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Utf8Length();
-      buf = new char[size + 1];
-      toStr->WriteUtf8(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUtf8String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUtf8String(const NanUtf8String&);
-    void operator=(const NanUtf8String&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUcs2String {
-   public:
-    NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new uint16_t[size + 1];
-      toStr->Write(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE uint16_t* operator*() { return buf; }
-    NAN_INLINE const uint16_t* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUcs2String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUcs2String(const NanUcs2String&);
-    void operator=(const NanUcs2String&);
-
-    uint16_t *buf;
-    int size;
-  };
-
-#endif  // NODE_MODULE_VERSION
-
-typedef void (*NanFreeCallback)(char *data, void *hint);
-
-#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS)
-#define NAN_GETTER(name)                                                       \
-    _NAN_GETTER_RETURN_TYPE name(                                              \
-        v8::Local<v8::String> property                                         \
-      , _NAN_GETTER_ARGS)
-#define NAN_SETTER(name)                                                       \
-    _NAN_SETTER_RETURN_TYPE name(                                              \
-        v8::Local<v8::String> property                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_SETTER_ARGS)
-#define NAN_PROPERTY_GETTER(name)                                              \
-    _NAN_PROPERTY_GETTER_RETURN_TYPE name(                                     \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_GETTER_ARGS)
-#define NAN_PROPERTY_SETTER(name)                                              \
-    _NAN_PROPERTY_SETTER_RETURN_TYPE name(                                     \
-        v8::Local<v8::String> property                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_PROPERTY_SETTER_ARGS)
-#define NAN_PROPERTY_ENUMERATOR(name)                                          \
-    _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS)
-#define NAN_PROPERTY_DELETER(name)                                             \
-    _NAN_PROPERTY_DELETER_RETURN_TYPE name(                                    \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_DELETER_ARGS)
-#define NAN_PROPERTY_QUERY(name)                                               \
-    _NAN_PROPERTY_QUERY_RETURN_TYPE name(                                      \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_QUERY_ARGS)
-# define NAN_INDEX_GETTER(name)                                                \
-    _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS)
-#define NAN_INDEX_SETTER(name)                                                 \
-    _NAN_INDEX_SETTER_RETURN_TYPE name(                                        \
-        uint32_t index                                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_INDEX_SETTER_ARGS)
-#define NAN_INDEX_ENUMERATOR(name)                                             \
-    _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS)
-#define NAN_INDEX_DELETER(name)                                                \
-    _NAN_INDEX_DELETER_RETURN_TYPE name(                                       \
-        uint32_t index                                                         \
-      , _NAN_INDEX_DELETER_ARGS)
-#define NAN_INDEX_QUERY(name)                                                  \
-    _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS)
-
-class NanCallback {
- public:
-  NanCallback() {
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(handle, obj);
-  }
-
-  explicit NanCallback(const v8::Handle<v8::Function> &fn) {
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(handle, obj);
-    SetFunction(fn);
-  }
-
-  ~NanCallback() {
-    if (handle.IsEmpty()) return;
-    NanDisposePersistent(handle);
-  }
-
-  NAN_INLINE void SetFunction(const v8::Handle<v8::Function> &fn) {
-    NanScope();
-    NanNew(handle)->Set(kCallbackIndex, fn);
-  }
-
-  NAN_INLINE v8::Local<v8::Function> GetFunction() const {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex)
-        .As<v8::Function>());
-  }
-
-  NAN_INLINE bool IsEmpty() const {
-    NanScope();
-    return NanNew(handle)->Get(kCallbackIndex)->IsUndefined();
-  }
-
-  NAN_INLINE v8::Handle<v8::Value>
-  Call(v8::Handle<v8::Object> target
-     , int argc
-     , v8::Handle<v8::Value> argv[]) const {
-#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-    v8::Isolate *isolate = v8::Isolate::GetCurrent();
-    return Call_(isolate, target, argc, argv);
-#else
-    return Call_(target, argc, argv);
-#endif
-  }
-
-  NAN_INLINE v8::Handle<v8::Value>
-  Call(int argc, v8::Handle<v8::Value> argv[]) const {
-#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-    v8::Isolate *isolate = v8::Isolate::GetCurrent();
-    return Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv);
-#else
-    return Call_(v8::Context::GetCurrent()->Global(), argc, argv);
-#endif
-  }
-
- private:
-  v8::Persistent<v8::Object> handle;
-  static const uint32_t kCallbackIndex = 0;
-
-#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-  v8::Handle<v8::Value> Call_(v8::Isolate *isolate
-                           , v8::Handle<v8::Object> target
-                           , int argc
-                           , v8::Handle<v8::Value> argv[]) const {
-#else
-  v8::Handle<v8::Value> Call_(v8::Handle<v8::Object> target
-                           , int argc
-                           , v8::Handle<v8::Value> argv[]) const {
-#endif
-    NanEscapableScope();
-#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-    v8::Local<v8::Function> callback = NanNew(handle)->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(node::MakeCallback(
-        isolate
-      , target
-      , callback
-      , argc
-      , argv
-    ));
-#else
-#if NODE_VERSION_AT_LEAST(0, 8, 0)
-    v8::Local<v8::Function> callback = handle->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(node::MakeCallback(
-        target
-      , callback
-      , argc
-      , argv
-    ));
-#else
-    v8::Local<v8::Function> callback = handle->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(NanMakeCallback(
-        target, callback, argc, argv));
-#endif
-#endif
-  }
-};
-
-
-/* abstract */ class NanAsyncWorker {
- public:
-  explicit NanAsyncWorker(NanCallback *callback_)
-      : callback(callback_), errmsg_(NULL) {
-    request.data = this;
-
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(persistentHandle, obj);
-  }
-
-  virtual ~NanAsyncWorker() {
-    NanScope();
-
-    if (!persistentHandle.IsEmpty())
-      NanDisposePersistent(persistentHandle);
-    if (callback)
-      delete callback;
-    if (errmsg_)
-      delete[] errmsg_;
-  }
-
-  virtual void WorkComplete() {
-    NanScope();
-
-    if (errmsg_ == NULL)
-      HandleOKCallback();
-    else
-      HandleErrorCallback();
-    delete callback;
-    callback = NULL;
-  }
-
-  NAN_INLINE void SaveToPersistent(
-      const char *key, const v8::Local<v8::Object> &obj) {
-    v8::Local<v8::Object> handle = NanNew(persistentHandle);
-    handle->Set(NanNew<v8::String>(key), obj);
-  }
-
-  v8::Local<v8::Object> GetFromPersistent(const char *key) const {
-    NanEscapableScope();
-    v8::Local<v8::Object> handle = NanNew(persistentHandle);
-    return NanEscapeScope(handle->Get(NanNew(key)).As<v8::Object>());
-  }
-
-  virtual void Execute() = 0;
-
-  uv_work_t request;
-
-  virtual void Destroy() {
-      delete this;
-  }
-
- protected:
-  v8::Persistent<v8::Object> persistentHandle;
-  NanCallback *callback;
-
-  virtual void HandleOKCallback() {
-    callback->Call(0, NULL);
-  }
-
-  virtual void HandleErrorCallback() {
-    NanScope();
-
-    v8::Local<v8::Value> argv[] = {
-        v8::Exception::Error(NanNew<v8::String>(ErrorMessage()))
-    };
-    callback->Call(1, argv);
-  }
-
-  void SetErrorMessage(const char *msg) {
-    if (errmsg_) {
-      delete[] errmsg_;
-    }
-
-    size_t size = strlen(msg) + 1;
-    errmsg_ = new char[size];
-    memcpy(errmsg_, msg, size);
-  }
-
-  const char* ErrorMessage() const {
-    return errmsg_;
-  }
-
- private:
-  char *errmsg_;
-};
-
-/* abstract */ class NanAsyncProgressWorker : public NanAsyncWorker {
- public:
-  explicit NanAsyncProgressWorker(NanCallback *callback_)
-      : NanAsyncWorker(callback_), asyncdata_(NULL), asyncsize_(0) {
-    async = new uv_async_t;
-    uv_async_init(
-        uv_default_loop()
-      , async
-      , AsyncProgress_
-    );
-    async->data = this;
-
-    uv_mutex_init(&async_lock);
-  }
-
-  virtual ~NanAsyncProgressWorker() {
-    uv_mutex_destroy(&async_lock);
-
-    if (asyncdata_) {
-      delete[] asyncdata_;
-    }
-  }
-
-  void WorkProgress() {
-    uv_mutex_lock(&async_lock);
-    char *data = asyncdata_;
-    size_t size = asyncsize_;
-    asyncdata_ = NULL;
-    uv_mutex_unlock(&async_lock);
-
-    // Dont send progress events after we've already completed.
-    if (callback) {
-        HandleProgressCallback(data, size);
-    }
-    delete[] data;
-  }
-
-  class ExecutionProgress {
-    friend class NanAsyncProgressWorker;
-   public:
-    // You could do fancy generics with templates here.
-    void Send(const char* data, size_t size) const {
-        that_->SendProgress_(data, size);
-    }
-
-   private:
-    explicit ExecutionProgress(NanAsyncProgressWorker* that) : that_(that) {}
-    // Prohibit copying and assignment.
-    ExecutionProgress(const ExecutionProgress&);
-    void operator=(const ExecutionProgress&);
-  #if __cplusplus >= 201103L
-    // Prohibit C++11 move semantics.
-    ExecutionProgress(ExecutionProgress&&) = delete;
-    void operator=(ExecutionProgress&&) = delete;
-  #endif
-    NanAsyncProgressWorker* const that_;
-  };
-
-  virtual void Execute(const ExecutionProgress& progress) = 0;
-  virtual void HandleProgressCallback(const char *data, size_t size) = 0;
-
-  virtual void Destroy() {
-      uv_close(reinterpret_cast<uv_handle_t*>(async), AsyncClose_);
-  }
-
- private:
-  void Execute() /*final override*/ {
-      ExecutionProgress progress(this);
-      Execute(progress);
-  }
-
-  void SendProgress_(const char *data, size_t size) {
-    char *new_data = new char[size];
-    memcpy(new_data, data, size);
-
-    uv_mutex_lock(&async_lock);
-    char *old_data = asyncdata_;
-    asyncdata_ = new_data;
-    asyncsize_ = size;
-    uv_mutex_unlock(&async_lock);
-
-    if (old_data) {
-      delete[] old_data;
-    }
-    uv_async_send(async);
-  }
-
-  NAN_INLINE static NAUV_WORK_CB(AsyncProgress_) {
-    NanAsyncProgressWorker *worker =
-            static_cast<NanAsyncProgressWorker*>(async->data);
-    worker->WorkProgress();
-  }
-
-  NAN_INLINE static void AsyncClose_(uv_handle_t* handle) {
-    NanAsyncProgressWorker *worker =
-            static_cast<NanAsyncProgressWorker*>(handle->data);
-    delete reinterpret_cast<uv_async_t*>(handle);
-    delete worker;
-  }
-
-  uv_async_t *async;
-  uv_mutex_t async_lock;
-  char *asyncdata_;
-  size_t asyncsize_;
-};
-
-NAN_INLINE void NanAsyncExecute (uv_work_t* req) {
-  NanAsyncWorker *worker = static_cast<NanAsyncWorker*>(req->data);
-  worker->Execute();
-}
-
-NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) {
-  NanAsyncWorker* worker = static_cast<NanAsyncWorker*>(req->data);
-  worker->WorkComplete();
-  worker->Destroy();
-}
-
-NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) {
-  uv_queue_work(
-      uv_default_loop()
-    , &worker->request
-    , NanAsyncExecute
-    , (uv_after_work_cb)NanAsyncExecuteComplete
-  );
-}
-
-//// Base 64 ////
-
-#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
-
-// Doesn't check for padding at the end.  Can be 1-2 bytes over.
-NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) {
-  size_t remainder = size % 4;
-
-  size = (size / 4) * 3;
-  if (remainder) {
-    if (size == 0 && remainder == 1) {
-      // special case: 1-byte input cannot be decoded
-      size = 0;
-    } else {
-      // non-padded input, add 1 or 2 extra bytes
-      size += 1 + (remainder == 3);
-    }
-  }
-
-  return size;
-}
-
-template<typename T>
-NAN_INLINE size_t _nan_base64_decoded_size(
-    const T* src
-  , size_t size
-) {
-  if (size == 0)
-    return 0;
-
-  if (src[size - 1] == '=')
-    size--;
-  if (size > 0 && src[size - 1] == '=')
-    size--;
-
-  return _nan_base64_decoded_size_fast(size);
-}
-
-// supports regular and URL-safe base64
-static const int _nan_unbase64_table[] = {
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63
-  , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1
-  , -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14
-  , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63
-  , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
-  , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)]
-
-template<typename T> static size_t _nan_base64_decode(
-    char* buf
-  , size_t len
-  , const T* src
-  , const size_t srcLen
-) {
-  char* dst = buf;
-  char* dstEnd = buf + len;
-  const T* srcEnd = src + srcLen;
-
-  while (src < srcEnd && dst < dstEnd) {
-    ptrdiff_t remaining = srcEnd - src;
-    char a, b, c, d;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining == 0 || *src == '=') break;
-    a = _nan_unbase64(*src++);
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 1 || *src == '=') break;
-    b = _nan_unbase64(*src++);
-
-    *dst++ = (a << 2) | ((b & 0x30) >> 4);
-    if (dst == dstEnd) break;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 2 || *src == '=') break;
-    c = _nan_unbase64(*src++);
-
-    *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
-    if (dst == dstEnd) break;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 3 || *src == '=') break;
-    d = _nan_unbase64(*src++);
-
-    *dst++ = ((c & 0x03) << 6) | (d & 0x3F);
-  }
-
-  return dst - buf;
-}
-
-//// HEX ////
-
-template<typename T> unsigned _nan_hex2bin(T c) {
-  if (c >= '0' && c <= '9') return c - '0';
-  if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
-  if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
-  return static_cast<unsigned>(-1);
-}
-
-template<typename T> static size_t _nan_hex_decode(
-    char* buf
-  , size_t len
-  , const T* src
-  , const size_t srcLen
-) {
-  size_t i;
-  for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
-    unsigned a = _nan_hex2bin(src[i * 2 + 0]);
-    unsigned b = _nan_hex2bin(src[i * 2 + 1]);
-    if (!~a || !~b) return i;
-    buf[i] = a * 16 + b;
-  }
-
-  return i;
-}
-
-namespace NanIntern {
-
-inline
-NanExternalOneByteStringResource const*
-GetExternalResource(v8::Local<v8::String> str) {
-#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
-    return str->GetExternalAsciiStringResource();
-#else
-    return str->GetExternalOneByteStringResource();
-#endif
-}
-
-inline
-bool
-IsExternal(v8::Local<v8::String> str) {
-#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION
-    return str->IsExternalAscii();
-#else
-    return str->IsExternalOneByte();
-#endif
-}
-
-}  // end of namespace NanIntern
-
-static bool _NanGetExternalParts(
-    v8::Handle<v8::Value> val
-  , const char** data
-  , size_t* len
-) {
-  if (node::Buffer::HasInstance(val)) {
-    *data = node::Buffer::Data(val.As<v8::Object>());
-    *len = node::Buffer::Length(val.As<v8::Object>());
-    return true;
-  }
-
-  assert(val->IsString());
-  v8::Local<v8::String> str = NanNew(val.As<v8::String>());
-
-  if (NanIntern::IsExternal(str)) {
-    const NanExternalOneByteStringResource* ext;
-    ext = NanIntern::GetExternalResource(str);
-    *data = ext->data();
-    *len = ext->length();
-    return true;
-  }
-
-  if (str->IsExternal()) {
-    const v8::String::ExternalStringResource* ext;
-    ext = str->GetExternalStringResource();
-    *data = reinterpret_cast<const char*>(ext->data());
-    *len = ext->length();
-    return true;
-  }
-
-  return false;
-}
-
-namespace Nan {
-  enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
-}
-
-#if !NODE_VERSION_AT_LEAST(0, 10, 0)
-# include "nan_string_bytes.h"  // NOLINT(build/include)
-#endif
-
-NAN_INLINE v8::Local<v8::Value> NanEncode(
-    const void *buf, size_t len, enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION)
-  v8::Isolate* isolate = v8::Isolate::GetCurrent();
-  node::encoding node_enc = static_cast<node::encoding>(encoding);
-
-  if (encoding == Nan::UCS2) {
-    return node::Encode(
-        isolate
-      , reinterpret_cast<const uint16_t *>(buf)
-      , len / 2);
-  } else {
-    return node::Encode(
-        isolate
-      , reinterpret_cast<const char *>(buf)
-      , len
-      , node_enc);
-  }
-#elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-  return node::Encode(
-      v8::Isolate::GetCurrent()
-    , buf, len
-    , static_cast<node::encoding>(encoding));
-#else
-# if NODE_VERSION_AT_LEAST(0, 10, 0)
-  return node::Encode(buf, len, static_cast<node::encoding>(encoding));
-# else
-  return NanIntern::Encode(reinterpret_cast<const char*>(buf), len, encoding);
-# endif
-#endif
-}
-
-NAN_INLINE ssize_t NanDecodeBytes(
-    v8::Handle<v8::Value> val, enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-  return node::DecodeBytes(
-      v8::Isolate::GetCurrent()
-    , val
-    , static_cast<node::encoding>(encoding));
-#else
-# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
-  if (encoding == Nan::BUFFER) {
-    return node::DecodeBytes(val, node::BINARY);
-  }
-# endif
-  return node::DecodeBytes(val, static_cast<node::encoding>(encoding));
-#endif
-}
-
-NAN_INLINE ssize_t NanDecodeWrite(
-    char *buf
-  , size_t len
-  , v8::Handle<v8::Value> val
-  , enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
-  return node::DecodeWrite(
-      v8::Isolate::GetCurrent()
-    , buf
-    , len
-    , val
-    , static_cast<node::encoding>(encoding));
-#else
-# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION)
-  if (encoding == Nan::BUFFER) {
-    return node::DecodeWrite(buf, len, val, node::BINARY);
-  }
-# endif
-  return node::DecodeWrite(
-      buf
-    , len
-    , val
-    , static_cast<node::encoding>(encoding));
-#endif
-}
-
-/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString(
-    v8::Handle<v8::Value> from
-  , enum Nan::Encoding encoding
-  , size_t *datalen
-  , void *buf
-  , size_t buflen
-  , int flags
-) {
-  NanScope();
-
-  size_t sz_;
-  size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION);
-  char *data = NULL;
-  size_t len;
-  bool is_extern = _NanGetExternalParts(
-      from
-    , const_cast<const char**>(&data)
-    , &len);
-
-  if (is_extern && !term_len) {
-    NanSetPointerSafe(datalen, len);
-    return data;
-  }
-
-  v8::Local<v8::String> toStr = from->ToString();
-
-  char *to = static_cast<char *>(buf);
-
-  switch (encoding) {
-    case Nan::ASCII:
-#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
-      sz_ = toStr->Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-      NanSetPointerSafe<size_t>(
-          datalen
-        , toStr->WriteAscii(to, 0, static_cast<int>(sz_ + term_len), flags));
-      return to;
-#endif
-    case Nan::BINARY:
-    case Nan::BUFFER:
-      sz_ = toStr->Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
-      {
-        uint16_t* twobytebuf = new uint16_t[sz_ + term_len];
-
-        size_t somelen = toStr->Write(twobytebuf, 0,
-          static_cast<int>(sz_ + term_len), flags);
-
-        for (size_t i = 0; i < sz_ + term_len && i < somelen + term_len; i++) {
-          unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
-          to[i] = *b;
-        }
-
-        NanSetPointerSafe<size_t>(datalen, somelen);
-
-        delete[] twobytebuf;
-        return to;
-      }
-#else
-      NanSetPointerSafe<size_t>(
-        datalen,
-        toStr->WriteOneByte(
-            reinterpret_cast<uint8_t *>(to)
-          , 0
-          , static_cast<int>(sz_ + term_len)
-          , flags));
-      return to;
-#endif
-    case Nan::UTF8:
-      sz_ = toStr->Utf8Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-      NanSetPointerSafe<size_t>(
-          datalen
-        , toStr->WriteUtf8(to, static_cast<int>(sz_ + term_len)
-            , NULL, flags)
-          - term_len);
-      return to;
-    case Nan::BASE64:
-      {
-        v8::String::Value value(toStr);
-        sz_ = _nan_base64_decoded_size(*value, value.length());
-        if (to == NULL) {
-          to = new char[sz_ + term_len];
-        } else {
-          assert(buflen >= sz_ + term_len);
-        }
-        NanSetPointerSafe<size_t>(
-            datalen
-          , _nan_base64_decode(to, sz_, *value, value.length()));
-        if (term_len) {
-          to[sz_] = '\0';
-        }
-        return to;
-      }
-    case Nan::UCS2:
-      {
-        sz_ = toStr->Length();
-        if (to == NULL) {
-          to = new char[(sz_ + term_len) * 2];
-        } else {
-          assert(buflen >= (sz_ + term_len) * 2 && "too small buffer");
-        }
-
-        int bc = 2 * toStr->Write(
-            reinterpret_cast<uint16_t *>(to)
-          , 0
-          , static_cast<int>(sz_ + term_len)
-          , flags);
-        NanSetPointerSafe<size_t>(datalen, bc);
-        return to;
-      }
-    case Nan::HEX:
-      {
-        v8::String::Value value(toStr);
-        sz_ = value.length();
-        assert(!(sz_ & 1) && "bad hex data");
-        if (to == NULL) {
-          to = new char[sz_ / 2 + term_len];
-        } else {
-          assert(buflen >= sz_ / 2 + term_len && "too small buffer");
-        }
-        NanSetPointerSafe<size_t>(
-            datalen
-          , _nan_hex_decode(to, sz_ / 2, *value, value.length()));
-      }
-      if (term_len) {
-        to[sz_ / 2] = '\0';
-      }
-      return to;
-    default:
-      assert(0 && "unknown encoding");
-  }
-  return to;
-}
-
-NAN_DEPRECATED NAN_INLINE void* NanRawString(
-    v8::Handle<v8::Value> from
-  , enum Nan::Encoding encoding
-  , size_t *datalen
-  , void *buf
-  , size_t buflen
-  , int flags
-) {
-  return _NanRawString(from, encoding, datalen, buf, buflen, flags);
-}
-
-
-NAN_DEPRECATED NAN_INLINE char* NanCString(
-    v8::Handle<v8::Value> from
-  , size_t *datalen
-  , char *buf = NULL
-  , size_t buflen = 0
-  , int flags = v8::String::NO_OPTIONS
-) {
-    return static_cast<char *>(
-      _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags)
-    );
-}
-
-NAN_INLINE void NanSetPrototypeTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , const char *name
-  , v8::Handle<v8::Data> value
-) {
-  NanSetTemplate(templ->PrototypeTemplate(), name, value);
-}
-
-NAN_INLINE void NanSetPrototypeTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , v8::Handle<v8::String> name
-  , v8::Handle<v8::Data> value
-  , v8::PropertyAttribute attributes
-) {
-  NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes);
-}
-
-NAN_INLINE void NanSetInstanceTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , const char *name
-  , v8::Handle<v8::Data> value
-) {
-  NanSetTemplate(templ->InstanceTemplate(), name, value);
-}
-
-NAN_INLINE void NanSetInstanceTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , v8::Handle<v8::String> name
-  , v8::Handle<v8::Data> value
-  , v8::PropertyAttribute attributes
-) {
-  NanSetTemplate(templ->InstanceTemplate(), name, value, attributes);
-}
-
-//=== Export ==================================================================
-
-inline
-void
-NanExport(v8::Handle<v8::Object> target, const char * name,
-    NanFunctionCallback f) {
-  target->Set(NanNew<v8::String>(name),
-      NanNew<v8::FunctionTemplate>(f)->GetFunction());
-}
-
-//=== Tap Reverse Binding =====================================================
-
-struct NanTap {
-  explicit NanTap(v8::Handle<v8::Value> t) : t_() {
-    NanAssignPersistent(t_, t->ToObject());
-  }
-
-  ~NanTap() { NanDisposePersistent(t_); }  // not sure if neccessary
-
-  inline void plan(int i) {
-    v8::Handle<v8::Value> arg = NanNew(i);
-    NanMakeCallback(NanNew(t_), "plan", 1, &arg);
-  }
-
-  inline void ok(bool isOk, const char * msg = NULL) {
-    v8::Handle<v8::Value> args[2];
-    args[0] = NanNew(isOk);
-    if (msg) args[1] = NanNew(msg);
-    NanMakeCallback(NanNew(t_), "ok", msg ? 2 : 1, args);
-  }
-
- private:
-  v8::Persistent<v8::Object> t_;
-};
-
-#define NAN_STRINGIZE2(x) #x
-#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x)
-#define NAN_TEST_EXPRESSION(expression) \
-  ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression
-
-#define return_NanValue(v) NanReturnValue(v)
-#define return_NanUndefined() NanReturnUndefined()
-#define NAN_EXPORT(target, function) NanExport(target, #function, function)
-
-#endif  // NAN_H_
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_12_inl.h b/input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_12_inl.h
deleted file mode 100644
index ff63ec0c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_12_inl.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_IMPLEMENTATION_12_INL_H_
-#define NAN_IMPLEMENTATION_12_INL_H_
-//==============================================================================
-// node v0.11 implementation
-//==============================================================================
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-namespace NanIntern {
-
-//=== Array ====================================================================
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New() {
-  return v8::Array::New(v8::Isolate::GetCurrent());
-}
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New(int length) {
-  return v8::Array::New(v8::Isolate::GetCurrent(), length);
-}
-
-//=== Boolean ==================================================================
-
-Factory<v8::Boolean>::return_t
-Factory<v8::Boolean>::New(bool value) {
-  return v8::Boolean::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Boolean Object ===========================================================
-
-Factory<v8::BooleanObject>::return_t
-Factory<v8::BooleanObject>::New(bool value) {
-  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-}
-
-//=== Context ==================================================================
-
-Factory<v8::Context>::return_t
-Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
-                         , v8::Handle<v8::ObjectTemplate> tmpl
-                         , v8::Handle<v8::Value> obj) {
-  return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj);
-}
-
-//=== Date =====================================================================
-
-Factory<v8::Date>::return_t
-Factory<v8::Date>::New(double value) {
-  return v8::Date::New(v8::Isolate::GetCurrent(), value).As<v8::Date>();
-}
-
-//=== External =================================================================
-
-Factory<v8::External>::return_t
-Factory<v8::External>::New(void * value) {
-  return v8::External::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Function =================================================================
-
-Factory<v8::Function>::return_t
-Factory<v8::Function>::New( NanFunctionCallback callback
-                          , v8::Handle<v8::Value> data) {
-  return v8::Function::New( v8::Isolate::GetCurrent()
-                          , callback
-                          , data);
-}
-
-//=== Function Template ========================================================
-
-Factory<v8::FunctionTemplate>::return_t
-Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
-                                  , v8::Handle<v8::Value> data
-                                  , v8::Handle<v8::Signature> signature) {
-  return v8::FunctionTemplate::New( v8::Isolate::GetCurrent()
-                                  , callback
-                                  , data
-                                  , signature);
-}
-
-//=== Number ===================================================================
-
-Factory<v8::Number>::return_t
-Factory<v8::Number>::New(double value) {
-  return v8::Number::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Number Object ============================================================
-
-Factory<v8::NumberObject>::return_t
-Factory<v8::NumberObject>::New(double value) {
-  return v8::NumberObject::New( v8::Isolate::GetCurrent()
-                              , value).As<v8::NumberObject>();
-}
-
-//=== Integer, Int32 and Uint32 ================================================
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(int32_t value) {
-  return To<T>(T::New(v8::Isolate::GetCurrent(), value));
-}
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(uint32_t value) {
-  return To<T>(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(int32_t value) {
-  return To<v8::Uint32>(
-      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(uint32_t value) {
-  return To<v8::Uint32>(
-      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-//=== Object ===================================================================
-
-Factory<v8::Object>::return_t
-Factory<v8::Object>::New() {
-  return v8::Object::New(v8::Isolate::GetCurrent());
-}
-
-//=== Object Template ==========================================================
-
-Factory<v8::ObjectTemplate>::return_t
-Factory<v8::ObjectTemplate>::New() {
-  return v8::ObjectTemplate::New(v8::Isolate::GetCurrent());
-}
-
-//=== RegExp ===================================================================
-
-Factory<v8::RegExp>::return_t
-Factory<v8::RegExp>::New(
-    v8::Handle<v8::String> pattern
-  , v8::RegExp::Flags flags) {
-  return v8::RegExp::New(pattern, flags);
-}
-
-//=== Script ===================================================================
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source) {
-  v8::ScriptCompiler::Source src(source);
-  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
-}
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source
-                        , v8::ScriptOrigin const& origin) {
-  v8::ScriptCompiler::Source src(source, origin);
-  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
-}
-
-//=== Signature ================================================================
-
-Factory<v8::Signature>::return_t
-Factory<v8::Signature>::New( Factory<v8::Signature>::FTH receiver
-                           , int argc
-                           , Factory<v8::Signature>::FTH argv[]) {
-  return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv);
-}
-
-//=== String ===================================================================
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New() {
-  return v8::String::Empty(v8::Isolate::GetCurrent());
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const char * value, int length) {
-  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value,
-      v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(std::string const& value) {
-  assert(value.size() <= INT_MAX && "string too long");
-  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(),
-      value.data(), v8::String::kNormalString, static_cast<int>(value.size()));
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint8_t * value, int length) {
-  return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
-        v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint16_t * value, int length) {
-  return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value,
-        v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
-  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(NanExternalOneByteStringResource * value) {
-  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
-}
-
-//=== String Object ============================================================
-
-Factory<v8::StringObject>::return_t
-Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
-  return v8::StringObject::New(value).As<v8::StringObject>();
-}
-
-//=== Unbound Script ===========================================================
-
-Factory<v8::UnboundScript>::return_t
-Factory<v8::UnboundScript>::New(v8::Local<v8::String> source) {
-  v8::ScriptCompiler::Source src(source);
-  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
-}
-
-Factory<v8::UnboundScript>::return_t
-Factory<v8::UnboundScript>::New( v8::Local<v8::String> source
-                               , v8::ScriptOrigin const& origin) {
-  v8::ScriptCompiler::Source src(source, origin);
-  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
-}
-
-}  // end of namespace NanIntern
-
-//=== Presistents and Handles ==================================================
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Handle<T> h) {
-  return v8::Local<T>::New(v8::Isolate::GetCurrent(), h);
-}
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
-  return v8::Local<T>::New(v8::Isolate::GetCurrent(), p);
-}
-
-#endif  // NAN_IMPLEMENTATION_12_INL_H_
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_pre_12_inl.h b/input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_pre_12_inl.h
deleted file mode 100644
index 85dd2754..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_implementation_pre_12_inl.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_
-#define NAN_IMPLEMENTATION_PRE_12_INL_H_
-
-#include <algorithm>
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# include <vector>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-# include <vector>
-#endif
-
-//==============================================================================
-// node v0.10 implementation
-//==============================================================================
-
-namespace NanIntern {
-
-//=== Array ====================================================================
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New() {
-  return v8::Array::New();
-}
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New(int length) {
-  return v8::Array::New(length);
-}
-
-//=== Boolean ==================================================================
-
-Factory<v8::Boolean>::return_t
-Factory<v8::Boolean>::New(bool value) {
-  return v8::Boolean::New(value)->ToBoolean();
-}
-
-//=== Boolean Object ===========================================================
-
-Factory<v8::BooleanObject>::return_t
-Factory<v8::BooleanObject>::New(bool value) {
-  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-}
-
-//=== Context ==================================================================
-
-Factory<v8::Context>::return_t
-Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
-                         , v8::Handle<v8::ObjectTemplate> tmpl
-                         , v8::Handle<v8::Value> obj) {
-  v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
-  v8::Local<v8::Context> lctx = v8::Local<v8::Context>::New(ctx);
-  ctx.Dispose();
-  return lctx;
-}
-
-//=== Date =====================================================================
-
-Factory<v8::Date>::return_t
-Factory<v8::Date>::New(double value) {
-  return v8::Date::New(value).As<v8::Date>();
-}
-
-//=== External =================================================================
-
-Factory<v8::External>::return_t
-Factory<v8::External>::New(void * value) {
-  return v8::External::New(value);
-}
-
-//=== Function =================================================================
-
-Factory<v8::Function>::return_t
-Factory<v8::Function>::New( NanFunctionCallback callback
-                          , v8::Handle<v8::Value> data) {
-  return Factory<v8::FunctionTemplate>::New( callback
-                                           , data
-                                           , v8::Handle<v8::Signature>()
-                                           )->GetFunction();
-}
-
-
-//=== FunctionTemplate =========================================================
-
-Factory<v8::FunctionTemplate>::return_t
-Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
-                                  , v8::Handle<v8::Value> data
-                                  , v8::Handle<v8::Signature> signature) {
-  // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find
-  // a way. Have at it though...
-  return v8::FunctionTemplate::New( callback
-                                  , data
-                                  , signature);
-}
-
-//=== Number ===================================================================
-
-Factory<v8::Number>::return_t
-Factory<v8::Number>::New(double value) {
-  return v8::Number::New(value);
-}
-
-//=== Number Object ============================================================
-
-Factory<v8::NumberObject>::return_t
-Factory<v8::NumberObject>::New(double value) {
-  return v8::NumberObject::New(value).As<v8::NumberObject>();
-}
-
-//=== Integer, Int32 and Uint32 ================================================
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(int32_t value) {
-  return To<T>(T::New(value));
-}
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(uint32_t value) {
-  return To<T>(T::NewFromUnsigned(value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(int32_t value) {
-  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(uint32_t value) {
-  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
-}
-
-
-//=== Object ===================================================================
-
-Factory<v8::Object>::return_t
-Factory<v8::Object>::New() {
-  return v8::Object::New();
-}
-
-//=== Object Template ==========================================================
-
-Factory<v8::ObjectTemplate>::return_t
-Factory<v8::ObjectTemplate>::New() {
-  return v8::ObjectTemplate::New();
-}
-
-//=== RegExp ===================================================================
-
-Factory<v8::RegExp>::return_t
-Factory<v8::RegExp>::New(
-    v8::Handle<v8::String> pattern
-  , v8::RegExp::Flags flags) {
-  return v8::RegExp::New(pattern, flags);
-}
-
-//=== Script ===================================================================
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source) {
-  return v8::Script::New(source);
-}
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source
-                        , v8::ScriptOrigin const& origin) {
-  return v8::Script::New(source, const_cast<v8::ScriptOrigin*>(&origin));
-}
-
-//=== Signature ================================================================
-
-Factory<v8::Signature>::return_t
-Factory<v8::Signature>::New( Factory<v8::Signature>::FTH receiver
-                           , int argc
-                           , Factory<v8::Signature>::FTH argv[]) {
-  return v8::Signature::New(receiver, argc, argv);
-}
-
-//=== String ===================================================================
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New() {
-  return v8::String::Empty();
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const char * value, int length) {
-  return v8::String::New(value, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(std::string const& value) {
-  assert(value.size() <= INT_MAX && "string too long");
-  return v8::String::New( value.data(), static_cast<int>(value.size()));
-}
-
-inline
-void
-widenString(std::vector<uint16_t> *ws, const uint8_t *s, int l = -1) {
-  size_t len = static_cast<size_t>(l);
-  if (l < 0) {
-    len = strlen(reinterpret_cast<const char*>(s));
-  }
-  assert(len <= INT_MAX && "string too long");
-  ws->resize(len);
-  std::copy(s, s + len, ws->begin());
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint16_t * value, int length) {
-  return v8::String::New(value, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint8_t * value, int length) {
-  std::vector<uint16_t> wideString;
-  widenString(&wideString, value, length);
-  if (wideString.size() == 0) {
-    return v8::String::Empty();
-  } else {
-    return v8::String::New(&wideString.front()
-         , static_cast<int>(wideString.size()));
-  }
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
-  return v8::String::NewExternal(value);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalAsciiStringResource * value) {
-  return v8::String::NewExternal(value);
-}
-
-//=== String Object ============================================================
-
-Factory<v8::StringObject>::return_t
-Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
-  return v8::StringObject::New(value).As<v8::StringObject>();
-}
-
-}  // end of namespace NanIntern
-
-//=== Presistents and Handles ==================================================
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Handle<T> h) {
-  return v8::Local<T>::New(h);
-}
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
-  return v8::Local<T>::New(p);
-}
-
-#endif  // NAN_IMPLEMENTATION_PRE_12_INL_H_
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_new.h b/input_devices/mag/node_modules/serialport/node_modules/nan/nan_new.h
deleted file mode 100644
index 95b6b51e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_new.h
+++ /dev/null
@@ -1,329 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_NEW_H_
-#define NAN_NEW_H_
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-namespace NanIntern {  // scnr
-
-// TODO(agnat): Generalize
-template <typename T> v8::Local<T> To(v8::Handle<v8::Integer> i);
-
-template <>
-inline
-v8::Local<v8::Integer>
-To<v8::Integer>(v8::Handle<v8::Integer> i) { return i->ToInteger(); }
-
-template <>
-inline
-v8::Local<v8::Int32>
-To<v8::Int32>(v8::Handle<v8::Integer> i)   { return i->ToInt32(); }
-
-template <>
-inline
-v8::Local<v8::Uint32>
-To<v8::Uint32>(v8::Handle<v8::Integer> i)  { return i->ToUint32(); }
-
-template <typename T> struct FactoryBase { typedef v8::Local<T> return_t; };
-
-template <typename T> struct Factory;
-
-template <>
-struct Factory<v8::Array> : FactoryBase<v8::Array> {
-  static inline return_t New();
-  static inline return_t New(int length);
-};
-
-template <>
-struct Factory<v8::Boolean> : FactoryBase<v8::Boolean> {
-  static inline return_t New(bool value);
-};
-
-template <>
-struct Factory<v8::BooleanObject> : FactoryBase<v8::BooleanObject> {
-  static inline return_t New(bool value);
-};
-
-template <>
-struct Factory<v8::Context> : FactoryBase<v8::Context> {
-  static inline
-  return_t
-  New( v8::ExtensionConfiguration* extensions = NULL
-     , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-     , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>());
-};
-
-template <>
-struct Factory<v8::Date> : FactoryBase<v8::Date> {
-  static inline return_t New(double value);
-};
-
-template <>
-struct Factory<v8::External> : FactoryBase<v8::External> {
-  static inline return_t New(void *value);
-};
-
-template <>
-struct Factory<v8::Function> : FactoryBase<v8::Function> {
-  static inline
-  return_t
-  New( NanFunctionCallback callback
-     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>());
-};
-
-template <>
-struct Factory<v8::FunctionTemplate> : FactoryBase<v8::FunctionTemplate> {
-  static inline
-  return_t
-  New( NanFunctionCallback callback = NULL
-     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-     , v8::Handle<v8::Signature> signature = v8::Handle<v8::Signature>());
-};
-
-template <>
-struct Factory<v8::Number> : FactoryBase<v8::Number> {
-  static inline return_t New(double value);
-};
-
-template <>
-struct Factory<v8::NumberObject> : FactoryBase<v8::NumberObject> {
-  static inline return_t New(double value);
-};
-
-template <typename T>
-struct IntegerFactory : FactoryBase<T> {
-  typedef typename FactoryBase<T>::return_t return_t;
-  static inline return_t New(int32_t value);
-  static inline return_t New(uint32_t value);
-};
-
-template <>
-struct Factory<v8::Integer> : IntegerFactory<v8::Integer> {};
-
-template <>
-struct Factory<v8::Int32> : IntegerFactory<v8::Int32> {};
-
-template <>
-struct Factory<v8::Uint32> : FactoryBase<v8::Uint32> {
-  static inline return_t New(int32_t value);
-  static inline return_t New(uint32_t value);
-};
-
-template <>
-struct Factory<v8::Object> : FactoryBase<v8::Object> {
-  static inline return_t New();
-};
-
-template <>
-struct Factory<v8::ObjectTemplate> : FactoryBase<v8::ObjectTemplate> {
-  static inline return_t New();
-};
-
-template <>
-struct Factory<v8::RegExp> : FactoryBase<v8::RegExp> {
-  static inline return_t New(
-      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags);
-};
-
-template <>
-struct Factory<v8::Script> : FactoryBase<v8::Script> {
-  static inline return_t New( v8::Local<v8::String> source);
-  static inline return_t New( v8::Local<v8::String> source
-                            , v8::ScriptOrigin const& origin);
-};
-
-template <>
-struct Factory<v8::Signature> : FactoryBase<v8::Signature> {
-  typedef v8::Handle<v8::FunctionTemplate> FTH;
-  static inline
-  return_t
-  New( FTH receiver = FTH(), int argc = 0, FTH argv[] = NULL );
-};
-
-template <>
-struct Factory<v8::String> : FactoryBase<v8::String> {
-  static inline return_t New();
-  static inline return_t New(const char *value, int length = -1);
-  static inline return_t New(const uint16_t *value, int length = -1);
-  static inline return_t New(std::string const& value);
-
-  static inline return_t New(v8::String::ExternalStringResource * value);
-  static inline return_t New(NanExternalOneByteStringResource * value);
-
-  // TODO(agnat): Deprecate.
-  static inline return_t New(const uint8_t * value, int length = -1);
-};
-
-template <>
-struct Factory<v8::StringObject> : FactoryBase<v8::StringObject> {
-  static inline return_t New(v8::Handle<v8::String> value);
-};
-
-}  // end of namespace NanIntern
-
-#if (NODE_MODULE_VERSION >= 12)
-
-namespace NanIntern {
-
-template <>
-struct Factory<v8::UnboundScript> : FactoryBase<v8::UnboundScript> {
-  static inline return_t New( v8::Local<v8::String> source);
-  static inline return_t New( v8::Local<v8::String> source
-                            , v8::ScriptOrigin const& origin);
-};
-
-}  // end of namespace NanIntern
-
-# include "nan_implementation_12_inl.h"
-
-#else  // NODE_MODULE_VERSION >= 12
-
-# include "nan_implementation_pre_12_inl.h"
-
-#endif
-
-//=== API ======================================================================
-
-template <typename T>
-typename NanIntern::Factory<T>::return_t
-NanNew() {
-  return NanIntern::Factory<T>::New();
-}
-
-template <typename T, typename A0>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0) {
-  return NanIntern::Factory<T>::New(arg0);
-}
-
-template <typename T, typename A0, typename A1>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1) {
-  return NanIntern::Factory<T>::New(arg0, arg1);
-}
-
-template <typename T, typename A0, typename A1, typename A2>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1, A2 arg2) {
-  return NanIntern::Factory<T>::New(arg0, arg1, arg2);
-}
-
-template <typename T, typename A0, typename A1, typename A2, typename A3>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1, A2 arg2, A3 arg3) {
-  return NanIntern::Factory<T>::New(arg0, arg1, arg2, arg3);
-}
-
-// Note(agnat): When passing overloaded function pointers to template functions
-// as generic arguments the compiler needs help in picking the right overload.
-// These two functions handle NanNew<Function> and NanNew<FunctionTemplate> with
-// all argument variations.
-
-// v8::Function and v8::FunctionTemplate with one or two arguments
-template <typename T>
-typename NanIntern::Factory<T>::return_t
-NanNew( NanFunctionCallback callback
-      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()) {
-    return NanIntern::Factory<T>::New(callback, data);
-}
-
-// v8::Function and v8::FunctionTemplate with three arguments
-template <typename T, typename A2>
-typename NanIntern::Factory<T>::return_t
-NanNew( NanFunctionCallback callback
-      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-      , A2 a2 = A2()) {
-    return NanIntern::Factory<T>::New(callback, data, a2);
-}
-
-// Convenience
-
-template <typename T> inline v8::Local<T> NanNew(v8::Handle<T> h);
-template <typename T> inline v8::Local<T> NanNew(v8::Persistent<T> const& p);
-
-inline
-NanIntern::Factory<v8::Boolean>::return_t
-NanNew(bool value) {
-  return NanNew<v8::Boolean>(value);
-}
-
-inline
-NanIntern::Factory<v8::Int32>::return_t
-NanNew(int32_t value) {
-  return NanNew<v8::Int32>(value);
-}
-
-inline
-NanIntern::Factory<v8::Uint32>::return_t
-NanNew(uint32_t value) {
-  return NanNew<v8::Uint32>(value);
-}
-
-inline
-NanIntern::Factory<v8::Number>::return_t
-NanNew(double value) {
-  return NanNew<v8::Number>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(std::string const& value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const char * value, int length) {
-  return NanNew<v8::String>(value, length);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const char * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const uint8_t * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const uint16_t * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(v8::String::ExternalStringResource * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(NanExternalOneByteStringResource * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::RegExp>::return_t
-NanNew(v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
-  return NanNew<v8::RegExp>(pattern, flags);
-}
-
-#endif  // NAN_NEW_H_
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_string_bytes.h b/input_devices/mag/node_modules/serialport/node_modules/nan/nan_string_bytes.h
deleted file mode 100644
index 9deecfbb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/nan_string_bytes.h
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-#ifndef NAN_STRING_BYTES_H_
-#define NAN_STRING_BYTES_H_
-
-// Decodes a v8::Handle<v8::String> or Buffer to a raw char*
-
-#include <node.h>
-#include <node_buffer.h>
-#include <assert.h>
-#include <string.h>  // memcpy
-#include <limits.h>
-
-namespace NanIntern {
-
-using v8::Local;
-using v8::Handle;
-using v8::Object;
-using v8::String;
-using v8::Value;
-
-
-//// Base 64 ////
-
-#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
-
-
-
-//// Nan::HEX ////
-
-static bool contains_non_ascii_slow(const char* buf, size_t len) {
-  for (size_t i = 0; i < len; ++i) {
-    if (buf[i] & 0x80) return true;
-  }
-  return false;
-}
-
-
-static bool contains_non_ascii(const char* src, size_t len) {
-  if (len < 16) {
-    return contains_non_ascii_slow(src, len);
-  }
-
-  const unsigned bytes_per_word = sizeof(void*);
-  const unsigned align_mask = bytes_per_word - 1;
-  const unsigned unaligned = reinterpret_cast<uintptr_t>(src) & align_mask;
-
-  if (unaligned > 0) {
-    const unsigned n = bytes_per_word - unaligned;
-    if (contains_non_ascii_slow(src, n)) return true;
-    src += n;
-    len -= n;
-  }
-
-
-#if defined(__x86_64__) || defined(_WIN64)
-  const uintptr_t mask = 0x8080808080808080ll;
-#else
-  const uintptr_t mask = 0x80808080l;
-#endif
-
-  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
-
-  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
-    if (srcw[i] & mask) return true;
-  }
-
-  const unsigned remainder = len & align_mask;
-  if (remainder > 0) {
-    const size_t offset = len - remainder;
-    if (contains_non_ascii_slow(src + offset, remainder)) return true;
-  }
-
-  return false;
-}
-
-
-static void force_ascii_slow(const char* src, char* dst, size_t len) {
-  for (size_t i = 0; i < len; ++i) {
-    dst[i] = src[i] & 0x7f;
-  }
-}
-
-
-static void force_ascii(const char* src, char* dst, size_t len) {
-  if (len < 16) {
-    force_ascii_slow(src, dst, len);
-    return;
-  }
-
-  const unsigned bytes_per_word = sizeof(void*);
-  const unsigned align_mask = bytes_per_word - 1;
-  const unsigned src_unalign = reinterpret_cast<uintptr_t>(src) & align_mask;
-  const unsigned dst_unalign = reinterpret_cast<uintptr_t>(dst) & align_mask;
-
-  if (src_unalign > 0) {
-    if (src_unalign == dst_unalign) {
-      const unsigned unalign = bytes_per_word - src_unalign;
-      force_ascii_slow(src, dst, unalign);
-      src += unalign;
-      dst += unalign;
-      len -= src_unalign;
-    } else {
-      force_ascii_slow(src, dst, len);
-      return;
-    }
-  }
-
-#if defined(__x86_64__) || defined(_WIN64)
-  const uintptr_t mask = ~0x8080808080808080ll;
-#else
-  const uintptr_t mask = ~0x80808080l;
-#endif
-
-  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
-  uintptr_t* dstw = reinterpret_cast<uintptr_t*>(dst);
-
-  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
-    dstw[i] = srcw[i] & mask;
-  }
-
-  const unsigned remainder = len & align_mask;
-  if (remainder > 0) {
-    const size_t offset = len - remainder;
-    force_ascii_slow(src + offset, dst + offset, remainder);
-  }
-}
-
-
-static size_t base64_encode(const char* src,
-                            size_t slen,
-                            char* dst,
-                            size_t dlen) {
-  // We know how much we'll write, just make sure that there's space.
-  assert(dlen >= base64_encoded_size(slen) &&
-      "not enough space provided for base64 encode");
-
-  dlen = base64_encoded_size(slen);
-
-  unsigned a;
-  unsigned b;
-  unsigned c;
-  unsigned i;
-  unsigned k;
-  unsigned n;
-
-  static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                              "abcdefghijklmnopqrstuvwxyz"
-                              "0123456789+/";
-
-  i = 0;
-  k = 0;
-  n = slen / 3 * 3;
-
-  while (i < n) {
-    a = src[i + 0] & 0xff;
-    b = src[i + 1] & 0xff;
-    c = src[i + 2] & 0xff;
-
-    dst[k + 0] = table[a >> 2];
-    dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
-    dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
-    dst[k + 3] = table[c & 0x3f];
-
-    i += 3;
-    k += 4;
-  }
-
-  if (n != slen) {
-    switch (slen - n) {
-      case 1:
-        a = src[i + 0] & 0xff;
-        dst[k + 0] = table[a >> 2];
-        dst[k + 1] = table[(a & 3) << 4];
-        dst[k + 2] = '=';
-        dst[k + 3] = '=';
-        break;
-
-      case 2:
-        a = src[i + 0] & 0xff;
-        b = src[i + 1] & 0xff;
-        dst[k + 0] = table[a >> 2];
-        dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
-        dst[k + 2] = table[(b & 0x0f) << 2];
-        dst[k + 3] = '=';
-        break;
-    }
-  }
-
-  return dlen;
-}
-
-
-static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) {
-  // We know how much we'll write, just make sure that there's space.
-  assert(dlen >= slen * 2 &&
-      "not enough space provided for hex encode");
-
-  dlen = slen * 2;
-  for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {
-    static const char hex[] = "0123456789abcdef";
-    uint8_t val = static_cast<uint8_t>(src[i]);
-    dst[k + 0] = hex[val >> 4];
-    dst[k + 1] = hex[val & 15];
-  }
-
-  return dlen;
-}
-
-
-
-static Local<Value> Encode(const char* buf,
-                           size_t buflen,
-                           enum Nan::Encoding encoding) {
-  assert(buflen <= node::Buffer::kMaxLength);
-  if (!buflen && encoding != Nan::BUFFER)
-    return NanNew("");
-
-  Local<String> val;
-  switch (encoding) {
-    case Nan::BUFFER:
-      return NanNewBufferHandle(buf, buflen);
-
-    case Nan::ASCII:
-      if (contains_non_ascii(buf, buflen)) {
-        char* out = new char[buflen];
-        force_ascii(buf, out, buflen);
-        val = NanNew<String>(out, buflen);
-        delete[] out;
-      } else {
-        val = NanNew<String>(buf, buflen);
-      }
-      break;
-
-    case Nan::UTF8:
-      val = NanNew<String>(buf, buflen);
-      break;
-
-    case Nan::BINARY: {
-      // TODO(isaacs) use ExternalTwoByteString?
-      const unsigned char *cbuf = reinterpret_cast<const unsigned char*>(buf);
-      uint16_t * twobytebuf = new uint16_t[buflen];
-      for (size_t i = 0; i < buflen; i++) {
-        // XXX is the following line platform independent?
-        twobytebuf[i] = cbuf[i];
-      }
-      val = NanNew<String>(twobytebuf, buflen);
-      delete[] twobytebuf;
-      break;
-    }
-
-    case Nan::BASE64: {
-      size_t dlen = base64_encoded_size(buflen);
-      char* dst = new char[dlen];
-
-      size_t written = base64_encode(buf, buflen, dst, dlen);
-      assert(written == dlen);
-
-      val = NanNew<String>(dst, dlen);
-      delete[] dst;
-      break;
-    }
-
-    case Nan::UCS2: {
-      const uint16_t* data = reinterpret_cast<const uint16_t*>(buf);
-      val = NanNew<String>(data, buflen / 2);
-      break;
-    }
-
-    case Nan::HEX: {
-      size_t dlen = buflen * 2;
-      char* dst = new char[dlen];
-      size_t written = hex_encode(buf, buflen, dst, dlen);
-      assert(written == dlen);
-
-      val = NanNew<String>(dst, dlen);
-      delete[] dst;
-      break;
-    }
-
-    default:
-      assert(0 && "unknown encoding");
-      break;
-  }
-
-  return val;
-}
-
-#undef base64_encoded_size
-
-}  // namespace NanIntern
-
-#endif  // NAN_STRING_BYTES_H_
diff --git a/input_devices/mag/node_modules/serialport/node_modules/nan/package.json b/input_devices/mag/node_modules/serialport/node_modules/nan/package.json
deleted file mode 100644
index d2001a1c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/nan/package.json
+++ /dev/null
@@ -1,69 +0,0 @@
-{
-  "name": "nan",
-  "version": "1.7.0",
-  "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility",
-  "main": "include_dirs.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/rvagg/nan.git"
-  },
-  "scripts": {
-    "test": "tap --gc test/js/*-test.js",
-    "rebuild-tests": "pangyp rebuild --directory test"
-  },
-  "contributors": [
-    {
-      "name": "Rod Vagg",
-      "email": "r@va.gg",
-      "url": "https://github.com/rvagg"
-    },
-    {
-      "name": "Benjamin Byholm",
-      "email": "bbyholm@abo.fi",
-      "url": "https://github.com/kkoopa/"
-    },
-    {
-      "name": "Trevor Norris",
-      "email": "trev.norris@gmail.com",
-      "url": "https://github.com/trevnorris"
-    },
-    {
-      "name": "Nathan Rajlich",
-      "email": "nathan@tootallnate.net",
-      "url": "https://github.com/TooTallNate"
-    },
-    {
-      "name": "Brett Lawson",
-      "email": "brett19@gmail.com",
-      "url": "https://github.com/brett19"
-    },
-    {
-      "name": "Ben Noordhuis",
-      "email": "info@bnoordhuis.nl",
-      "url": "https://github.com/bnoordhuis"
-    },
-    {
-      "name": "David Siegel",
-      "email": "david@artcom.de",
-      "url": "https://github.com/agnat"
-    }
-  ],
-  "devDependencies": {
-    "bindings": "~1.2.1",
-    "node-gyp": "~1.0.2",
-    "pangyp": "~2.0.1",
-    "tap": "~0.5.0",
-    "xtend": "~4.0.0"
-  },
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/rvagg/nan/issues"
-  },
-  "readme": "ERROR: No README data found!",
-  "_id": "nan@1.7.0",
-  "dist": {
-    "shasum": "a583103bd931a56634c0a134a931d7c65154d08f"
-  },
-  "_from": "nan@1.7.0",
-  "_resolved": "http://registry.npmjs.org/nan/-/nan-1.7.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/CHANGELOG.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/CHANGELOG.md
deleted file mode 100644
index 6a67a07e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/CHANGELOG.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# node-pre-gyp changelog
-
-## 0.5.19
-
- - Updated to know about more node-webkit releases
-
-## 0.5.18
-
- - Updated to know about more node-webkit releases
-
-## 0.5.17
-
- - Updated to know about node v0.10.29 release
-
-## 0.5.16
-
- - Now supporting all aws-sdk configuration parameters (http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html) (#86)
-
-## 0.5.15
-
- - Fixed installation of windows packages sub directories on unix systems (#84)
-
-## 0.5.14
-
- - Finished support for cross building using `--target_platform` option (#82)
- - Now skipping binary validation on install if target arch/platform do not match the host.
- - Removed multi-arch validing for OS X since it required a FAT node.js binary
-
-## 0.5.13
-
- - Fix problem in 0.5.12 whereby the wrong versions of mkdirp and semver where bundled.
-
-## 0.5.12
-
- - Improved support for node-webkit (@Mithgol)
-
-## 0.5.11
-
- - Updated target versions listing
-
-## 0.5.10
-
- - Fixed handling of `-debug` flag passed directory to node-pre-gyp (#72)
- - Added optional second arg to `node_pre_gyp.find` to customize the default versioning options used to locate the runtime binary
- - Failed install due to `testbinary` check failure no longer leaves behind binary (#70)
-
-## 0.5.9
-
- - Fixed regression in `testbinary` command causing installs to fail on windows with 0.5.7 (#60)
-
-## 0.5.8
-
- - Started bundling deps
-
-## 0.5.7
-
- - Fixed the `testbinary` check, which is used to determine whether to re-download or source compile, to work even in complex dependency situations (#63)
- - Exposed the internal `testbinary` command in node-pre-gyp command line tool
- - Fixed minor bug so that `fallback_to_build` option is always respected
-
-## 0.5.6
-
- - Added support for versioning on the `name` value in `package.json` (#57).
- - Moved to using streams for reading tarball when publishing (#52)
-
-## 0.5.5
-
- - Improved binary validation that also now works with node-webkit (@Mithgol)
- - Upgraded test apps to work with node v0.11.x
- - Improved test coverage
-
-## 0.5.4
-
- - No longer depends on external install of node-gyp for compiling builds.
-
-## 0.5.3
-
- - Reverted fix for debian/nodejs since it broke windows (#45)
-
-## 0.5.2
-
- - Support for debian systems where the node binary is named `nodejs` (#45)
- - Added `bin/node-pre-gyp.cmd` to be able to run command on windows locally (npm creates an .npm automatically when globally installed)
- - Updated abi-crosswalk with node v0.10.26 entry.
-
-## 0.5.1
-
- - Various minor bug fixes, several improving windows support for publishing.
-
-## 0.5.0
-
- - Changed property names in `binary` object: now required are `module_name`, `module_path`, and `host`.
- - Now `module_path` supports versioning, which allows developers to opt-in to using a versioned install path (#18).
- - Added `remote_path` which also supports versioning.
- - Changed `remote_uri` to `host`.
-
-## 0.4.2
-
- - Added support for `--target` flag to request cross-compile against a specific node/node-webkit version.
- - Added preliminary support for node-webkit
- - Fixed support for `--target_arch` option being respected in all cases.
-
-## 0.4.1
-
- - Fixed exception when only stderr is available in binary test (@bendi / #31) 
-
-## 0.4.0
-
- - Enforce only `https:` based remote publishing access.
- - Added `node-pre-gyp info` command to display listing of published binaries
- - Added support for changing the directory node-pre-gyp should build in with the `-C/--directory` option.
- - Added support for S3 prefixes.
-
-## 0.3.1
-
- - Added `unpublish` command.
- - Fixed module path construction in tests.
- - Added ability to disable falling back to build behavior via `npm install --fallback-to-build=false` which overrides setting in a depedencies package.json `install` target.
-
-## 0.3.0
-
- - Support for packaging all files in `module_path` directory - see `app4` for example
- - Added `testpackage` command.
- - Changed `clean` command to only delete `.node` not entire `build` directory since node-gyp will handle that.
- - `.node` modules must be in a folder of there own since tar-pack will remove everything when it unpacks.
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/LICENSE
deleted file mode 100644
index 888c4bd3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c), MapBox
-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 {organization} 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 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/README.md
deleted file mode 100644
index 0565baed..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/README.md
+++ /dev/null
@@ -1,448 +0,0 @@
-# node-pre-gyp
-
-#### node-pre-gyp makes it easy to publish and install Node.js C++ addons from binaries
-
-[![NPM](https://nodei.co/npm/node-pre-gyp.png)](https://nodei.co/npm/node-pre-gyp/)
-
-[![Build Status](https://api.travis-ci.org/mapbox/node-pre-gyp.svg)](https://travis-ci.org/mapbox/node-pre-gyp)
-
-[![Build status](https://ci.appveyor.com/api/projects/status/n6l9796p4vigsk0e)](https://ci.appveyor.com/project/springmeyer/node-pre-gyp)
-
-[![Dependencies](https://david-dm.org/mapbox/node-pre-gyp.svg)](https://david-dm.org/mapbox/node-pre-gyp)
-
-`node-pre-gyp` stands between [npm](https://github.com/npm/npm) and [node-gyp](https://github.com/Tootallnate/node-gyp) and offers a cross-platform method of binary deployment.
-
-### Features
-
- - A command line tool called `node-pre-gyp` that can install your package's c++ module from a binary.
- - A variety of developer targeted commands for packaging, testing, and publishing binaries.
- - A Javascript module that can dynamically require your installed binary: `require('node-pre-gyp').find`
-
-For a hello world example of a module packaged with `node-pre-gyp` see <https://github.com/springmeyer/node-addon-example> and [the wiki ](https://github.com/mapbox/node-pre-gyp/wiki/Modules-using-node-pre-gyp) for real world examples.
-
-## Credits
-
- - The module is modeled after [node-gyp](https://github.com/Tootallnate/node-gyp) by [@Tootallnate](https://github.com/Tootallnate)
- - Motivation for initial development came from [@ErisDS](https://github.com/ErisDS) and the [Ghost Project](https://github.com/TryGhost/Ghost).
- - Development is sponsored by [Mapbox](https://www.mapbox.com/)
-
-## Depends
-
- - Node.js 0.10.x or 0.8.x
-
-## Install
-
-`node-pre-gyp` is designed to be installed as a local dependency of your Node.js C++ addon and accessed like:
-
-    ./node_modules/.bin/node-pre-gyp --help
-
-But you can also install it globally:
-
-    npm install node-pre-gyp -g
-
-## Usage
-
-### Commands
-
-View all possible commands:
-
-    node-pre-gyp --help
-
-- clean - Removes the entire folder containing the compiled .node module
-- install - Attempts to install pre-built binary for module
-- reinstall - Runs "clean" and "install" at once
-- build - Attempts to compile the module by dispatching to node-gyp or nw-gyp
-- rebuild - Runs "clean" and "build" at once
-- package - Packs binary into tarball
-- testpackage - Tests that the staged package is valid
-- publish - Publishes pre-built binary
-- unpublish - Unpublishes pre-built binary
-- info - Fetches info on published binaries
-
-You can also chain commands:
-
-    node-pre-gyp clean build unpublish publish info
-
-### Options
-
-Options include:
-
- - `-C/--directory`: run the command in this directory
- - `--build-from-source`: build from source instead of using pre-built binary
- - `--runtime=node-webkit`: customize the runtime: `node` and `node-webkit` are the valid options
- - `--fallback-to-build`: fallback to building from source if pre-built binary is not available
- - `--target=0.10.25`: Pass the target node or node-webkit version to compile against
- - `--target_arch=ia32`: Pass the target arch and override the host `arch`. Valid values are 'ia32','x64', or `arm`.
- - `--target_platform=ia32`: Pass the target platform and override the host `platform`. Valid values are `linux`, `darwin`, `win32`, `sunos`, `freebsd`, `openbsd`, and `aix`.
-
-Both `--build-from-source` and `--fallback-to-build` can be passed alone or they can provide values. You can pass `--fallback-to-build=false` to override the option as declared in package.json. In addition to being able to pass `--build-from-source` you can also pass `--build-from-source=myapp` where `myapp` is the name of your module.
-
-For example: `npm install --build-from-source=myapp`. This is useful if:
-
- - `myapp` is referenced in the package.json of a larger app and therefore `myapp` is being installed as a dependent with `npm install`.
- - The larger app also depends on other modules installed with `node-pre-gyp`
- - You only want to trigger a source compile for `myapp` and the other modules.
-
-### Configuring
-
-This is a guide to configuring your module to use node-pre-gyp.
-
-#### 1) Add new entries to your `package.json`
-
- - Add `node-pre-gyp` to `bundledDependencies`
- - Add `aws-sdk` as a `devDependency`
- - Add a custom `install` script
- - Declare a `binary` object
-
-This looks like:
-
-```js
-    "dependencies"  : {
-      "node-pre-gyp": "0.5.x"
-    },
-    "bundledDependencies":["node-pre-gyp"],
-    "devDependencies": {
-      "aws-sdk": "~2.0.0-rc.15"
-    }
-    "scripts": {
-        "install": "node-pre-gyp install --fallback-to-build",
-    },
-    "binary": {
-        "module_name": "your_module",
-        "module_path": "./lib/binding/",
-        "host": "https://your_module.s3-us-west-1.amazonaws.com"
-    }
-```
-
-For a full example see [node-addon-examples's package.json](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/package.json#L11-L22).
-
-##### The `binary` object has three required properties
-
-###### module_name
-
-The name of your native node module. This value must:
-
- - Match the name passed to [the NODE_MODULE macro](http://nodejs.org/api/addons.html#addons_hello_world)
- - Must be a valid C variable name (e.g. it cannot contain `-`)
- - Should not include the `.node` extension.
-
-###### module_path
-
-The location your native module is placed after a build. This should be an empty directory without other javascript files. This entire directory will be packaged in the binary tarball. When installing from a remote package this directory will be overwritten with the contents of the tarball.
-
-Note: This property supports variables based on [Versioning](#versioning).
-
-###### host
-
-A url to the remote location where you've published tarball binaries (must be `https` not `http`).
-
-It is highly recommended that you use Amazon S3. The reasons are:
-
-  - Various node-pre-gyp commands like `publish` and `info` only work with an S3 host.
-  - S3 is a very solid hosting platform for distributing large files, even [Github recommends using it instead of github](https://help.github.com/articles/distributing-large-binaries).
-  - We provide detail documentation for using [S3 hosting](#s3-hosting) with node-pre-gyp.
-
-Why then not require S3? Because while some applications using node-pre-gyp need to distribute binaries as large as 20-30 MB, others might have very small binaries and might wish to store them in a github repo. This is not recommended, but if an author really wants to host in a non-s3 location then it should be possible.
-
-##### The `binary` object has two optional properties
-
-###### remote_path
-
-It **is recommended** that you customize this property. This is an extra path to use for publishing and finding remote tarballs. The default value for `remote_path` is `""` meaning that if you do not provide it then all packages will be published at the base of the `host`. It is recommended to provide a value like `./{name}/v{version}` to help organize remote packages in the case that you choose to publish multiple node addons to the same `host`.
-
-Note: This property supports variables based on [Versioning](#versioning).
-
-###### package_name
-
-It is **not recommended** to override this property unless you are also overriding the `remote_path`. This is the versioned name of the remote tarball containing the binary `.node` module and any supporting files you've placed inside the `module_path` directory. Unless you specify `package_name` in your `package.json` then it defaults to `{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz` which allows your binary to work across node versions, platforms, and architectures. If you are using `remote_path` that is also versioned by `./{module_name}/v{version}` then you could remove these variables from the `package_name` and just use: `{node_abi}-{platform}-{arch}.tar.gz`. Then your remote tarball will be looked up at, for example, `https://example.com/your-module/v0.1.0/node-v11-linux-x64.tar.gz`.
-
-Note: This property supports variables based on [Versioning](#versioning).
-
-#### 2) Add a new target to binding.gyp
-
-`node-pre-gyp` calls out to `node-gyp` to compile the module and passes variables along like [module_name](#module_name) and [module_path](#module_path).
-
-A new target must be added to `binding.gyp` that moves the compiled `.node` module from `./build/Release/module_name.node` into the directory specified by `module_path`.
-
-Add a target like this at the end of your `targets` list:
-
-```js
-    {
-      "target_name": "action_after_build",
-      "type": "none",
-      "dependencies": [ "<(module_name)" ],
-      "copies": [
-        {
-          "files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
-          "destination": "<(module_path)"
-        }
-      ]
-    }
-```
-
-For a full example see [node-addon-example's binding.gyp](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/binding.gyp).
-
-#### 3) Dynamically require your `.node`
-
-Inside the main js file that requires your addon module you are likely currently doing:
-
-```js
-var binding = require('../build/Release/binding.node');
-```
-
-or:
-
-```js
-var bindings = require('./bindings')
-```
-
-Change those lines to:
-
-```js
-var binary = require('node-pre-gyp');
-var path = require('path');
-var binding_path = binary.find(path.resolve(path.join(__dirname,'./package.json')));
-var binding = require(binding_path);
-```
-
-For a full example see [node-addon-example's index.js](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/index.js#L1-L4)
-
-#### 4) Build and package your app
-
-Now build your module from source:
-
-    npm install --build-from-source
-
-The `--build-from-source` tells `node-pre-gyp` to not look for a remote package and instead dispatch to node-gyp to build.
-
-Now `node-pre-gyp` should now also be installed as a local dependency so the command line tool it offers can be found at `./node_modules/.bin/node-pre-gyp`.
-
-#### 5) Test
-
-Now `npm test` should work just as it did before.
-
-#### 6) Publish the tarball
-
-Then package your app:
-
-    ./node_modules/.bin/node-pre-gyp package
-
-Once packaged, now you can publish:
-
-    ./node_modules/.bin/node-pre-gyp publish
-
-Currently the `publish` command pushes your binary to S3. This requires:
-
- - You have installed `aws-sdk` with `npm install aws-sdk`
- - You have created a bucket already.
- - The `host` points to an S3 http or https endpoint.
- - You have configured node-pre-gyp to read your S3 credentials (see [S3 hosting](#s3-hosting) for details).
-
-You can also host your binaries elsewhere. To do this requires:
-
- - You manually publish the binary created by the `package` command to an `https` endpoint
- - Ensure that the `host` value points to your custom `https` endpoint.
-
-#### 7) Automate builds
-
-Now you need to publish builds for all the platforms and node versions you wish to support. This is best automated. See [Travis Automation](#travis-automation) for how to auto-publish builds on OS X and Linux. On windows consider using a script [like this](https://github.com/mapbox/node-sqlite3/blob/master/scripts/build.bat) to quickly create and publish binaries and check out <https://appveyor.com>.
-
-#### 8) You're done!
-
-Now publish your package to the npm registry. Users will now be able to install your module from a binary. 
-
-What will happen is this:
-
-1. `npm install <your package>` will pull from the npm registry
-2. npm will run the `install` script which will call out to `node-pre-gyp`
-3. `node-pre-gyp` will fetch the binary `.node` module and unpack in the right place
-4. Assuming that all worked, you are done
-
-If a a binary was not available for a given platform and `--fallback-to-build` was used then `node-gyp rebuild` will be called to try to source compile the module.
-
-## S3 Hosting
-
-You can host wherever you choose but S3 is cheap, `node-pre-gyp publish` expects it, and S3 can be integrated well with [travis.ci](http://travis-ci.org) to automate builds for OS X and Ubuntu. Here is an approach to do this:
-
-First, get setup locally and test the workflow:
-
-#### 1) Create an S3 bucket
-
-And have your **key** and **secret key** ready for writing to the bucket.
-
-It is recommended to create a IAM user with a policy that only gives permissions to the specific bucket you plan to publish to. This can be done in the [IAM console](https://console.aws.amazon.com/iam/) by: 1) adding a new user, 2) choosing `Attach User Policy`, 3) Using the `Policy Generator`, 4) selecting `Amazon S3` for the service, 5) adding the actions: `DeleteObject`, `GetObject`, `GetObjectAcl`, `ListBucket`, `PutObject`, `PutObjectAcl`, 6) adding an ARN of `arn:aws:s3:::bucket/*` (replacing `bucket` with your bucket name), and finally 7) clicking `Add Statement` and saving the policy. It should generate a policy like:
-
-```js
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Sid": "Stmt1394587197000",
-      "Effect": "Allow",
-      "Action": [
-        "s3:DeleteObject",
-        "s3:GetObject",
-        "s3:GetObjectAcl",
-        "s3:ListBucket",
-        "s3:PutObject",
-        "s3:PutObjectAcl"
-      ],
-      "Resource": [
-        "arn:aws:s3:::node-pre-gyp-tests/*"
-      ]
-    }
-  ]
-}
-```
-
-#### 2) Install node-pre-gyp
-
-Either install it globally:
-
-    npm install node-pre-gyp -g
-
-Or put the local version on your PATH
-
-    export PATH=`pwd`/node_modules/.bin/:$PATH
-
-#### 3) Configure AWS credentials
-
-There are several ways to do this.
-
-You can use any of the methods described at http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html.
-
-Or you can create a `~/.node_pre_gyprc`
-
-Or pass options in any way supported by [RC](https://github.com/dominictarr/rc#standards)
-
-A `~/.node_pre_gyprc` looks like:
-
-```js
-{
-    "accessKeyId": "xxx",
-    "secretAccessKey": "xxx"
-}
-```
-
-Another way is to use your environment:
-
-    export node_pre_gyp_accessKeyId=xxx
-    export node_pre_gyp_secretAccessKey=xxx
-
-You may also need to specify the `region` if it is not explicit in the `host` value you use. The `bucket` can also be specified but it is optional because `node-pre-gyp` will detect it from the `host` value.
-
-#### 4) Package and publish your build
-
-Install the `aws-sdk`:
-
-    npm install aws-sdk
-
-Then publish:
-
-    node-pre-gyp package publish
-
-Note: if you hit an error like `Hostname/IP doesn't match certificate's altnames` it may mean that you need to provide the `region` option in your config.
-
-
-## Travis Automation
-
-Travis can push to S3 after a successful build and supports both:
-
- - Ubuntu Precise and OS X
- - Multiple Node.js versions
-
-This enables you to cheaply auto-build and auto-publish binaries for (likely) the majority of your users.
-
-For an example of doing this see [node-add-example's .travis.yml](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/.travis.yml).
-
-Below is a guide to getting set up:
-
-#### 1) Install the travis gem
-
-    gem install travis
-
-#### 2) Create secure `global` variables
-
-Make sure you run this command from within the directory of your module.
-
-Use `travis-encrypt` like:
-
-    travis encrypt node_pre_gyp_accessKeyId=${node_pre_gyp_accessKeyId}
-    travis encrypt node_pre_gyp_secretAccessKey=${node_pre_gyp_secretAccessKey}
-
-Then put those values in your `.travis.yml` like:
-
-```yaml
-env:
-  global:
-    - secure: F+sEL/v56CzHqmCSSES4pEyC9NeQlkoR0Gs/ZuZxX1ytrj8SKtp3MKqBj7zhIclSdXBz4Ev966Da5ctmcTd410p0b240MV6BVOkLUtkjZJyErMBOkeb8n8yVfSoeMx8RiIhBmIvEn+rlQq+bSFis61/JkE9rxsjkGRZi14hHr4M=
-    - secure: o2nkUQIiABD139XS6L8pxq3XO5gch27hvm/gOdV+dzNKc/s2KomVPWcOyXNxtJGhtecAkABzaW8KHDDi5QL1kNEFx6BxFVMLO8rjFPsMVaBG9Ks6JiDQkkmrGNcnVdxI/6EKTLHTH5WLsz8+J7caDBzvKbEfTux5EamEhxIWgrI=
-```
-
-More details on travis encryption at http://about.travis-ci.org/docs/user/encryption-keys/.
-
-#### 3) Hook up publishing
-
-Just put `node-pre-gyp package publish` in your `.travis.yml` after `npm install`.
-
-If you want binaries for OS X change your `.travis.yml` to use:
-
-```yml
-language: objective-c
-```
-
-Keep that change in a different git branch and sync that when you want binaries published. This little hack will hopefully become obsolete when [travis adds proper support for different operating systems](https://github.com/travis-ci/travis-ci/issues/216).
-
-Note: using `language: objective-c` instead of `language: nodejs` looses node.js specific travis sugar like a matrix for multiple node.js versions.
-
-But you can replicate the lost behavior by replacing:
-
-```yml
-node_js:
-  - "0.8"
-  - "0.10"
-```
-
-With:
-
-```yml
-env:
-  matrix:
-    - export NODE_VERSION="0.8"
-    - export NODE_VERSION="0.10"
-
-before_install:
- - git clone https://github.com/creationix/nvm.git ./.nvm
- - source ./.nvm/nvm.sh
- - nvm install $NODE_VERSION
- - nvm use $NODE_VERSION
-```
-
-#### 4) Publish when you want
-
-You might wish to publish binaries only on a specific commit. To do this you could borrow from the [travis.ci idea of commit keywords](http://about.travis-ci.org/docs/user/how-to-skip-a-build/) and add special handling for commit messages with `[publish binary]`:
-
-    COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
-    if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then node-pre-gyp publish; fi;
-
-Or you could automatically detect if the git branch is a tag:
-
-    if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]] ; then node-pre-gyp publish; fi
-
-Remember this publishing is not the same as `npm publish`. We're just talking about the
-binary module here and not your entire npm package. To automate the publishing of your entire package to npm on travis see http://about.travis-ci.org/docs/user/deployment/npm/
-
-# Versioning
-
-The `binary` properties of `module_path`, `remote_path`, and `package_name` support variable substitution. The strings are evaluated by `node-pre-gyp` depending on your system and any custom build flags you passed.
-
- - `configuration` - Either 'Release' or 'Debug' depending on if `--debug` is passed during the build.
- - `module_name` - the `binary.module_name` attribute from `package.json`.
- - `version` - the semver `version` value for your module from `package.json`.
- - `major`, `minor`, `patch`, and `prelease` match the individual semver values for your module's `version`
- - `node_abi`: The node C++ `ABI` number. This value is available in javascript as `process.versions.modules` as of [`>= v0.10.4 >= v0.11.7`](https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e) and in C++ as the `NODE_MODULE_VERSION` define much earlier. For versions of Node before this was available we fallback to the V8 major and minor version.
- - `platform` matches node's `process.platform` like `linux`, `darwin`, and `win32` unless the user passed the `--target_platform` option to override.
- - `arch` matches node's `process.arch` like `x64` or `ia32` unless the user passes the `--target_arch` option to override.
-
-
-The options are visible in the code at <https://github.com/mapbox/node-pre-gyp/blob/612b7bca2604508d881e1187614870ba19a7f0c5/lib/util/versioning.js#L114-L127>
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/appveyor.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/appveyor.yml
deleted file mode 100644
index 22ebf67c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/appveyor.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-environment:
-  matrix:
-    - nodejs_version: 0.8
-    - nodejs_version: 0.10
-
-platform:
-  - x64
-  - x86
-
-install:
-  - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) $env:Platform
-  - node --version
-  - npm --version
-  - node -e "console.log('node version ' + process.version + ', architecture ' + process.arch);"
-  # ensure python is on path so that srs_settings.js are generated
-  - cmd: SET PATH=c:\python27;%PATH%
-  - npm install
-  - cmd: test.bat
-
-build: OFF
-
-test: OFF
-
-test_script: OFF
-
-deploy: OFF
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp
deleted file mode 100755
index d68d18bb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Set the title.
- */
-
-process.title = 'node-pre-gyp'
-
-/**
- * Module dependencies.
- */
-
-var node_pre_gyp = require('../')
-var log = require('npmlog')
-
-/**
- * Process and execute the selected commands.
- */
-
-var prog = new node_pre_gyp.Run()
-var completed = false
-prog.parseArgv(process.argv)
-
-if (prog.todo.length === 0) {
-  if (~process.argv.indexOf('-v') || ~process.argv.indexOf('--version')) {
-    console.log('v%s', prog.version)
-  } else {
-    console.log('%s', prog.usage())
-  }
-  return process.exit(0)
-}
-
-// if --no-color is passed
-if (prog.opts && prog.opts.hasOwnProperty('color') && !prog.opts.color) {
-  log.disableColor();
-}
-
-log.info('it worked if it ends with', 'ok')
-log.verbose('cli', process.argv)
-log.info('using', process.title + '@%s', prog.version)
-log.info('using', 'node@%s | %s | %s', process.versions.node, process.platform, process.arch)
-
-
-/**
- * Change dir if -C/--directory was passed.
- */
-
-var dir = prog.opts.directory
-if (dir) {
-  var fs = require('fs')
-  try {
-    var stat = fs.statSync(dir)
-    if (stat.isDirectory()) {
-      log.info('chdir', dir)
-      process.chdir(dir)
-    } else {
-      log.warn('chdir', dir + ' is not a directory')
-    }
-  } catch (e) {
-    if (e.code === 'ENOENT') {
-      log.warn('chdir', dir + ' is not a directory')
-    } else {
-      log.warn('chdir', 'error during chdir() "%s"', e.message)
-    }
-  }
-}
-
-function run () {
-  var command = prog.todo.shift()
-  if (!command) {
-    // done!
-    completed = true
-    log.info('ok')
-    return
-  }
-
-  prog.commands[command.name](command.args, function (err) {
-    if (err) {
-      log.error(command.name + ' error')
-      log.error('stack', err.stack)
-      errorMessage()
-      log.error('not ok')
-      console.log(err.message);
-      return process.exit(1)
-    }
-    var args_array = [].slice.call(arguments, 1)
-    if (args_array.length) {
-      console.log.apply(console, args_array)
-    }
-    // now run the next command in the queue
-    process.nextTick(run)
-  })
-}
-
-process.on('exit', function (code) {
-  if (!completed && !code) {
-    log.error('Completion callback never invoked!')
-    issueMessage()
-    process.exit(6)
-  }
-})
-
-process.on('uncaughtException', function (err) {
-  log.error('UNCAUGHT EXCEPTION')
-  log.error('stack', err.stack)
-  issueMessage()
-  process.exit(7)
-})
-
-function errorMessage () {
-  // copied from npm's lib/util/error-handler.js
-  var os = require('os')
-  log.error('System', os.type() + ' ' + os.release())
-  log.error('command', process.argv
-            .map(JSON.stringify).join(' '))
-  log.error('cwd', process.cwd())
-  log.error('node -v', process.version)
-  log.error(process.title+' -v', 'v' + prog.package.version)
-}
-
-function issueMessage () {
-  errorMessage()
-  log.error('', [ 'This is a bug in `'+process.title+'`.'
-                , 'Try to update '+process.title+' and file an issue if it does not help:'
-                , '    <https://github.com/mapbox/'+process.title+'/issues>'
-                ].join('\n'))
-}
-
-// start running the given commands!
-run()
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp.cmd b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp.cmd
deleted file mode 100644
index 77655295..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/bin/node-pre-gyp.cmd
+++ /dev/null
@@ -1 +0,0 @@
-node  "%~dp0\node-pre-gyp" %*
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/build.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/build.js
deleted file mode 100644
index ba81b4d0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/build.js
+++ /dev/null
@@ -1,52 +0,0 @@
-
-module.exports = exports = build
-
-exports.usage = 'Attempts to compile the module by dispatching to node-gyp or nw-gyp'
-
-var fs = require('fs')
-  , compile = require('./util/compile.js')
-  , versioning = require('./util/versioning.js')
-  , path = require('path')
-  , fs = require('fs')
-  , mkdirp = require('mkdirp')
-
-function build(gyp, argv, callback) {
-    var gyp_args = [];
-    if (argv.length && argv[0] == 'rebuild') {
-        gyp_args.push('rebuild');
-    } else {
-        gyp_args.push('configure');
-        gyp_args.push('build');
-    }
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    // options look different depending on whether node-pre-gyp is called directly
-    // or whether it is called from npm install, hence the following line.
-    // TODO: check if this is really necessary with latest npm/nopt versions
-    var original_args = (typeof(gyp.opts.argv.original) === 'string') ? JSON.parse(gyp.opts.argv).original : gyp.opts.argv.original || [];
-    // add command line options to existing opts
-    original_args.forEach(function(opt) {
-        // we ignore any args like 'install' since we know
-        // we are either running 'build' or 'rebuild' but we
-        // do want to pass along to node-gyp/nw-gyp any command
-        // line options like --option or --option=value passed in
-        if (opt.length > 2 && opt.slice(0,2) == '--') {
-            var parts = opt.split('=');
-            if (parts.length > 1) {
-                var key = parts[0];
-                opts[key.slice(2)] = parts[1];
-            }
-        }
-    })
-    var command_line_args = [];
-    // turn back into command line options
-    Object.keys(opts).forEach(function(o) {
-        var val = opts[o];
-        if (val) {
-            command_line_args.push('--' + o + '=' + val);
-        }
-    })
-    compile.run_gyp(gyp_args.concat(command_line_args),opts,function(err,gopts) {
-        return callback(err);
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/clean.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/clean.js
deleted file mode 100644
index a717e9c8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/clean.js
+++ /dev/null
@@ -1,24 +0,0 @@
-
-module.exports = exports = clean
-
-exports.usage = 'Removes the entire folder containing the compiled .node module'
-
-var fs = require('fs')
-  , rm = require('rimraf')
-  , path = require('path')
-  , exists = require('fs').exists || require('path').exists
-  , log = require('npmlog')
-  , versioning = require('./util/versioning.js')
-
-function clean (gyp, argv, callback) {
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    var to_delete = opts.module_path;
-    exists(to_delete, function(found) {
-        if (found) {
-            if (!gyp.opts.silent_clean) console.log('['+package_json.name+'] Removing "%s"', to_delete);
-            return rm(to_delete, callback);
-        }
-        return callback();
-    })
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/info.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/info.js
deleted file mode 100644
index 5a54d41d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/info.js
+++ /dev/null
@@ -1,40 +0,0 @@
-
-module.exports = exports = unpublish
-
-exports.usage = 'Lists all published binaries (requires aws-sdk)'
-
-var fs = require('fs')
-  , path = require('path')
-  , log = require('npmlog')
-  , versioning = require('./util/versioning.js')
-  , s3_setup = require('./util/s3_setup.js')
-  , config = require('rc')("node_pre_gyp",{acl:"public-read"});
-
-function unpublish(gyp, argv, callback) {
-    var AWS = require("aws-sdk");
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    s3_setup.detect(opts.hosted_path,config);
-    AWS.config.update(config);
-    var s3 =  new AWS.S3();
-    var s3_opts = {  Bucket: config.bucket,
-                     Prefix: config.prefix
-                  };
-    s3.listObjects(s3_opts, function(err, meta){
-        if (err && err.code == 'NotFound') {
-            return callback(new Error('['+package_json.name+'] Not found: https://' + s3_opts.Bucket + '.s3.amazonaws.com/'+config.prefix));
-        } else if(err) {
-            return callback(err);
-        } else {
-            log.verbose(JSON.stringify(meta,null,1));
-            if (meta && meta.Contents) {
-                meta.Contents.forEach(function(obj) {
-                    console.log(obj.Key);
-                });
-            } else {
-                console.error('['+package_json.name+'] No objects found at https://' + s3_opts.Bucket + '.s3.amazonaws.com/'+config.prefix )
-            }
-            return callback();
-        }
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/install.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/install.js
deleted file mode 100644
index 516c59d7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/install.js
+++ /dev/null
@@ -1,198 +0,0 @@
-
-module.exports = exports = install
-
-exports.usage = 'Attempts to install pre-built binary for module'
-
-var fs = require('fs')
-  , tar = require('tar')
-  , path = require('path')
-  , zlib = require('zlib')
-  , log = require('npmlog')
-  , request = require('request')
-  , existsAsync = fs.exists || path.exists
-  , versioning = require('./util/versioning.js')
-  , compile = require('./util/compile.js')
-  , testbinary = require('./testbinary.js')
-  , clean = require('./clean.js')
-
-function download(uri,opts,callback) {
-    log.http('GET', uri)
-
-    var req = null
-    var requestOpts = {
-        uri: uri
-      , headers: {
-          'User-Agent': 'node-pre-gyp (node ' + process.version + ')'
-        }
-    }
-
-    var proxyUrl = opts.proxy
-                || process.env.http_proxy
-                || process.env.HTTP_PROXY
-                || process.env.npm_config_proxy
-    if (proxyUrl) {
-      if (/^https?:\/\//i.test(proxyUrl)) {
-        log.verbose('download', 'using proxy url: "%s"', proxyUrl)
-        requestOpts.proxy = proxyUrl
-      } else {
-        log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
-      }
-    }
-    try {
-      req = request(requestOpts)
-    } catch (e) {
-      return callback(e)
-    }
-    if (req) {
-      req.on('response', function (res) {
-        log.http(res.statusCode, uri)
-      })
-    }
-    return callback(null,req);
-}
-
-function place_binary(from,to,opts,callback) {
-    download(from,opts,function(err,req) {
-        if (err) return callback(err);
-        if (!req) return callback(new Error("empty req"));
-        var badDownload = false
-            , extractCount = 0
-            , gunzip = zlib.createGunzip()
-            , extracter = tar.Extract({ path: to, strip: 1});
-        function afterTarball(err) {
-            if (err) return callback(err);
-            if (badDownload) return callback(new Error("bad download"));
-            if (extractCount === 0) {
-              return callback(new Error('There was a fatal problem while downloading/extracting the tarball'))
-            }
-            log.info('tarball', 'done parsing tarball')
-            callback();
-        }
-        function filter_func(entry) {
-            // ensure directories are +x
-            // https://github.com/mapnik/node-mapnik/issues/262
-            entry.props.mode |= (entry.props.mode >>> 2) & 0111;
-            log.info('install','unpacking ' + entry.path);
-            extractCount++
-        }
-        gunzip.on('error', callback)
-        extracter.on('entry', filter_func)
-        extracter.on('error', callback)
-        extracter.on('end', afterTarball)
-
-        req.on('error', function (err) {
-            badDownload = true
-            callback(err)
-        })
-
-        req.on('close', function () {
-            if (extractCount === 0) {
-              callback(new Error('Connection closed while downloading tarball file'))
-            }
-        })
-
-        req.on('response', function (res) {
-            if (res.statusCode !== 200) {
-              badDownload = true
-              if (res.statusCode == 404) {
-                  return callback(new Error('Pre-built binary not available for your system'));
-              } else {
-                  return callback(new Error(res.statusCode + ' status code downloading tarball'));
-              }
-            }
-            // start unzipping and untaring
-            req.pipe(gunzip).pipe(extracter)
-        })
-    });
-}
-
-function do_build(gyp,argv,callback) {
-  gyp.todo.push( { name: 'build', args: ['rebuild'] } );
-  process.nextTick(callback);
-}
-
-function install(gyp, argv, callback) {
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var source_build = gyp.opts['build-from-source'] || gyp.opts['build_from_source'];
-    var should_do_source_build = source_build === package_json.name || (source_build === true || source_build === 'true');
-    if (should_do_source_build) {
-        log.info('build','requesting source compile');
-        return do_build(gyp,argv,callback);
-    } else {
-        var fallback_to_build = gyp.opts['fallback-to-build'] || gyp.opts['fallback_to_build'];
-        var should_do_fallback_build = fallback_to_build === package_json.name || (fallback_to_build === true || fallback_to_build === 'true');
-        // but allow override from npm
-        if (process.env.npm_config_argv) {
-            var cooked = JSON.parse(process.env.npm_config_argv).cooked;
-            var match = cooked.indexOf("--fallback-to-build");
-            if (match > -1 && cooked.length > match && cooked[match+1] == "false") {
-                should_do_fallback_build = false;
-                log.info('install','Build fallback disabled via npm flag: --fallback-to-build=false');
-            }
-        }
-        try {
-            var opts = versioning.evaluate(package_json, gyp.opts);
-        } catch (err) {
-            return callback(err);
-        }
-        var from = opts.hosted_tarball;
-        var to = opts.module_path;
-        var binary_module = path.join(to,opts.module_name + '.node');
-        if (existsAsync(binary_module,function(found) {
-            if (found) {
-                testbinary(gyp, argv, function(err) {
-                    if (err) {
-                        console.error('['+package_json.name+'] ' + err.message);
-                        log.error("Testing local pre-built binary failed, attempting to re-download");
-                        place_binary(from,to,opts,function(err) {
-                            if (err) {
-                                if (should_do_fallback_build) {
-                                    log.http(err.message + ' (falling back to source compile with node-gyp)');
-                                    return do_build(gyp,argv,callback);
-                                } else {
-                                    return callback(err);
-                                }
-                            } else {
-                                console.log('['+package_json.name+'] Success: "' + binary_module + '" is reinstalled via remote');
-                                return callback();
-                            }
-                        });
-                    } else {
-                        console.log('['+package_json.name+'] Success: "' + binary_module + '" already installed');
-                        console.log('Run pass --build-from-source to compile');
-                        return callback();
-                    }
-                });
-            } else {
-                log.info('check','checked for "' + binary_module + '" (not found)')
-                place_binary(from,to,opts,function(err) {
-                    if (err && should_do_fallback_build) {
-                        log.http(err.message + ' (falling back to source compile with node-gyp)');
-                        return do_build(gyp,argv,callback);
-                    } else if (err) {
-                        return callback(err);
-                    } else {
-                        testbinary(gyp, argv, function(err) {
-                            if (err) {
-                                gyp.opts.silent_clean = true;
-                                clean(gyp, argv, function(error) {
-                                    if (error) console.log(error);
-                                    if (should_do_fallback_build) {
-                                        console.error('['+package_json.name+'] ' + err.message);
-                                        log.error("Testing pre-built binary failed, attempting to source compile");
-                                        return do_build(gyp,argv,callback);
-                                    } else {
-                                        return callback(err);
-                                    }
-                                });
-                            } else {
-                                console.log('['+package_json.name+'] Success: "' + binary_module + '" is installed via remote');
-                                return callback();
-                            }
-                        });
-                    };
-                });
-            }
-        }));
-    }
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/node-pre-gyp.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/node-pre-gyp.js
deleted file mode 100644
index 3865a695..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/node-pre-gyp.js
+++ /dev/null
@@ -1,192 +0,0 @@
-
-/**
- * Module exports.
- */
-
-module.exports = exports;
-
-/**
- * Module dependencies.
- */
-
-var fs = require('fs')
-  , path = require('path')
-  , nopt = require('nopt')
-  , log = require('npmlog')
-  , child_process = require('child_process')
-  , EE = require('events').EventEmitter
-  , inherits = require('util').inherits
-  , commands = [
-      'clean',
-      'install',
-      'reinstall',
-      'build',
-      'rebuild',
-      'package',
-      'testpackage',
-      'publish',
-      'unpublish',
-      'info',
-      'testbinary'
-    ]
-  , aliases = {
-    }
-
-// differentiate node-pre-gyp's logs from npm's
-log.heading = 'node-pre-gyp'
-
-exports.find = require('./pre-binding').find;
-
-function Run() {
-  var self = this
-
-  this.commands = {}
-
-  commands.forEach(function (command) {
-    self.commands[command] = function (argv, callback) {
-      log.verbose('command', command, argv)
-      return require('./' + command)(self, argv, callback)
-    }
-  })
-}
-inherits(Run, EE)
-exports.Run = Run
-var proto = Run.prototype
-
-/**
- * Export the contents of the package.json.
- */
-
-proto.package = require('../package')
-
-/**
- * nopt configuration definitions
- */
-
-proto.configDefs = {
-    help: Boolean     // everywhere
-  , arch: String      // 'configure'
-  , debug: Boolean    // 'build'
-  , directory: String // bin
-  , proxy: String     // 'install'
-  , loglevel: String  // everywhere
-}
-
-/**
- * nopt shorthands
- */
-
-proto.shorthands = {
-    release: '--no-debug'
-  , C: '--directory'
-  , debug: '--debug'
-  , j: '--jobs'
-  , silly: '--loglevel=silly'
-  , verbose: '--loglevel=verbose'
-}
-
-/**
- * expose the command aliases for the bin file to use.
- */
-
-proto.aliases = aliases
-
-/**
- * Parses the given argv array and sets the 'opts',
- * 'argv' and 'command' properties.
- */
-
-proto.parseArgv = function parseOpts (argv) {
-  this.opts = nopt(this.configDefs, this.shorthands, argv)
-  this.argv = this.opts.argv.remain.slice()
-
-  var commands = this.todo = []
-
-  // create a copy of the argv array with aliases mapped
-  argv = this.argv.map(function (arg) {
-    // is this an alias?
-    if (arg in this.aliases) {
-      arg = this.aliases[arg]
-    }
-    return arg
-  }, this)
-
-  // process the mapped args into "command" objects ("name" and "args" props)
-  argv.slice().forEach(function (arg) {
-    if (arg in this.commands) {
-      var args = argv.splice(0, argv.indexOf(arg))
-      argv.shift()
-      if (commands.length > 0) {
-        commands[commands.length - 1].args = args
-      }
-      commands.push({ name: arg, args: [] })
-    }
-  }, this)
-  if (commands.length > 0) {
-    commands[commands.length - 1].args = argv.splice(0)
-  }
-
-  // support for inheriting config env variables from npm
-  var npm_config_prefix = 'npm_config_'
-  Object.keys(process.env).forEach(function (name) {
-    if (name.indexOf(npm_config_prefix) !== 0) return
-    var val = process.env[name]
-    if (name === npm_config_prefix + 'loglevel') {
-      log.level = val
-    } else {
-      // add the user-defined options to the config
-      name = name.substring(npm_config_prefix.length)
-      // avoid npm argv clobber already present args
-      // which avoids problem of 'npm test' calling
-      // script that runs unique npm install commands
-      if (name === 'argv') {
-         if (this.opts.argv &&
-             this.opts.argv.remain &&
-             this.opts.argv.remain.length) {
-            // do nothing
-         } else {
-            this.opts[name] = val
-         }
-      } else {
-        this.opts[name] = val
-      }
-    }
-  }, this)
-
-  if (this.opts.loglevel) {
-    log.level = this.opts.loglevel
-  }
-  log.resume()
-}
-
-/**
- * Returns the usage instructions for node-pre-gyp.
- */
-
-proto.usage = function usage () {
-  var str = [
-      ''
-    , '  Usage: node-pre-gyp <command> [options]'
-    , ''
-    , '  where <command> is one of:'
-    , commands.map(function (c) {
-        return '    - ' + c + ' - ' + require('./' + c).usage
-      }).join('\n')
-    , ''
-    , 'node-pre-gyp@' + this.version + '  ' + path.resolve(__dirname, '..')
-    , 'node@' + process.versions.node
-  ].join('\n')
-  return str
-}
-
-/**
- * Version number getter.
- */
-
-Object.defineProperty(proto, 'version', {
-    get: function () {
-      return this.package.version
-    }
-  , enumerable: true
-})
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/package.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/package.js
deleted file mode 100644
index b01cb951..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/package.js
+++ /dev/null
@@ -1,46 +0,0 @@
-
-module.exports = exports = package
-
-exports.usage = 'Packs binary (and enclosing directory) into locally staged tarball'
-
-var fs = require('fs')
-  , path = require('path')
-  , log = require('npmlog')
-  , versioning = require('./util/versioning.js')
-  , compile = require('./util/compile.js')
-  , write = require('fs').createWriteStream
-  , pack = require('tar-pack').pack
-  , existsAsync = fs.exists || path.exists
-  , mkdirp = require('mkdirp');
-
-function package(gyp, argv, callback) {
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    var from = opts.module_path;
-    var binary_module = path.join(from,opts.module_name + '.node');
-    existsAsync(binary_module,function(found) {
-        if (!found) {
-            return callback(new Error("Cannot package because " + binary_module + " missing: run `node-pre-gyp rebuild` first"))
-        }
-        var tarball = opts.staged_tarball;
-        var basedir = path.basename(from);
-        var filter_func = function (entry) {
-            // ensure directories are +x
-            // https://github.com/mapnik/node-mapnik/issues/262
-            log.info('package','packing ' + entry.path);
-            return true;
-        }
-        mkdirp(path.dirname(tarball),function(err) {
-            pack(from, { filter: filter_func })
-             .pipe(write(tarball))
-             .on('error', function (err) {
-                if (err)  console.error('['+package_json.name+'] ' + err.message);
-                return callback(err);
-             })
-             .on('close', function () {
-                log.info('package','Binary staged at "' + tarball + '"');
-                return callback();
-             })
-        });
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/pre-binding.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/pre-binding.js
deleted file mode 100644
index 60d60d5f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/pre-binding.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var fs = require('fs');
-var versioning = require('../lib/util/versioning.js')
-var existsSync = require('fs').existsSync || require('path').existsSync;
-var path = require('path');
-
-module.exports = exports;
-
-exports.usage = 'Finds the require path for the node-pre-gyp installed module'
-
-exports.validate = function(package_json) {
-    versioning.validate_config(package_json);
-}
-
-exports.find = function(package_json_path,opts) {
-   if (!existsSync(package_json_path)) {
-        throw new Error("package.json does not exist at " + package_json_path);
-   }
-   var package_json = require(package_json_path);
-   versioning.validate_config(package_json);
-   opts = opts || {};
-   if (!opts.module_root) opts.module_root = path.dirname(package_json_path);
-   var meta = versioning.evaluate(package_json,opts);
-   return path.join(meta.module_path,meta.module_name + '.node');
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/publish.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/publish.js
deleted file mode 100644
index 51c6fc3f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/publish.js
+++ /dev/null
@@ -1,58 +0,0 @@
-
-module.exports = exports = publish
-
-exports.usage = 'Publishes pre-built binary (requires aws-sdk)'
-
-var fs = require('fs')
-  , path = require('path')
-  , log = require('npmlog')
-  , versioning = require('./util/versioning.js')
-  , s3_setup = require('./util/s3_setup.js')
-  , mkdirp = require('mkdirp')
-  , existsAsync = fs.exists || path.exists
-  , url = require('url')
-  , config = require('rc')("node_pre_gyp",{acl:"public-read"});
-
-function publish(gyp, argv, callback) {
-    var AWS = require("aws-sdk");
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    var tarball = opts.staged_tarball;
-    existsAsync(tarball,function(found) {
-        if (!found) {
-            return callback(new Error("Cannot publish because " + tarball + " missing: run `node-pre-gyp package` first"))
-        }
-        s3_setup.detect(opts.hosted_path,config);
-        var key_name = url.resolve(config.prefix,opts.package_name)
-        AWS.config.update(config);
-        var s3 =  new AWS.S3();
-        var s3_opts = {  Bucket: config.bucket,
-                         Key: key_name
-                      };
-        s3.headObject(s3_opts, function(err, meta){
-            if (err && err.code == 'NotFound') {
-                // we are safe to publish because
-                // the object does not already exist
-                var s3 =  new AWS.S3();
-                var s3_obj_opts = {  ACL: config.acl,
-                                     Body: fs.createReadStream(tarball),
-                                     Bucket: config.bucket,
-                                     Key: key_name
-                                  };
-                s3.putObject(s3_obj_opts, function(err, resp){
-                    if(err) return callback(err);
-                    console.log('['+package_json.name+'] Success: published to https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key);
-                    return callback();
-                });
-            } else if(err) {
-                return callback(err);
-            } else {
-                log.error('publish','Cannot publish over existing version');
-                log.error('publish',"Update the 'version' field in package.json and try again");
-                log.error('publish','If the previous version was published in error see:');
-                log.error('publish','\t node-pre-gyp unpublish');
-                return callback(new Error('Failed to publish "' + s3_opts.Key + '"'));
-            }
-        });
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/rebuild.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/rebuild.js
deleted file mode 100644
index fe890960..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/rebuild.js
+++ /dev/null
@@ -1,12 +0,0 @@
-
-module.exports = exports = rebuild
-
-exports.usage = 'Runs "clean" and "build" at once'
-
-function rebuild (gyp, argv, callback) {
-  gyp.todo.unshift(
-      { name: 'clean', args: [] }
-    , { name: 'build', args: ['rebuild'] }
-  )
-  process.nextTick(callback)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/reinstall.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/reinstall.js
deleted file mode 100644
index fc156405..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/reinstall.js
+++ /dev/null
@@ -1,12 +0,0 @@
-
-module.exports = exports = rebuild
-
-exports.usage = 'Runs "clean" and "install" at once'
-
-function rebuild (gyp, argv, callback) {
-  gyp.todo.unshift(
-      { name: 'clean', args: [] }
-    , { name: 'install', args: [] }
-  )
-  process.nextTick(callback)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testbinary.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testbinary.js
deleted file mode 100644
index a64a72c4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testbinary.js
+++ /dev/null
@@ -1,72 +0,0 @@
-module.exports = exports = testbinary
-
-exports.usage = 'Tests that the binary.node can be required'
-
-var fs = require('fs')
-  , path = require('path')
-  , log = require('npmlog')
-  , cp = require('child_process')
-  , versioning = require('./util/versioning.js')
-  , path = require('path')
-
-function testbinary(gyp, argv, callback) {
-    var args = [];
-    var options = {}
-    var shell_cmd = process.execPath;
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    var binary_module = path.join(opts.module_path, opts.module_name + '.node');
-    // ensure on windows that / are used for require path
-    binary_module = binary_module.replace(/\\/g, '/');
-    var nw = (opts.runtime && opts.runtime === 'node-webkit'); 
-    if (nw) {
-        options.timeout = 5000;
-        if (process.platform === 'darwin') {
-            shell_cmd = 'node-webkit';
-        } else if (process.platform === 'win32') {
-            shell_cmd = 'nw.exe';
-        } else {
-            shell_cmd = 'nw';
-        }
-        var modulePath = path.resolve(binary_module);
-        var appDir = path.join(__dirname, 'util', 'nw-pre-gyp');
-        args.push(appDir);
-        args.push(modulePath);
-        log.info("validate","Running test command: '" + shell_cmd + ' ' + args.join(' ') + "'");
-        cp.execFile(shell_cmd, args, options, function(err, stdout, stderr) {
-            // check for normal timeout for node-webkit
-            if (err) {
-                if (err.killed == true && err.signal && err.signal.indexOf('SIG') > -1) {
-                    return callback();
-                }
-                var stderrLog = stderr.toString();
-                log.info('stderr', stderrLog);
-                if( /^\s*Xlib:\s*extension\s*"RANDR"\s*missing\s*on\s*display\s*":\d+\.\d+"\.\s*$/.test(stderrLog) ){
-                    log.info('RANDR', 'stderr contains only RANDR error, ignored');
-                    return callback();
-                }
-                return callback(err);
-            }
-            return callback();
-        });
-        return;
-    }
-    if ((process.arch != opts.target_arch) ||
-        (process.platform != opts.target_platform)) {
-        var msg = "skipping validation since host platform/arch (";
-        msg += process.platform+'/'+process.arch+")";
-        msg += " does not match target (";
-        msg += opts.target_platform+'/'+opts.target_arch+")";
-        log.info('validate', msg);
-        return callback();
-    }
-    args.push('--eval');
-    args.push("require('" + binary_module +"')");
-    log.info("validate","Running test command: '" + shell_cmd + ' ' + args.join(' ') + "'");
-    cp.execFile(shell_cmd, args, options, function(err, stdout, stderr) {
-        if (err) {
-            return callback(err);
-        }
-        return callback();
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testpackage.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testpackage.js
deleted file mode 100644
index c15d0676..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/testpackage.js
+++ /dev/null
@@ -1,49 +0,0 @@
-
-module.exports = exports = testpackage
-
-exports.usage = 'Tests that the staged package is valid'
-
-var fs = require('fs')
-  , path = require('path')
-  , log = require('npmlog')
-  , existsAsync = fs.exists || path.exists
-  , versioning = require('./util/versioning.js')
-  , testbinary = require('./testbinary.js')
-  , read = require('fs').createReadStream
-  , tar = require('tar')
-  , zlib = require('zlib')
-
-function testpackage(gyp, argv, callback) {
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    var tarball = opts.staged_tarball;
-    existsAsync(tarball, function(found) {
-        if (!found) {
-            return callback(new Error("Cannot test package because " + tarball + " missing: run `node-pre-gyp package` first"))
-        }
-        var to = opts.module_path;
-        var gunzip = zlib.createGunzip()
-        var extracter = tar.Extract({ path: to, strip: 1 });
-        function filter_func(entry) {
-            // ensure directories are +x
-            // https://github.com/mapnik/node-mapnik/issues/262
-            entry.props.mode |= (entry.props.mode >>> 2) & 0111;
-            log.info('install','unpacking ' + entry.path);
-        }
-        gunzip.on('error', callback)
-        extracter.on('error', callback)
-        extracter.on('entry', filter_func)
-        extracter.on('end', function(err) {
-            if (err) return callback(err);
-            testbinary(gyp,argv,function(err) {
-                if (err) {
-                    return callback(err);
-                } else {
-                    console.log('['+package_json.name+'] Package appears valid');
-                    return callback();
-                }
-            });
-        });
-        read(tarball).pipe(gunzip).pipe(extracter);
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/unpublish.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/unpublish.js
deleted file mode 100644
index 04118e0b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/unpublish.js
+++ /dev/null
@@ -1,41 +0,0 @@
-
-module.exports = exports = unpublish
-
-exports.usage = 'Unpublishes pre-built binary (requires aws-sdk)'
-
-var fs = require('fs')
-  , path = require('path')
-  , log = require('npmlog')
-  , versioning = require('./util/versioning.js')
-  , s3_setup = require('./util/s3_setup.js')
-  , url = require('url')
-  , config = require('rc')("node_pre_gyp",{acl:"public-read"});
-
-function unpublish(gyp, argv, callback) {
-    var AWS = require("aws-sdk");
-    var package_json = JSON.parse(fs.readFileSync('./package.json'));
-    var opts = versioning.evaluate(package_json, gyp.opts);
-    s3_setup.detect(opts.hosted_path,config);
-    AWS.config.update(config);
-    var key_name = url.resolve(config.prefix,opts.package_name)
-    var s3 =  new AWS.S3();
-    var s3_opts = {  Bucket: config.bucket,
-                     Key: key_name
-                  };
-    s3.headObject(s3_opts, function(err, meta) {
-        if (err && err.code == 'NotFound') {
-            console.log('['+package_json.name+'] Not found: https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key);
-            return callback();
-        } else if(err) {
-            return callback(err);
-        } else {
-            log.info(JSON.stringify(meta));
-            s3.deleteObject(s3_opts, function(err, resp) {
-                if (err) return callback(err);
-                log.info(JSON.stringify(resp));
-                console.log('['+package_json.name+'] Success: removed https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key);
-                return callback();
-            })
-        }
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/abi_crosswalk.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/abi_crosswalk.json
deleted file mode 100644
index ebf43a04..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/abi_crosswalk.json
+++ /dev/null
@@ -1,466 +0,0 @@
-{
-  "0.6.3": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.4": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.5": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.6": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.7": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.8": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.9": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.10": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.11": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.12": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.13": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.14": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.15": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.16": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.17": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.18": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.19": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.20": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.6.21": {
-    "node_abi": 1,
-    "v8": "3.6"
-  },
-  "0.7.0": {
-    "node_abi": 1,
-    "v8": "3.8"
-  },
-  "0.7.1": {
-    "node_abi": 1,
-    "v8": "3.8"
-  },
-  "0.7.2": {
-    "node_abi": 1,
-    "v8": "3.8"
-  },
-  "0.7.3": {
-    "node_abi": 1,
-    "v8": "3.9"
-  },
-  "0.7.4": {
-    "node_abi": 1,
-    "v8": "3.9"
-  },
-  "0.7.5": {
-    "node_abi": 1,
-    "v8": "3.9"
-  },
-  "0.7.6": {
-    "node_abi": 1,
-    "v8": "3.9"
-  },
-  "0.7.7": {
-    "node_abi": 1,
-    "v8": "3.9"
-  },
-  "0.7.8": {
-    "node_abi": 1,
-    "v8": "3.9"
-  },
-  "0.7.9": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.7.10": {
-    "node_abi": 1,
-    "v8": "3.9"
-  },
-  "0.7.11": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.7.12": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.0": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.1": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.2": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.3": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.4": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.5": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.6": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.7": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.8": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.9": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.10": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.11": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.12": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.13": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.14": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.15": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.16": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.17": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.18": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.19": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.20": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.21": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.22": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.23": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.24": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.25": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.8.26": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.9.0": {
-    "node_abi": 1,
-    "v8": "3.11"
-  },
-  "0.9.1": {
-    "node_abi": 10,
-    "v8": "3.11"
-  },
-  "0.9.2": {
-    "node_abi": 10,
-    "v8": "3.11"
-  },
-  "0.9.3": {
-    "node_abi": 10,
-    "v8": "3.13"
-  },
-  "0.9.4": {
-    "node_abi": 10,
-    "v8": "3.13"
-  },
-  "0.9.5": {
-    "node_abi": 10,
-    "v8": "3.13"
-  },
-  "0.9.6": {
-    "node_abi": 10,
-    "v8": "3.15"
-  },
-  "0.9.7": {
-    "node_abi": 10,
-    "v8": "3.15"
-  },
-  "0.9.8": {
-    "node_abi": 10,
-    "v8": "3.15"
-  },
-  "0.9.9": {
-    "node_abi": 11,
-    "v8": "3.15"
-  },
-  "0.9.10": {
-    "node_abi": 11,
-    "v8": "3.15"
-  },
-  "0.9.11": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.9.12": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.0": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.1": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.2": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.3": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.4": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.5": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.6": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.7": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.8": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.9": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.10": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.11": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.12": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.13": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.14": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.15": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.16": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.17": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.18": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.19": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.20": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.21": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.22": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.23": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.24": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.25": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.26": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.27": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.28": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.10.29": {
-    "node_abi": 11,
-    "v8": "3.14"
-  },
-  "0.11.0": {
-    "node_abi": 12,
-    "v8": "3.17"
-  },
-  "0.11.1": {
-    "node_abi": 12,
-    "v8": "3.18"
-  },
-  "0.11.2": {
-    "node_abi": 12,
-    "v8": "3.19"
-  },
-  "0.11.3": {
-    "node_abi": 12,
-    "v8": "3.19"
-  },
-  "0.11.4": {
-    "node_abi": 12,
-    "v8": "3.20"
-  },
-  "0.11.5": {
-    "node_abi": 12,
-    "v8": "3.20"
-  },
-  "0.11.6": {
-    "node_abi": 12,
-    "v8": "3.20"
-  },
-  "0.11.7": {
-    "node_abi": 12,
-    "v8": "3.20"
-  },
-  "0.11.8": {
-    "node_abi": 13,
-    "v8": "3.21"
-  },
-  "0.11.9": {
-    "node_abi": 13,
-    "v8": "3.22"
-  },
-  "0.11.10": {
-    "node_abi": 13,
-    "v8": "3.22"
-  },
-  "0.11.11": {
-    "node_abi": 14,
-    "v8": "3.22"
-  },
-  "0.11.12": {
-    "node_abi": 14,
-    "v8": "3.22"
-  },
-  "0.11.13": {
-    "node_abi": 14,
-    "v8": "3.25"
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/compile.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/compile.js
deleted file mode 100644
index da4c4883..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/compile.js
+++ /dev/null
@@ -1,80 +0,0 @@
-
-module.exports = exports;
-
-var fs = require('fs')
-  , tar = require('tar')
-  , path = require('path')
-  , zlib = require('zlib')
-  , log = require('npmlog')
-  , semver = require('semver')
-  , request = require('request')
-  , win = process.platform == 'win32'
-  , os = require('os')
-  , existsSync = fs.existsSync || path.existsSync
-  , cp = require('child_process')
-
-// try to build up the complete path to node-gyp
-/* priority:
-  - node-gyp on NODE_PATH
-  - node-gyp inside npm on NODE_PATH
-  - node-gyp inside npm beside node exe
-*/
-function which_node_gyp() {
-    try {
-        var node_gyp_main = require.resolve('node-gyp');
-        var node_gyp_bin = path.join(path.dirname(
-                                     path.dirname(node_gyp_main))
-                                     ,'bin/node-gyp.js');
-        if (existsSync(node_gyp_bin)) {
-            return node_gyp_bin;
-        }
-    } catch (err) { }
-    try {
-        var npm_main = require.resolve('npm');
-        var node_gyp_bin = path.join(path.dirname(
-                                     path.dirname(npm_main))
-                                     ,'node_modules/node-gyp/bin/node-gyp.js');
-        if (existsSync(node_gyp_bin)) {
-            return node_gyp_bin;
-        }
-    } catch (err) { }
-    var npm_base = path.join(path.dirname(
-                             path.dirname(process.execPath))
-                             ,'lib/node_modules/npm/')
-    var node_gyp_bin = path.join(npm_base,'node_modules/node-gyp/bin/node-gyp.js');
-    if (existsSync(node_gyp_bin)) {
-        return node_gyp_bin;
-    }
-}
-
-module.exports.run_gyp = function(args,opts,callback) {
-    var shell_cmd = '';
-    var cmd_args = [];
-    if (opts.runtime && opts.runtime == 'node-webkit') {
-        shell_cmd = 'nw-gyp';
-        if (win) shell_cmd += '.cmd';
-    } else {
-        var node_gyp_path = which_node_gyp();
-        if (node_gyp_path) {
-            shell_cmd = process.execPath;
-            cmd_args.push(node_gyp_path);
-        } else {
-            shell_cmd = 'node-gyp';
-            if (win) shell_cmd += '.cmd';
-        }
-    }
-    var final_args = cmd_args.concat(args);
-    var cmd = cp.spawn(shell_cmd, final_args, {cwd: undefined, env: process.env, customFds: [ 0, 1, 2]});
-    cmd.on('error', function (err) {
-        if (err) {
-            return callback(new Error("Failed to execute '" + shell_cmd + ' ' + final_args.join(' ') + "' (" + err + ")"));
-        }
-        callback(null,opts);
-    });
-    cmd.on('close', function (err, stdout, stderr) {
-        if (err) {
-            return callback(new Error("Failed to execute '" + shell_cmd + ' ' + args.join(' ') + "' (" + err + ")"));
-        }
-        callback(null,opts);
-    });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/index.html b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/index.html
deleted file mode 100644
index 244466c4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/index.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!doctype html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Node-webkit-based module test</title>
-<script>
-function nwModuleTest(){
-   var util = require('util');
-   var moduleFolder = require('nw.gui').App.argv[0];
-   try {
-      require(moduleFolder);
-   } catch(e) {
-      if( process.platform !== 'win32' ){
-         util.log('nw-pre-gyp error:');
-         util.log(e.stack);
-      }
-      process.exit(1);
-   }
-   process.exit(0);
-}
-</script>
-</head>
-<body onload="nwModuleTest()">
-<h1>Node-webkit-based module test</h1>
-</body>
-</html>
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json
deleted file mode 100644
index 71d03f82..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-"main": "index.html",
-"name": "nw-pre-gyp-module-test",
-"description": "Node-webkit-based module test.",
-"version": "0.0.1",
-"window": {
-   "show": false
-}
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw_crosswalk.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw_crosswalk.json
deleted file mode 100644
index 4926dcdb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/nw_crosswalk.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "0.10.0": "0.11.13",
-  "0.10.0-rc1": "0.11.13",
-  "0.9.2": "0.11.9",
-  "0.9.1": "0.11.9",
-  "0.9.0": "0.11.9",
-  "0.8.6": "0.10.22",
-  "0.8.5": "0.10.22",
-  "0.8.4": "0.10.22",
-  "0.8.3": "0.10.22",
-  "0.8.2": "0.10.22",
-  "0.8.1": "0.10.22",
-  "0.8.0": "0.10.18",
-  "0.7.5": "0.10.18",
-  "0.7.4": "0.10.18",
-  "0.7.3": "0.10.18",
-  "0.7.2": "0.10.12",
-  "0.7.1": "0.10.12",
-  "0.7.0": "0.10.12",
-  "0.6.3": "0.10.12",
-  "0.6.2": "0.10.12",
-  "0.6.1": "0.10.5",
-  "0.6.0": "0.10.5",
-  "0.5.1": "0.10.5",
-  "0.5.0": "0.8.17",
-  "0.4.2": "0.8.17"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/s3_setup.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/s3_setup.js
deleted file mode 100644
index 16211b75..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/s3_setup.js
+++ /dev/null
@@ -1,21 +0,0 @@
-
-module.exports = exports;
-
-var url = require('url')
-
-module.exports.detect = function(to,config) {
-    var uri = url.parse(to);
-    var url_paths = uri.hostname.split('.');
-    config.prefix = (!uri.pathname || uri.pathname == '/') ? '' : uri.pathname.replace('/','');
-    if (!config.bucket && url_paths && url_paths[0]) {
-        config.bucket = url_paths[0];
-    }
-    if (!config.region && url_paths && url_paths[1]) {
-        var s3_domain = url_paths[1];
-        if (s3_domain.slice(0,3) == 's3-' &&
-            s3_domain.length >= 3) {
-            // it appears the region is explicit in the url
-            config.region = s3_domain.replace('s3-','');
-        }
-    }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/versioning.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/versioning.js
deleted file mode 100644
index 6c02552b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/lib/util/versioning.js
+++ /dev/null
@@ -1,158 +0,0 @@
-
-module.exports = exports;
-
-var path = require('path')
-  , semver = require('semver')
-  , url = require('url')
-  , abi_crosswalk = require('./abi_crosswalk.json')
-  , nw_crosswalk = require('./nw_crosswalk.json')
-
-
-function get_node_abi(runtime, target) {
-    if (target) {
-        // abi_crosswalk generated with ./scripts/abi_crosswalk.js
-        var abi = '';
-        if (runtime === 'node-webkit') {
-            var node_version = nw_crosswalk[target];
-            if (!node_version) {
-                throw new Error("node-webkit version '"+target+"' not supported");
-            }
-            abi = abi_crosswalk[node_version].node_abi;
-        } else {
-            if (abi_crosswalk[target]) {
-                abi = abi_crosswalk[target].node_abi;
-            }
-        }
-        if (!abi) {
-            throw new Error("Unsupported target version: " + target);
-        }
-        if (abi > 1) {
-            return runtime+'-v' + (+abi);
-        } else {
-            // no support for node-webkit unless > 0.10.x
-            if (runtime != 'node') {
-                throw new Error("Runtime '" + runtime + "' unsupported for target version: " + target);
-            }
-            if (!abi_crosswalk[target]) {
-                throw new Error("Unsupported target version: " + target);
-            }
-            abi = abi_crosswalk[target].v8;
-            return 'v8-' + abi;
-        }
-    } else {
-        // process.versions.modules added in >= v0.10.4 and v0.11.7
-        // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e
-        return process.versions.modules ? runtime+'-v' + (+process.versions.modules) :
-               'v8-' + process.versions.v8.split('.').slice(0,2).join('.');
-    }
-}
-
-var required_parameters = [
-    'module_name',
-    'module_path',
-    'host'
-];
-
-function validate_config(package_json,callback) {
-    var msg = package_json.name + ' package.json is not node-pre-gyp ready:\n';
-    var missing = [];
-    if (!package_json.main) {
-        missing.push('main');
-    }
-    if (!package_json.name) {
-        missing.push('name');
-    }
-    if (!package_json.binary) {
-        missing.push('binary');
-    }
-    var o = package_json.binary;
-    required_parameters.forEach(function(p) {
-        if (missing.indexOf('binary') > -1) {
-            missing.pop('binary');
-        }
-        if (!o || o[p] == undefined) {
-            missing.push('binary.' + p);
-        }
-    });
-    if (missing.length >= 1) {
-        throw new Error(msg+"package.json must declare these properties: \n" + missing.join('\n'));
-    }
-    if (o) {
-        // enforce https over http
-        var protocol = url.parse(o.host).protocol;
-        if (protocol === 'http:') {
-            throw new Error("'host' protocol ("+protocol+") is invalid - only 'https:' is accepted");
-        }
-    }
-};
-
-module.exports.validate_config = validate_config;
-
-function eval_template(template,opts) {
-    Object.keys(opts).forEach(function(key) {
-        var pattern = '{'+key+'}';
-        while (template.indexOf(pattern) > -1) {
-            template = template.replace(pattern,opts[key]);
-        }
-    });
-    return template;
-}
-
-// url.resolve needs single trailing slash
-// to behave correctly, otherwise a double slash
-// may end up in the url which breaks requests
-// and a lacking slash may not lead to proper joining
-function add_trailing_slash(pathname) {
-    if (pathname.slice(-1) != '/') {
-        return pathname + '/';
-    }
-    return pathname;
-}
-
-var default_package_name = '{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz';
-var default_remote_path = '';
-
-module.exports.evaluate = function(package_json,options) {
-    options = options || {};
-    validate_config(package_json);
-    var v = package_json.version;
-    var module_version = semver.parse(v);
-    var runtime = options.runtime || (process.versions['node-webkit'] ? 'node-webkit' : 'node');
-    options.debug = Boolean(options.debug);
-    var opts = {
-          name: package_json.name
-        , configuration: options.debug ? 'Debug' : 'Release'
-        , debug: options.debug
-        , module_name: package_json.binary.module_name
-        , version: module_version.version
-        , prerelease: module_version.prerelease.length ? v.slice(v.indexOf(module_version.prerelease[0])) : ''
-        , major: module_version.major
-        , minor: module_version.minor
-        , patch: module_version.patch
-        , runtime: runtime
-        , node_abi: get_node_abi(runtime,options.target)
-        , target: options.target || ''
-        , platform: options.target_platform || process.platform
-        , target_platform: options.target_platform || process.platform
-        , arch: options.target_arch || process.arch
-        , target_arch: options.target_arch || process.arch
-        , module_main: package_json.main
-    }
-    opts.host = add_trailing_slash(eval_template(package_json.binary.host,opts));
-    opts.module_path = eval_template(package_json.binary.module_path,opts);
-    // now we resolve the module_path to ensure it is absolute so that binding.gyp variables work predictably
-    if (options.module_root) {
-        // resolve relative to known module root: works for pre-binding require
-        opts.module_path = path.join(options.module_root,opts.module_path);
-    } else {
-        // resolve relative to current working directory: works for node-pre-gyp commands
-        opts.module_path = path.resolve(opts.module_path);
-    }
-    opts.remote_path = package_json.binary.remote_path ? add_trailing_slash(eval_template(package_json.binary.remote_path,opts)) : default_remote_path;
-    var package_name = package_json.binary.package_name ? package_json.binary.package_name : default_package_name;
-    opts.package_name = eval_template(package_name,opts);
-    opts.staged_tarball = path.join('build/stage',opts.remote_path,opts.package_name);
-    opts.hosted_path = url.resolve(opts.host,opts.remote_path);
-    opts.hosted_tarball = url.resolve(opts.hosted_path,opts.package_name);
-    return opts;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/nopt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/nopt
deleted file mode 120000
index 6b6566ea..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/nopt
+++ /dev/null
@@ -1 +0,0 @@
-../nopt/bin/nopt.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rc b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rc
deleted file mode 120000
index a3f6fc7f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rc
+++ /dev/null
@@ -1 +0,0 @@
-../rc/index.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rimraf b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rimraf
deleted file mode 120000
index 4cd49a49..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/.bin/rimraf
+++ /dev/null
@@ -1 +0,0 @@
-../rimraf/bin.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.npmignore
deleted file mode 100644
index 9303c347..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules/
-npm-debug.log
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.travis.yml
deleted file mode 100644
index c693a939..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
-  - 0.8
-  - "0.10"
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/index.js
deleted file mode 100644
index a1742b20..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/index.js
+++ /dev/null
@@ -1,97 +0,0 @@
-var path = require('path');
-var fs = require('fs');
-
-module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
-
-function mkdirP (p, opts, f, made) {
-    if (typeof opts === 'function') {
-        f = opts;
-        opts = {};
-    }
-    else if (!opts || typeof opts !== 'object') {
-        opts = { mode: opts };
-    }
-    
-    var mode = opts.mode;
-    var xfs = opts.fs || fs;
-    
-    if (mode === undefined) {
-        mode = 0777 & (~process.umask());
-    }
-    if (!made) made = null;
-    
-    var cb = f || function () {};
-    p = path.resolve(p);
-    
-    xfs.mkdir(p, mode, function (er) {
-        if (!er) {
-            made = made || p;
-            return cb(null, made);
-        }
-        switch (er.code) {
-            case 'ENOENT':
-                mkdirP(path.dirname(p), opts, function (er, made) {
-                    if (er) cb(er, made);
-                    else mkdirP(p, opts, cb, made);
-                });
-                break;
-
-            // In the case of any other error, just see if there's a dir
-            // there already.  If so, then hooray!  If not, then something
-            // is borked.
-            default:
-                xfs.stat(p, function (er2, stat) {
-                    // if the stat fails, then that's super weird.
-                    // let the original error be the failure reason.
-                    if (er2 || !stat.isDirectory()) cb(er, made)
-                    else cb(null, made);
-                });
-                break;
-        }
-    });
-}
-
-mkdirP.sync = function sync (p, opts, made) {
-    if (!opts || typeof opts !== 'object') {
-        opts = { mode: opts };
-    }
-    
-    var mode = opts.mode;
-    var xfs = opts.fs || fs;
-    
-    if (mode === undefined) {
-        mode = 0777 & (~process.umask());
-    }
-    if (!made) made = null;
-
-    p = path.resolve(p);
-
-    try {
-        xfs.mkdirSync(p, mode);
-        made = made || p;
-    }
-    catch (err0) {
-        switch (err0.code) {
-            case 'ENOENT' :
-                made = sync(path.dirname(p), opts, made);
-                sync(p, opts, made);
-                break;
-
-            // In the case of any other error, just see if there's a dir
-            // there already.  If so, then hooray!  If not, then something
-            // is borked.
-            default:
-                var stat;
-                try {
-                    stat = xfs.statSync(p);
-                }
-                catch (err1) {
-                    throw err0;
-                }
-                if (!stat.isDirectory()) throw err0;
-                break;
-        }
-    }
-
-    return made;
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/package.json
deleted file mode 100644
index 2c1e0401..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/node_modules/minimist/package.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-  "name": "minimist",
-  "version": "0.0.8",
-  "description": "parse argument options",
-  "main": "index.js",
-  "devDependencies": {
-    "tape": "~1.0.4",
-    "tap": "~0.4.0"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "testling": {
-    "files": "test/*.js",
-    "browsers": [
-      "ie/6..latest",
-      "ff/5",
-      "firefox/latest",
-      "chrome/10",
-      "chrome/latest",
-      "safari/5.1",
-      "safari/latest",
-      "opera/12"
-    ]
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/substack/minimist.git"
-  },
-  "homepage": "https://github.com/substack/minimist",
-  "keywords": [
-    "argv",
-    "getopt",
-    "parser",
-    "optimist"
-  ],
-  "author": {
-    "name": "James Halliday",
-    "email": "mail@substack.net",
-    "url": "http://substack.net"
-  },
-  "license": "MIT",
-  "readme": "# minimist\n\nparse argument options\n\nThis module is the guts of optimist's argument parser without all the\nfanciful decoration.\n\n[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)\n\n[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)\n\n# example\n\n``` js\nvar argv = require('minimist')(process.argv.slice(2));\nconsole.dir(argv);\n```\n\n```\n$ node example/parse.js -a beep -b boop\n{ _: [], a: 'beep', b: 'boop' }\n```\n\n```\n$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz\n{ _: [ 'foo', 'bar', 'baz' ],\n  x: 3,\n  y: 4,\n  n: 5,\n  a: true,\n  b: true,\n  c: true,\n  beep: 'boop' }\n```\n\n# methods\n\n``` js\nvar parseArgs = require('minimist')\n```\n\n## var argv = parseArgs(args, opts={})\n\nReturn an argument object `argv` populated with the array arguments from `args`.\n\n`argv._` contains all the arguments that didn't have an option associated with\nthem.\n\nNumeric-looking arguments will be returned as numbers unless `opts.string` or\n`opts.boolean` is set for that argument name.\n\nAny arguments after `'--'` will not be parsed and will end up in `argv._`.\n\noptions can be:\n\n* `opts.string` - a string or array of strings argument names to always treat as\nstrings\n* `opts.boolean` - a string or array of strings to always treat as booleans\n* `opts.alias` - an object mapping string names to strings or arrays of string\nargument names to use as aliases\n* `opts.default` - an object mapping string argument names to default values\n\n# install\n\nWith [npm](https://npmjs.org) do:\n\n```\nnpm install minimist\n```\n\n# license\n\nMIT\n",
-  "readmeFilename": "readme.markdown",
-  "bugs": {
-    "url": "https://github.com/substack/minimist/issues"
-  },
-  "_id": "minimist@0.0.8",
-  "_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
-  "_from": "minimist@0.0.8",
-  "_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/package.json
deleted file mode 100644
index b01c4314..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/package.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
-  "name": "mkdirp",
-  "description": "Recursively mkdir, like `mkdir -p`",
-  "version": "0.5.0",
-  "author": {
-    "name": "James Halliday",
-    "email": "mail@substack.net",
-    "url": "http://substack.net"
-  },
-  "main": "./index",
-  "keywords": [
-    "mkdir",
-    "directory"
-  ],
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/substack/node-mkdirp.git"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "dependencies": {
-    "minimist": "0.0.8"
-  },
-  "devDependencies": {
-    "tap": "~0.4.0",
-    "mock-fs": "~2.2.0"
-  },
-  "bin": {
-    "mkdirp": "bin/cmd.js"
-  },
-  "license": "MIT",
-  "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n    \nmkdirp('/tmp/foo/bar/baz', function (err) {\n    if (err) console.error(err)\n    else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, opts, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `opts.mode`. If `opts` is a non-object, it will be treated as\nthe `opts.mode`.\n\nIf `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\nYou can optionally pass in an alternate `fs` implementation by passing in\n`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and\n`opts.fs.stat(path, cb)`.\n\n## mkdirp.sync(dir, opts)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `opts.mode`. If `opts` is a non-object, it will be\ntreated as the `opts.mode`.\n\nIf `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\nYou can optionally pass in an alternate `fs` implementation by passing in\n`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and\n`opts.fs.statSync(path)`.\n\n# usage\n\nThis package also ships with a `mkdirp` command.\n\n```\nusage: mkdirp [DIR1,DIR2..] {OPTIONS}\n\n  Create each supplied directory including any necessary parent directories that\n  don't yet exist.\n  \n  If the directory already exists, do nothing.\n\nOPTIONS are:\n\n  -m, --mode   If a directory needs to be created, set the mode as an octal\n               permission string.\n\n```\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\nto get the library, or\n\n```\nnpm install -g mkdirp\n```\n\nto get the command.\n\n# license\n\nMIT\n",
-  "readmeFilename": "readme.markdown",
-  "bugs": {
-    "url": "https://github.com/substack/node-mkdirp/issues"
-  },
-  "homepage": "https://github.com/substack/node-mkdirp",
-  "_id": "mkdirp@0.5.0",
-  "_shasum": "1d73076a6df986cd9344e15e71fcc05a4c9abf12",
-  "_from": "mkdirp@~0.5.0",
-  "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/chmod.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/chmod.js
deleted file mode 100644
index 520dcb8e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/chmod.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-var ps = [ '', 'tmp' ];
-
-for (var i = 0; i < 25; i++) {
-    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    ps.push(dir);
-}
-
-var file = ps.join('/');
-
-test('chmod-pre', function (t) {
-    var mode = 0744
-    mkdirp(file, mode, function (er) {
-        t.ifError(er, 'should not error');
-        fs.stat(file, function (er, stat) {
-            t.ifError(er, 'should exist');
-            t.ok(stat && stat.isDirectory(), 'should be directory');
-            t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
-            t.end();
-        });
-    });
-});
-
-test('chmod', function (t) {
-    var mode = 0755
-    mkdirp(file, mode, function (er) {
-        t.ifError(er, 'should not error');
-        fs.stat(file, function (er, stat) {
-            t.ifError(er, 'should exist');
-            t.ok(stat && stat.isDirectory(), 'should be directory');
-            t.end();
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/clobber.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/clobber.js
deleted file mode 100644
index 0eb70998..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/clobber.js
+++ /dev/null
@@ -1,37 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-var ps = [ '', 'tmp' ];
-
-for (var i = 0; i < 25; i++) {
-    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    ps.push(dir);
-}
-
-var file = ps.join('/');
-
-// a file in the way
-var itw = ps.slice(0, 3).join('/');
-
-
-test('clobber-pre', function (t) {
-    console.error("about to write to "+itw)
-    fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
-
-    fs.stat(itw, function (er, stat) {
-        t.ifError(er)
-        t.ok(stat && stat.isFile(), 'should be file')
-        t.end()
-    })
-})
-
-test('clobber', function (t) {
-    t.plan(2);
-    mkdirp(file, 0755, function (err) {
-        t.ok(err);
-        t.equal(err.code, 'ENOTDIR');
-        t.end();
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/mkdirp.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/mkdirp.js
deleted file mode 100644
index 3b624ddb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/mkdirp.js
+++ /dev/null
@@ -1,26 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('woo', function (t) {
-    t.plan(5);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var file = '/tmp/' + [x,y,z].join('/');
-    
-    mkdirp(file, 0755, function (err) {
-        t.ifError(err);
-        exists(file, function (ex) {
-            t.ok(ex, 'file created');
-            fs.stat(file, function (err, stat) {
-                t.ifError(err);
-                t.equal(stat.mode & 0777, 0755);
-                t.ok(stat.isDirectory(), 'target not a directory');
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm.js
deleted file mode 100644
index 2c975905..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('async perm', function (t) {
-    t.plan(5);
-    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
-    
-    mkdirp(file, 0755, function (err) {
-        t.ifError(err);
-        exists(file, function (ex) {
-            t.ok(ex, 'file created');
-            fs.stat(file, function (err, stat) {
-                t.ifError(err);
-                t.equal(stat.mode & 0777, 0755);
-                t.ok(stat.isDirectory(), 'target not a directory');
-            })
-        })
-    });
-});
-
-test('async root perm', function (t) {
-    mkdirp('/tmp', 0755, function (err) {
-        if (err) t.fail(err);
-        t.end();
-    });
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm_sync.js
deleted file mode 100644
index 327e54b2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/perm_sync.js
+++ /dev/null
@@ -1,34 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('sync perm', function (t) {
-    t.plan(4);
-    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
-    
-    mkdirp.sync(file, 0755);
-    exists(file, function (ex) {
-        t.ok(ex, 'file created');
-        fs.stat(file, function (err, stat) {
-            t.ifError(err);
-            t.equal(stat.mode & 0777, 0755);
-            t.ok(stat.isDirectory(), 'target not a directory');
-        });
-    });
-});
-
-test('sync root perm', function (t) {
-    t.plan(3);
-    
-    var file = '/tmp';
-    mkdirp.sync(file, 0755);
-    exists(file, function (ex) {
-        t.ok(ex, 'file created');
-        fs.stat(file, function (err, stat) {
-            t.ifError(err);
-            t.ok(stat.isDirectory(), 'target not a directory');
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/race.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/race.js
deleted file mode 100644
index 7c295f41..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/race.js
+++ /dev/null
@@ -1,40 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('race', function (t) {
-    t.plan(6);
-    var ps = [ '', 'tmp' ];
-    
-    for (var i = 0; i < 25; i++) {
-        var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-        ps.push(dir);
-    }
-    var file = ps.join('/');
-    
-    var res = 2;
-    mk(file, function () {
-        if (--res === 0) t.end();
-    });
-    
-    mk(file, function () {
-        if (--res === 0) t.end();
-    });
-    
-    function mk (file, cb) {
-        mkdirp(file, 0755, function (err) {
-            t.ifError(err);
-            exists(file, function (ex) {
-                t.ok(ex, 'file created');
-                fs.stat(file, function (err, stat) {
-                    t.ifError(err);
-                    t.equal(stat.mode & 0777, 0755);
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    if (cb) cb();
-                });
-            })
-        });
-    }
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/rel.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/rel.js
deleted file mode 100644
index d1f175c2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/rel.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('rel', function (t) {
-    t.plan(5);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var cwd = process.cwd();
-    process.chdir('/tmp');
-    
-    var file = [x,y,z].join('/');
-    
-    mkdirp(file, 0755, function (err) {
-        t.ifError(err);
-        exists(file, function (ex) {
-            t.ok(ex, 'file created');
-            fs.stat(file, function (err, stat) {
-                t.ifError(err);
-                process.chdir(cwd);
-                t.equal(stat.mode & 0777, 0755);
-                t.ok(stat.isDirectory(), 'target not a directory');
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/root.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/root.js
deleted file mode 100644
index 97ad7a2f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/root.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('root', function (t) {
-    // '/' on unix, 'c:/' on windows.
-    var file = path.resolve('/');
-
-    mkdirp(file, 0755, function (err) {
-        if (err) throw err
-        fs.stat(file, function (er, stat) {
-            if (er) throw er
-            t.ok(stat.isDirectory(), 'target is a directory');
-            t.end();
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/sync.js
deleted file mode 100644
index 88fa4324..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/sync.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('sync', function (t) {
-    t.plan(4);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    try {
-        mkdirp.sync(file, 0755);
-    } catch (err) {
-        t.fail(err);
-        return t.end();
-    }
-
-    exists(file, function (ex) {
-        t.ok(ex, 'file created');
-        fs.stat(file, function (err, stat) {
-            t.ifError(err);
-            t.equal(stat.mode & 0777, 0755);
-            t.ok(stat.isDirectory(), 'target not a directory');
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask.js
deleted file mode 100644
index 82c393a0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask.js
+++ /dev/null
@@ -1,26 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('implicit mode from umask', function (t) {
-    t.plan(5);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var file = '/tmp/' + [x,y,z].join('/');
-    
-    mkdirp(file, function (err) {
-        t.ifError(err);
-        exists(file, function (ex) {
-            t.ok(ex, 'file created');
-            fs.stat(file, function (err, stat) {
-                t.ifError(err);
-                t.equal(stat.mode & 0777, 0777 & (~process.umask()));
-                t.ok(stat.isDirectory(), 'target not a directory');
-            });
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask_sync.js
deleted file mode 100644
index e537fbe4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/mkdirp/test/umask_sync.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var exists = fs.exists || path.exists;
-var test = require('tap').test;
-
-test('umask sync modes', function (t) {
-    t.plan(4);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    try {
-        mkdirp.sync(file);
-    } catch (err) {
-        t.fail(err);
-        return t.end();
-    }
-
-    exists(file, function (ex) {
-        t.ok(ex, 'file created');
-        fs.stat(file, function (err, stat) {
-            t.ifError(err);
-            t.equal(stat.mode & 0777, (0777 & (~process.umask())));
-            t.ok(stat.isDirectory(), 'target not a directory');
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/LICENSE
deleted file mode 100644
index 05a40109..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
-All rights reserved.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/README.md
deleted file mode 100644
index 96798a1d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/README.md
+++ /dev/null
@@ -1,210 +0,0 @@
-If you want to write an option parser, and have it be good, there are
-two ways to do it.  The Right Way, and the Wrong Way.
-
-The Wrong Way is to sit down and write an option parser.  We've all done
-that.
-
-The Right Way is to write some complex configurable program with so many
-options that you go half-insane just trying to manage them all, and put
-it off with duct-tape solutions until you see exactly to the core of the
-problem, and finally snap and write an awesome option parser.
-
-If you want to write an option parser, don't write an option parser.
-Write a package manager, or a source control system, or a service
-restarter, or an operating system.  You probably won't end up with a
-good one of those, but if you don't give up, and you are relentless and
-diligent enough in your procrastination, you may just end up with a very
-nice option parser.
-
-## USAGE
-
-    // my-program.js
-    var nopt = require("nopt")
-      , Stream = require("stream").Stream
-      , path = require("path")
-      , knownOpts = { "foo" : [String, null]
-                    , "bar" : [Stream, Number]
-                    , "baz" : path
-                    , "bloo" : [ "big", "medium", "small" ]
-                    , "flag" : Boolean
-                    , "pick" : Boolean
-                    , "many" : [String, Array]
-                    }
-      , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
-                     , "b7" : ["--bar", "7"]
-                     , "m" : ["--bloo", "medium"]
-                     , "p" : ["--pick"]
-                     , "f" : ["--flag"]
-                     }
-                 // everything is optional.
-                 // knownOpts and shorthands default to {}
-                 // arg list defaults to process.argv
-                 // slice defaults to 2
-      , parsed = nopt(knownOpts, shortHands, process.argv, 2)
-    console.log(parsed)
-
-This would give you support for any of the following:
-
-```bash
-$ node my-program.js --foo "blerp" --no-flag
-{ "foo" : "blerp", "flag" : false }
-
-$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag
-{ bar: 7, foo: "Mr. Hand", flag: true }
-
-$ node my-program.js --foo "blerp" -f -----p
-{ foo: "blerp", flag: true, pick: true }
-
-$ node my-program.js -fp --foofoo
-{ foo: "Mr. Foo", flag: true, pick: true }
-
-$ node my-program.js --foofoo -- -fp  # -- stops the flag parsing.
-{ foo: "Mr. Foo", argv: { remain: ["-fp"] } }
-
-$ node my-program.js --blatzk -fp # unknown opts are ok.
-{ blatzk: true, flag: true, pick: true }
-
-$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value
-{ blatzk: 1000, flag: true, pick: true }
-
-$ node my-program.js --no-blatzk -fp # unless they start with "no-"
-{ blatzk: false, flag: true, pick: true }
-
-$ node my-program.js --baz b/a/z # known paths are resolved.
-{ baz: "/Users/isaacs/b/a/z" }
-
-# if Array is one of the types, then it can take many
-# values, and will always be an array.  The other types provided
-# specify what types are allowed in the list.
-
-$ node my-program.js --many 1 --many null --many foo
-{ many: ["1", "null", "foo"] }
-
-$ node my-program.js --many foo
-{ many: ["foo"] }
-```
-
-Read the tests at the bottom of `lib/nopt.js` for more examples of
-what this puppy can do.
-
-## Types
-
-The following types are supported, and defined on `nopt.typeDefs`
-
-* String: A normal string.  No parsing is done.
-* path: A file system path.  Gets resolved against cwd if not absolute.
-* url: A url.  If it doesn't parse, it isn't accepted.
-* Number: Must be numeric.
-* Date: Must parse as a date. If it does, and `Date` is one of the options,
-  then it will return a Date object, not a string.
-* Boolean: Must be either `true` or `false`.  If an option is a boolean,
-  then it does not need a value, and its presence will imply `true` as
-  the value.  To negate boolean flags, do `--no-whatever` or `--whatever
-  false`
-* NaN: Means that the option is strictly not allowed.  Any value will
-  fail.
-* Stream: An object matching the "Stream" class in node.  Valuable
-  for use when validating programmatically.  (npm uses this to let you
-  supply any WriteStream on the `outfd` and `logfd` config options.)
-* Array: If `Array` is specified as one of the types, then the value
-  will be parsed as a list of options.  This means that multiple values
-  can be specified, and that the value will always be an array.
-
-If a type is an array of values not on this list, then those are
-considered valid values.  For instance, in the example above, the
-`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`,
-and any other value will be rejected.
-
-When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be
-interpreted as their JavaScript equivalents, and numeric values will be
-interpreted as a number.
-
-You can also mix types and values, or multiple types, in a list.  For
-instance `{ blah: [Number, null] }` would allow a value to be set to
-either a Number or null.  When types are ordered, this implies a
-preference, and the first type that can be used to properly interpret
-the value will be used.
-
-To define a new type, add it to `nopt.typeDefs`.  Each item in that
-hash is an object with a `type` member and a `validate` method.  The
-`type` member is an object that matches what goes in the type list.  The
-`validate` method is a function that gets called with `validate(data,
-key, val)`.  Validate methods should assign `data[key]` to the valid
-value of `val` if it can be handled properly, or return boolean
-`false` if it cannot.
-
-You can also call `nopt.clean(data, types, typeDefs)` to clean up a
-config object and remove its invalid properties.
-
-## Error Handling
-
-By default, nopt outputs a warning to standard error when invalid
-options are found.  You can change this behavior by assigning a method
-to `nopt.invalidHandler`.  This method will be called with
-the offending `nopt.invalidHandler(key, val, types)`.
-
-If no `nopt.invalidHandler` is assigned, then it will console.error
-its whining.  If it is assigned to boolean `false` then the warning is
-suppressed.
-
-## Abbreviations
-
-Yes, they are supported.  If you define options like this:
-
-```javascript
-{ "foolhardyelephants" : Boolean
-, "pileofmonkeys" : Boolean }
-```
-
-Then this will work:
-
-```bash
-node program.js --foolhar --pil
-node program.js --no-f --pileofmon
-# etc.
-```
-
-## Shorthands
-
-Shorthands are a hash of shorter option names to a snippet of args that
-they expand to.
-
-If multiple one-character shorthands are all combined, and the
-combination does not unambiguously match any other option or shorthand,
-then they will be broken up into their constituent parts.  For example:
-
-```json
-{ "s" : ["--loglevel", "silent"]
-, "g" : "--global"
-, "f" : "--force"
-, "p" : "--parseable"
-, "l" : "--long"
-}
-```
-
-```bash
-npm ls -sgflp
-# just like doing this:
-npm ls --loglevel silent --global --force --long --parseable
-```
-
-## The Rest of the args
-
-The config object returned by nopt is given a special member called
-`argv`, which is an object with the following fields:
-
-* `remain`: The remaining args after all the parsing has occurred.
-* `original`: The args as they originally appeared.
-* `cooked`: The args after flags and shorthands are expanded.
-
-## Slicing
-
-Node programs are called with more or less the exact argv as it appears
-in C land, after the v8 and node-specific options have been plucked off.
-As such, `argv[0]` is always `node` and `argv[1]` is always the
-JavaScript program being run.
-
-That's usually not very useful to you.  So they're sliced off by
-default.  If you want them, then you can pass in `0` as the last
-argument, or any other number that you'd like to slice off the start of
-the list.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/bin/nopt.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/bin/nopt.js
deleted file mode 100755
index 30e9fdba..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/bin/nopt.js
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env node
-var nopt = require("../lib/nopt")
-  , types = { num: Number
-            , bool: Boolean
-            , help: Boolean
-            , list: Array
-            , "num-list": [Number, Array]
-            , "str-list": [String, Array]
-            , "bool-list": [Boolean, Array]
-            , str: String
-            , clear: Boolean
-            , config: Boolean
-            , length: Number
-            }
-  , shorthands = { s: [ "--str", "astring" ]
-                 , b: [ "--bool" ]
-                 , nb: [ "--no-bool" ]
-                 , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ]
-                 , "?": ["--help"]
-                 , h: ["--help"]
-                 , H: ["--help"]
-                 , n: [ "--num", "125" ]
-                 , c: ["--config"]
-                 , l: ["--length"]
-                 }
-  , parsed = nopt( types
-                 , shorthands
-                 , process.argv
-                 , 2 )
-
-console.log("parsed", parsed)
-
-if (parsed.help) {
-  console.log("")
-  console.log("nopt cli tester")
-  console.log("")
-  console.log("types")
-  console.log(Object.keys(types).map(function M (t) {
-    var type = types[t]
-    if (Array.isArray(type)) {
-      return [t, type.map(function (type) { return type.name })]
-    }
-    return [t, type && type.name]
-  }).reduce(function (s, i) {
-    s[i[0]] = i[1]
-    return s
-  }, {}))
-  console.log("")
-  console.log("shorthands")
-  console.log(shorthands)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/examples/my-program.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/examples/my-program.js
deleted file mode 100755
index 142447e1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/examples/my-program.js
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env node
-
-//process.env.DEBUG_NOPT = 1
-
-// my-program.js
-var nopt = require("../lib/nopt")
-  , Stream = require("stream").Stream
-  , path = require("path")
-  , knownOpts = { "foo" : [String, null]
-                , "bar" : [Stream, Number]
-                , "baz" : path
-                , "bloo" : [ "big", "medium", "small" ]
-                , "flag" : Boolean
-                , "pick" : Boolean
-                }
-  , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
-                 , "b7" : ["--bar", "7"]
-                 , "m" : ["--bloo", "medium"]
-                 , "p" : ["--pick"]
-                 , "f" : ["--flag", "true"]
-                 , "g" : ["--flag"]
-                 , "s" : "--flag"
-                 }
-             // everything is optional.
-             // knownOpts and shorthands default to {}
-             // arg list defaults to process.argv
-             // slice defaults to 2
-  , parsed = nopt(knownOpts, shortHands, process.argv, 2)
-
-console.log("parsed =\n"+ require("util").inspect(parsed))
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/lib/nopt.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/lib/nopt.js
deleted file mode 100644
index 9efab7af..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/lib/nopt.js
+++ /dev/null
@@ -1,412 +0,0 @@
-// info about each config option.
-
-var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG
-  ? function () { console.error.apply(console, arguments) }
-  : function () {}
-
-var url = require("url")
-  , path = require("path")
-  , Stream = require("stream").Stream
-  , abbrev = require("abbrev")
-
-module.exports = exports = nopt
-exports.clean = clean
-
-exports.typeDefs =
-  { String  : { type: String,  validate: validateString  }
-  , Boolean : { type: Boolean, validate: validateBoolean }
-  , url     : { type: url,     validate: validateUrl     }
-  , Number  : { type: Number,  validate: validateNumber  }
-  , path    : { type: path,    validate: validatePath    }
-  , Stream  : { type: Stream,  validate: validateStream  }
-  , Date    : { type: Date,    validate: validateDate    }
-  }
-
-function nopt (types, shorthands, args, slice) {
-  args = args || process.argv
-  types = types || {}
-  shorthands = shorthands || {}
-  if (typeof slice !== "number") slice = 2
-
-  debug(types, shorthands, args, slice)
-
-  args = args.slice(slice)
-  var data = {}
-    , key
-    , remain = []
-    , cooked = args
-    , original = args.slice(0)
-
-  parse(args, data, remain, types, shorthands)
-  // now data is full
-  clean(data, types, exports.typeDefs)
-  data.argv = {remain:remain,cooked:cooked,original:original}
-  Object.defineProperty(data.argv, 'toString', { value: function () {
-    return this.original.map(JSON.stringify).join(" ")
-  }, enumerable: false })
-  return data
-}
-
-function clean (data, types, typeDefs) {
-  typeDefs = typeDefs || exports.typeDefs
-  var remove = {}
-    , typeDefault = [false, true, null, String, Number, Array]
-
-  Object.keys(data).forEach(function (k) {
-    if (k === "argv") return
-    var val = data[k]
-      , isArray = Array.isArray(val)
-      , type = types[k]
-    if (!isArray) val = [val]
-    if (!type) type = typeDefault
-    if (type === Array) type = typeDefault.concat(Array)
-    if (!Array.isArray(type)) type = [type]
-
-    debug("val=%j", val)
-    debug("types=", type)
-    val = val.map(function (val) {
-      // if it's an unknown value, then parse false/true/null/numbers/dates
-      if (typeof val === "string") {
-        debug("string %j", val)
-        val = val.trim()
-        if ((val === "null" && ~type.indexOf(null))
-            || (val === "true" &&
-               (~type.indexOf(true) || ~type.indexOf(Boolean)))
-            || (val === "false" &&
-               (~type.indexOf(false) || ~type.indexOf(Boolean)))) {
-          val = JSON.parse(val)
-          debug("jsonable %j", val)
-        } else if (~type.indexOf(Number) && !isNaN(val)) {
-          debug("convert to number", val)
-          val = +val
-        } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) {
-          debug("convert to date", val)
-          val = new Date(val)
-        }
-      }
-
-      if (!types.hasOwnProperty(k)) {
-        return val
-      }
-
-      // allow `--no-blah` to set 'blah' to null if null is allowed
-      if (val === false && ~type.indexOf(null) &&
-          !(~type.indexOf(false) || ~type.indexOf(Boolean))) {
-        val = null
-      }
-
-      var d = {}
-      d[k] = val
-      debug("prevalidated val", d, val, types[k])
-      if (!validate(d, k, val, types[k], typeDefs)) {
-        if (exports.invalidHandler) {
-          exports.invalidHandler(k, val, types[k], data)
-        } else if (exports.invalidHandler !== false) {
-          debug("invalid: "+k+"="+val, types[k])
-        }
-        return remove
-      }
-      debug("validated val", d, val, types[k])
-      return d[k]
-    }).filter(function (val) { return val !== remove })
-
-    if (!val.length) delete data[k]
-    else if (isArray) {
-      debug(isArray, data[k], val)
-      data[k] = val
-    } else data[k] = val[0]
-
-    debug("k=%s val=%j", k, val, data[k])
-  })
-}
-
-function validateString (data, k, val) {
-  data[k] = String(val)
-}
-
-function validatePath (data, k, val) {
-  if (val === true) return false
-  val = String(val)
-  var homePattern = process.platform === 'win32' ? /^~(\/|\\)/ : /^~\//
-  if (val.match(homePattern) && process.env.HOME) {
-    val = path.resolve(process.env.HOME, val.substr(2))
-  }
-  data[k] = path.resolve(String(val))
-  return true
-}
-
-function validateNumber (data, k, val) {
-  debug("validate Number %j %j %j", k, val, isNaN(val))
-  if (isNaN(val)) return false
-  data[k] = +val
-}
-
-function validateDate (data, k, val) {
-  debug("validate Date %j %j %j", k, val, Date.parse(val))
-  var s = Date.parse(val)
-  if (isNaN(s)) return false
-  data[k] = new Date(val)
-}
-
-function validateBoolean (data, k, val) {
-  if (val instanceof Boolean) val = val.valueOf()
-  else if (typeof val === "string") {
-    if (!isNaN(val)) val = !!(+val)
-    else if (val === "null" || val === "false") val = false
-    else val = true
-  } else val = !!val
-  data[k] = val
-}
-
-function validateUrl (data, k, val) {
-  val = url.parse(String(val))
-  if (!val.host) return false
-  data[k] = val.href
-}
-
-function validateStream (data, k, val) {
-  if (!(val instanceof Stream)) return false
-  data[k] = val
-}
-
-function validate (data, k, val, type, typeDefs) {
-  // arrays are lists of types.
-  if (Array.isArray(type)) {
-    for (var i = 0, l = type.length; i < l; i ++) {
-      if (type[i] === Array) continue
-      if (validate(data, k, val, type[i], typeDefs)) return true
-    }
-    delete data[k]
-    return false
-  }
-
-  // an array of anything?
-  if (type === Array) return true
-
-  // NaN is poisonous.  Means that something is not allowed.
-  if (type !== type) {
-    debug("Poison NaN", k, val, type)
-    delete data[k]
-    return false
-  }
-
-  // explicit list of values
-  if (val === type) {
-    debug("Explicitly allowed %j", val)
-    // if (isArray) (data[k] = data[k] || []).push(val)
-    // else data[k] = val
-    data[k] = val
-    return true
-  }
-
-  // now go through the list of typeDefs, validate against each one.
-  var ok = false
-    , types = Object.keys(typeDefs)
-  for (var i = 0, l = types.length; i < l; i ++) {
-    debug("test type %j %j %j", k, val, types[i])
-    var t = typeDefs[types[i]]
-    if (t && type === t.type) {
-      var d = {}
-      ok = false !== t.validate(d, k, val)
-      val = d[k]
-      if (ok) {
-        // if (isArray) (data[k] = data[k] || []).push(val)
-        // else data[k] = val
-        data[k] = val
-        break
-      }
-    }
-  }
-  debug("OK? %j (%j %j %j)", ok, k, val, types[i])
-
-  if (!ok) delete data[k]
-  return ok
-}
-
-function parse (args, data, remain, types, shorthands) {
-  debug("parse", args, data, remain)
-
-  var key = null
-    , abbrevs = abbrev(Object.keys(types))
-    , shortAbbr = abbrev(Object.keys(shorthands))
-
-  for (var i = 0; i < args.length; i ++) {
-    var arg = args[i]
-    debug("arg", arg)
-
-    if (arg.match(/^-{2,}$/)) {
-      // done with keys.
-      // the rest are args.
-      remain.push.apply(remain, args.slice(i + 1))
-      args[i] = "--"
-      break
-    }
-    var hadEq = false
-    if (arg.charAt(0) === "-" && arg.length > 1) {
-      if (arg.indexOf("=") !== -1) {
-        hadEq = true
-        var v = arg.split("=")
-        arg = v.shift()
-        v = v.join("=")
-        args.splice.apply(args, [i, 1].concat([arg, v]))
-      }
-
-      // see if it's a shorthand
-      // if so, splice and back up to re-parse it.
-      var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs)
-      debug("arg=%j shRes=%j", arg, shRes)
-      if (shRes) {
-        debug(arg, shRes)
-        args.splice.apply(args, [i, 1].concat(shRes))
-        if (arg !== shRes[0]) {
-          i --
-          continue
-        }
-      }
-      arg = arg.replace(/^-+/, "")
-      var no = null
-      while (arg.toLowerCase().indexOf("no-") === 0) {
-        no = !no
-        arg = arg.substr(3)
-      }
-
-      if (abbrevs[arg]) arg = abbrevs[arg]
-
-      var isArray = types[arg] === Array ||
-        Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1
-
-      // allow unknown things to be arrays if specified multiple times.
-      if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) {
-        if (!Array.isArray(data[arg]))
-          data[arg] = [data[arg]]
-        isArray = true
-      }
-
-      var val
-        , la = args[i + 1]
-
-      var isBool = typeof no === 'boolean' ||
-        types[arg] === Boolean ||
-        Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 ||
-        (typeof types[arg] === 'undefined' && !hadEq) ||
-        (la === "false" &&
-         (types[arg] === null ||
-          Array.isArray(types[arg]) && ~types[arg].indexOf(null)))
-
-      if (isBool) {
-        // just set and move along
-        val = !no
-        // however, also support --bool true or --bool false
-        if (la === "true" || la === "false") {
-          val = JSON.parse(la)
-          la = null
-          if (no) val = !val
-          i ++
-        }
-
-        // also support "foo":[Boolean, "bar"] and "--foo bar"
-        if (Array.isArray(types[arg]) && la) {
-          if (~types[arg].indexOf(la)) {
-            // an explicit type
-            val = la
-            i ++
-          } else if ( la === "null" && ~types[arg].indexOf(null) ) {
-            // null allowed
-            val = null
-            i ++
-          } else if ( !la.match(/^-{2,}[^-]/) &&
-                      !isNaN(la) &&
-                      ~types[arg].indexOf(Number) ) {
-            // number
-            val = +la
-            i ++
-          } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) {
-            // string
-            val = la
-            i ++
-          }
-        }
-
-        if (isArray) (data[arg] = data[arg] || []).push(val)
-        else data[arg] = val
-
-        continue
-      }
-
-      if (types[arg] === String && la === undefined)
-        la = ""
-
-      if (la && la.match(/^-{2,}$/)) {
-        la = undefined
-        i --
-      }
-
-      val = la === undefined ? true : la
-      if (isArray) (data[arg] = data[arg] || []).push(val)
-      else data[arg] = val
-
-      i ++
-      continue
-    }
-    remain.push(arg)
-  }
-}
-
-function resolveShort (arg, shorthands, shortAbbr, abbrevs) {
-  // handle single-char shorthands glommed together, like
-  // npm ls -glp, but only if there is one dash, and only if
-  // all of the chars are single-char shorthands, and it's
-  // not a match to some other abbrev.
-  arg = arg.replace(/^-+/, '')
-
-  // if it's an exact known option, then don't go any further
-  if (abbrevs[arg] === arg)
-    return null
-
-  // if it's an exact known shortopt, same deal
-  if (shorthands[arg]) {
-    // make it an array, if it's a list of words
-    if (shorthands[arg] && !Array.isArray(shorthands[arg]))
-      shorthands[arg] = shorthands[arg].split(/\s+/)
-
-    return shorthands[arg]
-  }
-
-  // first check to see if this arg is a set of single-char shorthands
-  var singles = shorthands.___singles
-  if (!singles) {
-    singles = Object.keys(shorthands).filter(function (s) {
-      return s.length === 1
-    }).reduce(function (l,r) {
-      l[r] = true
-      return l
-    }, {})
-    shorthands.___singles = singles
-    debug('shorthand singles', singles)
-  }
-
-  var chrs = arg.split("").filter(function (c) {
-    return singles[c]
-  })
-
-  if (chrs.join("") === arg) return chrs.map(function (c) {
-    return shorthands[c]
-  }).reduce(function (l, r) {
-    return l.concat(r)
-  }, [])
-
-
-  // if it's an arg abbrev, and not a literal shorthand, then prefer the arg
-  if (abbrevs[arg] && !shorthands[arg])
-    return null
-
-  // if it's an abbr for a shorthand, then use that
-  if (shortAbbr[arg])
-    arg = shortAbbr[arg]
-
-  // make it an array, if it's a list of words
-  if (shorthands[arg] && !Array.isArray(shorthands[arg]))
-    shorthands[arg] = shorthands[arg].split(/\s+/)
-
-  return shorthands[arg]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md
deleted file mode 100644
index 2f302612..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/CONTRIBUTING.md
+++ /dev/null
@@ -1,3 +0,0 @@
- To get started, <a
- href="http://www.clahub.com/agreements/isaacs/abbrev-js">sign the
- Contributor License Agreement</a>.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/LICENSE
deleted file mode 100644
index 05a40109..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
-All rights reserved.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/README.md
deleted file mode 100644
index 99746fe6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# abbrev-js
-
-Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
-
-Usage:
-
-    var abbrev = require("abbrev");
-    abbrev("foo", "fool", "folding", "flop");
-    
-    // returns:
-    { fl: 'flop'
-    , flo: 'flop'
-    , flop: 'flop'
-    , fol: 'folding'
-    , fold: 'folding'
-    , foldi: 'folding'
-    , foldin: 'folding'
-    , folding: 'folding'
-    , foo: 'foo'
-    , fool: 'fool'
-    }
-
-This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/abbrev.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/abbrev.js
deleted file mode 100644
index 69cfeac5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/abbrev.js
+++ /dev/null
@@ -1,62 +0,0 @@
-
-module.exports = exports = abbrev.abbrev = abbrev
-
-abbrev.monkeyPatch = monkeyPatch
-
-function monkeyPatch () {
-  Object.defineProperty(Array.prototype, 'abbrev', {
-    value: function () { return abbrev(this) },
-    enumerable: false, configurable: true, writable: true
-  })
-
-  Object.defineProperty(Object.prototype, 'abbrev', {
-    value: function () { return abbrev(Object.keys(this)) },
-    enumerable: false, configurable: true, writable: true
-  })
-}
-
-function abbrev (list) {
-  if (arguments.length !== 1 || !Array.isArray(list)) {
-    list = Array.prototype.slice.call(arguments, 0)
-  }
-  for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
-    args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
-  }
-
-  // sort them lexicographically, so that they're next to their nearest kin
-  args = args.sort(lexSort)
-
-  // walk through each, seeing how much it has in common with the next and previous
-  var abbrevs = {}
-    , prev = ""
-  for (var i = 0, l = args.length ; i < l ; i ++) {
-    var current = args[i]
-      , next = args[i + 1] || ""
-      , nextMatches = true
-      , prevMatches = true
-    if (current === next) continue
-    for (var j = 0, cl = current.length ; j < cl ; j ++) {
-      var curChar = current.charAt(j)
-      nextMatches = nextMatches && curChar === next.charAt(j)
-      prevMatches = prevMatches && curChar === prev.charAt(j)
-      if (!nextMatches && !prevMatches) {
-        j ++
-        break
-      }
-    }
-    prev = current
-    if (j === cl) {
-      abbrevs[current] = current
-      continue
-    }
-    for (var a = current.substr(0, j) ; j <= cl ; j ++) {
-      abbrevs[a] = current
-      a += current.charAt(j)
-    }
-  }
-  return abbrevs
-}
-
-function lexSort (a, b) {
-  return a === b ? 0 : a > b ? 1 : -1
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/package.json
deleted file mode 100644
index 91f1dd9c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/package.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-  "name": "abbrev",
-  "version": "1.0.5",
-  "description": "Like ruby's abbrev module, but in js",
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me"
-  },
-  "main": "abbrev.js",
-  "scripts": {
-    "test": "node test.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "http://github.com/isaacs/abbrev-js"
-  },
-  "license": {
-    "type": "MIT",
-    "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE"
-  },
-  "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n    var abbrev = require(\"abbrev\");\n    abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n    \n    // returns:\n    { fl: 'flop'\n    , flo: 'flop'\n    , flop: 'flop'\n    , fol: 'folding'\n    , fold: 'folding'\n    , foldi: 'folding'\n    , foldin: 'folding'\n    , folding: 'folding'\n    , foo: 'foo'\n    , fool: 'fool'\n    }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/abbrev-js/issues"
-  },
-  "homepage": "https://github.com/isaacs/abbrev-js",
-  "_id": "abbrev@1.0.5",
-  "_shasum": "5d8257bd9ebe435e698b2fa431afde4fe7b10b03",
-  "_from": "abbrev@1",
-  "_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/test.js
deleted file mode 100644
index d5a7303e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/node_modules/abbrev/test.js
+++ /dev/null
@@ -1,47 +0,0 @@
-var abbrev = require('./abbrev.js')
-var assert = require("assert")
-var util = require("util")
-
-console.log("TAP Version 13")
-var count = 0
-
-function test (list, expect) {
-  count++
-  var actual = abbrev(list)
-  assert.deepEqual(actual, expect,
-    "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+
-    "actual: "+util.inspect(actual))
-  actual = abbrev.apply(exports, list)
-  assert.deepEqual(abbrev.apply(exports, list), expect,
-    "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+
-    "actual: "+util.inspect(actual))
-  console.log('ok - ' + list.join(' '))
-}
-
-test([ "ruby", "ruby", "rules", "rules", "rules" ],
-{ rub: 'ruby'
-, ruby: 'ruby'
-, rul: 'rules'
-, rule: 'rules'
-, rules: 'rules'
-})
-test(["fool", "foom", "pool", "pope"],
-{ fool: 'fool'
-, foom: 'foom'
-, poo: 'pool'
-, pool: 'pool'
-, pop: 'pope'
-, pope: 'pope'
-})
-test(["a", "ab", "abc", "abcd", "abcde", "acde"],
-{ a: 'a'
-, ab: 'ab'
-, abc: 'abc'
-, abcd: 'abcd'
-, abcde: 'abcde'
-, ac: 'acde'
-, acd: 'acde'
-, acde: 'acde'
-})
-
-console.log("0..%d", count)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/package.json
deleted file mode 100644
index 049247be..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/package.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "name": "nopt",
-  "version": "2.2.1",
-  "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.",
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "main": "lib/nopt.js",
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "http://github.com/isaacs/nopt"
-  },
-  "bin": {
-    "nopt": "./bin/nopt.js"
-  },
-  "license": {
-    "type": "MIT",
-    "url": "https://github.com/isaacs/nopt/raw/master/LICENSE"
-  },
-  "dependencies": {
-    "abbrev": "1"
-  },
-  "devDependencies": {
-    "tap": "~0.4.8"
-  },
-  "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it.  The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser.  We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system.  You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n    // my-program.js\n    var nopt = require(\"nopt\")\n      , Stream = require(\"stream\").Stream\n      , path = require(\"path\")\n      , knownOpts = { \"foo\" : [String, null]\n                    , \"bar\" : [Stream, Number]\n                    , \"baz\" : path\n                    , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n                    , \"flag\" : Boolean\n                    , \"pick\" : Boolean\n                    , \"many\" : [String, Array]\n                    }\n      , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n                     , \"b7\" : [\"--bar\", \"7\"]\n                     , \"m\" : [\"--bloo\", \"medium\"]\n                     , \"p\" : [\"--pick\"]\n                     , \"f\" : [\"--flag\"]\n                     }\n                 // everything is optional.\n                 // knownOpts and shorthands default to {}\n                 // arg list defaults to process.argv\n                 // slice defaults to 2\n      , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n    console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp  # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk -fp # unknown opts are ok.\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array.  The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string.  No parsing is done.\n* path: A file system path.  Gets resolved against cwd if not absolute.\n* url: A url.  If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n  then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`.  If an option is a boolean,\n  then it does not need a value, and its presence will imply `true` as\n  the value.  To negate boolean flags, do `--no-whatever` or `--whatever\n  false`\n* NaN: Means that the option is strictly not allowed.  Any value will\n  fail.\n* Stream: An object matching the \"Stream\" class in node.  Valuable\n  for use when validating programmatically.  (npm uses this to let you\n  supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n  will be parsed as a list of options.  This means that multiple values\n  can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values.  For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list.  For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null.  When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`.  Each item in that\nhash is an object with a `type` member and a `validate` method.  The\n`type` member is an object that matches what goes in the type list.  The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`.  Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found.  You can change this behavior by assigning a method\nto `nopt.invalidHandler`.  This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining.  If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported.  If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts.  For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you.  So they're sliced off by\ndefault.  If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/nopt/issues"
-  },
-  "homepage": "https://github.com/isaacs/nopt",
-  "_id": "nopt@2.2.1",
-  "_shasum": "2aa09b7d1768487b3b89a9c5aa52335bff0baea7",
-  "_from": "nopt@~2.2.0",
-  "_resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/test/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/test/basic.js
deleted file mode 100644
index b31dccf5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/nopt/test/basic.js
+++ /dev/null
@@ -1,243 +0,0 @@
-var nopt = require("../")
-  , test = require('tap').test
-
-
-test("passing a string results in a string", function (t) {
-  var parsed = nopt({ key: String }, {}, ["--key", "myvalue"], 0)
-  t.same(parsed.key, "myvalue")
-  t.end()
-})
-
-// https://github.com/npm/nopt/issues/31
-test("Empty String results in empty string, not true", function (t) {
-  var parsed = nopt({ empty: String }, {}, ["--empty"], 0)
-  t.same(parsed.empty, "")
-  t.end()
-})
-
-test("~ path is resolved to $HOME", function (t) {
-  var path = require("path")
-  if (!process.env.HOME) process.env.HOME = "/tmp"
-  var parsed = nopt({key: path}, {}, ["--key=~/val"], 0)
-  t.same(parsed.key, path.resolve(process.env.HOME, "val"))
-  t.end()
-})
-
-test("other tests", function (t) {
-
-  var util = require("util")
-    , Stream = require("stream")
-    , path = require("path")
-    , url = require("url")
-
-    , shorthands =
-      { s : ["--loglevel", "silent"]
-      , d : ["--loglevel", "info"]
-      , dd : ["--loglevel", "verbose"]
-      , ddd : ["--loglevel", "silly"]
-      , noreg : ["--no-registry"]
-      , reg : ["--registry"]
-      , "no-reg" : ["--no-registry"]
-      , silent : ["--loglevel", "silent"]
-      , verbose : ["--loglevel", "verbose"]
-      , h : ["--usage"]
-      , H : ["--usage"]
-      , "?" : ["--usage"]
-      , help : ["--usage"]
-      , v : ["--version"]
-      , f : ["--force"]
-      , desc : ["--description"]
-      , "no-desc" : ["--no-description"]
-      , "local" : ["--no-global"]
-      , l : ["--long"]
-      , p : ["--parseable"]
-      , porcelain : ["--parseable"]
-      , g : ["--global"]
-      }
-
-    , types =
-      { aoa: Array
-      , nullstream: [null, Stream]
-      , date: Date
-      , str: String
-      , browser : String
-      , cache : path
-      , color : ["always", Boolean]
-      , depth : Number
-      , description : Boolean
-      , dev : Boolean
-      , editor : path
-      , force : Boolean
-      , global : Boolean
-      , globalconfig : path
-      , group : [String, Number]
-      , gzipbin : String
-      , logfd : [Number, Stream]
-      , loglevel : ["silent","win","error","warn","info","verbose","silly"]
-      , long : Boolean
-      , "node-version" : [false, String]
-      , npaturl : url
-      , npat : Boolean
-      , "onload-script" : [false, String]
-      , outfd : [Number, Stream]
-      , parseable : Boolean
-      , pre: Boolean
-      , prefix: path
-      , proxy : url
-      , "rebuild-bundle" : Boolean
-      , registry : url
-      , searchopts : String
-      , searchexclude: [null, String]
-      , shell : path
-      , t: [Array, String]
-      , tag : String
-      , tar : String
-      , tmp : path
-      , "unsafe-perm" : Boolean
-      , usage : Boolean
-      , user : String
-      , username : String
-      , userconfig : path
-      , version : Boolean
-      , viewer: path
-      , _exit : Boolean
-      , path: path
-      }
-
-  ; [["-v", {version:true}, []]
-    ,["---v", {version:true}, []]
-    ,["ls -s --no-reg connect -d",
-      {loglevel:"info",registry:null},["ls","connect"]]
-    ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]]
-    ,["ls --registry blargle", {}, ["ls"]]
-    ,["--no-registry", {registry:null}, []]
-    ,["--no-color true", {color:false}, []]
-    ,["--no-color false", {color:true}, []]
-    ,["--no-color", {color:false}, []]
-    ,["--color false", {color:false}, []]
-    ,["--color --logfd 7", {logfd:7,color:true}, []]
-    ,["--color=true", {color:true}, []]
-    ,["--logfd=10", {logfd:10}, []]
-    ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]]
-    ,["--tmp=tmp -tar=gtar",
-      {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]]
-    ,["--logfd x", {}, []]
-    ,["a -true -- -no-false", {true:true},["a","-no-false"]]
-    ,["a -no-false", {false:false},["a"]]
-    ,["a -no-no-true", {true:true}, ["a"]]
-    ,["a -no-no-no-false", {false:false}, ["a"]]
-    ,["---NO-no-No-no-no-no-nO-no-no"+
-      "-No-no-no-no-no-no-no-no-no"+
-      "-no-no-no-no-NO-NO-no-no-no-no-no-no"+
-      "-no-body-can-do-the-boogaloo-like-I-do"
-     ,{"body-can-do-the-boogaloo-like-I-do":false}, []]
-    ,["we are -no-strangers-to-love "+
-      "--you-know=the-rules --and=so-do-i "+
-      "---im-thinking-of=a-full-commitment "+
-      "--no-you-would-get-this-from-any-other-guy "+
-      "--no-gonna-give-you-up "+
-      "-no-gonna-let-you-down=true "+
-      "--no-no-gonna-run-around false "+
-      "--desert-you=false "+
-      "--make-you-cry false "+
-      "--no-tell-a-lie "+
-      "--no-no-and-hurt-you false"
-     ,{"strangers-to-love":false
-      ,"you-know":"the-rules"
-      ,"and":"so-do-i"
-      ,"you-would-get-this-from-any-other-guy":false
-      ,"gonna-give-you-up":false
-      ,"gonna-let-you-down":false
-      ,"gonna-run-around":false
-      ,"desert-you":false
-      ,"make-you-cry":false
-      ,"tell-a-lie":false
-      ,"and-hurt-you":false
-      },["we", "are"]]
-    ,["-t one -t two -t three"
-     ,{t: ["one", "two", "three"]}
-     ,[]]
-    ,["-t one -t null -t three four five null"
-     ,{t: ["one", "null", "three"]}
-     ,["four", "five", "null"]]
-    ,["-t foo"
-     ,{t:["foo"]}
-     ,[]]
-    ,["--no-t"
-     ,{t:["false"]}
-     ,[]]
-    ,["-no-no-t"
-     ,{t:["true"]}
-     ,[]]
-    ,["-aoa one -aoa null -aoa 100"
-     ,{aoa:["one", null, 100]}
-     ,[]]
-    ,["-str 100"
-     ,{str:"100"}
-     ,[]]
-    ,["--color always"
-     ,{color:"always"}
-     ,[]]
-    ,["--no-nullstream"
-     ,{nullstream:null}
-     ,[]]
-    ,["--nullstream false"
-     ,{nullstream:null}
-     ,[]]
-    ,["--notadate=2011-01-25"
-     ,{notadate: "2011-01-25"}
-     ,[]]
-    ,["--date 2011-01-25"
-     ,{date: new Date("2011-01-25")}
-     ,[]]
-    ,["-cl 1"
-     ,{config: true, length: 1}
-     ,[]
-     ,{config: Boolean, length: Number, clear: Boolean}
-     ,{c: "--config", l: "--length"}]
-    ,["--acount bla"
-     ,{"acount":true}
-     ,["bla"]
-     ,{account: Boolean, credentials: Boolean, options: String}
-     ,{a:"--account", c:"--credentials",o:"--options"}]
-    ,["--clear"
-     ,{clear:true}
-     ,[]
-     ,{clear:Boolean,con:Boolean,len:Boolean,exp:Boolean,add:Boolean,rep:Boolean}
-     ,{c:"--con",l:"--len",e:"--exp",a:"--add",r:"--rep"}]
-    ,["--file -"
-     ,{"file":"-"}
-     ,[]
-     ,{file:String}
-     ,{}]
-    ,["--file -"
-     ,{"file":true}
-     ,["-"]
-     ,{file:Boolean}
-     ,{}]
-    ,["--path"
-     ,{"path":null}
-     ,[]]
-    ,["--path ."
-     ,{"path":process.cwd()}
-     ,[]]
-    ].forEach(function (test) {
-      var argv = test[0].split(/\s+/)
-        , opts = test[1]
-        , rem = test[2]
-        , actual = nopt(test[3] || types, test[4] || shorthands, argv, 0)
-        , parsed = actual.argv
-      delete actual.argv
-      for (var i in opts) {
-        var e = JSON.stringify(opts[i])
-          , a = JSON.stringify(actual[i] === undefined ? null : actual[i])
-        if (e && typeof e === "object") {
-          t.deepEqual(e, a)
-        } else {
-          t.equal(e, a)
-        }
-      }
-      t.deepEqual(rem, parsed.remain)
-    })
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/README.md
deleted file mode 100644
index ad67688d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/README.md
+++ /dev/null
@@ -1,153 +0,0 @@
-# npmlog
-
-The logger util that npm uses.
-
-This logger is very basic.  It does the logging for npm.  It supports
-custom levels and colored output.
-
-By default, logs are written to stderr.  If you want to send log messages
-to outputs other than streams, then you can change the `log.stream`
-member, or you can just listen to the events that it emits, and do
-whatever you want with them.
-
-# Basic Usage
-
-```
-var log = require('npmlog')
-
-// additional stuff ---------------------------+
-// message ----------+                         |
-// prefix ----+      |                         |
-// level -+   |      |                         |
-//        v   v      v                         v
-    log.info('fyi', 'I have a kitty cat: %j', myKittyCat)
-```
-
-## log.level
-
-* {String}
-
-The level to display logs at.  Any logs at or above this level will be
-displayed.  The special level `silent` will prevent anything from being
-displayed ever.
-
-## log.record
-
-* {Array}
-
-An array of all the log messages that have been entered.
-
-## log.maxRecordSize
-
-* {Number}
-
-The maximum number of records to keep.  If log.record gets bigger than
-10% over this value, then it is sliced down to 90% of this value.
-
-The reason for the 10% window is so that it doesn't have to resize a
-large array on every log entry.
-
-## log.prefixStyle
-
-* {Object}
-
-A style object that specifies how prefixes are styled.  (See below)
-
-## log.headingStyle
-
-* {Object}
-
-A style object that specifies how the heading is styled.  (See below)
-
-## log.heading
-
-* {String} Default: ""
-
-If set, a heading that is printed at the start of every line.
-
-## log.stream
-
-* {Stream} Default: `process.stderr`
-
-The stream where output is written.
-
-## log.enableColor()
-
-Force colors to be used on all messages, regardless of the output
-stream.
-
-## log.disableColor()
-
-Disable colors on all messages.
-
-## log.pause()
-
-Stop emitting messages to the stream, but do not drop them.
-
-## log.resume()
-
-Emit all buffered messages that were written while paused.
-
-## log.log(level, prefix, message, ...)
-
-* `level` {String} The level to emit the message at
-* `prefix` {String} A string prefix.  Set to "" to skip.
-* `message...` Arguments to `util.format`
-
-Emit a log message at the specified level.
-
-## log\[level](prefix, message, ...)
-
-For example,
-
-* log.silly(prefix, message, ...)
-* log.verbose(prefix, message, ...)
-* log.info(prefix, message, ...)
-* log.http(prefix, message, ...)
-* log.warn(prefix, message, ...)
-* log.error(prefix, message, ...)
-
-Like `log.log(level, prefix, message, ...)`.  In this way, each level is
-given a shorthand, so you can do `log.info(prefix, message)`.
-
-## log.addLevel(level, n, style, disp)
-
-* `level` {String} Level indicator
-* `n` {Number} The numeric level
-* `style` {Object} Object with fg, bg, inverse, etc.
-* `disp` {String} Optional replacement for `level` in the output.
-
-Sets up a new level with a shorthand function and so forth.
-
-Note that if the number is `Infinity`, then setting the level to that
-will cause all log messages to be suppressed.  If the number is
-`-Infinity`, then the only way to show it is to enable all log messages.
-
-# Events
-
-Events are all emitted with the message object.
-
-* `log` Emitted for all messages
-* `log.<level>` Emitted for all messages with the `<level>` level.
-* `<prefix>` Messages with prefixes also emit their prefix as an event.
-
-# Style Objects
-
-Style objects can have the following fields:
-
-* `fg` {String} Color for the foreground text
-* `bg` {String} Color for the background
-* `bold`, `inverse`, `underline` {Boolean} Set the associated property
-* `bell` {Boolean} Make a noise (This is pretty annoying, probably.)
-
-# Message Objects
-
-Every log event is emitted with a message object, and the `log.record`
-list contains all of them that have been created.  They have the
-following fields:
-
-* `id` {Number}
-* `level` {String}
-* `prefix` {String}
-* `message` {String} Result of `util.format()`
-* `messageRaw` {Array} Arguments to `util.format()`
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/example.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/example.js
deleted file mode 100644
index c009fb15..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/example.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var log = require('./log.js')
-
-log.heading = 'npm'
-
-console.error('log.level=silly')
-log.level = 'silly'
-log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}})
-log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}})
-log.info('info prefix', 'x = %j', {foo:{bar:'baz'}})
-log.http('http prefix', 'x = %j', {foo:{bar:'baz'}})
-log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}})
-log.error('error prefix', 'x = %j', {foo:{bar:'baz'}})
-log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}})
-
-console.error('log.level=silent')
-log.level = 'silent'
-log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}})
-log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}})
-log.info('info prefix', 'x = %j', {foo:{bar:'baz'}})
-log.http('http prefix', 'x = %j', {foo:{bar:'baz'}})
-log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}})
-log.error('error prefix', 'x = %j', {foo:{bar:'baz'}})
-log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}})
-
-console.error('log.level=info')
-log.level = 'info'
-log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}})
-log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}})
-log.info('info prefix', 'x = %j', {foo:{bar:'baz'}})
-log.http('http prefix', 'x = %j', {foo:{bar:'baz'}})
-log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}})
-log.error('error prefix', 'x = %j', {foo:{bar:'baz'}})
-log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}})
-log.error('404', 'This is a longer\n'+
-                 'message, with some details\n'+
-                 'and maybe a stack.\n'+
-                 new Error('a 404 error').stack)
-log.addLevel('noise', 10000, {beep: true})
-log.noise(false, 'LOUD NOISES')
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/log.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/log.js
deleted file mode 100644
index 38b7c74a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/log.js
+++ /dev/null
@@ -1,154 +0,0 @@
-var EE = require('events').EventEmitter
-var log = exports = module.exports = new EE
-var util = require('util')
-
-var ansi = require('ansi')
-log.cursor = ansi(process.stderr)
-log.stream = process.stderr
-
-// by default, let ansi decide based on tty-ness.
-var colorEnabled = undefined
-log.enableColor = function () {
-  colorEnabled = true
-  this.cursor.enabled = true
-}
-log.disableColor = function () {
-  colorEnabled = false
-  this.cursor.enabled = false
-}
-
-// default level
-log.level = 'info'
-
-// temporarily stop emitting, but don't drop
-log.pause = function () {
-  this._paused = true
-}
-
-log.resume = function () {
-  if (!this._paused) return
-  this._paused = false
-
-  var b = this._buffer
-  this._buffer = []
-  b.forEach(function (m) {
-    this.emitLog(m)
-  }, this)
-}
-
-log._buffer = []
-
-var id = 0
-log.record = []
-log.maxRecordSize = 10000
-log.log = function (lvl, prefix, message) {
-  var l = this.levels[lvl]
-  if (l === undefined) {
-    return this.emit('error', new Error(util.format(
-      'Undefined log level: %j', lvl)))
-  }
-
-  var a = new Array(arguments.length - 2)
-  var stack = null
-  for (var i = 2; i < arguments.length; i ++) {
-    var arg = a[i-2] = arguments[i]
-
-    // resolve stack traces to a plain string.
-    if (typeof arg === 'object' && arg &&
-        (arg instanceof Error) && arg.stack) {
-      arg.stack = stack = arg.stack + ''
-    }
-  }
-  if (stack) a.unshift(stack + '\n')
-  message = util.format.apply(util, a)
-
-  var m = { id: id++,
-            level: lvl,
-            prefix: String(prefix || ''),
-            message: message,
-            messageRaw: a }
-
-  this.emit('log', m)
-  this.emit('log.' + lvl, m)
-  if (m.prefix) this.emit(m.prefix, m)
-
-  this.record.push(m)
-  var mrs = this.maxRecordSize
-  var n = this.record.length - mrs
-  if (n > mrs / 10) {
-    var newSize = Math.floor(mrs * 0.9)
-    this.record = this.record.slice(-1 * newSize)
-  }
-
-  this.emitLog(m)
-}.bind(log)
-
-log.emitLog = function (m) {
-  if (this._paused) {
-    this._buffer.push(m)
-    return
-  }
-  var l = this.levels[m.level]
-  if (l === undefined) return
-  if (l < this.levels[this.level]) return
-  if (l > 0 && !isFinite(l)) return
-
-  var style = log.style[m.level]
-  var disp = log.disp[m.level] || m.level
-  m.message.split(/\r?\n/).forEach(function (line) {
-    if (this.heading) {
-      this.write(this.heading, this.headingStyle)
-      this.write(' ')
-    }
-    this.write(disp, log.style[m.level])
-    var p = m.prefix || ''
-    if (p) this.write(' ')
-    this.write(p, this.prefixStyle)
-    this.write(' ' + line + '\n')
-  }, this)
-}
-
-log.write = function (msg, style) {
-  if (!this.cursor) return
-  if (this.stream !== this.cursor.stream) {
-    this.cursor = ansi(this.stream, { enabled: colorEnabled })
-  }
-
-  style = style || {}
-  if (style.fg) this.cursor.fg[style.fg]()
-  if (style.bg) this.cursor.bg[style.bg]()
-  if (style.bold) this.cursor.bold()
-  if (style.underline) this.cursor.underline()
-  if (style.inverse) this.cursor.inverse()
-  if (style.beep) this.cursor.beep()
-  this.cursor.write(msg).reset()
-}
-
-log.addLevel = function (lvl, n, style, disp) {
-  if (!disp) disp = lvl
-  this.levels[lvl] = n
-  this.style[lvl] = style
-  if (!this[lvl]) this[lvl] = function () {
-    var a = new Array(arguments.length + 1)
-    a[0] = lvl
-    for (var i = 0; i < arguments.length; i ++) {
-      a[i + 1] = arguments[i]
-    }
-    return this.log.apply(this, a)
-  }.bind(this)
-  this.disp[lvl] = disp
-}
-
-log.prefixStyle = { fg: 'magenta' }
-log.headingStyle = { fg: 'white', bg: 'black' }
-
-log.style = {}
-log.levels = {}
-log.disp = {}
-log.addLevel('silly', -Infinity, { inverse: true }, 'sill')
-log.addLevel('verbose', 1000, { fg: 'blue', bg: 'black' }, 'verb')
-log.addLevel('info', 2000, { fg: 'green' })
-log.addLevel('http', 3000, { fg: 'green', bg: 'black' })
-log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN')
-log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!')
-log.addLevel('silent', Infinity)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/README.md
deleted file mode 100644
index 2f9bb140..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-ansi.js
-=========
-### Advanced ANSI formatting tool for Node.js
-
-`ansi.js` is a module for Node.js that provides an easy-to-use API for
-writing ANSI escape codes to `Stream` instances. ANSI escape codes are used to do
-fancy things in a terminal window, like render text in colors, delete characters,
-lines, the entire window, or hide and show the cursor, and lots more!
-
-The code for the example in the screenshot above can be found in the
-`examples/imgcat` directory.
-
-#### Features:
-
- * 256 color support for the terminal!
- * Make a beep sound from your terminal!
- * Works with *any* writable `Stream` instance.
- * Allows you to move the cursor anywhere on the terminal window.
- * Allows you to delete existing contents from the terminal window.
- * Allows you to hide and show the cursor.
- * Converts CSS color codes and RGB values into ANSI escape codes.
- * Low-level; you are in control of when escape codes are used, it's not abstracted.
-
-
-Installation
-------------
-
-Install with `npm`:
-
-``` bash
-$ npm install ansi
-```
-
-
-Example
--------
-
-``` js
-var ansi = require('ansi')
-  , cursor = ansi(process.stdout)
-
-// You can chain your calls forever:
-cursor
-  .red()                 // Set font color to red
-  .bg.grey()             // Set background color to grey
-  .write('Hello World!') // Write 'Hello World!' to stdout
-  .bg.reset()            // Reset the bgcolor before writing the trailing \n,
-                         //      to avoid Terminal glitches
-  .write('\n')           // And a final \n to wrap things up
-
-// Rendering modes are persistent:
-cursor.hex('#660000').bold().underline()
-
-// You can use the regular logging functions, text will be green
-console.log('This is blood red, bold text')
-
-// To reset just the foreground color:
-cursor.fg.reset()
-
-console.log('This will still be bold')
-
-// Clean up after yourself!
-cursor.reset()
-```
-
-
-License
--------
-
-(The MIT License)
-
-Copyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/color-spaces.pl b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/color-spaces.pl
deleted file mode 100644
index 8774c044..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/color-spaces.pl
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/perl
-# Author: Todd Larason <jtl@molehill.org>
-# $XFree86: xc/programs/xterm/vttests/256colors2.pl,v 1.1 1999/07/11 08:49:54 dawes Exp $
-
-print "256 color mode\n\n";
-
-# display back ground colors
-
-for ($fgbg = 38; $fgbg <= 48; $fgbg +=10) {
-
-# first the system ones:
-print "System colors:\n";
-for ($color = 0; $color < 8; $color++) {
-    print "\x1b[${fgbg};5;${color}m::";
-}
-print "\x1b[0m\n";
-for ($color = 8; $color < 16; $color++) {
-    print "\x1b[${fgbg};5;${color}m::";
-}
-print "\x1b[0m\n\n";
-
-# now the color cube
-print "Color cube, 6x6x6:\n";
-for ($green = 0; $green < 6; $green++) {
-    for ($red = 0; $red < 6; $red++) {
-	for ($blue = 0; $blue < 6; $blue++) {
-	    $color = 16 + ($red * 36) + ($green * 6) + $blue;
-	    print "\x1b[${fgbg};5;${color}m::";
-	}
-	print "\x1b[0m ";
-    }
-    print "\n";
-}
-
-# now the grayscale ramp
-print "Grayscale ramp:\n";
-for ($color = 232; $color < 256; $color++) {
-    print "\x1b[${fgbg};5;${color}m::";
-}
-print "\x1b[0m\n\n";
-
-}
-
-print "Examples for the 3-byte color mode\n\n";
-
-for ($fgbg = 38; $fgbg <= 48; $fgbg +=10) {
-
-# now the color cube
-print "Color cube\n";
-for ($green = 0; $green < 256; $green+=51) {
-    for ($red = 0; $red < 256; $red+=51) {
-	for ($blue = 0; $blue < 256; $blue+=51) {
-            print "\x1b[${fgbg};2;${red};${green};${blue}m::";
-	}
-	print "\x1b[0m ";
-    }
-    print "\n";
-}
-
-# now the grayscale ramp
-print "Grayscale ramp:\n";
-for ($gray = 8; $gray < 256; $gray+=10) {
-    print "\x1b[${fgbg};2;${gray};${gray};${gray}m::";
-}
-print "\x1b[0m\n\n";
-
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/beep/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/beep/index.js
deleted file mode 100755
index c1ec929d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/beep/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Invokes the terminal "beep" sound once per second on every exact second.
- */
-
-process.title = 'beep'
-
-var cursor = require('../../')(process.stdout)
-
-function beep () {
-  cursor.beep()
-  setTimeout(beep, 1000 - (new Date()).getMilliseconds())
-}
-
-setTimeout(beep, 1000 - (new Date()).getMilliseconds())
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/clear/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/clear/index.js
deleted file mode 100755
index 6ac21ffa..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/clear/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Like GNU ncurses "clear" command.
- * https://github.com/mscdex/node-ncurses/blob/master/deps/ncurses/progs/clear.c
- */
-
-process.title = 'clear'
-
-function lf () { return '\n' }
-
-require('../../')(process.stdout)
-  .write(Array.apply(null, Array(process.stdout.getWindowSize()[1])).map(lf).join(''))
-  .eraseData(2)
-  .goto(1, 1)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/cursorPosition.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/cursorPosition.js
deleted file mode 100755
index 50f96449..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/cursorPosition.js
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env node
-
-var tty = require('tty')
-var cursor = require('../')(process.stdout)
-
-// listen for the queryPosition report on stdin
-process.stdin.resume()
-raw(true)
-
-process.stdin.once('data', function (b) {
-  var match = /\[(\d+)\;(\d+)R$/.exec(b.toString())
-  if (match) {
-    var xy = match.slice(1, 3).reverse().map(Number)
-    console.error(xy)
-  }
-
-  // cleanup and close stdin
-  raw(false)
-  process.stdin.pause()
-})
-
-
-// send the query position request code to stdout
-cursor.queryPosition()
-
-function raw (mode) {
-  if (process.stdin.setRawMode) {
-    process.stdin.setRawMode(mode)
-  } else {
-    tty.setRawMode(mode)
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/progress/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/progress/index.js
deleted file mode 100644
index d28dbda2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/progress/index.js
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env node
-
-var assert = require('assert')
-  , ansi = require('../../')
-
-function Progress (stream, width) {
-  this.cursor = ansi(stream)
-  this.delta = this.cursor.newlines
-  this.width = width | 0 || 10
-  this.open = '['
-  this.close = ']'
-  this.complete = '█'
-  this.incomplete = '_'
-
-  // initial render
-  this.progress = 0
-}
-
-Object.defineProperty(Progress.prototype, 'progress', {
-    get: get
-  , set: set
-  , configurable: true
-  , enumerable: true
-})
-
-function get () {
-  return this._progress
-}
-
-function set (v) {
-  this._progress = Math.max(0, Math.min(v, 100))
-
-  var w = this.width - this.complete.length - this.incomplete.length
-    , n = w * (this._progress / 100) | 0
-    , i = w - n
-    , com = c(this.complete, n)
-    , inc = c(this.incomplete, i)
-    , delta = this.cursor.newlines - this.delta
-
-  assert.equal(com.length + inc.length, w)
-
-  if (delta > 0) {
-    this.cursor.up(delta)
-    this.delta = this.cursor.newlines
-  }
-
-  this.cursor
-    .horizontalAbsolute(0)
-    .eraseLine(2)
-    .fg.white()
-    .write(this.open)
-    .fg.grey()
-    .bold()
-    .write(com)
-    .resetBold()
-    .write(inc)
-    .fg.white()
-    .write(this.close)
-    .fg.reset()
-    .write('\n')
-}
-
-function c (char, length) {
-  return Array.apply(null, Array(length)).map(function () {
-    return char
-  }).join('')
-}
-
-
-
-
-// Usage
-var width = parseInt(process.argv[2], 10) || process.stdout.getWindowSize()[0] / 2
-  , p = new Progress(process.stdout, width)
-
-;(function tick () {
-  p.progress += Math.random() * 5
-  p.cursor
-    .eraseLine(2)
-    .write('Progress: ')
-    .bold().write(p.progress.toFixed(2))
-    .write('%')
-    .resetBold()
-    .write('\n')
-  if (p.progress < 100)
-    setTimeout(tick, 100)
-})()
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/starwars.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/starwars.js
deleted file mode 100755
index 06f8ba84..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/examples/starwars.js
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * A little script to play the ASCII Star Wars, but with a hidden cursor,
- * since over `telnet(1)` the cursor remains visible which is annoying.
- */
-
-process.title = 'starwars'
-
-var net = require('net')
-  , cursor = require('../')(process.stdout)
-  , color = process.argv[2]
-
-// enable "raw mode" so that keystrokes aren't visible
-process.stdin.resume()
-if (process.stdin.setRawMode) {
-  process.stdin.setRawMode(true)
-} else {
-  require('tty').setRawMode(true)
-}
-
-// connect to the ASCII Star Wars server
-var socket = net.connect(23, 'towel.blinkenlights.nl')
-
-socket.on('connect', function () {
-  if (color in cursor.fg) {
-    cursor.fg[color]()
-  }
-  cursor.hide()
-  socket.pipe(process.stdout)
-})
-
-process.stdin.on('data', function (data) {
-  if (data.toString() === '\u0003') {
-    // Ctrl+C; a.k.a SIGINT
-    socket.destroy()
-    process.stdin.pause()
-  }
-})
-
-process.on('exit', function () {
-  cursor
-    .show()
-    .fg.reset()
-    .write('\n')
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/ansi.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/ansi.js
deleted file mode 100644
index 52fc8ec8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/ansi.js
+++ /dev/null
@@ -1,405 +0,0 @@
-
-/**
- * References:
- *
- *   - http://en.wikipedia.org/wiki/ANSI_escape_code
- *   - http://www.termsys.demon.co.uk/vtansi.htm
- *
- */
-
-/**
- * Module dependencies.
- */
-
-var emitNewlineEvents = require('./newlines')
-  , prefix = '\x1b[' // For all escape codes
-  , suffix = 'm'     // Only for color codes
-
-/**
- * The ANSI escape sequences.
- */
-
-var codes = {
-    up: 'A'
-  , down: 'B'
-  , forward: 'C'
-  , back: 'D'
-  , nextLine: 'E'
-  , previousLine: 'F'
-  , horizontalAbsolute: 'G'
-  , eraseData: 'J'
-  , eraseLine: 'K'
-  , scrollUp: 'S'
-  , scrollDown: 'T'
-  , savePosition: 's'
-  , restorePosition: 'u'
-  , queryPosition: '6n'
-  , hide: '?25l'
-  , show: '?25h'
-}
-
-/**
- * Rendering ANSI codes.
- */
-
-var styles = {
-    bold: 1
-  , italic: 3
-  , underline: 4
-  , inverse: 7
-}
-
-/**
- * The negating ANSI code for the rendering modes.
- */
-
-var reset = {
-    bold: 22
-  , italic: 23
-  , underline: 24
-  , inverse: 27
-}
-
-/**
- * The standard, styleable ANSI colors.
- */
-
-var colors = {
-    white: 37
-  , black: 30
-  , blue: 34
-  , cyan: 36
-  , green: 32
-  , magenta: 35
-  , red: 31
-  , yellow: 33
-  , grey: 90
-  , brightBlack: 90
-  , brightRed: 91
-  , brightGreen: 92
-  , brightYellow: 93
-  , brightBlue: 94
-  , brightMagenta: 95
-  , brightCyan: 96
-  , brightWhite: 97
-}
-
-
-/**
- * Creates a Cursor instance based off the given `writable stream` instance.
- */
-
-function ansi (stream, options) {
-  if (stream._ansicursor) {
-    return stream._ansicursor
-  } else {
-    return stream._ansicursor = new Cursor(stream, options)
-  }
-}
-module.exports = exports = ansi
-
-/**
- * The `Cursor` class.
- */
-
-function Cursor (stream, options) {
-  if (!(this instanceof Cursor)) {
-    return new Cursor(stream, options)
-  }
-  if (typeof stream != 'object' || typeof stream.write != 'function') {
-    throw new Error('a valid Stream instance must be passed in')
-  }
-
-  // the stream to use
-  this.stream = stream
-
-  // when 'enabled' is false then all the functions are no-ops except for write()
-  this.enabled = options && options.enabled
-  if (typeof this.enabled === 'undefined') {
-    this.enabled = stream.isTTY
-  }
-  this.enabled = !!this.enabled
-
-  // then `buffering` is true, then `write()` calls are buffered in
-  // memory until `flush()` is invoked
-  this.buffering = !!(options && options.buffering)
-  this._buffer = []
-
-  // controls the foreground and background colors
-  this.fg = this.foreground = new Colorer(this, 0)
-  this.bg = this.background = new Colorer(this, 10)
-
-  // defaults
-  this.Bold = false
-  this.Italic = false
-  this.Underline = false
-  this.Inverse = false
-
-  // keep track of the number of "newlines" that get encountered
-  this.newlines = 0
-  emitNewlineEvents(stream)
-  stream.on('newline', function () {
-    this.newlines++
-  }.bind(this))
-}
-exports.Cursor = Cursor
-
-/**
- * Helper function that calls `write()` on the underlying Stream.
- * Returns `this` instead of the write() return value to keep
- * the chaining going.
- */
-
-Cursor.prototype.write = function (data) {
-  if (this.buffering) {
-    this._buffer.push(arguments)
-  } else {
-    this.stream.write.apply(this.stream, arguments)
-  }
-  return this
-}
-
-/**
- * Buffer `write()` calls into memory.
- *
- * @api public
- */
-
-Cursor.prototype.buffer = function () {
-  this.buffering = true
-  return this
-}
-
-/**
- * Write out the in-memory buffer.
- *
- * @api public
- */
-
-Cursor.prototype.flush = function () {
-  this.buffering = false
-  var str = this._buffer.map(function (args) {
-    if (args.length != 1) throw new Error('unexpected args length! ' + args.length);
-    return args[0];
-  }).join('');
-  this._buffer.splice(0); // empty
-  this.write(str);
-  return this
-}
-
-
-/**
- * The `Colorer` class manages both the background and foreground colors.
- */
-
-function Colorer (cursor, base) {
-  this.current = null
-  this.cursor = cursor
-  this.base = base
-}
-exports.Colorer = Colorer
-
-/**
- * Write an ANSI color code, ensuring that the same code doesn't get rewritten.
- */
-
-Colorer.prototype._setColorCode = function setColorCode (code) {
-  var c = String(code)
-  if (this.current === c) return
-  this.cursor.enabled && this.cursor.write(prefix + c + suffix)
-  this.current = c
-  return this
-}
-
-
-/**
- * Set up the positional ANSI codes.
- */
-
-Object.keys(codes).forEach(function (name) {
-  var code = String(codes[name])
-  Cursor.prototype[name] = function () {
-    var c = code
-    if (arguments.length > 0) {
-      c = toArray(arguments).map(Math.round).join(';') + code
-    }
-    this.enabled && this.write(prefix + c)
-    return this
-  }
-})
-
-/**
- * Set up the functions for the rendering ANSI codes.
- */
-
-Object.keys(styles).forEach(function (style) {
-  var name = style[0].toUpperCase() + style.substring(1)
-    , c = styles[style]
-    , r = reset[style]
-
-  Cursor.prototype[style] = function () {
-    if (this[name]) return
-    this.enabled && this.write(prefix + c + suffix)
-    this[name] = true
-    return this
-  }
-
-  Cursor.prototype['reset' + name] = function () {
-    if (!this[name]) return
-    this.enabled && this.write(prefix + r + suffix)
-    this[name] = false
-    return this
-  }
-})
-
-/**
- * Setup the functions for the standard colors.
- */
-
-Object.keys(colors).forEach(function (color) {
-  var code = colors[color]
-
-  Colorer.prototype[color] = function () {
-    this._setColorCode(this.base + code)
-    return this.cursor
-  }
-
-  Cursor.prototype[color] = function () {
-    return this.foreground[color]()
-  }
-})
-
-/**
- * Makes a beep sound!
- */
-
-Cursor.prototype.beep = function () {
-  this.enabled && this.write('\x07')
-  return this
-}
-
-/**
- * Moves cursor to specific position
- */
-
-Cursor.prototype.goto = function (x, y) {
-  x = x | 0
-  y = y | 0
-  this.enabled && this.write(prefix + y + ';' + x + 'H')
-  return this
-}
-
-/**
- * Resets the color.
- */
-
-Colorer.prototype.reset = function () {
-  this._setColorCode(this.base + 39)
-  return this.cursor
-}
-
-/**
- * Resets all ANSI formatting on the stream.
- */
-
-Cursor.prototype.reset = function () {
-  this.enabled && this.write(prefix + '0' + suffix)
-  this.Bold = false
-  this.Italic = false
-  this.Underline = false
-  this.Inverse = false
-  this.foreground.current = null
-  this.background.current = null
-  return this
-}
-
-/**
- * Sets the foreground color with the given RGB values.
- * The closest match out of the 216 colors is picked.
- */
-
-Colorer.prototype.rgb = function (r, g, b) {
-  var base = this.base + 38
-    , code = rgb(r, g, b)
-  this._setColorCode(base + ';5;' + code)
-  return this.cursor
-}
-
-/**
- * Same as `cursor.fg.rgb(r, g, b)`.
- */
-
-Cursor.prototype.rgb = function (r, g, b) {
-  return this.foreground.rgb(r, g, b)
-}
-
-/**
- * Accepts CSS color codes for use with ANSI escape codes.
- * For example: `#FF000` would be bright red.
- */
-
-Colorer.prototype.hex = function (color) {
-  return this.rgb.apply(this, hex(color))
-}
-
-/**
- * Same as `cursor.fg.hex(color)`.
- */
-
-Cursor.prototype.hex = function (color) {
-  return this.foreground.hex(color)
-}
-
-
-// UTIL FUNCTIONS //
-
-/**
- * Translates a 255 RGB value to a 0-5 ANSI RGV value,
- * then returns the single ANSI color code to use.
- */
-
-function rgb (r, g, b) {
-  var red = r / 255 * 5
-    , green = g / 255 * 5
-    , blue = b / 255 * 5
-  return rgb5(red, green, blue)
-}
-
-/**
- * Turns rgb 0-5 values into a single ANSI color code to use.
- */
-
-function rgb5 (r, g, b) {
-  var red = Math.round(r)
-    , green = Math.round(g)
-    , blue = Math.round(b)
-  return 16 + (red*36) + (green*6) + blue
-}
-
-/**
- * Accepts a hex CSS color code string (# is optional) and
- * translates it into an Array of 3 RGB 0-255 values, which
- * can then be used with rgb().
- */
-
-function hex (color) {
-  var c = color[0] === '#' ? color.substring(1) : color
-    , r = c.substring(0, 2)
-    , g = c.substring(2, 4)
-    , b = c.substring(4, 6)
-  return [parseInt(r, 16), parseInt(g, 16), parseInt(b, 16)]
-}
-
-/**
- * Turns an array-like object into a real array.
- */
-
-function toArray (a) {
-  var i = 0
-    , l = a.length
-    , rtn = []
-  for (; i<l; i++) {
-    rtn.push(a[i])
-  }
-  return rtn
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/newlines.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/newlines.js
deleted file mode 100644
index 4e37a0ad..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/lib/newlines.js
+++ /dev/null
@@ -1,71 +0,0 @@
-
-/**
- * Accepts any node Stream instance and hijacks its "write()" function,
- * so that it can count any newlines that get written to the output.
- *
- * When a '\n' byte is encountered, then a "newline" event will be emitted
- * on the stream, with no arguments. It is up to the listeners to determine
- * any necessary deltas required for their use-case.
- *
- * Ex:
- *
- *   var cursor = ansi(process.stdout)
- *     , ln = 0
- *   process.stdout.on('newline', function () {
- *    ln++
- *   })
- */
-
-/**
- * Module dependencies.
- */
-
-var assert = require('assert')
-var NEWLINE = '\n'.charCodeAt(0)
-
-function emitNewlineEvents (stream) {
-  if (stream._emittingNewlines) {
-    // already emitting newline events
-    return
-  }
-
-  var write = stream.write
-
-  stream.write = function (data) {
-    // first write the data
-    var rtn = write.apply(stream, arguments)
-
-    if (stream.listeners('newline').length > 0) {
-      var len = data.length
-        , i = 0
-      // now try to calculate any deltas
-      if (typeof data == 'string') {
-        for (; i<len; i++) {
-          processByte(stream, data.charCodeAt(i))
-        }
-      } else {
-        // buffer
-        for (; i<len; i++) {
-          processByte(stream, data[i])
-        }
-      }
-    }
-
-    return rtn
-  }
-
-  stream._emittingNewlines = true
-}
-module.exports = emitNewlineEvents
-
-
-/**
- * Processes an individual byte being written to a stream
- */
-
-function processByte (stream, b) {
-  assert.equal(typeof b, 'number')
-  if (b === NEWLINE) {
-    stream.emit('newline')
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/package.json
deleted file mode 100644
index d5e7be16..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/package.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
-  "name": "ansi",
-  "description": "Advanced ANSI formatting tool for Node.js",
-  "keywords": [
-    "ansi",
-    "formatting",
-    "cursor",
-    "color",
-    "terminal",
-    "rgb",
-    "256",
-    "stream"
-  ],
-  "version": "0.2.1",
-  "author": {
-    "name": "Nathan Rajlich",
-    "email": "nathan@tootallnate.net",
-    "url": "http://tootallnate.net"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/TooTallNate/ansi.js.git"
-  },
-  "main": "./lib/ansi.js",
-  "bin": {
-    "beep": "./examples/beep/index.js",
-    "clear": "./examples/clear/index.js",
-    "starwars": "./examples/starwars.js"
-  },
-  "scripts": {
-    "test": "mocha --reporter spec"
-  },
-  "devDependencies": {
-    "mocha": "*"
-  },
-  "engines": {
-    "node": "*"
-  },
-  "readme": "ansi.js\n=========\n### Advanced ANSI formatting tool for Node.js\n\n`ansi.js` is a module for Node.js that provides an easy-to-use API for\nwriting ANSI escape codes to `Stream` instances. ANSI escape codes are used to do\nfancy things in a terminal window, like render text in colors, delete characters,\nlines, the entire window, or hide and show the cursor, and lots more!\n\nThe code for the example in the screenshot above can be found in the\n`examples/imgcat` directory.\n\n#### Features:\n\n * 256 color support for the terminal!\n * Make a beep sound from your terminal!\n * Works with *any* writable `Stream` instance.\n * Allows you to move the cursor anywhere on the terminal window.\n * Allows you to delete existing contents from the terminal window.\n * Allows you to hide and show the cursor.\n * Converts CSS color codes and RGB values into ANSI escape codes.\n * Low-level; you are in control of when escape codes are used, it's not abstracted.\n\n\nInstallation\n------------\n\nInstall with `npm`:\n\n``` bash\n$ npm install ansi\n```\n\n\nExample\n-------\n\n``` js\nvar ansi = require('ansi')\n  , cursor = ansi(process.stdout)\n\n// You can chain your calls forever:\ncursor\n  .red()                 // Set font color to red\n  .bg.grey()             // Set background color to grey\n  .write('Hello World!') // Write 'Hello World!' to stdout\n  .bg.reset()            // Reset the bgcolor before writing the trailing \\n,\n                         //      to avoid Terminal glitches\n  .write('\\n')           // And a final \\n to wrap things up\n\n// Rendering modes are persistent:\ncursor.hex('#660000').bold().underline()\n\n// You can use the regular logging functions, text will be green\nconsole.log('This is blood red, bold text')\n\n// To reset just the foreground color:\ncursor.fg.reset()\n\nconsole.log('This will still be bold')\n\n// Clean up after yourself!\ncursor.reset()\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/TooTallNate/ansi.js/issues"
-  },
-  "homepage": "https://github.com/TooTallNate/ansi.js",
-  "_id": "ansi@0.2.1",
-  "_shasum": "3ab568ec18cd0ab7753c83117d57dad684a1c017",
-  "_from": "ansi@~0.2.1",
-  "_resolved": "https://registry.npmjs.org/ansi/-/ansi-0.2.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/package.json
deleted file mode 100644
index 3e938faf..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "npmlog",
-  "description": "logger for npm",
-  "version": "0.0.6",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/npmlog.git"
-  },
-  "main": "log.js",
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "dependencies": {
-    "ansi": "~0.2.1"
-  },
-  "devDependencies": {
-    "tap": ""
-  },
-  "license": "BSD",
-  "readme": "# npmlog\n\nThe logger util that npm uses.\n\nThis logger is very basic.  It does the logging for npm.  It supports\ncustom levels and colored output.\n\nBy default, logs are written to stderr.  If you want to send log messages\nto outputs other than streams, then you can change the `log.stream`\nmember, or you can just listen to the events that it emits, and do\nwhatever you want with them.\n\n# Basic Usage\n\n```\nvar log = require('npmlog')\n\n// additional stuff ---------------------------+\n// message ----------+                         |\n// prefix ----+      |                         |\n// level -+   |      |                         |\n//        v   v      v                         v\n    log.info('fyi', 'I have a kitty cat: %j', myKittyCat)\n```\n\n## log.level\n\n* {String}\n\nThe level to display logs at.  Any logs at or above this level will be\ndisplayed.  The special level `silent` will prevent anything from being\ndisplayed ever.\n\n## log.record\n\n* {Array}\n\nAn array of all the log messages that have been entered.\n\n## log.maxRecordSize\n\n* {Number}\n\nThe maximum number of records to keep.  If log.record gets bigger than\n10% over this value, then it is sliced down to 90% of this value.\n\nThe reason for the 10% window is so that it doesn't have to resize a\nlarge array on every log entry.\n\n## log.prefixStyle\n\n* {Object}\n\nA style object that specifies how prefixes are styled.  (See below)\n\n## log.headingStyle\n\n* {Object}\n\nA style object that specifies how the heading is styled.  (See below)\n\n## log.heading\n\n* {String} Default: \"\"\n\nIf set, a heading that is printed at the start of every line.\n\n## log.stream\n\n* {Stream} Default: `process.stderr`\n\nThe stream where output is written.\n\n## log.enableColor()\n\nForce colors to be used on all messages, regardless of the output\nstream.\n\n## log.disableColor()\n\nDisable colors on all messages.\n\n## log.pause()\n\nStop emitting messages to the stream, but do not drop them.\n\n## log.resume()\n\nEmit all buffered messages that were written while paused.\n\n## log.log(level, prefix, message, ...)\n\n* `level` {String} The level to emit the message at\n* `prefix` {String} A string prefix.  Set to \"\" to skip.\n* `message...` Arguments to `util.format`\n\nEmit a log message at the specified level.\n\n## log\\[level](prefix, message, ...)\n\nFor example,\n\n* log.silly(prefix, message, ...)\n* log.verbose(prefix, message, ...)\n* log.info(prefix, message, ...)\n* log.http(prefix, message, ...)\n* log.warn(prefix, message, ...)\n* log.error(prefix, message, ...)\n\nLike `log.log(level, prefix, message, ...)`.  In this way, each level is\ngiven a shorthand, so you can do `log.info(prefix, message)`.\n\n## log.addLevel(level, n, style, disp)\n\n* `level` {String} Level indicator\n* `n` {Number} The numeric level\n* `style` {Object} Object with fg, bg, inverse, etc.\n* `disp` {String} Optional replacement for `level` in the output.\n\nSets up a new level with a shorthand function and so forth.\n\nNote that if the number is `Infinity`, then setting the level to that\nwill cause all log messages to be suppressed.  If the number is\n`-Infinity`, then the only way to show it is to enable all log messages.\n\n# Events\n\nEvents are all emitted with the message object.\n\n* `log` Emitted for all messages\n* `log.<level>` Emitted for all messages with the `<level>` level.\n* `<prefix>` Messages with prefixes also emit their prefix as an event.\n\n# Style Objects\n\nStyle objects can have the following fields:\n\n* `fg` {String} Color for the foreground text\n* `bg` {String} Color for the background\n* `bold`, `inverse`, `underline` {Boolean} Set the associated property\n* `bell` {Boolean} Make a noise (This is pretty annoying, probably.)\n\n# Message Objects\n\nEvery log event is emitted with a message object, and the `log.record`\nlist contains all of them that have been created.  They have the\nfollowing fields:\n\n* `id` {Number}\n* `level` {String}\n* `prefix` {String}\n* `message` {String} Result of `util.format()`\n* `messageRaw` {Array} Arguments to `util.format()`\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/npmlog/issues"
-  },
-  "homepage": "https://github.com/isaacs/npmlog",
-  "_id": "npmlog@0.0.6",
-  "_shasum": "685043fe71aa1665d6e3b2acef180640caf40873",
-  "_from": "npmlog@~0.0.6",
-  "_resolved": "https://registry.npmjs.org/npmlog/-/npmlog-0.0.6.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/test/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/test/basic.js
deleted file mode 100644
index 1afcabd1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/test/basic.js
+++ /dev/null
@@ -1,228 +0,0 @@
-var tap = require('tap')
-var log = require('../')
-
-var result = []
-var logEvents = []
-var logInfoEvents = []
-var logPrefixEvents = []
-
-var util = require('util')
-
-var resultExpect =
-[ '\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[7msill\u001b[0m \u001b[0m\u001b[35msilly prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[34m\u001b[40mverb\u001b[0m \u001b[0m\u001b[35mverbose prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32minfo\u001b[0m \u001b[0m\u001b[35minfo prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32m\u001b[40mhttp\u001b[0m \u001b[0m\u001b[35mhttp prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[30m\u001b[43mWARN\u001b[0m \u001b[0m\u001b[35mwarn prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35merror prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32minfo\u001b[0m \u001b[0m\u001b[35minfo prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32m\u001b[40mhttp\u001b[0m \u001b[0m\u001b[35mhttp prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[30m\u001b[43mWARN\u001b[0m \u001b[0m\u001b[35mwarn prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35merror prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m This is a longer\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m message, with some details\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m and maybe a stack.\n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m \n',
-  '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u0007noise\u001b[0m\u001b[35m\u001b[0m LOUD NOISES\n',
-  '\u001b[0m' ]
-
-var logPrefixEventsExpect =
-[ { id: 2,
-    level: 'info',
-    prefix: 'info prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 9,
-    level: 'info',
-    prefix: 'info prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 16,
-    level: 'info',
-    prefix: 'info prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] } ]
-
-// should be the same.
-var logInfoEventsExpect = logPrefixEventsExpect
-
-var logEventsExpect =
-[ { id: 0,
-    level: 'silly',
-    prefix: 'silly prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 1,
-    level: 'verbose',
-    prefix: 'verbose prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 2,
-    level: 'info',
-    prefix: 'info prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 3,
-    level: 'http',
-    prefix: 'http prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 4,
-    level: 'warn',
-    prefix: 'warn prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 5,
-    level: 'error',
-    prefix: 'error prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 6,
-    level: 'silent',
-    prefix: 'silent prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 7,
-    level: 'silly',
-    prefix: 'silly prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 8,
-    level: 'verbose',
-    prefix: 'verbose prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 9,
-    level: 'info',
-    prefix: 'info prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 10,
-    level: 'http',
-    prefix: 'http prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 11,
-    level: 'warn',
-    prefix: 'warn prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 12,
-    level: 'error',
-    prefix: 'error prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 13,
-    level: 'silent',
-    prefix: 'silent prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 14,
-    level: 'silly',
-    prefix: 'silly prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 15,
-    level: 'verbose',
-    prefix: 'verbose prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 16,
-    level: 'info',
-    prefix: 'info prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 17,
-    level: 'http',
-    prefix: 'http prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 18,
-    level: 'warn',
-    prefix: 'warn prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 19,
-    level: 'error',
-    prefix: 'error prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 20,
-    level: 'silent',
-    prefix: 'silent prefix',
-    message: 'x = {"foo":{"bar":"baz"}}',
-    messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] },
-  { id: 21,
-    level: 'error',
-    prefix: '404',
-    message: 'This is a longer\nmessage, with some details\nand maybe a stack.\n',
-    messageRaw: [ 'This is a longer\nmessage, with some details\nand maybe a stack.\n' ] },
-  { id: 22,
-    level: 'noise',
-    prefix: false,
-    message: 'LOUD NOISES',
-    messageRaw: [ 'LOUD NOISES' ] } ]
-
-var Stream = require('stream').Stream
-var s = new Stream()
-s.write = function (m) {
-  result.push(m)
-}
-
-s.writable = true
-s.isTTY = true
-s.end = function () {}
-
-log.stream = s
-
-log.heading = 'npm'
-
-
-tap.test('basic', function (t) {
-  log.on('log', logEvents.push.bind(logEvents))
-  log.on('log.info', logInfoEvents.push.bind(logInfoEvents))
-  log.on('info prefix', logPrefixEvents.push.bind(logPrefixEvents))
-
-  console.error('log.level=silly')
-  log.level = 'silly'
-  log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.info('info prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.http('http prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.error('error prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}})
-
-  console.error('log.level=silent')
-  log.level = 'silent'
-  log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.info('info prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.http('http prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.error('error prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}})
-
-  console.error('log.level=info')
-  log.level = 'info'
-  log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.info('info prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.http('http prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.error('error prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}})
-  log.error('404', 'This is a longer\n'+
-                   'message, with some details\n'+
-                   'and maybe a stack.\n')
-  log.addLevel('noise', 10000, {beep: true})
-  log.noise(false, 'LOUD NOISES')
-
-  t.deepEqual(result.join('').trim(), resultExpect.join('').trim(), 'result')
-  t.deepEqual(log.record, logEventsExpect, 'record')
-  t.deepEqual(logEvents, logEventsExpect, 'logEvents')
-  t.deepEqual(logInfoEvents, logInfoEventsExpect, 'logInfoEvents')
-  t.deepEqual(logPrefixEvents, logPrefixEventsExpect, 'logPrefixEvents')
-
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/.npmignore
deleted file mode 100644
index 13abef4f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules
-node_modules/*
-npm_debug.log
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/README.md
deleted file mode 100644
index 408b2c57..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/README.md
+++ /dev/null
@@ -1,127 +0,0 @@
-# rc
-
-The non-configurable configuration loader for lazy people.
-
-## Usage
-
-The only option is to pass rc the name of your app, and your default configuration.
-
-```javascript
-var conf = require('rc')(appname, {
-  //defaults go here.
-  port: 2468,
-
-  //defaults which are objects will be merged, not replaced
-  views: {
-    engine: 'jade'
-  }
-});
-```
-
-`rc` will return your configuration options merged with the defaults you specify.
-If you pass in a predefined defaults object, it will be mutated:
-
-```javascript
-var conf = {};
-require('rc')(appname, conf);
-```
-
-
-## Standards
-
-Given your application name (`appname`), rc will look in all the obvious places for configuration.
-
-  * command line arguments (parsed by minimist)
-  * environment variables prefixed with `${appname}_`
-  * if you passed an option `--config file` then from that file
-  * a local `.${appname}rc` or the first found looking in `./ ../ ../../ ../../../` etc.
-  * `$HOME/.${appname}rc`
-  * `$HOME/.${appname}/config`
-  * `$HOME/.config/${appname}`
-  * `$HOME/.config/${appname}/config`
-  * `/etc/${appname}rc`
-  * `/etc/${appname}/config`
-  * the defaults object you passed in.
-
-All configuration sources that were found will be flattened into one object,
-so that sources **earlier** in this list override later ones.
-
-
-## Configuration File Formats
-
-Configuration files (e.g. `.appnamerc`) may be in either [json](http://json.org/example) or [ini](http://en.wikipedia.org/wiki/INI_file) format. The example configurations below are equivalent:
-
-
-#### Formatted as `ini`
-
-```
-; You can include comments in `ini` format if you want.
-
-dependsOn=0.10.0
-
-
-; `rc` has built-in support for ini sections, see?
-
-[commands]
-  www     = ./commands/www
-  console = ./commands/repl
-
-
-; You can even do nested sections
-
-[generators.options]
-  engine  = ejs
-
-[generators.modules]
-  new     = generate-new
-  engine  = generate-backend
-
-```
-
-#### Formatted as `json`
-
-```json
-{
-  // You can even comment your JSON, if you want
-  "dependsOn": "0.10.0",
-  "commands": {
-    "www": "./commands/www",
-    "console": "./commands/repl"
-  },
-  "generators": {
-    "options": {
-      "engine": "ejs"
-    },
-    "modules": {
-      "new": "generate-new",
-      "backend": "generate-backend"
-    }
-  }
-}
-```
-
-Comments are stripped from JSON config via [strip-json-comments](https://github.com/sindresorhus/strip-json-comments).
-
-> Since ini, and env variables do not have a standard for types, your application needs be prepared for strings.
-
-
-
-## Advanced Usage
-
-#### Pass in your own `argv`
-
-You may pass in your own `argv` as the third argument to `rc`.  This is in case you want to [use your own command-line opts parser](https://github.com/dominictarr/rc/pull/12).
-
-```javascript
-require('rc')(appname, defaults, customArgvParser);
-```
-
-
-## Note on Performance
-
-`rc` is running `fs.statSync`-- so make sure you don't use it in a hot code path (e.g. a request handler) 
-
-
-## License
-
-BSD / MIT / Apache2
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/index.js
deleted file mode 100755
index 6181a967..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/index.js
+++ /dev/null
@@ -1,42 +0,0 @@
-#! /usr/bin/env node
-var cc   = require('./lib/utils')
-var join = require('path').join
-var deepExtend = require('deep-extend')
-var etc = '/etc'
-var win = process.platform === "win32"
-var home = win
-           ? process.env.USERPROFILE
-           : process.env.HOME
-
-module.exports = function (name, defaults, argv) {
-  if(!name)
-    throw new Error('nameless configuration fail')
-  if(!argv)
-    argv = require('minimist')(process.argv.slice(2))
-  defaults = (
-      'string' === typeof defaults
-    ? cc.json(defaults) : defaults
-    ) || {}
-
-  var local = cc.find('.'+name+'rc')
-
-  return deepExtend.apply(null, [
-    defaults,
-    win ? {} : cc.json(join(etc, name, 'config')),
-    win ? {} : cc.json(join(etc, name + 'rc')),
-    home ? cc.json(join(home, '.config', name, 'config')) : {},
-    home ? cc.json(join(home, '.config', name)) : {},
-    home ? cc.json(join(home, '.' + name, 'config')) : {},
-    home ? cc.json(join(home, '.' + name + 'rc')) : {},
-    cc.json(local || argv.config),
-    local ? {config: local} : null,
-    cc.env(name + '_'),
-    argv
-  ])
-}
-
-if(!module.parent) {
-  console.log(
-    JSON.stringify(module.exports(process.argv[2]), false, 2)
-  )
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/lib/utils.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/lib/utils.js
deleted file mode 100644
index cd46eb5a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/lib/utils.js
+++ /dev/null
@@ -1,58 +0,0 @@
-var fs   = require('fs')
-var ini  = require('ini')
-var path = require('path')
-var stripJsonComments = require('strip-json-comments')
-
-var parse = exports.parse = function (content, file) {
-
-  //if it ends in .json or starts with { then it must be json.
-  //must be done this way, because ini accepts everything.
-  //can't just try and parse it and let it throw if it's not ini.
-  //everything is ini. even json with a systax error.
-
-  if((file && /\.json$/.test(file)) || /^\s*{/.test(content)) 
-    return JSON.parse(stripJsonComments(content))
-  return ini.parse(content)
-
-}
-
-var json = exports.json = function () {
-  var args = [].slice.call(arguments).filter(function (arg) { return arg != null })
-  var file = path.join.apply(null, args)
-  var content
-  try {
-    content = fs.readFileSync(file,'utf-8')
-  } catch (err) {
-    return
-  }
-  return parse(content)
-}
-
-var env = exports.env = function (prefix, env) {
-  env = env || process.env
-  var obj = {}
-  var l = prefix.length
-  for(var k in env) {
-    if((k.indexOf(prefix)) === 0)
-      obj[k.substring(l)] = env[k]
-  }
-
-  return obj
-}
-
-var find = exports.find = function () {
-  var rel = path.join.apply(null, [].slice.call(arguments))
-
-  function find(start, rel) {
-    var file = path.join(start, rel)
-    try {
-      fs.statSync(file)
-      return file
-    } catch (err) {
-      if(path.dirname(start) !== start) // root
-        return find(path.dirname(start), rel)
-    }
-  }
-  return find(process.cwd(), rel)
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/.npmignore
deleted file mode 100644
index 3c3629e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/LICENSE
deleted file mode 100644
index e9502364..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Viacheslav Lotsmanov
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/README.md
deleted file mode 100644
index 0457c524..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-Node.JS module “Deep Extend”
-============================
-
-Recursive object extending.
-
-Install
------
-
-    npm install deep-extend
-
-Usage
------
-
-    var deepExtend = require('deep-extend');
-    var obj1 = {
-        a: 1,
-        b: 2,
-        d: {
-            a: 1,
-            b: [],
-            c: { test1: 123, test2: 321 }
-        },
-        f: 5,
-        g: 123
-    };
-    var obj2 = {
-        b: 3,
-        c: 5,
-        d: {
-            b: { first: 'one', second: 'two' },
-            c: { test2: 222 }
-        },
-        e: { one: 1, two: 2 },
-        f: [],
-        g: (void 0)
-    };
-
-    deepExtend(obj1, obj2);
-
-    console.log(obj1);
-    /*
-        { a: 1,
-          b: 3,
-          d:
-           { a: 1,
-             b: { first: 'one', second: 'two' },
-             c: { test1: 123, test2: 222 } },
-          f: [],
-          c: 5,
-          e: { one: 1, two: 2 },
-          g: undefined }
-    */
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/index.js
deleted file mode 100644
index e75ec463..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/index.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/*!
- * Node.JS module "Deep Extend"
- * @description Recursive object extending.
- * @author Viacheslav Lotsmanov (unclechu) <lotsmanov89@gmail.com>
- * @license MIT
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013 Viacheslav Lotsmanov
- *
- * 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.
- */
-
-/**
- * Extening object that entered in first argument.
- * Returns extended object or false if have no target object or incorrect type.
- * If you wish to clone object, simply use that:
- *  deepExtend({}, yourObj_1, [yourObj_N]) - first arg is new empty object
- */
-var deepExtend = module.exports = function (/*obj_1, [obj_2], [obj_N]*/) {
-    if (arguments.length < 1 || typeof arguments[0] !== 'object') {
-        return false;
-    }
-
-    if (arguments.length < 2) return arguments[0];
-
-    var target = arguments[0];
-
-    // convert arguments to array and cut off target object
-    var args = Array.prototype.slice.call(arguments, 1);
-
-    var key, val, src, clone, tmpBuf;
-
-    args.forEach(function (obj) {
-        if (typeof obj !== 'object') return;
-
-        for (key in obj) {
-            if ( ! (key in obj)) continue;
-
-            src = target[key];
-            val = obj[key];
-
-            if (val === target) continue;
-
-            if (typeof val !== 'object' || val === null) {
-                target[key] = val;
-                continue;
-            } else if (val instanceof Buffer) {
-                tmpBuf = new Buffer(val.length);
-                val.copy(tmpBuf);
-                target[key] = tmpBuf;
-                continue;
-            }
-
-            if (typeof src !== 'object' || src === null) {
-                clone = (Array.isArray(val)) ? [] : {};
-                target[key] = deepExtend(clone, val);
-                continue;
-            }
-
-            if (Array.isArray(val)) {
-                clone = (Array.isArray(src)) ? src : [];
-            } else {
-                clone = (!Array.isArray(src)) ? src : {};
-            }
-
-            target[key] = deepExtend(clone, val);
-        }
-    });
-
-    return target;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/package.json
deleted file mode 100644
index c49eefaf..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/package.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
-  "name": "deep-extend",
-  "description": "Recursive object extending.",
-  "license": "MIT",
-  "version": "0.2.10",
-  "homepage": "https://github.com/unclechu/node-deep-extend",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/unclechu/node-deep-extend.git"
-  },
-  "author": {
-    "name": "Viacheslav Lotsmanov",
-    "email": "lotsmanov89@gmail.com",
-    "url": "unclechu"
-  },
-  "contributors": [
-    {
-      "name": "Romain Prieto",
-      "url": "https://github.com/rprieto"
-    }
-  ],
-  "main": "index",
-  "engines": {
-    "node": ">=0.4"
-  },
-  "scripts": {
-    "test": "mocha"
-  },
-  "devDependencies": {
-    "mocha": "~1.19.0",
-    "should": "~3.3.2"
-  },
-  "directories": {
-    "test": "./test"
-  },
-  "readme": "Node.JS module “Deep Extend”\r\n============================\r\n\r\nRecursive object extending.\r\n\r\nInstall\r\n-----\r\n\r\n    npm install deep-extend\r\n\r\nUsage\r\n-----\r\n\r\n    var deepExtend = require('deep-extend');\r\n    var obj1 = {\r\n        a: 1,\r\n        b: 2,\r\n        d: {\r\n            a: 1,\r\n            b: [],\r\n            c: { test1: 123, test2: 321 }\r\n        },\r\n        f: 5,\r\n        g: 123\r\n    };\r\n    var obj2 = {\r\n        b: 3,\r\n        c: 5,\r\n        d: {\r\n            b: { first: 'one', second: 'two' },\r\n            c: { test2: 222 }\r\n        },\r\n        e: { one: 1, two: 2 },\r\n        f: [],\r\n        g: (void 0)\r\n    };\r\n\r\n    deepExtend(obj1, obj2);\r\n\r\n    console.log(obj1);\r\n    /*\r\n        { a: 1,\r\n          b: 3,\r\n          d:\r\n           { a: 1,\r\n             b: { first: 'one', second: 'two' },\r\n             c: { test1: 123, test2: 222 } },\r\n          f: [],\r\n          c: 5,\r\n          e: { one: 1, two: 2 },\r\n          g: undefined }\r\n    */\r\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/unclechu/node-deep-extend/issues"
-  },
-  "_id": "deep-extend@0.2.10",
-  "_shasum": "8dd87f56835e91a7da57d07f3c5472165cf5d467",
-  "_from": "deep-extend@~0.2.5",
-  "_resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.10.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/index.spec.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/index.spec.js
deleted file mode 100644
index d8cd64c8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/index.spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var should = require('should');
-var extend = require('../index');
-
-describe('deep-extend', function() {
-
-  it('can extend on 1 level', function() {
-    var a = { hello: 1 };
-    var b = { world: 2 };
-    extend(a, b);
-    a.should.eql({
-      hello: 1,
-      world: 2
-    });
-  });
-
-  it('can extend on 2 levels', function() {
-    var a = { person: { name: 'John' } };
-    var b = { person: { age: 30 } };
-    extend(a, b);
-    a.should.eql({
-      person: { name: 'John', age: 30 }
-    });
-  });
-
-  it('can extend with Buffer values', function() {
-    var a = { hello: 1 };
-    var b = { value: new Buffer('world') };
-    extend(a, b);
-    a.should.eql({
-      hello: 1,
-      value: new Buffer('world')
-    });
-  });
-
-  it('Buffer is cloned', function () {
-    var a = { };
-    var b = { value: new Buffer('foo') };
-    extend(a, b);
-    a.value.write('bar');
-    a.value.toString().should.eql('bar');
-    b.value.toString().should.eql('foo');
-  });
-
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/mocha.opts b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/mocha.opts
deleted file mode 100644
index 5ada47be..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/deep-extend/test/mocha.opts
+++ /dev/null
@@ -1 +0,0 @@
---reporter spec
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/LICENSE
deleted file mode 100644
index 05a40109..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
-All rights reserved.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/README.md
deleted file mode 100644
index acbe8ec8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/README.md
+++ /dev/null
@@ -1,79 +0,0 @@
-An ini format parser and serializer for node.
-
-Sections are treated as nested objects.  Items before the first heading
-are saved on the object directly.
-
-## Usage
-
-Consider an ini-file `config.ini` that looks like this:
-
-    ; this comment is being ignored
-    scope = global
-
-    [database]
-    user = dbuser
-    password = dbpassword
-    database = use_this_database
-
-    [paths.default]
-    datadir = /var/lib/data
-    array[] = first value
-    array[] = second value
-    array[] = third value
-
-You can read, manipulate and write the ini-file like so:
-
-    var fs = require('fs')
-      , ini = require('ini')
-
-    var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'))
-
-    config.scope = 'local'
-    config.database.database = 'use_another_database'
-    config.paths.default.tmpdir = '/tmp'
-    delete config.paths.default.datadir
-    config.paths.default.array.push('fourth value')
-
-    fs.writeFileSync('./config_modified.ini', ini.stringify(config, 'section'))
-
-This will result in a file called `config_modified.ini` being written to the filesystem with the following content:
-
-    [section]
-    scope = local
-    [section.database]
-    user = dbuser
-    password = dbpassword
-    database = use_another_database
-    [section.paths.default]
-    tmpdir = /tmp
-    array[] = first value
-    array[] = second value
-    array[] = third value
-    array[] = fourth value
-
-
-## API
-
-### decode(inistring)
-Decode the ini-style formatted `inistring` into a nested object.
-
-### parse(inistring)
-Alias for `decode(inistring)`
-
-### encode(object, [section])
-Encode the object `object` into an ini-style formatted string. If the optional parameter `section` is given, then all top-level properties of the object are put into this section and the `section`-string is prepended to all sub-sections, see the usage example above.
-
-### stringify(object, [section])
-Alias for `encode(object, [section])`
-
-### safe(val)
-Escapes the string `val` such that it is safe to be used as a key or value in an ini-file. Basically escapes quotes. For example
-
-    ini.safe('"unsafe string"')
-
-would result in
-
-    "\"unsafe string\""
-
-### unsafe(val)
-Unescapes the string `val`
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/ini.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/ini.js
deleted file mode 100644
index eaf32093..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/ini.js
+++ /dev/null
@@ -1,166 +0,0 @@
-
-exports.parse = exports.decode = decode
-exports.stringify = exports.encode = encode
-
-exports.safe = safe
-exports.unsafe = unsafe
-
-var eol = process.platform === "win32" ? "\r\n" : "\n"
-
-function encode (obj, section) {
-  var children = []
-    , out = ""
-
-  Object.keys(obj).forEach(function (k, _, __) {
-    var val = obj[k]
-    if (val && Array.isArray(val)) {
-        val.forEach(function(item) {
-            out += safe(k + "[]") + " = " + safe(item) + "\n"
-        })
-    }
-    else if (val && typeof val === "object") {
-      children.push(k)
-    } else {
-      out += safe(k) + " = " + safe(val) + eol
-    }
-  })
-
-  if (section && out.length) {
-    out = "[" + safe(section) + "]" + eol + out
-  }
-
-  children.forEach(function (k, _, __) {
-    var nk = dotSplit(k).join('\\.')
-    var child = encode(obj[k], (section ? section + "." : "") + nk)
-    if (out.length && child.length) {
-      out += eol
-    }
-    out += child
-  })
-
-  return out
-}
-
-function dotSplit (str) {
-  return str.replace(/\1/g, '\2LITERAL\\1LITERAL\2')
-         .replace(/\\\./g, '\1')
-         .split(/\./).map(function (part) {
-           return part.replace(/\1/g, '\\.')
-                  .replace(/\2LITERAL\\1LITERAL\2/g, '\1')
-         })
-}
-
-function decode (str) {
-  var out = {}
-    , p = out
-    , section = null
-    , state = "START"
-           // section     |key = value
-    , re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i
-    , lines = str.split(/[\r\n]+/g)
-    , section = null
-
-  lines.forEach(function (line, _, __) {
-    if (!line || line.match(/^\s*;/)) return
-    var match = line.match(re)
-    if (!match) return
-    if (match[1] !== undefined) {
-      section = unsafe(match[1])
-      p = out[section] = out[section] || {}
-      return
-    }
-    var key = unsafe(match[2])
-      , value = match[3] ? unsafe((match[4] || "")) : true
-    switch (value) {
-      case 'true':
-      case 'false':
-      case 'null': value = JSON.parse(value)
-    }
-
-    // Convert keys with '[]' suffix to an array
-    if (key.length > 2 && key.slice(-2) === "[]") {
-        key = key.substring(0, key.length - 2)
-        if (!p[key]) {
-          p[key] = []
-        }
-        else if (!Array.isArray(p[key])) {
-          p[key] = [p[key]]
-        }
-    }
-
-    // safeguard against resetting a previously defined
-    // array by accidentally forgetting the brackets
-    if (Array.isArray(p[key])) {
-      p[key].push(value)
-    }
-    else {
-      p[key] = value
-    }
-  })
-
-  // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
-  // use a filter to return the keys that have to be deleted.
-  Object.keys(out).filter(function (k, _, __) {
-    if (!out[k] || typeof out[k] !== "object" || Array.isArray(out[k])) return false
-    // see if the parent section is also an object.
-    // if so, add it to that, and mark this one for deletion
-    var parts = dotSplit(k)
-      , p = out
-      , l = parts.pop()
-      , nl = l.replace(/\\\./g, '.')
-    parts.forEach(function (part, _, __) {
-      if (!p[part] || typeof p[part] !== "object") p[part] = {}
-      p = p[part]
-    })
-    if (p === out && nl === l) return false
-    p[nl] = out[k]
-    return true
-  }).forEach(function (del, _, __) {
-    delete out[del]
-  })
-
-  return out
-}
-
-function safe (val) {
-  return ( typeof val !== "string"
-         || val.match(/[\r\n]/)
-         || val.match(/^\[/)
-         || (val.length > 1
-             && val.charAt(0) === "\""
-             && val.slice(-1) === "\"")
-         || val !== val.trim() )
-         ? JSON.stringify(val)
-         : val.replace(/;/g, '\\;')
-}
-
-function unsafe (val, doUnesc) {
-  val = (val || "").trim()
-  if (val.charAt(0) === "\"" && val.slice(-1) === "\"") {
-    try { val = JSON.parse(val) } catch (_) {}
-  } else {
-    // walk the val to find the first not-escaped ; character
-    var esc = false
-    var unesc = "";
-    for (var i = 0, l = val.length; i < l; i++) {
-      var c = val.charAt(i)
-      if (esc) {
-        if (c === "\\" || c === ";")
-          unesc += c
-        else
-          unesc += "\\" + c
-        esc = false
-      } else if (c === ";") {
-        break
-      } else if (c === "\\") {
-        esc = true
-      } else {
-        unesc += c
-      }
-    }
-    if (esc)
-      unesc += "\\"
-    return unesc
-  }
-  return val
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/package.json
deleted file mode 100644
index 0e2cdd20..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "ini",
-  "description": "An ini encoder/decoder for node",
-  "version": "1.1.0",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/ini.git"
-  },
-  "main": "ini.js",
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "engines": {
-    "node": "*"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "tap": "~0.0.9"
-  },
-  "readme": "An ini format parser and serializer for node.\n\nSections are treated as nested objects.  Items before the first heading\nare saved on the object directly.\n\n## Usage\n\nConsider an ini-file `config.ini` that looks like this:\n\n    ; this comment is being ignored\n    scope = global\n\n    [database]\n    user = dbuser\n    password = dbpassword\n    database = use_this_database\n\n    [paths.default]\n    datadir = /var/lib/data\n    array[] = first value\n    array[] = second value\n    array[] = third value\n\nYou can read, manipulate and write the ini-file like so:\n\n    var fs = require('fs')\n      , ini = require('ini')\n\n    var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'))\n\n    config.scope = 'local'\n    config.database.database = 'use_another_database'\n    config.paths.default.tmpdir = '/tmp'\n    delete config.paths.default.datadir\n    config.paths.default.array.push('fourth value')\n\n    fs.writeFileSync('./config_modified.ini', ini.stringify(config, 'section'))\n\nThis will result in a file called `config_modified.ini` being written to the filesystem with the following content:\n\n    [section]\n    scope = local\n    [section.database]\n    user = dbuser\n    password = dbpassword\n    database = use_another_database\n    [section.paths.default]\n    tmpdir = /tmp\n    array[] = first value\n    array[] = second value\n    array[] = third value\n    array[] = fourth value\n\n\n## API\n\n### decode(inistring)\nDecode the ini-style formatted `inistring` into a nested object.\n\n### parse(inistring)\nAlias for `decode(inistring)`\n\n### encode(object, [section])\nEncode the object `object` into an ini-style formatted string. If the optional parameter `section` is given, then all top-level properties of the object are put into this section and the `section`-string is prepended to all sub-sections, see the usage example above.\n\n### stringify(object, [section])\nAlias for `encode(object, [section])`\n\n### safe(val)\nEscapes the string `val` such that it is safe to be used as a key or value in an ini-file. Basically escapes quotes. For example\n\n    ini.safe('\"unsafe string\"')\n\nwould result in\n\n    \"\\\"unsafe string\\\"\"\n\n### unsafe(val)\nUnescapes the string `val`\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/ini/issues"
-  },
-  "homepage": "https://github.com/isaacs/ini",
-  "_id": "ini@1.1.0",
-  "_shasum": "4e808c2ce144c6c1788918e034d6797bc6cf6281",
-  "_from": "ini@~1.1.0",
-  "_resolved": "https://registry.npmjs.org/ini/-/ini-1.1.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/bar.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/bar.js
deleted file mode 100644
index cb16176e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/bar.js
+++ /dev/null
@@ -1,23 +0,0 @@
-//test that parse(stringify(obj) deepEqu
-
-var ini = require('../')
-var test = require('tap').test
-
-var data = {
-  'number':  {count: 10},
-  'string':  {drink: 'white russian'},
-  'boolean': {isTrue: true},
-  'nested boolean': {theDude: {abides: true, rugCount: 1}}
-}
-
-
-test('parse(stringify(x)) deepEqual x', function (t) {
-
-  for (var k in data) {
-    var s = ini.stringify(data[k])
-    console.log(s, data[k])
-    t.deepEqual(ini.parse(s), data[k])
-  }
-
-  t.end() 
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/fixtures/foo.ini b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/fixtures/foo.ini
deleted file mode 100644
index 1d81378f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/fixtures/foo.ini
+++ /dev/null
@@ -1,47 +0,0 @@
-o = p
-
-   a with spaces   =     b  c
-
-; wrap in quotes to JSON-decode and preserve spaces
-" xa  n          p " = "\"\r\nyoyoyo\r\r\n"
-
-; wrap in quotes to get a key with a bracket, not a section.
-"[disturbing]" = hey you never know
-
-; Test arrays
-zr[] = deedee
-ar[] = one
-ar[] = three
-; This should be included in the array
-ar   = this is included
-
-; Test resetting of a value (and not turn it into an array)
-br = cold
-br = warm
-
-; a section
-[a]
-av = a val
-e = { o: p, a: { av: a val, b: { c: { e: "this [value]" } } } }
-j = "{ o: "p", a: { av: "a val", b: { c: { e: "this [value]" } } } }"
-"[]" = a square?
-
-; Nested array
-cr[] = four
-cr[] = eight
-
-; nested child without middle parent
-; should create otherwise-empty a.b
-[a.b.c]
-e = 1
-j = 2
-
-; dots in the section name should be literally interpreted
-[x\.y\.z]
-x.y.z = xyz
-
-[x\.y\.z.a\.b\.c]
-a.b.c = abc
-
-; this next one is not a comment!  it's escaped!
-nocomment = this\; this is not a comment
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/foo.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/foo.js
deleted file mode 100644
index 3a05eaf3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/ini/test/foo.js
+++ /dev/null
@@ -1,71 +0,0 @@
-var i = require("../")
-  , tap = require("tap")
-  , test = tap.test
-  , fs = require("fs")
-  , path = require("path")
-  , fixture = path.resolve(__dirname, "./fixtures/foo.ini")
-  , data = fs.readFileSync(fixture, "utf8")
-  , d
-  , expectE = 'o = p\n'
-            + 'a with spaces = b  c\n'
-            + '" xa  n          p " = "\\"\\r\\nyoyoyo\\r\\r\\n"\n'
-            + '"[disturbing]" = hey you never know\n'
-            + 'zr[] = deedee\n'
-            + 'ar[] = one\n'
-            + 'ar[] = three\n'
-            + 'ar[] = this is included\n'
-            + 'br = warm\n'
-            + '\n'
-            + '[a]\n'
-            + 'av = a val\n'
-            + 'e = { o: p, a: '
-            + '{ av: a val, b: { c: { e: "this [value]" '
-            + '} } } }\nj = "\\"{ o: \\"p\\", a: { av:'
-            + ' \\"a val\\", b: { c: { e: \\"this [value]'
-            + '\\" } } } }\\""\n"[]" = a square?\n'
-            + 'cr[] = four\ncr[] = eight\n\n'
-            +'[a.b.c]\ne = 1\n'
-            + 'j = 2\n\n[x\\.y\\.z]\nx.y.z = xyz\n\n'
-            + '[x\\.y\\.z.a\\.b\\.c]\na.b.c = abc\n'
-            + 'nocomment = this\\; this is not a comment\n'
-  , expectD =
-    { o: 'p',
-      'a with spaces': 'b  c',
-      " xa  n          p ":'"\r\nyoyoyo\r\r\n',
-      '[disturbing]': 'hey you never know',
-      'zr': ['deedee'],
-      'ar': ['one', 'three', 'this is included'],
-      'br': 'warm',
-      a:
-       { av: 'a val',
-         e: '{ o: p, a: { av: a val, b: { c: { e: "this [value]" } } } }',
-         j: '"{ o: "p", a: { av: "a val", b: { c: { e: "this [value]" } } } }"',
-         "[]": "a square?",
-         cr: ['four', 'eight'],
-         b: { c: { e: '1', j: '2' } } },
-      'x.y.z': {
-        'x.y.z': 'xyz',
-        'a.b.c': {
-          'a.b.c': 'abc',
-          'nocomment': 'this\; this is not a comment'
-        }
-      }
-    }
-
-test("decode from file", function (t) {
-  var d = i.decode(data)
-  t.deepEqual(d, expectD)
-  t.end()
-})
-
-test("encode from data", function (t) {
-  var e = i.encode(expectD)
-  t.deepEqual(e, expectE)
-
-  var obj = {log: { type:'file', level: {label:'debug', value:10} } }
-  e = i.encode(obj)
-  t.notEqual(e.slice(0, 1), '\n', 'Never a blank first line')
-  t.notEqual(e.slice(-2), '\n\n', 'Never a blank final line')
-
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/index.js
deleted file mode 100644
index 71fb8305..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/index.js
+++ /dev/null
@@ -1,187 +0,0 @@
-module.exports = function (args, opts) {
-    if (!opts) opts = {};
-    
-    var flags = { bools : {}, strings : {} };
-    
-    [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
-        flags.bools[key] = true;
-    });
-    
-    var aliases = {};
-    Object.keys(opts.alias || {}).forEach(function (key) {
-        aliases[key] = [].concat(opts.alias[key]);
-        aliases[key].forEach(function (x) {
-            aliases[x] = [key].concat(aliases[key].filter(function (y) {
-                return x !== y;
-            }));
-        });
-    });
-
-    [].concat(opts.string).filter(Boolean).forEach(function (key) {
-        flags.strings[key] = true;
-        if (aliases[key]) {
-            flags.strings[aliases[key]] = true;
-        }
-     });
-
-    var defaults = opts['default'] || {};
-    
-    var argv = { _ : [] };
-    Object.keys(flags.bools).forEach(function (key) {
-        setArg(key, defaults[key] === undefined ? false : defaults[key]);
-    });
-    
-    var notFlags = [];
-
-    if (args.indexOf('--') !== -1) {
-        notFlags = args.slice(args.indexOf('--')+1);
-        args = args.slice(0, args.indexOf('--'));
-    }
-
-    function setArg (key, val) {
-        var value = !flags.strings[key] && isNumber(val)
-            ? Number(val) : val
-        ;
-        setKey(argv, key.split('.'), value);
-        
-        (aliases[key] || []).forEach(function (x) {
-            setKey(argv, x.split('.'), value);
-        });
-    }
-    
-    for (var i = 0; i < args.length; i++) {
-        var arg = args[i];
-        
-        if (/^--.+=/.test(arg)) {
-            // 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 (/^--no-.+/.test(arg)) {
-            var key = arg.match(/^--no-(.+)/)[1];
-            setArg(key, false);
-        }
-        else if (/^--.+/.test(arg)) {
-            var key = arg.match(/^--(.+)/)[1];
-            var next = args[i + 1];
-            if (next !== undefined && !/^-/.test(next)
-            && !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, flags.strings[key] ? '' : true);
-            }
-        }
-        else if (/^-[^-]+/.test(arg)) {
-            var letters = arg.slice(1,-1).split('');
-            
-            var broken = false;
-            for (var j = 0; j < letters.length; j++) {
-                var next = arg.slice(j+2);
-                
-                if (next === '-') {
-                    setArg(letters[j], next)
-                    continue;
-                }
-                
-                if (/[A-Za-z]/.test(letters[j])
-                && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
-                    setArg(letters[j], next);
-                    broken = true;
-                    break;
-                }
-                
-                if (letters[j+1] && letters[j+1].match(/\W/)) {
-                    setArg(letters[j], arg.slice(j+2));
-                    broken = true;
-                    break;
-                }
-                else {
-                    setArg(letters[j], flags.strings[letters[j]] ? '' : true);
-                }
-            }
-            
-            var key = arg.slice(-1)[0];
-            if (!broken && key !== '-') {
-                if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
-                && !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, flags.strings[key] ? '' : true);
-                }
-            }
-        }
-        else {
-            argv._.push(
-                flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
-            );
-        }
-    }
-    
-    Object.keys(defaults).forEach(function (key) {
-        if (!hasKey(argv, key.split('.'))) {
-            setKey(argv, key.split('.'), defaults[key]);
-            
-            (aliases[key] || []).forEach(function (x) {
-                setKey(argv, x.split('.'), defaults[key]);
-            });
-        }
-    });
-    
-    notFlags.forEach(function(key) {
-        argv._.push(key);
-    });
-
-    return argv;
-};
-
-function hasKey (obj, keys) {
-    var o = obj;
-    keys.slice(0,-1).forEach(function (key) {
-        o = (o[key] || {});
-    });
-
-    var key = keys[keys.length - 1];
-    return key in o;
-}
-
-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 ];
-    }
-}
-
-function isNumber (x) {
-    if (typeof x === 'number') return true;
-    if (/^0x[0-9a-f]+$/i.test(x)) return true;
-    return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/package.json
deleted file mode 100644
index 42a7f1bf..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/package.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-  "name": "minimist",
-  "version": "0.0.10",
-  "description": "parse argument options",
-  "main": "index.js",
-  "devDependencies": {
-    "tape": "~1.0.4",
-    "tap": "~0.4.0"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "testling": {
-    "files": "test/*.js",
-    "browsers": [
-      "ie/6..latest",
-      "ff/5",
-      "firefox/latest",
-      "chrome/10",
-      "chrome/latest",
-      "safari/5.1",
-      "safari/latest",
-      "opera/12"
-    ]
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/substack/minimist.git"
-  },
-  "homepage": "https://github.com/substack/minimist",
-  "keywords": [
-    "argv",
-    "getopt",
-    "parser",
-    "optimist"
-  ],
-  "author": {
-    "name": "James Halliday",
-    "email": "mail@substack.net",
-    "url": "http://substack.net"
-  },
-  "license": "MIT",
-  "readme": "# minimist\n\nparse argument options\n\nThis module is the guts of optimist's argument parser without all the\nfanciful decoration.\n\n[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)\n\n[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)\n\n# example\n\n``` js\nvar argv = require('minimist')(process.argv.slice(2));\nconsole.dir(argv);\n```\n\n```\n$ node example/parse.js -a beep -b boop\n{ _: [], a: 'beep', b: 'boop' }\n```\n\n```\n$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz\n{ _: [ 'foo', 'bar', 'baz' ],\n  x: 3,\n  y: 4,\n  n: 5,\n  a: true,\n  b: true,\n  c: true,\n  beep: 'boop' }\n```\n\n# methods\n\n``` js\nvar parseArgs = require('minimist')\n```\n\n## var argv = parseArgs(args, opts={})\n\nReturn an argument object `argv` populated with the array arguments from `args`.\n\n`argv._` contains all the arguments that didn't have an option associated with\nthem.\n\nNumeric-looking arguments will be returned as numbers unless `opts.string` or\n`opts.boolean` is set for that argument name.\n\nAny arguments after `'--'` will not be parsed and will end up in `argv._`.\n\noptions can be:\n\n* `opts.string` - a string or array of strings argument names to always treat as\nstrings\n* `opts.boolean` - a string or array of strings to always treat as booleans\n* `opts.alias` - an object mapping string names to strings or arrays of string\nargument names to use as aliases\n* `opts.default` - an object mapping string argument names to default values\n\n# install\n\nWith [npm](https://npmjs.org) do:\n\n```\nnpm install minimist\n```\n\n# license\n\nMIT\n",
-  "readmeFilename": "readme.markdown",
-  "bugs": {
-    "url": "https://github.com/substack/minimist/issues"
-  },
-  "_id": "minimist@0.0.10",
-  "_shasum": "de3f98543dbf96082be48ad1a0c7cda836301dcf",
-  "_from": "minimist@~0.0.7",
-  "_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/readme.markdown b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/readme.markdown
deleted file mode 100644
index c2563532..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/readme.markdown
+++ /dev/null
@@ -1,73 +0,0 @@
-# minimist
-
-parse argument options
-
-This module is the guts of optimist's argument parser without all the
-fanciful decoration.
-
-[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)
-
-[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)
-
-# example
-
-``` js
-var argv = require('minimist')(process.argv.slice(2));
-console.dir(argv);
-```
-
-```
-$ node example/parse.js -a beep -b boop
-{ _: [], a: 'beep', b: 'boop' }
-```
-
-```
-$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
-{ _: [ 'foo', 'bar', 'baz' ],
-  x: 3,
-  y: 4,
-  n: 5,
-  a: true,
-  b: true,
-  c: true,
-  beep: 'boop' }
-```
-
-# methods
-
-``` js
-var parseArgs = require('minimist')
-```
-
-## var argv = parseArgs(args, opts={})
-
-Return an argument object `argv` populated with the array arguments from `args`.
-
-`argv._` contains all the arguments that didn't have an option associated with
-them.
-
-Numeric-looking arguments will be returned as numbers unless `opts.string` or
-`opts.boolean` is set for that argument name.
-
-Any arguments after `'--'` will not be parsed and will end up in `argv._`.
-
-options can be:
-
-* `opts.string` - a string or array of strings argument names to always treat as
-strings
-* `opts.boolean` - a string or array of strings to always treat as booleans
-* `opts.alias` - an object mapping string names to strings or arrays of string
-argument names to use as aliases
-* `opts.default` - an object mapping string argument names to default values
-
-# install
-
-With [npm](https://npmjs.org) do:
-
-```
-npm install minimist
-```
-
-# license
-
-MIT
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/bool.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/bool.js
deleted file mode 100644
index 749e083c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/bool.js
+++ /dev/null
@@ -1,119 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('flag boolean default false', function (t) {
-    var argv = parse(['moo'], {
-        boolean: ['t', 'verbose'],
-        default: { verbose: false, t: false }
-    });
-    
-    t.deepEqual(argv, {
-        verbose: false,
-        t: false,
-        _: ['moo']
-    });
-    
-    t.deepEqual(typeof argv.verbose, 'boolean');
-    t.deepEqual(typeof argv.t, 'boolean');
-    t.end();
-
-});
-
-test('boolean groups', function (t) {
-    var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], {
-        boolean: ['x','y','z']
-    });
-    
-    t.deepEqual(argv, {
-        x : true,
-        y : false,
-        z : true,
-        _ : [ 'one', 'two', 'three' ]
-    });
-    
-    t.deepEqual(typeof argv.x, 'boolean');
-    t.deepEqual(typeof argv.y, 'boolean');
-    t.deepEqual(typeof argv.z, 'boolean');
-    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 = parse(aliased, {
-        boolean: 'herp',
-        alias: { h: 'herp' }
-    });
-    var propertyArgv = parse(regular, {
-        boolean: 'herp',
-        alias: { h: 'herp' }
-    });
-    var expected = {
-        herp: true,
-        h: true,
-        '_': [ 'derp' ]
-    };
-    
-    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 = {
-        alias: { 'h': 'herp' },
-        boolean: 'herp'
-    };
-    var aliasedArgv = parse(aliased, opts);
-    var propertyArgv = parse(regular, opts);
-    var expected = {
-        herp: true,
-        h: true,
-        '_': [ 'derp' ]
-    };
-    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 = {
-        alias: { h: 'herp' },
-        boolean: 'h'
-    };
-    var aliasedArgv = parse(aliased, opts);
-    var propertyArgv = parse(regular, opts);
-    var expected = {
-        herp: true,
-        h: true,
-        '_': [ ]
-    };
-
-    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 = parse(['--boool', '--other=true'], {
-        boolean: 'boool'
-    });
-
-    t.same(parsed.boool, true);
-    t.same(parsed.other, 'true');
-
-    parsed = parse(['--boool', '--other=false'], {
-        boolean: 'boool'
-    });
-    
-    t.same(parsed.boool, true);
-    t.same(parsed.other, 'false');
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/dash.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/dash.js
deleted file mode 100644
index 8b034b99..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/dash.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('-', function (t) {
-    t.plan(5);
-    t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] });
-    t.deepEqual(parse([ '-' ]), { _: [ '-' ] });
-    t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] });
-    t.deepEqual(
-        parse([ '-b', '-' ], { boolean: 'b' }),
-        { b: true, _: [ '-' ] }
-    );
-    t.deepEqual(
-        parse([ '-s', '-' ], { string: 's' }),
-        { s: '-', _: [] }
-    );
-});
-
-test('-a -- b', function (t) {
-    t.plan(3);
-    t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] });
-    t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
-    t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/default_bool.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/default_bool.js
deleted file mode 100644
index f0041ee4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/default_bool.js
+++ /dev/null
@@ -1,20 +0,0 @@
-var test = require('tape');
-var parse = require('../');
-
-test('boolean default true', function (t) {
-    var argv = parse([], {
-        boolean: 'sometrue',
-        default: { sometrue: true }
-    });
-    t.equal(argv.sometrue, true);
-    t.end();
-});
-
-test('boolean default false', function (t) {
-    var argv = parse([], {
-        boolean: 'somefalse',
-        default: { somefalse: false }
-    });
-    t.equal(argv.somefalse, false);
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/parse_modified.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/parse_modified.js
deleted file mode 100644
index 21851b03..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/minimist/test/parse_modified.js
+++ /dev/null
@@ -1,9 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('parse with modifier functions' , function (t) {
-    t.plan(1);
-    
-    var argv = parse([ '-b', '123' ], { boolean: 'b' });
-    t.deepEqual(argv, { b: true, _: ['123'] });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/cli.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/cli.js
deleted file mode 100755
index ac4da484..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/cli.js
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env node
-'use strict';
-var fs = require('fs');
-var strip = require('./strip-json-comments');
-var input = process.argv[2];
-
-
-function getStdin(cb) {
-	var ret = '';
-
-	process.stdin.setEncoding('utf8');
-
-	process.stdin.on('data', function (data) {
-		ret += data;
-	});
-
-	process.stdin.on('end', function () {
-		cb(ret);
-	});
-}
-
-if (process.argv.indexOf('-h') !== -1 || process.argv.indexOf('--help') !== -1) {
-	console.log('strip-json-comments <input file> > <output file>');
-	console.log('or');
-	console.log('cat <input file> | strip-json-comments > <output file>');
-	return;
-}
-
-if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--version') !== -1) {
-	console.log(require('./package').version);
-	return;
-}
-
-if (input) {
-	process.stdout.write(strip(fs.readFileSync(input, 'utf8')));
-	return;
-}
-
-getStdin(function (data) {
-	process.stdout.write(strip(data));
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/package.json
deleted file mode 100644
index bd34da4f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/package.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "name": "strip-json-comments",
-  "version": "0.1.3",
-  "description": "Strip comments from JSON. Lets you use comments in your JSON files!",
-  "keywords": [
-    "json",
-    "strip",
-    "remove",
-    "delete",
-    "trim",
-    "comments",
-    "multiline",
-    "parse",
-    "config",
-    "configuration",
-    "conf",
-    "settings",
-    "util",
-    "env",
-    "environment",
-    "cli",
-    "bin"
-  ],
-  "license": "MIT",
-  "author": {
-    "name": "Sindre Sorhus",
-    "email": "sindresorhus@gmail.com",
-    "url": "http://sindresorhus.com"
-  },
-  "files": [
-    "cli.js",
-    "strip-json-comments.js"
-  ],
-  "main": "strip-json-comments",
-  "bin": {
-    "strip-json-comments": "cli.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/sindresorhus/strip-json-comments"
-  },
-  "scripts": {
-    "test": "mocha"
-  },
-  "devDependencies": {
-    "mocha": "*"
-  },
-  "engines": {
-    "node": ">=0.8.0"
-  },
-  "readme": "# strip-json-comments [![Build Status](https://travis-ci.org/sindresorhus/strip-json-comments.svg?branch=master)](https://travis-ci.org/sindresorhus/strip-json-comments)\n\n> Strip comments from JSON. Lets you use comments in your JSON files!\n\nThis is now possible:\n\n```js\n{\n\t// rainbows\n\t\"unicorn\": /* ❤ */ \"cake\"\n}\n```\n\nIt will remove single-line comments `//` and mult-line comments `/**/`.\n\nAlso available as a [gulp](https://github.com/sindresorhus/gulp-strip-json-comments)/[grunt](https://github.com/sindresorhus/grunt-strip-json-comments)/[broccoli](https://github.com/sindresorhus/broccoli-strip-json-comments) plugin and a [require hook](https://github.com/uTest/autostrip-json-comments).\n\n\n*There's already [json-comments](https://npmjs.org/package/json-comments), but it's only for Node.js and uses a naive regex to strip comments which fails on simple cases like `{\"a\":\"//\"}`. This module however parses out the comments.*\n\n\n## Install\n\n```sh\n$ npm install --save strip-json-comments\n```\n\n```sh\n$ bower install --save strip-json-comments\n```\n\n```sh\n$ component install sindresorhus/strip-json-comments\n```\n\n\n## Usage\n\n```js\nvar json = '{/*rainbows*/\"unicorn\":\"cake\"}';\nJSON.parse(stripJsonComments(json));\n//=> {unicorn: 'cake'}\n```\n\n\n## API\n\n### stripJsonComments(input)\n\n#### input\n\nType: `string`\n\nAccepts a string with JSON and returns a string without comments.\n\n\n## CLI\n\n```sh\n$ npm install --global strip-json-comments\n```\n\n```sh\n$ strip-json-comments --help\n\nstrip-json-comments <input-file> > <output-file>\n# or\ncat <input-file> | strip-json-comments > <output-file>\n```\n\n\n## License\n\nMIT © [Sindre Sorhus](http://sindresorhus.com)\n",
-  "readmeFilename": "readme.md",
-  "bugs": {
-    "url": "https://github.com/sindresorhus/strip-json-comments/issues"
-  },
-  "homepage": "https://github.com/sindresorhus/strip-json-comments",
-  "_id": "strip-json-comments@0.1.3",
-  "_shasum": "164c64e370a8a3cc00c9e01b539e569823f0ee54",
-  "_from": "strip-json-comments@0.1.x",
-  "_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/readme.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/readme.md
deleted file mode 100644
index ad6a178c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/readme.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# strip-json-comments [![Build Status](https://travis-ci.org/sindresorhus/strip-json-comments.svg?branch=master)](https://travis-ci.org/sindresorhus/strip-json-comments)
-
-> Strip comments from JSON. Lets you use comments in your JSON files!
-
-This is now possible:
-
-```js
-{
-	// rainbows
-	"unicorn": /* ❤ */ "cake"
-}
-```
-
-It will remove single-line comments `//` and mult-line comments `/**/`.
-
-Also available as a [gulp](https://github.com/sindresorhus/gulp-strip-json-comments)/[grunt](https://github.com/sindresorhus/grunt-strip-json-comments)/[broccoli](https://github.com/sindresorhus/broccoli-strip-json-comments) plugin and a [require hook](https://github.com/uTest/autostrip-json-comments).
-
-
-*There's already [json-comments](https://npmjs.org/package/json-comments), but it's only for Node.js and uses a naive regex to strip comments which fails on simple cases like `{"a":"//"}`. This module however parses out the comments.*
-
-
-## Install
-
-```sh
-$ npm install --save strip-json-comments
-```
-
-```sh
-$ bower install --save strip-json-comments
-```
-
-```sh
-$ component install sindresorhus/strip-json-comments
-```
-
-
-## Usage
-
-```js
-var json = '{/*rainbows*/"unicorn":"cake"}';
-JSON.parse(stripJsonComments(json));
-//=> {unicorn: 'cake'}
-```
-
-
-## API
-
-### stripJsonComments(input)
-
-#### input
-
-Type: `string`
-
-Accepts a string with JSON and returns a string without comments.
-
-
-## CLI
-
-```sh
-$ npm install --global strip-json-comments
-```
-
-```sh
-$ strip-json-comments --help
-
-strip-json-comments <input-file> > <output-file>
-# or
-cat <input-file> | strip-json-comments > <output-file>
-```
-
-
-## License
-
-MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/strip-json-comments.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/strip-json-comments.js
deleted file mode 100644
index 2e7fdef2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/node_modules/strip-json-comments/strip-json-comments.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*!
-	strip-json-comments
-	Strip comments from JSON. Lets you use comments in your JSON files!
-	https://github.com/sindresorhus/strip-json-comments
-	by Sindre Sorhus
-	MIT License
-*/
-(function () {
-	'use strict';
-
-	function stripJsonComments(str) {
-		var currentChar;
-		var nextChar;
-		var insideString = false;
-		var insideComment = false;
-		var ret = '';
-
-		for (var i = 0; i < str.length; i++) {
-			currentChar = str[i];
-			nextChar = str[i + 1];
-
-			if (!insideComment && str[i - 1] !== '\\' && currentChar === '"') {
-				insideString = !insideString;
-			}
-
-			if (insideString) {
-				ret += currentChar;
-				continue;
-			}
-
-			if (!insideComment && currentChar + nextChar === '//') {
-				insideComment = 'single';
-				i++;
-			} else if (insideComment === 'single' && currentChar + nextChar === '\r\n') {
-				insideComment = false;
-				i++;
-			} else if (insideComment === 'single' && currentChar === '\n') {
-				insideComment = false;
-			} else if (!insideComment && currentChar + nextChar === '/*') {
-				insideComment = 'multi';
-				i++;
-				continue;
-			} else if (insideComment === 'multi' && currentChar + nextChar === '*/') {
-				insideComment = false;
-				i++;
-				continue;
-			}
-
-			if (insideComment) {
-				continue;
-			}
-
-			ret += currentChar;
-		}
-
-		return ret;
-	}
-
-	if (typeof module !== 'undefined' && module.exports) {
-		module.exports = stripJsonComments;
-	} else {
-		window.stripJsonComments = stripJsonComments;
-	}
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/package.json
deleted file mode 100644
index 5525c611..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/package.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
-  "name": "rc",
-  "version": "0.4.0",
-  "description": "hardwired configuration loader",
-  "main": "index.js",
-  "browserify": "browser.js",
-  "scripts": {
-    "test": "set -e; node test/test.js; node test/ini.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/dominictarr/rc.git"
-  },
-  "keywords": [
-    "config",
-    "rc",
-    "unix",
-    "defaults"
-  ],
-  "bin": {
-    "rc": "./index.js"
-  },
-  "author": {
-    "name": "Dominic Tarr",
-    "email": "dominic.tarr@gmail.com",
-    "url": "dominictarr.com"
-  },
-  "licenses": [
-    "BSD",
-    "MIT",
-    "Apache2"
-  ],
-  "dependencies": {
-    "minimist": "~0.0.7",
-    "deep-extend": "~0.2.5",
-    "strip-json-comments": "0.1.x",
-    "ini": "~1.1.0"
-  },
-  "readme": "# rc\n\nThe non-configurable configuration loader for lazy people.\n\n## Usage\n\nThe only option is to pass rc the name of your app, and your default configuration.\n\n```javascript\nvar conf = require('rc')(appname, {\n  //defaults go here.\n  port: 2468,\n\n  //defaults which are objects will be merged, not replaced\n  views: {\n    engine: 'jade'\n  }\n});\n```\n\n`rc` will return your configuration options merged with the defaults you specify.\nIf you pass in a predefined defaults object, it will be mutated:\n\n```javascript\nvar conf = {};\nrequire('rc')(appname, conf);\n```\n\n\n## Standards\n\nGiven your application name (`appname`), rc will look in all the obvious places for configuration.\n\n  * command line arguments (parsed by minimist)\n  * environment variables prefixed with `${appname}_`\n  * if you passed an option `--config file` then from that file\n  * a local `.${appname}rc` or the first found looking in `./ ../ ../../ ../../../` etc.\n  * `$HOME/.${appname}rc`\n  * `$HOME/.${appname}/config`\n  * `$HOME/.config/${appname}`\n  * `$HOME/.config/${appname}/config`\n  * `/etc/${appname}rc`\n  * `/etc/${appname}/config`\n  * the defaults object you passed in.\n\nAll configuration sources that were found will be flattened into one object,\nso that sources **earlier** in this list override later ones.\n\n\n## Configuration File Formats\n\nConfiguration files (e.g. `.appnamerc`) may be in either [json](http://json.org/example) or [ini](http://en.wikipedia.org/wiki/INI_file) format. The example configurations below are equivalent:\n\n\n#### Formatted as `ini`\n\n```\n; You can include comments in `ini` format if you want.\n\ndependsOn=0.10.0\n\n\n; `rc` has built-in support for ini sections, see?\n\n[commands]\n  www     = ./commands/www\n  console = ./commands/repl\n\n\n; You can even do nested sections\n\n[generators.options]\n  engine  = ejs\n\n[generators.modules]\n  new     = generate-new\n  engine  = generate-backend\n\n```\n\n#### Formatted as `json`\n\n```json\n{\n  // You can even comment your JSON, if you want\n  \"dependsOn\": \"0.10.0\",\n  \"commands\": {\n    \"www\": \"./commands/www\",\n    \"console\": \"./commands/repl\"\n  },\n  \"generators\": {\n    \"options\": {\n      \"engine\": \"ejs\"\n    },\n    \"modules\": {\n      \"new\": \"generate-new\",\n      \"backend\": \"generate-backend\"\n    }\n  }\n}\n```\n\nComments are stripped from JSON config via [strip-json-comments](https://github.com/sindresorhus/strip-json-comments).\n\n> Since ini, and env variables do not have a standard for types, your application needs be prepared for strings.\n\n\n\n## Advanced Usage\n\n#### Pass in your own `argv`\n\nYou may pass in your own `argv` as the third argument to `rc`.  This is in case you want to [use your own command-line opts parser](https://github.com/dominictarr/rc/pull/12).\n\n```javascript\nrequire('rc')(appname, defaults, customArgvParser);\n```\n\n\n## Note on Performance\n\n`rc` is running `fs.statSync`-- so make sure you don't use it in a hot code path (e.g. a request handler) \n\n\n## License\n\nBSD / MIT / Apache2\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/dominictarr/rc/issues"
-  },
-  "homepage": "https://github.com/dominictarr/rc",
-  "_id": "rc@0.4.0",
-  "_shasum": "ce24a2029ad94c3a40d09604a87227027d7210d3",
-  "_from": "rc@~0.4.0",
-  "_resolved": "https://registry.npmjs.org/rc/-/rc-0.4.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/test/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/test/test.js
deleted file mode 100644
index badc9303..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rc/test/test.js
+++ /dev/null
@@ -1,56 +0,0 @@
-
-var n = 'rc'+Math.random()
-var assert = require('assert')
-
-process.env[n+'_envOption'] = 42
-
-var config = require('../')(n, {
-  option: true
-})
-
-console.log(config)
-
-assert.equal(config.option, true)
-assert.equal(config.envOption, 42)
-
-var customArgv = require('../')(n, {
-  option: true
-}, { // nopt-like argv
-  option: false,
-  envOption: 24,
-  argv: {
-    remain: [],
-    cooked: ['--no-option', '--envOption', '24'],
-    original: ['--no-option', '--envOption=24']
-  }
-})
-
-console.log(customArgv)
-
-assert.equal(customArgv.option, false)
-assert.equal(customArgv.envOption, 24)
-
-var fs = require('fs')
-var path = require('path')
-var jsonrc = path.resolve('.' + n + 'rc');
-
-fs.writeFileSync(jsonrc, [
-  '{',
-    '// json overrides default',
-    '"option": false,',
-    '/* env overrides json */',
-    '"envOption": 24',
-  '}'
-].join('\n'));
-
-var commentedJSON = require('../')(n, {
-  option: true
-})
-
-fs.unlinkSync(jsonrc);
-
-console.log(commentedJSON)
-
-assert.equal(commentedJSON.option, false)
-assert.equal(commentedJSON.envOption, 42)
-assert.equal(commentedJSON.config, jsonrc)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.npmignore
deleted file mode 100644
index 80e59ef5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-tests
-node_modules
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.travis.yml
deleted file mode 100644
index 0bce8152..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-language: node_js
-node_js:
-  - 0.8
-  - 0.10
-
-env:
-  - OPTIONALS=Y
-  - OPTIONALS=N
-
-install:
-  - if [[ "$OPTIONALS" == "Y" ]]; then npm install; fi
-  - if [[ "$OPTIONALS" == "N" ]]; then npm install --no-optional; fi
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/CHANGELOG.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/CHANGELOG.md
deleted file mode 100644
index 7324f337..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/CHANGELOG.md
+++ /dev/null
@@ -1,388 +0,0 @@
-## Change Log
-
-### v2.34.0 (2014/02/18 19:35 +00:00)
-- [#781](https://github.com/mikeal/request/pull/781) simpler isReadStream function (@joaojeronimo)
-
-- [#785](https://github.com/mikeal/request/pull/785) Provide ability to override content-type when `json` option used (@vvo)
-
-- [#793](https://github.com/mikeal/request/pull/793) Adds content-length calculation when submitting forms using form-data li... (@Juul)
-
-- [#802](https://github.com/mikeal/request/pull/802) Added the Apache license to the package.json. (@keskival)
-
-- [#516](https://github.com/mikeal/request/pull/516) UNIX Socket URL Support (@lyuzashi)
-
-- [#801](https://github.com/mikeal/request/pull/801) Ignore cookie parsing and domain errors (@lalitkapoor)
-
-
-### v2.32.0 (2014/01/16 19:33 +00:00)
-- [#757](https://github.com/mikeal/request/pull/757) require aws-sign2 (@mafintosh)
-
-- [#744](https://github.com/mikeal/request/pull/744) Use Cookie.parse (@lalitkapoor)
-
-- [#763](https://github.com/mikeal/request/pull/763) Upgrade tough-cookie to 0.10.0 (@stash)
-
-- [#764](https://github.com/mikeal/request/pull/764) Case-insensitive authentication scheme (@bobyrizov)
-
-- [#767](https://github.com/mikeal/request/pull/767) Use tough-cookie CookieJar sync API (@stash)
-
-
-### v2.31.0 (2014/01/08 02:57 +00:00)
-- [#736](https://github.com/mikeal/request/pull/736) Fix callback arguments documentation (@mmalecki)
-
-- [#741](https://github.com/mikeal/request/pull/741) README example is using old cookie jar api (@emkay)
-
-- [#742](https://github.com/mikeal/request/pull/742) Add note about JSON output body type (@iansltx)
-
-- [#745](https://github.com/mikeal/request/pull/745) updating setCookie example to make it clear that the callback is required (@emkay)
-
-- [#746](https://github.com/mikeal/request/pull/746) README: Markdown code highlight (@weakish)
-
-- [#645](https://github.com/mikeal/request/pull/645) update twitter api url to v1.1 (@mick)
-
-
-### v2.30.0 (2013/12/13 19:17 +00:00)
-- [#732](https://github.com/mikeal/request/pull/732) JSHINT: Creating global 'for' variable. Should be 'for (var ...'. (@Fritz-Lium)
-
-- [#730](https://github.com/mikeal/request/pull/730) better HTTP DIGEST support (@dai-shi)
-
-- [#728](https://github.com/mikeal/request/pull/728) Fix TypeError when calling request.cookie (@scarletmeow)
-
-
-### v2.29.0 (2013/12/06 20:05 +00:00)
-- [#727](https://github.com/mikeal/request/pull/727) fix requester bug (@jchris)
-
-
-### v2.28.0 (2013/12/04 19:42 +00:00)
-- [#662](https://github.com/mikeal/request/pull/662) option.tunnel to explicitly disable tunneling (@seanmonstar)
-
-- [#656](https://github.com/mikeal/request/pull/656) Test case for #304. (@diversario)
-
-- [#666](https://github.com/mikeal/request/pull/666) make `ciphers` and `secureProtocol` to work in https request (@richarddong)
-
-- [#683](https://github.com/mikeal/request/pull/683) Travis CI support (@Turbo87)
-
-- [#690](https://github.com/mikeal/request/pull/690) Handle blank password in basic auth. (@diversario)
-
-- [#694](https://github.com/mikeal/request/pull/694) Typo in README (@VRMink)
-
-- [#696](https://github.com/mikeal/request/pull/696) Edited README.md for formatting and clarity of phrasing (@Zearin)
-
-- [#630](https://github.com/mikeal/request/pull/630) Send random cnonce for HTTP Digest requests (@wprl)
-
-- [#710](https://github.com/mikeal/request/pull/710) Fixing listing in callback part of docs. (@lukasz-zak)
-
-- [#715](https://github.com/mikeal/request/pull/715) Request.multipart no longer crashes when header 'Content-type' present (@pastaclub)
-
-- [#682](https://github.com/mikeal/request/pull/682) Optional dependencies (@Turbo87)
-
-- [#719](https://github.com/mikeal/request/pull/719) Made a comment gender neutral. (@oztu)
-
-- [#724](https://github.com/mikeal/request/pull/724) README.md: add custom HTTP Headers example. (@tcort)
-
-- [#674](https://github.com/mikeal/request/pull/674) change cookie module,to tough-cookie.please check it . (@sxyizhiren)
-
-- [#659](https://github.com/mikeal/request/pull/659) fix failure when running with NODE_DEBUG=request, and a test for that (@jrgm)
-
-
-### v2.27.0 (2013/08/15 21:30 +00:00)
-- [#619](https://github.com/mikeal/request/pull/619) decouple things a bit (@joaojeronimo)
-
-
-### v2.26.0 (2013/08/07 16:31 +00:00)
-- [#605](https://github.com/mikeal/request/pull/605) Only include ":" + pass in Basic Auth if it's defined (fixes #602) (@bendrucker)
-
-- [#613](https://github.com/mikeal/request/pull/613) Fixes #583, moved initialization of self.uri.pathname  (@lexander)
-
-
-### v2.24.0 (2013/07/23 20:51 +00:00)
-- [#601](https://github.com/mikeal/request/pull/601) Fixed a small typo (@michalstanko)
-
-- [#594](https://github.com/mikeal/request/pull/594) Emit complete event when there is no callback (@RomainLK)
-
-- [#596](https://github.com/mikeal/request/pull/596) Global agent is being used when pool is specified (@Cauldrath)
-
-
-### v2.23.0 (2013/07/23 02:44 +00:00)
-- [#589](https://github.com/mikeal/request/pull/589) Prevent setting headers after they are sent (@wpreul)
-
-- [#587](https://github.com/mikeal/request/pull/587) Global cookie jar disabled by default (@threepointone)
-
-
-### v2.22.0 (2013/07/05 17:12 +00:00)
-- [#542](https://github.com/mikeal/request/pull/542) Expose Request class (@regality)
-
-- [#541](https://github.com/mikeal/request/pull/541) The exported request function doesn't have an auth method (@tschaub)
-
-- [#564](https://github.com/mikeal/request/pull/564) Fix redirections (@criloz)
-
-- [#568](https://github.com/mikeal/request/pull/568) use agentOptions to create agent when specified in request (@SamPlacette)
-
-- [#581](https://github.com/mikeal/request/pull/581) Fix spelling of "ignoring." (@bigeasy)
-
-- [#544](https://github.com/mikeal/request/pull/544) Update http-signature version. (@davidlehn)
-
-
-### v2.21.0 (2013/04/30 21:28 +00:00)
-- [#529](https://github.com/mikeal/request/pull/529) dependencies versions bump (@jodaka)
-
-- [#521](https://github.com/mikeal/request/pull/521) Improving test-localAddress.js (@noway421)
-
-- [#503](https://github.com/mikeal/request/pull/503) Fix basic auth for passwords that contain colons (@tonistiigi)
-
-- [#497](https://github.com/mikeal/request/pull/497) Added redirect event (@Cauldrath)
-
-- [#532](https://github.com/mikeal/request/pull/532) fix typo (@fredericosilva)
-
-- [#536](https://github.com/mikeal/request/pull/536) Allow explicitly empty user field for basic authentication. (@mikeando)
-
-
-### v2.17.0 (2013/04/22 15:52 +00:00)
-- [#19](https://github.com/mikeal/request/pull/19) Request is unusable without native ssl support in node (@davglass)
-
-- [#31](https://github.com/mikeal/request/pull/31) Error on piping a request to a destination (@tobowers)
-
-- [#35](https://github.com/mikeal/request/pull/35) The "end" event isn't emitted for some responses (@voxpelli)
-
-- [#45](https://github.com/mikeal/request/pull/45) Added timeout option (@mbrevoort)
-
-- [#66](https://github.com/mikeal/request/pull/66) Do not overwrite established content-type headers for read stream deliver (@voodootikigod)
-
-- [#67](https://github.com/mikeal/request/pull/67) fixed global variable leaks (@aheckmann)
-
-- [#69](https://github.com/mikeal/request/pull/69) Flatten chunked requests properly (@isaacs)
-
-- [#73](https://github.com/mikeal/request/pull/73) Fix #71 Respect the strictSSL flag (@isaacs)
-
-- [#70](https://github.com/mikeal/request/pull/70) add test script to package.json (@isaacs)
-
-- [#76](https://github.com/mikeal/request/pull/76) Bug when a request fails and a timeout is set (@Marsup)
-
-- [#78](https://github.com/mikeal/request/pull/78) Don't try to do strictSSL for non-ssl connections (@isaacs)
-
-- [#79](https://github.com/mikeal/request/pull/79) Proxy auth bug (@isaacs)
-
-- [#81](https://github.com/mikeal/request/pull/81) Enhance redirect handling (@danmactough)
-
-- [#96](https://github.com/mikeal/request/pull/96) Authless parsed url host support (@isaacs)
-
-- [#84](https://github.com/mikeal/request/pull/84) Document strictSSL option (@isaacs)
-
-- [#97](https://github.com/mikeal/request/pull/97) Typo in previous pull causes TypeError in non-0.5.11 versions (@isaacs)
-
-- [#53](https://github.com/mikeal/request/pull/53) Parse json: Issue #51 (@benatkin)
-
-- [#102](https://github.com/mikeal/request/pull/102) Implemented cookies - closes issue 82: https://github.com/mikeal/request/issues/82 (@alessioalex)
-
-- [#105](https://github.com/mikeal/request/pull/105) added test for proxy option. (@dominictarr)
-
-- [#86](https://github.com/mikeal/request/pull/86) Can't post binary to multipart requests (@kkaefer)
-
-- [#110](https://github.com/mikeal/request/pull/110) Update to Iris Couch URL (@jhs)
-
-- [#117](https://github.com/mikeal/request/pull/117) Remove the global `i` (@3rd-Eden)
-
-- [#121](https://github.com/mikeal/request/pull/121) Another patch for cookie handling regression (@jhurliman)
-
-- [#104](https://github.com/mikeal/request/pull/104) Cookie handling contains bugs (@janjongboom)
-
-- [#112](https://github.com/mikeal/request/pull/112) Support using a custom http-like module (@jhs)
-
-- [#132](https://github.com/mikeal/request/pull/132) return the body as a Buffer when encoding is set to null (@jahewson)
-
-- [#135](https://github.com/mikeal/request/pull/135) host vs hostname (@iangreenleaf)
-
-- [#133](https://github.com/mikeal/request/pull/133) Fixed cookies parsing (@afanasy)
-
-- [#144](https://github.com/mikeal/request/pull/144) added "form" option to readme (@petejkim)
-
-- [#146](https://github.com/mikeal/request/pull/146) Multipart should respect content-type if previously set (@apeace)
-
-- [#148](https://github.com/mikeal/request/pull/148) Retry Agent (@thejh)
-
-- [#90](https://github.com/mikeal/request/pull/90) add option followAllRedirects to follow post/put redirects (@jroes)
-
-- [#162](https://github.com/mikeal/request/pull/162) Fix issue #159 (@dpetukhov)
-
-- [#161](https://github.com/mikeal/request/pull/161) Fix cookie jar/headers.cookie collision (#125) (@papandreou)
-
-- [#168](https://github.com/mikeal/request/pull/168) Picking off an EasyFix by adding some missing mimetypes. (@serby)
-
-- [#170](https://github.com/mikeal/request/pull/170) can't create a cookie in a wrapped request (defaults) (@fabianonunes)
-
-- [#179](https://github.com/mikeal/request/pull/179) fix to add opts in .pipe(stream, opts) (@substack)
-
-- [#180](https://github.com/mikeal/request/pull/180) Modified the post, put, head and del shortcuts to support uri optional param (@twilson63)
-
-- [#177](https://github.com/mikeal/request/pull/177) Issue #173 Support uri as first and optional config as second argument (@twilson63)
-
-- [#182](https://github.com/mikeal/request/pull/182) Fix request.defaults to support (uri, options, callback) api (@twilson63)
-
-- [#176](https://github.com/mikeal/request/pull/176) Querystring option (@csainty)
-
-- [#188](https://github.com/mikeal/request/pull/188) Add abort support to the returned request (@itay)
-
-- [#193](https://github.com/mikeal/request/pull/193) Fixes GH-119 (@goatslacker)
-
-- [#197](https://github.com/mikeal/request/pull/197) Make ForeverAgent work with HTTPS (@isaacs)
-
-- [#198](https://github.com/mikeal/request/pull/198) Bugfix on forever usage of util.inherits (@isaacs)
-
-- [#199](https://github.com/mikeal/request/pull/199) Tunnel (@isaacs)
-
-- [#203](https://github.com/mikeal/request/pull/203) Fix cookie and redirect bugs and add auth support for HTTPS tunnel (@milewise)
-
-- [#217](https://github.com/mikeal/request/pull/217) need to use Authorization (titlecase) header with Tumblr OAuth (@visnup)
-
-- [#224](https://github.com/mikeal/request/pull/224) Multipart content-type change (@janjongboom)
-
-- [#211](https://github.com/mikeal/request/pull/211) Replace all occurrences of special chars in RFC3986 (@chriso)
-
-- [#240](https://github.com/mikeal/request/pull/240) don't error when null is passed for options (@polotek)
-
-- [#243](https://github.com/mikeal/request/pull/243) Dynamic boundary (@zephrax)
-
-- [#246](https://github.com/mikeal/request/pull/246) Fixing the set-cookie header (@jeromegn)
-
-- [#260](https://github.com/mikeal/request/pull/260) fixed just another leak of 'i' (@sreuter)
-
-- [#255](https://github.com/mikeal/request/pull/255) multipart allow body === '' ( the empty string ) (@Filirom1)
-
-- [#261](https://github.com/mikeal/request/pull/261) Setting 'pool' to 'false' does NOT disable Agent pooling (@timshadel)
-
-- [#262](https://github.com/mikeal/request/pull/262) JSON test should check for equality (@timshadel)
-
-- [#265](https://github.com/mikeal/request/pull/265) uncaughtException when redirected to invalid URI (@naholyr)
-
-- [#263](https://github.com/mikeal/request/pull/263) Bug in OAuth key generation for sha1 (@nanodocumet)
-
-- [#268](https://github.com/mikeal/request/pull/268) I'm not OCD seriously (@TehShrike)
-
-- [#273](https://github.com/mikeal/request/pull/273) Pipe back pressure issue (@mafintosh)
-
-- [#279](https://github.com/mikeal/request/pull/279) fix tests with boundary by injecting boundry from header (@benatkin)
-
-- [#241](https://github.com/mikeal/request/pull/241) Composability updates suggested by issue #239 (@polotek)
-
-- [#284](https://github.com/mikeal/request/pull/284) Remove stray `console.log()` call in multipart generator. (@bcherry)
-
-- [#272](https://github.com/mikeal/request/pull/272) Boundary begins with CRLF? (@proksoup)
-
-- [#207](https://github.com/mikeal/request/pull/207) Fix #206 Change HTTP/HTTPS agent when redirecting between protocols (@isaacs)
-
-- [#280](https://github.com/mikeal/request/pull/280) Like in node.js print options if NODE_DEBUG contains the word request (@Filirom1)
-
-- [#290](https://github.com/mikeal/request/pull/290) A test for #289 (@isaacs)
-
-- [#293](https://github.com/mikeal/request/pull/293) Allow parser errors to bubble up to request (@mscdex)
-
-- [#317](https://github.com/mikeal/request/pull/317) Workaround for #313 (@isaacs)
-
-- [#318](https://github.com/mikeal/request/pull/318) Pass servername to tunneling secure socket creation (@isaacs)
-
-- [#326](https://github.com/mikeal/request/pull/326) Do not try to remove listener from an undefined connection (@strk)
-
-- [#320](https://github.com/mikeal/request/pull/320) request.defaults() doesn't need to wrap jar() (@StuartHarris)
-
-- [#343](https://github.com/mikeal/request/pull/343) Allow AWS to work in more situations, added a note in the README on its usage (@nlf)
-
-- [#332](https://github.com/mikeal/request/pull/332) Fix #296 - Only set Content-Type if body exists (@Marsup)
-
-- [#355](https://github.com/mikeal/request/pull/355) stop sending erroneous headers on redirected requests (@azylman)
-
-- [#360](https://github.com/mikeal/request/pull/360) Delete self._form along with everything else on redirect (@jgautier)
-
-- [#361](https://github.com/mikeal/request/pull/361) Don't create a Content-Length header if we already have it set (@danjenkins)
-
-- [#362](https://github.com/mikeal/request/pull/362) Running `rfc3986` on `base_uri` in `oauth.hmacsign` instead of just `encodeURIComponent` (@jeffmarshall)
-
-- [#363](https://github.com/mikeal/request/pull/363) rfc3986 on base_uri, now passes tests (@jeffmarshall)
-
-- [#344](https://github.com/mikeal/request/pull/344) Make AWS auth signing find headers correctly (@nlf)
-
-- [#369](https://github.com/mikeal/request/pull/369) Don't remove x_auth_mode for Twitter reverse auth (@drudge)
-
-- [#370](https://github.com/mikeal/request/pull/370) Twitter reverse auth uses x_auth_mode not x_auth_type (@drudge)
-
-- [#374](https://github.com/mikeal/request/pull/374) Correct Host header for proxy tunnel CONNECT (@ypocat)
-
-- [#375](https://github.com/mikeal/request/pull/375) Fix for missing oauth_timestamp parameter (@jplock)
-
-- [#376](https://github.com/mikeal/request/pull/376) Headers lost on redirect (@kapetan)
-
-- [#380](https://github.com/mikeal/request/pull/380) Fixes missing host header on retried request when using forever agent (@mac-)
-
-- [#381](https://github.com/mikeal/request/pull/381) Resolving "Invalid signature. Expected signature base string: " (@landeiro)
-
-- [#398](https://github.com/mikeal/request/pull/398) Add more reporting to tests (@mmalecki)
-
-- [#403](https://github.com/mikeal/request/pull/403) Optimize environment lookup to happen once only (@mmalecki)
-
-- [#415](https://github.com/mikeal/request/pull/415) Fixed a typo. (@jerem)
-
-- [#430](https://github.com/mikeal/request/pull/430) Respect specified {Host,host} headers, not just {host} (@andrewschaaf)
-
-- [#338](https://github.com/mikeal/request/pull/338) Add more auth options, including digest support (@nylen)
-
-- [#448](https://github.com/mikeal/request/pull/448) Convenience method for PATCH (@mloar)
-
-- [#413](https://github.com/mikeal/request/pull/413) rename googledoodle.png to .jpg (@nfriedly)
-
-- [#454](https://github.com/mikeal/request/pull/454) Destroy the response if present when destroying the request (clean merge) (@mafintosh)
-
-- [#429](https://github.com/mikeal/request/pull/429) Copy options before adding callback. (@nrn)
-
-- [#462](https://github.com/mikeal/request/pull/462) if query params are empty, then request path shouldn't end with a '?' (merges cleanly now) (@jaipandya)
-
-- [#471](https://github.com/mikeal/request/pull/471) Using querystring library from visionmedia (@kbackowski)
-
-- [#473](https://github.com/mikeal/request/pull/473) V0.10 compat (@isaacs)
-
-- [#475](https://github.com/mikeal/request/pull/475) Use `unescape` from `querystring` (@shimaore)
-
-- [#479](https://github.com/mikeal/request/pull/479) Changing so if Accept header is explicitly set, sending json does not ov... (@RoryH)
-
-- [#490](https://github.com/mikeal/request/pull/490) Empty response body (3-rd argument) must be passed to callback as an empty string (@Olegas)
-
-- [#498](https://github.com/mikeal/request/pull/498) Moving response emit above setHeaders on destination streams (@kenperkins)
-
-- [#512](https://github.com/mikeal/request/pull/512) Make password optional to support the format: http://username@hostname/ (@pajato1)
-
-- [#508](https://github.com/mikeal/request/pull/508) Honor the .strictSSL option when using proxies (tunnel-agent) (@jhs)
-
-- [#519](https://github.com/mikeal/request/pull/519) Update internal path state on post-creation QS changes (@jblebrun)
-
-- [#520](https://github.com/mikeal/request/pull/520) Fixing test-tunnel.js (@noway421)
-
-- [#523](https://github.com/mikeal/request/pull/523) Updating dependencies (@noway421)
-
-- [#510](https://github.com/mikeal/request/pull/510) Add HTTP Signature support. (@davidlehn)
-
-- [#456](https://github.com/mikeal/request/pull/456) hawk 0.9.0 (@hueniverse)
-
-- [#460](https://github.com/mikeal/request/pull/460) hawk 0.10.0 (@hueniverse)
-
-- [#444](https://github.com/mikeal/request/pull/444) protect against double callbacks on error path (@spollack)
-
-- [#322](https://github.com/mikeal/request/pull/322) Fix + test for piped into request bumped into redirect. #321 (@alexindigo)
-
-- [#513](https://github.com/mikeal/request/pull/513) add 'localAddress' support (@yyfrankyy)
-
-- [#249](https://github.com/mikeal/request/pull/249) Fix for the fix of your (closed) issue #89 where self.headers[content-length] is set to 0 for all methods (@sethbridges)
-
-- [#502](https://github.com/mikeal/request/pull/502) Fix POST (and probably other) requests that are retried after 401 Unauthorized (@nylen)
-
-- [#282](https://github.com/mikeal/request/pull/282) OAuth Authorization header contains non-"oauth_" parameters (@jplock)
-
-- [#388](https://github.com/mikeal/request/pull/388) Ensure "safe" toJSON doesn't break EventEmitters (@othiym23)
-
-- [#214](https://github.com/mikeal/request/pull/214) documenting additional behavior of json option (@jphaas)
-
-- [#310](https://github.com/mikeal/request/pull/310) Twitter Oauth Stuff Out of Date; Now Updated (@joemccann)
-
-- [#433](https://github.com/mikeal/request/pull/433) Added support for HTTPS cert & key (@indexzero)
-
-- [#461](https://github.com/mikeal/request/pull/461) Strip the UTF8 BOM from a UTF encoded response (@kppullin)
-
-
-### v1.2.0 (2011/01/30 22:04 +00:00)
-- [#3](https://github.com/mikeal/request/pull/3) JSON body (@Stanley)
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/README.md
deleted file mode 100644
index 3651e499..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/README.md
+++ /dev/null
@@ -1,395 +0,0 @@
-# Request -- Simplified HTTP client
-
-[![NPM](https://nodei.co/npm/request.png)](https://nodei.co/npm/request/)
-
-## Super simple to use
-
-Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.
-
-```javascript
-var request = require('request');
-request('http://www.google.com', function (error, response, body) {
-  if (!error && response.statusCode == 200) {
-    console.log(body) // Print the google web page.
-  }
-})
-```
-
-## Streaming
-
-You can stream any response to a file stream.
-
-```javascript
-request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
-```
-
-You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types (in this case `application/json`) and use the proper `content-type` in the PUT request (if the headers don’t already provide one).
-
-```javascript
-fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
-```
-
-Request can also `pipe` to itself. When doing so, `content-type` and `content-length` are preserved in the PUT headers.
-
-```javascript
-request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
-```
-
-Now let’s get fancy.
-
-```javascript
-http.createServer(function (req, resp) {
-  if (req.url === '/doodle.png') {
-    if (req.method === 'PUT') {
-      req.pipe(request.put('http://mysite.com/doodle.png'))
-    } else if (req.method === 'GET' || req.method === 'HEAD') {
-      request.get('http://mysite.com/doodle.png').pipe(resp)
-    }
-  }
-})
-```
-
-You can also `pipe()` from `http.ServerRequest` instances, as well as to `http.ServerResponse` instances. The HTTP method, headers, and entity-body data will be sent. Which means that, if you don't really care about security, you can do:
-
-```javascript
-http.createServer(function (req, resp) {
-  if (req.url === '/doodle.png') {
-    var x = request('http://mysite.com/doodle.png')
-    req.pipe(x)
-    x.pipe(resp)
-  }
-})
-```
-
-And since `pipe()` returns the destination stream in ≥ Node 0.5.x you can do one line proxying. :)
-
-```javascript
-req.pipe(request('http://mysite.com/doodle.png')).pipe(resp)
-```
-
-Also, none of this new functionality conflicts with requests previous features, it just expands them.
-
-```javascript
-var r = request.defaults({'proxy':'http://localproxy.com'})
-
-http.createServer(function (req, resp) {
-  if (req.url === '/doodle.png') {
-    r.get('http://google.com/doodle.png').pipe(resp)
-  }
-})
-```
-
-You can still use intermediate proxies, the requests will still follow HTTP forwards, etc.
-
-## UNIX Socket 
-
-`request` supports the `unix://` protocol for all requests. The path is assumed to be absolute to the root of the host file system. 
-
-HTTP paths are extracted from the supplied URL by testing each level of the full URL against net.connect for a socket response.
-
-Thus the following request will GET `/httppath` from the HTTP server listening on `/tmp/unix.socket`
-
-```javascript
-request.get('unix://tmp/unix.socket/httppath')
-```
-
-## Forms
-
-`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.
-
-URL-encoded forms are simple.
-
-```javascript
-request.post('http://service.com/upload', {form:{key:'value'}})
-// or
-request.post('http://service.com/upload').form({key:'value'})
-```
-
-For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don’t need to worry about piping the form object or setting the headers, `request` will handle that for you.
-
-```javascript
-var r = request.post('http://service.com/upload', function optionalCallback (err, httpResponse, body) {
-  if (err) {
-    return console.error('upload failed:', err);
-  }
-  console.log('Upload successful!  Server responded with:', body);
-})
-var form = r.form()
-form.append('my_field', 'my_value')
-form.append('my_buffer', new Buffer([1, 2, 3]))
-form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')))
-form.append('remote_file', request('http://google.com/doodle.png'))
-
-// Just like always, `r` is a writable stream, and can be used as such (you have until nextTick to pipe it, etc.)
-// Alternatively, you can provide a callback (that's what this example does-- see `optionalCallback` above).
-```
-
-## HTTP Authentication
-
-```javascript
-request.get('http://some.server.com/').auth('username', 'password', false);
-// or
-request.get('http://some.server.com/', {
-  'auth': {
-    'user': 'username',
-    'pass': 'password',
-    'sendImmediately': false
-  }
-});
-// or
-request.get('http://some.server.com/').auth(null, null, true, 'bearerToken');
-// or
-request.get('http://some.server.com/', {
-  'auth': {
-    'bearer': 'bearerToken'
-  }
-});
-```
-
-If passed as an option, `auth` should be a hash containing values `user` || `username`, `pass` || `password`, and `sendImmediately` (optional).  The method form takes parameters `auth(username, password, sendImmediately)`.
-
-`sendImmediately` defaults to `true`, which causes a basic authentication header to be sent.  If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a `401` response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).
-
-Digest authentication is supported, but it only works with `sendImmediately` set to `false`; otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail.
-
-Bearer authentication is supported, and is activated when the `bearer` value is available. The value may be either a `String` or a `Function` returning a `String`. Using a function to supply the bearer token is particularly useful if used in conjuction with `defaults` to allow a single function to supply the last known token at the time or sending a request or to compute one on the fly.
-
-## OAuth Signing
-
-```javascript
-// Twitter OAuth
-var qs = require('querystring')
-  , oauth =
-    { callback: 'http://mysite.com/callback/'
-    , consumer_key: CONSUMER_KEY
-    , consumer_secret: CONSUMER_SECRET
-    }
-  , url = 'https://api.twitter.com/oauth/request_token'
-  ;
-request.post({url:url, oauth:oauth}, function (e, r, body) {
-  // Ideally, you would take the body in the response
-  // and construct a URL that a user clicks on (like a sign in button).
-  // The verifier is only available in the response after a user has
-  // verified with twitter that they are authorizing your app.
-  var access_token = qs.parse(body)
-    , oauth =
-      { consumer_key: CONSUMER_KEY
-      , consumer_secret: CONSUMER_SECRET
-      , token: access_token.oauth_token
-      , verifier: access_token.oauth_verifier
-      }
-    , url = 'https://api.twitter.com/oauth/access_token'
-    ;
-  request.post({url:url, oauth:oauth}, function (e, r, body) {
-    var perm_token = qs.parse(body)
-      , oauth =
-        { consumer_key: CONSUMER_KEY
-        , consumer_secret: CONSUMER_SECRET
-        , token: perm_token.oauth_token
-        , token_secret: perm_token.oauth_token_secret
-        }
-      , url = 'https://api.twitter.com/1.1/users/show.json?'
-      , params =
-        { screen_name: perm_token.screen_name
-        , user_id: perm_token.user_id
-        }
-      ;
-    url += qs.stringify(params)
-    request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {
-      console.log(user)
-    })
-  })
-})
-```
-
-### Custom HTTP Headers
-
-HTTP Headers, such as `User-Agent`, can be set in the `options` object.
-In the example below, we call the github API to find out the number
-of stars and forks for the request repository. This requires a
-custom `User-Agent` header as well as https.
-
-```javascript
-var request = require('request');
-
-var options = {
-	url: 'https://api.github.com/repos/mikeal/request',
-	headers: {
-		'User-Agent': 'request'
-	}
-};
-
-function callback(error, response, body) {
-	if (!error && response.statusCode == 200) {
-		var info = JSON.parse(body);
-		console.log(info.stargazers_count + " Stars");
-		console.log(info.forks_count + " Forks");
-	}
-}
-
-request(options, callback);
-```
-
-### request(options, callback)
-
-The first argument can be either a `url` or an `options` object. The only required option is `uri`; all others are optional.
-
-* `uri` || `url` - fully qualified uri or a parsed url object from `url.parse()`
-* `qs` - object containing querystring values to be appended to the `uri`
-* `method` - http method (default: `"GET"`)
-* `headers` - http headers (default: `{}`)
-* `body` - entity body for PATCH, POST and PUT requests. Must be a `Buffer` or `String`.
-* `form` - when passed an object, this sets `body` to a querystring representation of value, and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no options, a `FormData` instance is returned (and is piped to request).
-* `auth` - A hash containing values `user` || `username`, `pass` || `password`, and `sendImmediately` (optional).  See documentation above.
-* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.  Additionally, parses the response body as JSON.
-* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.
-* `followRedirect` - follow HTTP 3xx responses as redirects (default: `true`)
-* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects (default: `false`)
-* `maxRedirects` - the maximum number of redirects to follow (default: `10`)
-* `encoding` - Encoding to be used on `setEncoding` of response data. If `null`, the `body` is returned as a `Buffer`.
-* `pool` - A hash object containing the agents for these requests. If omitted, the request will use the global pool (which is set to node's default `maxSockets`)
-* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.
-* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request
-* `proxy` - An HTTP proxy to be used. Supports proxy Auth with Basic Auth, identical to support for the `url` parameter (by embedding the auth info in the `uri`)
-* `oauth` - Options for OAuth HMAC-SHA1 signing. See documentation above.
-* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).
-* `strictSSL` - If `true`, requires SSL certificates be valid. **Note:** to use your own certificate authority, you need to specify an agent that was created with that CA as an option.
-* `jar` - If `true`, remember cookies for future use (or define your custom cookie jar; see examples section)
-* `aws` - `object` containing AWS signing information. Should have the properties `key`, `secret`. Also requires the property `bucket`, unless you’re specifying your `bucket` as part of the path, or the request doesn’t use a bucket (i.e. GET Services)
-* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.
-* `localAddress` - Local interface to bind for network connections.
-
-
-The callback argument gets 3 arguments: 
-
-1. An `error` when applicable (usually from [`http.ClientRequest`](http://nodejs.org/api/http.html#http_class_http_clientrequest) object)
-2. An [`http.IncomingMessage`](http://nodejs.org/api/http.html#http_http_incomingmessage) object
-3. The third is the `response` body (`String` or `Buffer`, or JSON object if the `json` option is supplied)
-
-## Convenience methods
-
-There are also shorthand methods for different HTTP METHODs and some other conveniences.
-
-### request.defaults(options)
-
-This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.
-
-### request.put
-
-Same as `request()`, but defaults to `method: "PUT"`.
-
-```javascript
-request.put(url)
-```
-
-### request.patch
-
-Same as `request()`, but defaults to `method: "PATCH"`.
-
-```javascript
-request.patch(url)
-```
-
-### request.post
-
-Same as `request()`, but defaults to `method: "POST"`.
-
-```javascript
-request.post(url)
-```
-
-### request.head
-
-Same as request() but defaults to `method: "HEAD"`.
-
-```javascript
-request.head(url)
-```
-
-### request.del
-
-Same as `request()`, but defaults to `method: "DELETE"`.
-
-```javascript
-request.del(url)
-```
-
-### request.get
-
-Same as `request()` (for uniformity).
-
-```javascript
-request.get(url)
-```
-### request.cookie
-
-Function that creates a new cookie.
-
-```javascript
-request.cookie('cookie_string_here')
-```
-### request.jar
-
-Function that creates a new cookie jar.
-
-```javascript
-request.jar()
-```
-
-
-## Examples:
-
-```javascript
-  var request = require('request')
-    , rand = Math.floor(Math.random()*100000000).toString()
-    ;
-  request(
-    { method: 'PUT'
-    , uri: 'http://mikeal.iriscouch.com/testjs/' + rand
-    , multipart:
-      [ { 'content-type': 'application/json'
-        ,  body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
-        }
-      , { body: 'I am an attachment' }
-      ]
-    }
-  , function (error, response, body) {
-      if(response.statusCode == 201){
-        console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)
-      } else {
-        console.log('error: '+ response.statusCode)
-        console.log(body)
-      }
-    }
-  )
-```
-
-Cookies are disabled by default (else, they would be used in subsequent requests). To enable cookies, set `jar` to `true` (either in `defaults` or `options`).
-
-```javascript
-var request = request.defaults({jar: true})
-request('http://www.google.com', function () {
-  request('http://images.google.com')
-})
-```
-
-To use a custom cookie jar (instead of `request`’s global cookie jar), set `jar` to an instance of `request.jar()` (either in `defaults` or `options`)
-
-```javascript
-var j = request.jar()
-var request = request.defaults({jar:j})
-request('http://www.google.com', function () {
-  request('http://images.google.com')
-})
-```
-
-OR
-
-```javascript
-var j = request.jar()
-var cookie = request.cookie('your_cookie_here')
-j.setCookie(cookie, uri);
-request({url: 'http://www.google.com', jar: j}, function () {
-  request('http://images.google.com')
-})
-```
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/index.js
deleted file mode 100755
index 506282d5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/index.js
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2010-2012 Mikeal Rogers
-//
-//    Licensed under the Apache License, Version 2.0 (the "License");
-//    you may not use this file except in compliance with the License.
-//    You may obtain a copy of the License at
-//
-//        http://www.apache.org/licenses/LICENSE-2.0
-//
-//    Unless required by applicable law or agreed to in writing, software
-//    distributed under the License is distributed on an "AS IS" BASIS,
-//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//    See the License for the specific language governing permissions and
-//    limitations under the License.
-
-var cookies = require('./lib/cookies')
-  , copy = require('./lib/copy')
-  , Request = require('./request')
-  , util = require('util')
-  ;
-
-
-
-// organize params for patch, post, put, head, del
-function initParams(uri, options, callback) {
-  var opts;
-  if ((typeof options === 'function') && !callback) callback = options
-  if (options && typeof options === 'object') {
-    opts = util._extend({}, options);
-    opts.uri = uri
-  } else if (typeof uri === 'string') {
-    opts = {uri:uri}
-  } else {
-    opts = util._extend({}, uri);
-    uri = opts.uri
-  }
-
-  return { uri: uri, options: opts, callback: callback }
-}
-
-function request (uri, options, callback) {
-  var opts;
-  if (typeof uri === 'undefined') throw new Error('undefined is not a valid uri or options object.')
-  if ((typeof options === 'function') && !callback) callback = options
-  if (options && typeof options === 'object') {
-    opts = util._extend({}, options);
-    opts.uri = uri
-  } else if (typeof uri === 'string') {
-    opts = {uri:uri}
-  } else {
-    opts = util._extend({}, uri);
-  }
-
-  if (callback) opts.callback = callback
-  var r = new Request(opts)
-  return r
-}
-
-module.exports = request
-
-request.Request = Request;
-
-request.debug = process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG)
-
-request.initParams = initParams
-
-request.defaults = function (options, requester) {
-  var def = function (method) {
-    var d = function (uri, opts, callback) {
-      var params = initParams(uri, opts, callback)
-      for (var i in options) {
-        if (params.options[i] === undefined) params.options[i] = options[i]
-      }
-      if(typeof requester === 'function') {
-        if(method === request) {
-          method = requester
-        } else {
-          params.options._requester = requester
-        }
-      }
-      return method(params.options, params.callback)
-    }
-    return d
-  }
-  var de = def(request)
-  de.get = def(request.get)
-  de.patch = def(request.patch)
-  de.post = def(request.post)
-  de.put = def(request.put)
-  de.head = def(request.head)
-  de.del = def(request.del)
-  de.cookie = def(request.cookie)
-  de.jar = request.jar
-  return de
-}
-
-function requester(params) {
-  if(typeof params.options._requester === 'function') {
-    return params.options._requester
-  } else {
-    return request
-  }
-}
-
-request.forever = function (agentOptions, optionsArg) {
-  var options = {}
-  if (optionsArg) {
-    for (var option in optionsArg) {
-      options[option] = optionsArg[option]
-    }
-  }
-  if (agentOptions) options.agentOptions = agentOptions
-  options.forever = true
-  return request.defaults(options)
-}
-
-request.get = function (uri, options, callback) {
-  var params = initParams(uri, options, callback)
-  params.options.method = 'GET'
-  return requester(params)(params.uri || null, params.options, params.callback)
-}
-request.post = function (uri, options, callback) {
-  var params = initParams(uri, options, callback)
-  params.options.method = 'POST'
-  return requester(params)(params.uri || null, params.options, params.callback)
-}
-request.put = function (uri, options, callback) {
-  var params = initParams(uri, options, callback)
-  params.options.method = 'PUT'
-  return requester(params)(params.uri || null, params.options, params.callback)
-}
-request.patch = function (uri, options, callback) {
-  var params = initParams(uri, options, callback)
-  params.options.method = 'PATCH'
-  return requester(params)(params.uri || null, params.options, params.callback)
-}
-request.head = function (uri, options, callback) {
-  var params = initParams(uri, options, callback)
-  params.options.method = 'HEAD'
-  if (params.options.body ||
-      params.options.requestBodyStream ||
-      (params.options.json && typeof params.options.json !== 'boolean') ||
-      params.options.multipart) {
-    throw new Error("HTTP HEAD requests MUST NOT include a request body.")
-  }
-
-  return requester(params)(params.uri || null, params.options, params.callback)
-}
-request.del = function (uri, options, callback) {
-  var params = initParams(uri, options, callback)
-  params.options.method = 'DELETE'
-  return requester(params)(params.uri || null, params.options, params.callback)
-}
-request.jar = function () {
-  return cookies.jar();
-}
-request.cookie = function (str) {
-  return cookies.parse(str);
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/cookies.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/cookies.js
deleted file mode 100644
index 4eb641c5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/cookies.js
+++ /dev/null
@@ -1,36 +0,0 @@
-var optional = require('./optional')
-  , tough = optional('tough-cookie')
-  , Cookie = tough && tough.Cookie
-  , CookieJar = tough && tough.CookieJar
-  ;
-
-exports.parse = function(str) {
-  if (str && str.uri) str = str.uri
-  if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param")
-  if (!Cookie) {
-    return null;
-  }
-  return Cookie.parse(str)
-};
-
-// Adapt the sometimes-Async api of tough.CookieJar to our requirements
-function RequestJar() {
-  this._jar = new CookieJar();
-}
-RequestJar.prototype.setCookie = function(cookieOrStr, uri, options) {
-  return this._jar.setCookieSync(cookieOrStr, uri, options || {});
-};
-RequestJar.prototype.getCookieString = function(uri) {
-  return this._jar.getCookieStringSync(uri);
-};
-
-exports.jar = function() {
-  if (!CookieJar) {
-    // tough-cookie not loaded, return a stub object:
-    return {
-      setCookie: function(){},
-      getCookieString: function(){}
-    };
-  }
-  return new RequestJar();
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/copy.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/copy.js
deleted file mode 100644
index 56831ff8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/copy.js
+++ /dev/null
@@ -1,8 +0,0 @@
-module.exports =
-function copy (obj) {
-  var o = {}
-  Object.keys(obj).forEach(function (i) {
-    o[i] = obj[i]
-  })
-  return o
-}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/debug.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/debug.js
deleted file mode 100644
index fa27b24b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/debug.js
+++ /dev/null
@@ -1,7 +0,0 @@
-var util = require('util')
-
-module.exports =
-function debug () {
-  if (/\brequest\b/.test(process.env.NODE_DEBUG))
-    console.error('REQUEST %s', util.format.apply(util, arguments))
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/getSafe.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/getSafe.js
deleted file mode 100644
index 28e07ea5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/getSafe.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Safe toJSON
-module.exports =
-function getSafe (self, uuid) {
-  if (typeof self === 'object' || typeof self === 'function') var safe = {}
-  if (Array.isArray(self)) var safe = []
-
-  var recurse = []
-
-  Object.defineProperty(self, uuid, {})
-
-  var attrs = Object.keys(self).filter(function (i) {
-    if (i === uuid) return false
-    if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true
-    return !(Object.getOwnPropertyDescriptor(self[i], uuid))
-  })
-
-
-  for (var i=0;i<attrs.length;i++) {
-    if ( (typeof self[attrs[i]] !== 'object' && typeof self[attrs[i]] !== 'function') ||
-          self[attrs[i]] === null
-        ) {
-      safe[attrs[i]] = self[attrs[i]]
-    } else {
-      recurse.push(attrs[i])
-      Object.defineProperty(self[attrs[i]], uuid, {})
-    }
-  }
-
-  for (var i=0;i<recurse.length;i++) {
-    safe[recurse[i]] = getSafe(self[recurse[i]], uuid)
-  }
-
-  return safe
-}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/optional.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/optional.js
deleted file mode 100644
index 0c4fe853..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/lib/optional.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = function(module) {
-  try {
-    return require(module);
-  } catch (e) {}
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/LICENSE
deleted file mode 100644
index a4a9aee0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/LICENSE
+++ /dev/null
@@ -1,55 +0,0 @@
-Apache License
-
-Version 2.0, January 2004
-
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
-
-"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of this License; and
-
-You must cause any modified files to carry prominent notices stating that You changed the files; and
-
-You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
-
-If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/README.md
deleted file mode 100644
index 763564e0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-aws-sign
-========
-
-AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/index.js
deleted file mode 100644
index 576e49dd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/index.js
+++ /dev/null
@@ -1,202 +0,0 @@
-
-/*!
- * knox - auth
- * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
- * MIT Licensed
- */
-
-/**
- * Module dependencies.
- */
-
-var crypto = require('crypto')
-  , parse = require('url').parse
-  ;
-
-/**
- * Valid keys.
- */
-
-var keys = 
-  [ 'acl'
-  , 'location'
-  , 'logging'
-  , 'notification'
-  , 'partNumber'
-  , 'policy'
-  , 'requestPayment'
-  , 'torrent'
-  , 'uploadId'
-  , 'uploads'
-  , 'versionId'
-  , 'versioning'
-  , 'versions'
-  , 'website'
-  ]
-
-/**
- * Return an "Authorization" header value with the given `options`
- * in the form of "AWS <key>:<signature>"
- *
- * @param {Object} options
- * @return {String}
- * @api private
- */
-
-function authorization (options) {
-  return 'AWS ' + options.key + ':' + sign(options)
-}
-
-module.exports = authorization
-module.exports.authorization = authorization
-
-/**
- * Simple HMAC-SHA1 Wrapper
- *
- * @param {Object} options
- * @return {String}
- * @api private
- */ 
-
-function hmacSha1 (options) {
-  return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64')
-}
-
-module.exports.hmacSha1 = hmacSha1
-
-/**
- * Create a base64 sha1 HMAC for `options`. 
- * 
- * @param {Object} options
- * @return {String}
- * @api private
- */
-
-function sign (options) {
-  options.message = stringToSign(options)
-  return hmacSha1(options)
-}
-module.exports.sign = sign
-
-/**
- * Create a base64 sha1 HMAC for `options`. 
- *
- * Specifically to be used with S3 presigned URLs
- * 
- * @param {Object} options
- * @return {String}
- * @api private
- */
-
-function signQuery (options) {
-  options.message = queryStringToSign(options)
-  return hmacSha1(options)
-}
-module.exports.signQuery= signQuery
-
-/**
- * Return a string for sign() with the given `options`.
- *
- * Spec:
- * 
- *    <verb>\n
- *    <md5>\n
- *    <content-type>\n
- *    <date>\n
- *    [headers\n]
- *    <resource>
- *
- * @param {Object} options
- * @return {String}
- * @api private
- */
-
-function stringToSign (options) {
-  var headers = options.amazonHeaders || ''
-  if (headers) headers += '\n'
-  var r = 
-    [ options.verb
-    , options.md5
-    , options.contentType
-    , options.date ? options.date.toUTCString() : ''
-    , headers + options.resource
-    ]
-  return r.join('\n')
-}
-module.exports.queryStringToSign = stringToSign
-
-/**
- * Return a string for sign() with the given `options`, but is meant exclusively
- * for S3 presigned URLs
- *
- * Spec:
- * 
- *    <date>\n
- *    <resource>
- *
- * @param {Object} options
- * @return {String}
- * @api private
- */
-
-function queryStringToSign (options){
-  return 'GET\n\n\n' + options.date + '\n' + options.resource
-}
-module.exports.queryStringToSign = queryStringToSign
-
-/**
- * Perform the following:
- *
- *  - ignore non-amazon headers
- *  - lowercase fields
- *  - sort lexicographically
- *  - trim whitespace between ":"
- *  - join with newline
- *
- * @param {Object} headers
- * @return {String}
- * @api private
- */
-
-function canonicalizeHeaders (headers) {
-  var buf = []
-    , fields = Object.keys(headers)
-    ;
-  for (var i = 0, len = fields.length; i < len; ++i) {
-    var field = fields[i]
-      , val = headers[field]
-      , field = field.toLowerCase()
-      ;
-    if (0 !== field.indexOf('x-amz')) continue
-    buf.push(field + ':' + val)
-  }
-  return buf.sort().join('\n')
-}
-module.exports.canonicalizeHeaders = canonicalizeHeaders
-
-/**
- * Perform the following:
- *
- *  - ignore non sub-resources
- *  - sort lexicographically
- *
- * @param {String} resource
- * @return {String}
- * @api private
- */
-
-function canonicalizeResource (resource) {
-  var url = parse(resource, true)
-    , path = url.pathname
-    , buf = []
-    ;
-
-  Object.keys(url.query).forEach(function(key){
-    if (!~keys.indexOf(key)) return
-    var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key])
-    buf.push(key + val)
-  })
-
-  return path + (buf.length ? '?' + buf.sort().join('&') : '')
-}
-module.exports.canonicalizeResource = canonicalizeResource
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/package.json
deleted file mode 100644
index 21776dbe..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/aws-sign2/package.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "author": {
-    "name": "Mikeal Rogers",
-    "email": "mikeal.rogers@gmail.com",
-    "url": "http://www.futurealoof.com"
-  },
-  "name": "aws-sign2",
-  "description": "AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.",
-  "version": "0.5.0",
-  "repository": {
-    "url": "https://github.com/mikeal/aws-sign"
-  },
-  "main": "index.js",
-  "dependencies": {},
-  "devDependencies": {},
-  "optionalDependencies": {},
-  "engines": {
-    "node": "*"
-  },
-  "readme": "aws-sign\n========\n\nAWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/mikeal/aws-sign/issues"
-  },
-  "homepage": "https://github.com/mikeal/aws-sign",
-  "_id": "aws-sign2@0.5.0",
-  "_shasum": "c57103f7a17fc037f02d7c2e64b602ea223f7d63",
-  "_from": "aws-sign2@~0.5.0",
-  "_resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/LICENSE
deleted file mode 100644
index a4a9aee0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/LICENSE
+++ /dev/null
@@ -1,55 +0,0 @@
-Apache License
-
-Version 2.0, January 2004
-
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
-
-"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of this License; and
-
-You must cause any modified files to carry prominent notices stating that You changed the files; and
-
-You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
-
-If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/README.md
deleted file mode 100644
index 9d5b6634..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-forever-agent
-=============
-
-HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/index.js
deleted file mode 100644
index 1e8efcdf..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/index.js
+++ /dev/null
@@ -1,119 +0,0 @@
-module.exports = ForeverAgent
-ForeverAgent.SSL = ForeverAgentSSL
-
-var util = require('util')
-  , Agent = require('http').Agent
-  , net = require('net')
-  , tls = require('tls')
-  , AgentSSL = require('https').Agent
-
-function ForeverAgent(options) {
-  var self = this
-  self.options = options || {}
-  self.requests = {}
-  self.sockets = {}
-  self.freeSockets = {}
-  self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets
-  self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets
-  self.on('free', function(socket, host, port) {
-    var name = host + ':' + port
-    if (self.requests[name] && self.requests[name].length) {
-      self.requests[name].shift().onSocket(socket)
-    } else if (self.sockets[name].length < self.minSockets) {
-      if (!self.freeSockets[name]) self.freeSockets[name] = []
-      self.freeSockets[name].push(socket)
-      
-      // if an error happens while we don't use the socket anyway, meh, throw the socket away
-      var onIdleError = function() {
-        socket.destroy()
-      }
-      socket._onIdleError = onIdleError
-      socket.on('error', onIdleError)
-    } else {
-      // If there are no pending requests just destroy the
-      // socket and it will get removed from the pool. This
-      // gets us out of timeout issues and allows us to
-      // default to Connection:keep-alive.
-      socket.destroy()
-    }
-  })
-
-}
-util.inherits(ForeverAgent, Agent)
-
-ForeverAgent.defaultMinSockets = 5
-
-
-ForeverAgent.prototype.createConnection = net.createConnection
-ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest
-ForeverAgent.prototype.addRequest = function(req, host, port) {
-  var name = host + ':' + port
-  if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) {
-    var idleSocket = this.freeSockets[name].pop()
-    idleSocket.removeListener('error', idleSocket._onIdleError)
-    delete idleSocket._onIdleError
-    req._reusedSocket = true
-    req.onSocket(idleSocket)
-  } else {
-    this.addRequestNoreuse(req, host, port)
-  }
-}
-
-ForeverAgent.prototype.removeSocket = function(s, name, host, port) {
-  if (this.sockets[name]) {
-    var index = this.sockets[name].indexOf(s)
-    if (index !== -1) {
-      this.sockets[name].splice(index, 1)
-    }
-  } else if (this.sockets[name] && this.sockets[name].length === 0) {
-    // don't leak
-    delete this.sockets[name]
-    delete this.requests[name]
-  }
-  
-  if (this.freeSockets[name]) {
-    var index = this.freeSockets[name].indexOf(s)
-    if (index !== -1) {
-      this.freeSockets[name].splice(index, 1)
-      if (this.freeSockets[name].length === 0) {
-        delete this.freeSockets[name]
-      }
-    }
-  }
-
-  if (this.requests[name] && this.requests[name].length) {
-    // If we have pending requests and a socket gets closed a new one
-    // needs to be created to take over in the pool for the one that closed.
-    this.createSocket(name, host, port).emit('free')
-  }
-}
-
-function ForeverAgentSSL (options) {
-  ForeverAgent.call(this, options)
-}
-util.inherits(ForeverAgentSSL, ForeverAgent)
-
-ForeverAgentSSL.prototype.createConnection = createConnectionSSL
-ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest
-
-function createConnectionSSL (port, host, options) {
-  if (typeof port === 'object') {
-    options = port;
-  } else if (typeof host === 'object') {
-    options = host;
-  } else if (typeof options === 'object') {
-    options = options;
-  } else {
-    options = {};
-  }
-
-  if (typeof port === 'number') {
-    options.port = port;
-  }
-
-  if (typeof host === 'string') {
-    options.host = host;
-  }
-
-  return tls.connect(options);
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/package.json
deleted file mode 100644
index 6ec5529a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/forever-agent/package.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "author": {
-    "name": "Mikeal Rogers",
-    "email": "mikeal.rogers@gmail.com",
-    "url": "http://www.futurealoof.com"
-  },
-  "name": "forever-agent",
-  "description": "HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.",
-  "version": "0.5.2",
-  "repository": {
-    "url": "https://github.com/mikeal/forever-agent"
-  },
-  "main": "index.js",
-  "dependencies": {},
-  "devDependencies": {},
-  "optionalDependencies": {},
-  "engines": {
-    "node": "*"
-  },
-  "readme": "forever-agent\n=============\n\nHTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/mikeal/forever-agent/issues"
-  },
-  "homepage": "https://github.com/mikeal/forever-agent",
-  "_id": "forever-agent@0.5.2",
-  "_shasum": "6d0e09c4921f94a27f63d3b49c5feff1ea4c5130",
-  "_from": "forever-agent@~0.5.0",
-  "_resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/License b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/License
deleted file mode 100644
index c7ff12a2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/License
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
-
- 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/Readme.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/Readme.md
deleted file mode 100644
index dc73c463..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/Readme.md
+++ /dev/null
@@ -1,163 +0,0 @@
-# Form-Data [![Build Status](https://travis-ci.org/felixge/node-form-data.png?branch=master)](https://travis-ci.org/felixge/node-form-data) [![Dependency Status](https://gemnasium.com/felixge/node-form-data.png)](https://gemnasium.com/felixge/node-form-data)
-
-A module to create readable ```"multipart/form-data"``` streams. Can be used to submit forms and file uploads to other web applications.
-
-The API of this module is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd].
-
-[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface
-[streams2-thing]: http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions
-
-## Install
-
-```
-npm install form-data
-```
-
-## Usage
-
-In this example we are constructing a form with 3 fields that contain a string,
-a buffer and a file stream.
-
-``` javascript
-var FormData = require('form-data');
-var fs = require('fs');
-
-var form = new FormData();
-form.append('my_field', 'my value');
-form.append('my_buffer', new Buffer(10));
-form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
-```
-
-Also you can use http-response stream:
-
-``` javascript
-var FormData = require('form-data');
-var http = require('http');
-
-var form = new FormData();
-
-http.request('http://nodejs.org/images/logo.png', function(response) {
-  form.append('my_field', 'my value');
-  form.append('my_buffer', new Buffer(10));
-  form.append('my_logo', response);
-});
-```
-
-Or @mikeal's request stream:
-
-``` javascript
-var FormData = require('form-data');
-var request = require('request');
-
-var form = new FormData();
-
-form.append('my_field', 'my value');
-form.append('my_buffer', new Buffer(10));
-form.append('my_logo', request('http://nodejs.org/images/logo.png'));
-```
-
-In order to submit this form to a web application, call ```submit(url, [callback])``` method:
-
-``` javascript
-form.submit('http://example.org/', function(err, res) {
-  // res – response object (http.IncomingMessage)  //
-  res.resume(); // for node-0.10.x
-});
-
-```
-
-For more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods.
-
-### Alternative submission methods
-
-You can use node's http client interface:
-
-``` javascript
-var http = require('http');
-
-var request = http.request({
-  method: 'post',
-  host: 'example.org',
-  path: '/upload',
-  headers: form.getHeaders()
-});
-
-form.pipe(request);
-
-request.on('response', function(res) {
-  console.log(res.statusCode);
-});
-```
-
-Or if you would prefer the `'Content-Length'` header to be set for you:
-
-``` javascript
-form.submit('example.org/upload', function(err, res) {
-  console.log(res.statusCode);
-});
-```
-
-To use custom headers and pre-known length in parts:
-
-``` javascript
-var CRLF = '\r\n';
-var form = new FormData();
-
-var options = {
-  header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,
-  knownLength: 1
-};
-
-form.append('my_buffer', buffer, options);
-
-form.submit('http://example.com/', function(err, res) {
-  if (err) throw err;
-  console.log('Done');
-});
-```
-
-Form-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide "file"-related information manually:
-
-``` javascript
-someModule.stream(function(err, stdout, stderr) {
-  if (err) throw err;
-
-  var form = new FormData();
-
-  form.append('file', stdout, {
-    filename: 'unicycle.jpg',
-    contentType: 'image/jpg',
-    knownLength: 19806
-  });
-
-  form.submit('http://example.com/', function(err, res) {
-    if (err) throw err;
-    console.log('Done');
-  });
-});
-```
-
-For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:
-
-``` javascript
-form.submit({
-  host: 'example.com',
-  path: '/probably.php?extra=params',
-  auth: 'username:password'
-}, function(err, res) {
-  console.log(res.statusCode);
-});
-```
-
-## Notes
-
-- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround.
-- If it feels like FormData hangs after submit and you're on ```node-0.10```, please check [Compatibility with Older Node Versions][streams2-thing]
-
-## TODO
-
-- Add new streams (0.10) support and try really hard not to break it for 0.8.x.
-
-## License
-
-Form-Data is licensed under the MIT license.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/lib/form_data.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/lib/form_data.js
deleted file mode 100644
index d1064748..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/lib/form_data.js
+++ /dev/null
@@ -1,325 +0,0 @@
-var CombinedStream = require('combined-stream');
-var util = require('util');
-var path = require('path');
-var http = require('http');
-var https = require('https');
-var parseUrl = require('url').parse;
-var fs = require('fs');
-var mime = require('mime');
-var async = require('async');
-
-module.exports = FormData;
-function FormData() {
-  this._overheadLength = 0;
-  this._valueLength = 0;
-  this._lengthRetrievers = [];
-
-  CombinedStream.call(this);
-}
-util.inherits(FormData, CombinedStream);
-
-FormData.LINE_BREAK = '\r\n';
-
-FormData.prototype.append = function(field, value, options) {
-  options = options || {};
-
-  var append = CombinedStream.prototype.append.bind(this);
-
-  // all that streamy business can't handle numbers
-  if (typeof value == 'number') value = ''+value;
-
-  // https://github.com/felixge/node-form-data/issues/38
-  if (util.isArray(value)) {
-    // Please convert your array into string
-    // the way web server expects it
-    this._error(new Error('Arrays are not supported.'));
-    return;
-  }
-
-  var header = this._multiPartHeader(field, value, options);
-  var footer = this._multiPartFooter(field, value, options);
-
-  append(header);
-  append(value);
-  append(footer);
-
-  // pass along options.knownLength
-  this._trackLength(header, value, options);
-};
-
-FormData.prototype._trackLength = function(header, value, options) {
-  var valueLength = 0;
-
-  // used w/ getLengthSync(), when length is known.
-  // e.g. for streaming directly from a remote server,
-  // w/ a known file a size, and not wanting to wait for
-  // incoming file to finish to get its size.
-  if (options.knownLength != null) {
-    valueLength += +options.knownLength;
-  } else if (Buffer.isBuffer(value)) {
-    valueLength = value.length;
-  } else if (typeof value === 'string') {
-    valueLength = Buffer.byteLength(value);
-  }
-
-  this._valueLength += valueLength;
-
-  // @check why add CRLF? does this account for custom/multiple CRLFs?
-  this._overheadLength +=
-    Buffer.byteLength(header) +
-    + FormData.LINE_BREAK.length;
-
-  // empty or either doesn't have path or not an http response
-  if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) {
-    return;
-  }
-
-  // no need to bother with the length
-  if (!options.knownLength)
-  this._lengthRetrievers.push(function(next) {
-
-    if (value.hasOwnProperty('fd')) {
-      fs.stat(value.path, function(err, stat) {
-        if (err) {
-          next(err);
-          return;
-        }
-
-        next(null, stat.size);
-      });
-
-    // or http response
-    } else if (value.hasOwnProperty('httpVersion')) {
-      next(null, +value.headers['content-length']);
-
-    // or request stream http://github.com/mikeal/request
-    } else if (value.hasOwnProperty('httpModule')) {
-      // wait till response come back
-      value.on('response', function(response) {
-        value.pause();
-        next(null, +response.headers['content-length']);
-      });
-      value.resume();
-
-    // something else
-    } else {
-      next('Unknown stream');
-    }
-  });
-};
-
-FormData.prototype._multiPartHeader = function(field, value, options) {
-  var boundary = this.getBoundary();
-  var header = '';
-
-  // custom header specified (as string)?
-  // it becomes responsible for boundary
-  // (e.g. to handle extra CRLFs on .NET servers)
-  if (options.header != null) {
-    header = options.header;
-  } else {
-    header += '--' + boundary + FormData.LINE_BREAK +
-      'Content-Disposition: form-data; name="' + field + '"';
-
-    // fs- and request- streams have path property
-    // or use custom filename and/or contentType
-    // TODO: Use request's response mime-type
-    if (options.filename || value.path) {
-      header +=
-        '; filename="' + path.basename(options.filename || value.path) + '"' + FormData.LINE_BREAK +
-        'Content-Type: ' +  (options.contentType || mime.lookup(options.filename || value.path));
-
-    // http response has not
-    } else if (value.readable && value.hasOwnProperty('httpVersion')) {
-      header +=
-        '; filename="' + path.basename(value.client._httpMessage.path) + '"' + FormData.LINE_BREAK +
-        'Content-Type: ' + value.headers['content-type'];
-    }
-
-    header += FormData.LINE_BREAK + FormData.LINE_BREAK;
-  }
-
-  return header;
-};
-
-FormData.prototype._multiPartFooter = function(field, value, options) {
-  return function(next) {
-    var footer = FormData.LINE_BREAK;
-
-    var lastPart = (this._streams.length === 0);
-    if (lastPart) {
-      footer += this._lastBoundary();
-    }
-
-    next(footer);
-  }.bind(this);
-};
-
-FormData.prototype._lastBoundary = function() {
-  return '--' + this.getBoundary() + '--';
-};
-
-FormData.prototype.getHeaders = function(userHeaders) {
-  var formHeaders = {
-    'content-type': 'multipart/form-data; boundary=' + this.getBoundary()
-  };
-
-  for (var header in userHeaders) {
-    formHeaders[header.toLowerCase()] = userHeaders[header];
-  }
-
-  return formHeaders;
-}
-
-FormData.prototype.getCustomHeaders = function(contentType) {
-    contentType = contentType ? contentType : 'multipart/form-data';
-
-    var formHeaders = {
-        'content-type': contentType + '; boundary=' + this.getBoundary(),
-        'content-length': this.getLengthSync()
-    };
-
-    return formHeaders;
-}
-
-FormData.prototype.getBoundary = function() {
-  if (!this._boundary) {
-    this._generateBoundary();
-  }
-
-  return this._boundary;
-};
-
-FormData.prototype._generateBoundary = function() {
-  // This generates a 50 character boundary similar to those used by Firefox.
-  // They are optimized for boyer-moore parsing.
-  var boundary = '--------------------------';
-  for (var i = 0; i < 24; i++) {
-    boundary += Math.floor(Math.random() * 10).toString(16);
-  }
-
-  this._boundary = boundary;
-};
-
-// Note: getLengthSync DOESN'T calculate streams length
-// As workaround one can calculate file size manually
-// and add it as knownLength option
-FormData.prototype.getLengthSync = function(debug) {
-  var knownLength = this._overheadLength + this._valueLength;
-
-  // Don't get confused, there are 3 "internal" streams for each keyval pair
-  // so it basically checks if there is any value added to the form
-  if (this._streams.length) {
-    knownLength += this._lastBoundary().length;
-  }
-
-  // https://github.com/felixge/node-form-data/issues/40
-  if (this._lengthRetrievers.length) {
-    // Some async length retrivers are present
-    // therefore synchronous length calculation is false.
-    // Please use getLength(callback) to get proper length
-    this._error(new Error('Cannot calculate proper length in synchronous way.'));
-  }
-
-  return knownLength;
-};
-
-FormData.prototype.getLength = function(cb) {
-  var knownLength = this._overheadLength + this._valueLength;
-
-  if (this._streams.length) {
-    knownLength += this._lastBoundary().length;
-  }
-
-  if (!this._lengthRetrievers.length) {
-    process.nextTick(cb.bind(this, null, knownLength));
-    return;
-  }
-
-  async.parallel(this._lengthRetrievers, function(err, values) {
-    if (err) {
-      cb(err);
-      return;
-    }
-
-    values.forEach(function(length) {
-      knownLength += length;
-    });
-
-    cb(null, knownLength);
-  });
-};
-
-FormData.prototype.submit = function(params, cb) {
-
-  var request
-    , options
-    , defaults = {
-        method : 'post',
-        headers: this.getHeaders()
-    };
-
-  // parse provided url if it's string
-  // or treat it as options object
-  if (typeof params == 'string') {
-    params = parseUrl(params);
-
-    options = populate({
-      port: params.port,
-      path: params.pathname,
-      host: params.hostname
-    }, defaults);
-  }
-  else // use custom params
-  {
-    options = populate(params, defaults);
-    // if no port provided use default one
-    if (!options.port) {
-      options.port = options.protocol == 'https:' ? 443 : 80;
-    }
-  }
-
-  // https if specified, fallback to http in any other case
-  if (params.protocol == 'https:') {
-    request = https.request(options);
-  } else {
-    request = http.request(options);
-  }
-
-  // get content length and fire away
-  this.getLength(function(err, length) {
-
-    // TODO: Add chunked encoding when no length (if err)
-
-    // add content length
-    request.setHeader('Content-Length', length);
-
-    this.pipe(request);
-    if (cb) {
-      request.on('error', cb);
-      request.on('response', cb.bind(this, null));
-    }
-  }.bind(this));
-
-  return request;
-};
-
-FormData.prototype._error = function(err) {
-  if (this.error) return;
-
-  this.error = err;
-  this.pause();
-  this.emit('error', err);
-};
-
-/*
- * Santa's little helpers
- */
-
-// populates missing values
-function populate(dst, src) {
-  for (var prop in src) {
-    if (!dst[prop]) dst[prop] = src[prop];
-  }
-  return dst;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/LICENSE
deleted file mode 100644
index b7f9d500..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/README.md
deleted file mode 100644
index 951f76e9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/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
-<script type="text/javascript" src="async.js"></script>
-<script type="text/javascript">
-
-    async.map(data, asyncProcess, function(err, results){
-        alert(results);
-    });
-
-</script>
-```
-
-## 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
-
-<a name="forEach" />
-<a name="each" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="forEachSeries" />
-<a name="eachSeries" />
-### 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.
-
-
----------------------------------------
-
-<a name="forEachLimit" />
-<a name="eachLimit" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="map" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="mapSeries" />
-### 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.
-
-
----------------------------------------
-
-<a name="mapLimit" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="filter" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="filterSeries" />
-### 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.
-
----------------------------------------
-
-<a name="reject" />
-### reject(arr, iterator, callback)
-
-The opposite of filter. Removes values that pass an async truth test.
-
----------------------------------------
-
-<a name="rejectSeries" />
-### rejectSeries(arr, iterator, callback)
-
-The same as reject, only the iterator is applied to each item in the array
-in series.
-
-
----------------------------------------
-
-<a name="reduce" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="reduceRight" />
-### reduceRight(arr, memo, iterator, callback)
-
-__Alias:__ foldr
-
-Same as reduce, only operates on the items in the array in reverse order.
-
-
----------------------------------------
-
-<a name="detect" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="detectSeries" />
-### 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.
-
-
----------------------------------------
-
-<a name="sortBy" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="some" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="every" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="concat" />
-### 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
-});
-```
-
----------------------------------------
-
-<a name="concatSeries" />
-### concatSeries(arr, iterator, callback)
-
-Same as async.concat, but executes in series instead of parallel.
-
-
-## Control Flow
-
-<a name="series" />
-### 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}
-});
-```
-
----------------------------------------
-
-<a name="parallel" />
-### 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}
-});
-```
-
----------------------------------------
-
-<a name="parallel" />
-### 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.
-
----------------------------------------
-
-<a name="whilst" />
-### 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
-    }
-);
-```
-
----------------------------------------
-
-<a name="doWhilst" />
-### 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.
-
----------------------------------------
-
-<a name="until" />
-### 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.
-
----------------------------------------
-
-<a name="doUntil" />
-### doUntil(fn, test, callback)
-
-Like doWhilst except the test is inverted. Note the argument ordering differs from `until`.
-
----------------------------------------
-
-<a name="forever" />
-### 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.
-
----------------------------------------
-
-<a name="waterfall" />
-### 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'    
-});
-```
-
----------------------------------------
-<a name="compose" />
-### 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
-});
-```
-
----------------------------------------
-<a name="applyEach" />
-### 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
-);
-```
-
----------------------------------------
-
-<a name="applyEachSeries" />
-### applyEachSeries(arr, iterator, callback)
-
-The same as applyEach only the functions are applied in series.
-
----------------------------------------
-
-<a name="queue" />
-### 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');
-});
-```
-
----------------------------------------
-
-<a name="cargo" />
-### 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<tasks.length; i++){
-      console.log('hello ' + tasks[i].name);
-    }
-    callback();
-}, 2);
-
-
-// add some items
-
-cargo.push({name: 'foo'}, function (err) {
-    console.log('finished processing foo');
-});
-cargo.push({name: 'bar'}, function (err) {
-    console.log('finished processing bar');
-});
-cargo.push({name: 'baz'}, function (err) {
-    console.log('finished processing baz');
-});
-```
-
----------------------------------------
-
-<a name="auto" />
-### 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.
-
-
----------------------------------------
-
-<a name="iterator" />
-### 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'
-```
-
----------------------------------------
-
-<a name="apply" />
-### 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
-```
-
----------------------------------------
-
-<a name="nextTick" />
-### 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')
-```
-
-<a name="times" />
-### 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
-});
-```
-
-<a name="timesSeries" />
-### 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
-
-<a name="memoize" />
-### 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
-});
-```
-
-<a name="unmemoize" />
-### unmemoize(fn)
-
-Undoes a memoized function, reverting it to the original, unmemoized
-form. Comes handy in tests.
-
-__Arguments__
-
-* fn - the memoized function
-
-<a name="log" />
-### 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'
-```
-
----------------------------------------
-
-<a name="dir" />
-### 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'}
-```
-
----------------------------------------
-
-<a name="noConflict" />
-### noConflict()
-
-Changes the value of async back to its original value, returning a reference to the
-async object.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/component.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/component.json
deleted file mode 100644
index bbb01154..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js
deleted file mode 100755
index 1eebb153..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js
+++ /dev/null
@@ -1,958 +0,0 @@
-/*global setImmediate: false, setTimeout: false, console: false */
-(function () {
-
-    var async = {};
-
-    // global on the server, window in the browser
-    var root, previous_async;
-
-    root = this;
-    if (root != null) {
-      previous_async = root.async;
-    }
-
-    async.noConflict = function () {
-        root.async = previous_async;
-        return async;
-    };
-
-    function only_once(fn) {
-        var called = false;
-        return function() {
-            if (called) throw new Error("Callback was already called.");
-            called = true;
-            fn.apply(root, arguments);
-        }
-    }
-
-    //// cross-browser compatiblity functions ////
-
-    var _each = function (arr, iterator) {
-        if (arr.forEach) {
-            return arr.forEach(iterator);
-        }
-        for (var i = 0; i < arr.length; i += 1) {
-            iterator(arr[i], i, arr);
-        }
-    };
-
-    var _map = function (arr, iterator) {
-        if (arr.map) {
-            return arr.map(iterator);
-        }
-        var results = [];
-        _each(arr, function (x, i, a) {
-            results.push(iterator(x, i, a));
-        });
-        return results;
-    };
-
-    var _reduce = function (arr, iterator, memo) {
-        if (arr.reduce) {
-            return arr.reduce(iterator, memo);
-        }
-        _each(arr, function (x, i, a) {
-            memo = iterator(memo, x, i, a);
-        });
-        return memo;
-    };
-
-    var _keys = function (obj) {
-        if (Object.keys) {
-            return Object.keys(obj);
-        }
-        var keys = [];
-        for (var k in obj) {
-            if (obj.hasOwnProperty(k)) {
-                keys.push(k);
-            }
-        }
-        return keys;
-    };
-
-    //// exported async module functions ////
-
-    //// nextTick implementation with browser-compatible fallback ////
-    if (typeof process === 'undefined' || !(process.nextTick)) {
-        if (typeof setImmediate === 'function') {
-            async.nextTick = function (fn) {
-                // not a direct alias for IE10 compatibility
-                setImmediate(fn);
-            };
-            async.setImmediate = async.nextTick;
-        }
-        else {
-            async.nextTick = function (fn) {
-                setTimeout(fn, 0);
-            };
-            async.setImmediate = async.nextTick;
-        }
-    }
-    else {
-        async.nextTick = process.nextTick;
-        if (typeof setImmediate !== 'undefined') {
-            async.setImmediate = function (fn) {
-              // not a direct alias for IE10 compatibility
-              setImmediate(fn);
-            };
-        }
-        else {
-            async.setImmediate = async.nextTick;
-        }
-    }
-
-    async.each = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        _each(arr, function (x) {
-            iterator(x, only_once(function (err) {
-                if (err) {
-                    callback(err);
-                    callback = function () {};
-                }
-                else {
-                    completed += 1;
-                    if (completed >= arr.length) {
-                        callback(null);
-                    }
-                }
-            }));
-        });
-    };
-    async.forEach = async.each;
-
-    async.eachSeries = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        var iterate = function () {
-            iterator(arr[completed], function (err) {
-                if (err) {
-                    callback(err);
-                    callback = function () {};
-                }
-                else {
-                    completed += 1;
-                    if (completed >= arr.length) {
-                        callback(null);
-                    }
-                    else {
-                        iterate();
-                    }
-                }
-            });
-        };
-        iterate();
-    };
-    async.forEachSeries = async.eachSeries;
-
-    async.eachLimit = function (arr, limit, iterator, callback) {
-        var fn = _eachLimit(limit);
-        fn.apply(null, [arr, iterator, callback]);
-    };
-    async.forEachLimit = async.eachLimit;
-
-    var _eachLimit = function (limit) {
-
-        return function (arr, iterator, callback) {
-            callback = callback || function () {};
-            if (!arr.length || limit <= 0) {
-                return callback();
-            }
-            var completed = 0;
-            var started = 0;
-            var running = 0;
-
-            (function replenish () {
-                if (completed >= arr.length) {
-                    return callback();
-                }
-
-                while (running < limit && started < arr.length) {
-                    started += 1;
-                    running += 1;
-                    iterator(arr[started - 1], function (err) {
-                        if (err) {
-                            callback(err);
-                            callback = function () {};
-                        }
-                        else {
-                            completed += 1;
-                            running -= 1;
-                            if (completed >= arr.length) {
-                                callback();
-                            }
-                            else {
-                                replenish();
-                            }
-                        }
-                    });
-                }
-            })();
-        };
-    };
-
-
-    var doParallel = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.each].concat(args));
-        };
-    };
-    var doParallelLimit = function(limit, fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [_eachLimit(limit)].concat(args));
-        };
-    };
-    var doSeries = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.eachSeries].concat(args));
-        };
-    };
-
-
-    var _asyncMap = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (err, v) {
-                results[x.index] = v;
-                callback(err);
-            });
-        }, function (err) {
-            callback(err, results);
-        });
-    };
-    async.map = doParallel(_asyncMap);
-    async.mapSeries = doSeries(_asyncMap);
-    async.mapLimit = function (arr, limit, iterator, callback) {
-        return _mapLimit(limit)(arr, iterator, callback);
-    };
-
-    var _mapLimit = function(limit) {
-        return doParallelLimit(limit, _asyncMap);
-    };
-
-    // reduce only has a series version, as doing reduce in parallel won't
-    // work in many situations.
-    async.reduce = function (arr, memo, iterator, callback) {
-        async.eachSeries(arr, function (x, callback) {
-            iterator(memo, x, function (err, v) {
-                memo = v;
-                callback(err);
-            });
-        }, function (err) {
-            callback(err, memo);
-        });
-    };
-    // inject alias
-    async.inject = async.reduce;
-    // foldl alias
-    async.foldl = async.reduce;
-
-    async.reduceRight = function (arr, memo, iterator, callback) {
-        var reversed = _map(arr, function (x) {
-            return x;
-        }).reverse();
-        async.reduce(reversed, memo, iterator, callback);
-    };
-    // foldr alias
-    async.foldr = async.reduceRight;
-
-    var _filter = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.filter = doParallel(_filter);
-    async.filterSeries = doSeries(_filter);
-    // select alias
-    async.select = async.filter;
-    async.selectSeries = async.filterSeries;
-
-    var _reject = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (!v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.reject = doParallel(_reject);
-    async.rejectSeries = doSeries(_reject);
-
-    var _detect = function (eachfn, arr, iterator, main_callback) {
-        eachfn(arr, function (x, callback) {
-            iterator(x, function (result) {
-                if (result) {
-                    main_callback(x);
-                    main_callback = function () {};
-                }
-                else {
-                    callback();
-                }
-            });
-        }, function (err) {
-            main_callback();
-        });
-    };
-    async.detect = doParallel(_detect);
-    async.detectSeries = doSeries(_detect);
-
-    async.some = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (v) {
-                    main_callback(true);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(false);
-        });
-    };
-    // any alias
-    async.any = async.some;
-
-    async.every = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (!v) {
-                    main_callback(false);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(true);
-        });
-    };
-    // all alias
-    async.all = async.every;
-
-    async.sortBy = function (arr, iterator, callback) {
-        async.map(arr, function (x, callback) {
-            iterator(x, function (err, criteria) {
-                if (err) {
-                    callback(err);
-                }
-                else {
-                    callback(null, {value: x, criteria: criteria});
-                }
-            });
-        }, function (err, results) {
-            if (err) {
-                return callback(err);
-            }
-            else {
-                var fn = function (left, right) {
-                    var a = left.criteria, b = right.criteria;
-                    return a < b ? -1 : a > b ? 1 : 0;
-                };
-                callback(null, _map(results.sort(fn), function (x) {
-                    return x.value;
-                }));
-            }
-        });
-    };
-
-    async.auto = function (tasks, callback) {
-        callback = callback || function () {};
-        var keys = _keys(tasks);
-        if (!keys.length) {
-            return callback(null);
-        }
-
-        var results = {};
-
-        var listeners = [];
-        var addListener = function (fn) {
-            listeners.unshift(fn);
-        };
-        var removeListener = function (fn) {
-            for (var i = 0; i < listeners.length; i += 1) {
-                if (listeners[i] === fn) {
-                    listeners.splice(i, 1);
-                    return;
-                }
-            }
-        };
-        var taskComplete = function () {
-            _each(listeners.slice(0), function (fn) {
-                fn();
-            });
-        };
-
-        addListener(function () {
-            if (_keys(results).length === keys.length) {
-                callback(null, results);
-                callback = function () {};
-            }
-        });
-
-        _each(keys, function (k) {
-            var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
-            var taskCallback = function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (args.length <= 1) {
-                    args = args[0];
-                }
-                if (err) {
-                    var safeResults = {};
-                    _each(_keys(results), function(rkey) {
-                        safeResults[rkey] = results[rkey];
-                    });
-                    safeResults[k] = args;
-                    callback(err, safeResults);
-                    // stop subsequent errors hitting callback multiple times
-                    callback = function () {};
-                }
-                else {
-                    results[k] = args;
-                    async.setImmediate(taskComplete);
-                }
-            };
-            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
-            var ready = function () {
-                return _reduce(requires, function (a, x) {
-                    return (a && results.hasOwnProperty(x));
-                }, true) && !results.hasOwnProperty(k);
-            };
-            if (ready()) {
-                task[task.length - 1](taskCallback, results);
-            }
-            else {
-                var listener = function () {
-                    if (ready()) {
-                        removeListener(listener);
-                        task[task.length - 1](taskCallback, results);
-                    }
-                };
-                addListener(listener);
-            }
-        });
-    };
-
-    async.waterfall = function (tasks, callback) {
-        callback = callback || function () {};
-        if (tasks.constructor !== Array) {
-          var err = new Error('First argument to waterfall must be an array of functions');
-          return callback(err);
-        }
-        if (!tasks.length) {
-            return callback();
-        }
-        var wrapIterator = function (iterator) {
-            return function (err) {
-                if (err) {
-                    callback.apply(null, arguments);
-                    callback = function () {};
-                }
-                else {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    var next = iterator.next();
-                    if (next) {
-                        args.push(wrapIterator(next));
-                    }
-                    else {
-                        args.push(callback);
-                    }
-                    async.setImmediate(function () {
-                        iterator.apply(null, args);
-                    });
-                }
-            };
-        };
-        wrapIterator(async.iterator(tasks))();
-    };
-
-    var _parallel = function(eachfn, tasks, callback) {
-        callback = callback || function () {};
-        if (tasks.constructor === Array) {
-            eachfn.map(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            eachfn.each(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-
-    async.parallel = function (tasks, callback) {
-        _parallel({ map: async.map, each: async.each }, tasks, callback);
-    };
-
-    async.parallelLimit = function(tasks, limit, callback) {
-        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
-    };
-
-    async.series = function (tasks, callback) {
-        callback = callback || function () {};
-        if (tasks.constructor === Array) {
-            async.mapSeries(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            async.eachSeries(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-
-    async.iterator = function (tasks) {
-        var makeCallback = function (index) {
-            var fn = function () {
-                if (tasks.length) {
-                    tasks[index].apply(null, arguments);
-                }
-                return fn.next();
-            };
-            fn.next = function () {
-                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
-            };
-            return fn;
-        };
-        return makeCallback(0);
-    };
-
-    async.apply = function (fn) {
-        var args = Array.prototype.slice.call(arguments, 1);
-        return function () {
-            return fn.apply(
-                null, args.concat(Array.prototype.slice.call(arguments))
-            );
-        };
-    };
-
-    var _concat = function (eachfn, arr, fn, callback) {
-        var r = [];
-        eachfn(arr, function (x, cb) {
-            fn(x, function (err, y) {
-                r = r.concat(y || []);
-                cb(err);
-            });
-        }, function (err) {
-            callback(err, r);
-        });
-    };
-    async.concat = doParallel(_concat);
-    async.concatSeries = doSeries(_concat);
-
-    async.whilst = function (test, iterator, callback) {
-        if (test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.whilst(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
-    };
-
-    async.doWhilst = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            if (test()) {
-                async.doWhilst(iterator, test, callback);
-            }
-            else {
-                callback();
-            }
-        });
-    };
-
-    async.until = function (test, iterator, callback) {
-        if (!test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.until(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
-    };
-
-    async.doUntil = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            if (!test()) {
-                async.doUntil(iterator, test, callback);
-            }
-            else {
-                callback();
-            }
-        });
-    };
-
-    async.queue = function (worker, concurrency) {
-        if (concurrency === undefined) {
-            concurrency = 1;
-        }
-        function _insert(q, data, pos, callback) {
-          if(data.constructor !== Array) {
-              data = [data];
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-
-              if (pos) {
-                q.tasks.unshift(item);
-              } else {
-                q.tasks.push(item);
-              }
-
-              if (q.saturated && q.tasks.length === concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
-        }
-
-        var workers = 0;
-        var q = {
-            tasks: [],
-            concurrency: concurrency,
-            saturated: null,
-            empty: null,
-            drain: null,
-            push: function (data, callback) {
-              _insert(q, data, false, callback);
-            },
-            unshift: function (data, callback) {
-              _insert(q, data, true, callback);
-            },
-            process: function () {
-                if (workers < q.concurrency && q.tasks.length) {
-                    var task = q.tasks.shift();
-                    if (q.empty && q.tasks.length === 0) {
-                        q.empty();
-                    }
-                    workers += 1;
-                    var next = function () {
-                        workers -= 1;
-                        if (task.callback) {
-                            task.callback.apply(task, arguments);
-                        }
-                        if (q.drain && q.tasks.length + workers === 0) {
-                            q.drain();
-                        }
-                        q.process();
-                    };
-                    var cb = only_once(next);
-                    worker(task.data, cb);
-                }
-            },
-            length: function () {
-                return q.tasks.length;
-            },
-            running: function () {
-                return workers;
-            }
-        };
-        return q;
-    };
-
-    async.cargo = function (worker, payload) {
-        var working     = false,
-            tasks       = [];
-
-        var cargo = {
-            tasks: tasks,
-            payload: payload,
-            saturated: null,
-            empty: null,
-            drain: null,
-            push: function (data, callback) {
-                if(data.constructor !== Array) {
-                    data = [data];
-                }
-                _each(data, function(task) {
-                    tasks.push({
-                        data: task,
-                        callback: typeof callback === 'function' ? callback : null
-                    });
-                    if (cargo.saturated && tasks.length === payload) {
-                        cargo.saturated();
-                    }
-                });
-                async.setImmediate(cargo.process);
-            },
-            process: function process() {
-                if (working) return;
-                if (tasks.length === 0) {
-                    if(cargo.drain) cargo.drain();
-                    return;
-                }
-
-                var ts = typeof payload === 'number'
-                            ? tasks.splice(0, payload)
-                            : tasks.splice(0);
-
-                var ds = _map(ts, function (task) {
-                    return task.data;
-                });
-
-                if(cargo.empty) cargo.empty();
-                working = true;
-                worker(ds, function () {
-                    working = false;
-
-                    var args = arguments;
-                    _each(ts, function (data) {
-                        if (data.callback) {
-                            data.callback.apply(null, args);
-                        }
-                    });
-
-                    process();
-                });
-            },
-            length: function () {
-                return tasks.length;
-            },
-            running: function () {
-                return working;
-            }
-        };
-        return cargo;
-    };
-
-    var _console_fn = function (name) {
-        return function (fn) {
-            var args = Array.prototype.slice.call(arguments, 1);
-            fn.apply(null, args.concat([function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (typeof console !== 'undefined') {
-                    if (err) {
-                        if (console.error) {
-                            console.error(err);
-                        }
-                    }
-                    else if (console[name]) {
-                        _each(args, function (x) {
-                            console[name](x);
-                        });
-                    }
-                }
-            }]));
-        };
-    };
-    async.log = _console_fn('log');
-    async.dir = _console_fn('dir');
-    /*async.info = _console_fn('info');
-    async.warn = _console_fn('warn');
-    async.error = _console_fn('error');*/
-
-    async.memoize = function (fn, hasher) {
-        var memo = {};
-        var queues = {};
-        hasher = hasher || function (x) {
-            return x;
-        };
-        var memoized = function () {
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            var key = hasher.apply(null, args);
-            if (key in memo) {
-                callback.apply(null, memo[key]);
-            }
-            else if (key in queues) {
-                queues[key].push(callback);
-            }
-            else {
-                queues[key] = [callback];
-                fn.apply(null, args.concat([function () {
-                    memo[key] = arguments;
-                    var q = queues[key];
-                    delete queues[key];
-                    for (var i = 0, l = q.length; i < l; i++) {
-                      q[i].apply(null, arguments);
-                    }
-                }]));
-            }
-        };
-        memoized.memo = memo;
-        memoized.unmemoized = fn;
-        return memoized;
-    };
-
-    async.unmemoize = function (fn) {
-      return function () {
-        return (fn.unmemoized || fn).apply(null, arguments);
-      };
-    };
-
-    async.times = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.map(counter, iterator, callback);
-    };
-
-    async.timesSeries = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.mapSeries(counter, iterator, callback);
-    };
-
-    async.compose = function (/* functions... */) {
-        var fns = Array.prototype.reverse.call(arguments);
-        return function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            async.reduce(fns, args, function (newargs, fn, cb) {
-                fn.apply(that, newargs.concat([function () {
-                    var err = arguments[0];
-                    var nextargs = Array.prototype.slice.call(arguments, 1);
-                    cb(err, nextargs);
-                }]))
-            },
-            function (err, results) {
-                callback.apply(that, [err].concat(results));
-            });
-        };
-    };
-
-    var _applyEach = function (eachfn, fns /*args...*/) {
-        var go = function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            return eachfn(fns, function (fn, cb) {
-                fn.apply(that, args.concat([cb]));
-            },
-            callback);
-        };
-        if (arguments.length > 2) {
-            var args = Array.prototype.slice.call(arguments, 2);
-            return go.apply(this, args);
-        }
-        else {
-            return go;
-        }
-    };
-    async.applyEach = doParallel(_applyEach);
-    async.applyEachSeries = doSeries(_applyEach);
-
-    async.forever = function (fn, callback) {
-        function next(err) {
-            if (err) {
-                if (callback) {
-                    return callback(err);
-                }
-                throw err;
-            }
-            fn(next);
-        }
-        next();
-    };
-
-    // AMD / RequireJS
-    if (typeof define !== 'undefined' && define.amd) {
-        define([], function () {
-            return async;
-        });
-    }
-    // Node.js
-    else if (typeof module !== 'undefined' && module.exports) {
-        module.exports = async;
-    }
-    // included directly via <script> tag
-    else {
-        root.async = async;
-    }
-
-}());
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/package.json
deleted file mode 100644
index 5648629d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/async/package.json
+++ /dev/null
@@ -1,45 +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": "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"
-  },
-  "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<script type=\"text/javascript\" src=\"async.js\"></script>\n<script type=\"text/javascript\">\n\n    async.map(data, asyncProcess, function(err, results){\n        alert(results);\n    });\n\n</script>\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<a name=\"forEach\" />\n<a name=\"each\" />\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<a name=\"forEachSeries\" />\n<a name=\"eachSeries\" />\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<a name=\"forEachLimit\" />\n<a name=\"eachLimit\" />\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<a name=\"map\" />\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<a name=\"mapSeries\" />\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<a name=\"mapLimit\" />\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<a name=\"filter\" />\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<a name=\"filterSeries\" />\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<a name=\"reject\" />\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n<a name=\"rejectSeries\" />\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<a name=\"reduce\" />\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<a name=\"reduceRight\" />\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<a name=\"detect\" />\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<a name=\"detectSeries\" />\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<a name=\"sortBy\" />\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<a name=\"some\" />\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<a name=\"every\" />\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<a name=\"concat\" />\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<a name=\"concatSeries\" />\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n<a name=\"series\" />\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<a name=\"parallel\" />\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<a name=\"parallel\" />\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<a name=\"whilst\" />\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<a name=\"doWhilst\" />\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<a name=\"until\" />\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<a name=\"doUntil\" />\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n<a name=\"forever\" />\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<a name=\"waterfall\" />\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<a name=\"compose\" />\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<a name=\"applyEach\" />\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<a name=\"applyEachSeries\" />\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n<a name=\"queue\" />\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<a name=\"cargo\" />\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<tasks.length; i++){\n      console.log('hello ' + tasks[i].name);\n    }\n    callback();\n}, 2);\n\n\n// add some items\n\ncargo.push({name: 'foo'}, function (err) {\n    console.log('finished processing foo');\n});\ncargo.push({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\ncargo.push({name: 'baz'}, function (err) {\n    console.log('finished processing baz');\n});\n```\n\n---------------------------------------\n\n<a name=\"auto\" />\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<a name=\"iterator\" />\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<a name=\"apply\" />\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<a name=\"nextTick\" />\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<a name=\"times\" />\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<a name=\"timesSeries\" />\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<a name=\"memoize\" />\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<a name=\"unmemoize\" />\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<a name=\"log\" />\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<a name=\"dir\" />\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<a name=\"noConflict\" />\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",
-  "_id": "async@0.2.10",
-  "_shasum": "b6bbe0b0674b9d719708ca38de8c237cb526c3d1",
-  "_from": "async@~0.2.9",
-  "_resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore
deleted file mode 100644
index aba34f01..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.un~
-/node_modules
-/test/tmp
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/License b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/License
deleted file mode 100644
index 4804b7ab..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/License
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile
deleted file mode 100644
index b4ff85a3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-SHELL := /bin/bash
-
-test:
-	@./test/run.js
-
-.PHONY: test
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md
deleted file mode 100644
index 1a9999eb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# combined-stream
-
-A stream that emits multiple other streams one after another.
-
-## Installation
-
-``` bash
-npm install combined-stream
-```
-
-## Usage
-
-Here is a simple example that shows how you can use combined-stream to combine
-two files into one:
-
-``` javascript
-var CombinedStream = require('combined-stream');
-var fs = require('fs');
-
-var combinedStream = CombinedStream.create();
-combinedStream.append(fs.createReadStream('file1.txt'));
-combinedStream.append(fs.createReadStream('file2.txt'));
-
-combinedStream.pipe(fs.createWriteStream('combined.txt'));
-```
-
-While the example above works great, it will pause all source streams until
-they are needed. If you don't want that to happen, you can set `pauseStreams`
-to `false`:
-
-``` javascript
-var CombinedStream = require('combined-stream');
-var fs = require('fs');
-
-var combinedStream = CombinedStream.create({pauseStreams: false});
-combinedStream.append(fs.createReadStream('file1.txt'));
-combinedStream.append(fs.createReadStream('file2.txt'));
-
-combinedStream.pipe(fs.createWriteStream('combined.txt'));
-```
-
-However, what if you don't have all the source streams yet, or you don't want
-to allocate the resources (file descriptors, memory, etc.) for them right away?
-Well, in that case you can simply provide a callback that supplies the stream
-by calling a `next()` function:
-
-``` javascript
-var CombinedStream = require('combined-stream');
-var fs = require('fs');
-
-var combinedStream = CombinedStream.create();
-combinedStream.append(function(next) {
-  next(fs.createReadStream('file1.txt'));
-});
-combinedStream.append(function(next) {
-  next(fs.createReadStream('file2.txt'));
-});
-
-combinedStream.pipe(fs.createWriteStream('combined.txt'));
-```
-
-## API
-
-### CombinedStream.create([options])
-
-Returns a new combined stream object. Available options are:
-
-* `maxDataSize`
-* `pauseStreams`
-
-The effect of those options is described below.
-
-### combinedStream.pauseStreams = true
-
-Whether to apply back pressure to the underlaying streams. If set to `false`,
-the underlaying streams will never be paused. If set to `true`, the
-underlaying streams will be paused right after being appended, as well as when
-`delayedStream.pipe()` wants to throttle.
-
-### combinedStream.maxDataSize = 2 * 1024 * 1024
-
-The maximum amount of bytes (or characters) to buffer for all source streams.
-If this value is exceeded, `combinedStream` emits an `'error'` event.
-
-### combinedStream.dataSize = 0
-
-The amount of bytes (or characters) currently buffered by `combinedStream`.
-
-### combinedStream.append(stream)
-
-Appends the given `stream` to the combinedStream object. If `pauseStreams` is
-set to `true, this stream will also be paused right away.
-
-`streams` can also be a function that takes one parameter called `next`. `next`
-is a function that must be invoked in order to provide the `next` stream, see
-example above.
-
-Regardless of how the `stream` is appended, combined-stream always attaches an
-`'error'` listener to it, so you don't have to do that manually.
-
-Special case: `stream` can also be a String or Buffer.
-
-### combinedStream.write(data)
-
-You should not call this, `combinedStream` takes care of piping the appended
-streams into itself for you.
-
-### combinedStream.resume()
-
-Causes `combinedStream` to start drain the streams it manages. The function is
-idempotent, and also emits a `'resume'` event each time which usually goes to
-the stream that is currently being drained.
-
-### combinedStream.pause();
-
-If `combinedStream.pauseStreams` is set to `false`, this does nothing.
-Otherwise a `'pause'` event is emitted, this goes to the stream that is
-currently being drained, so you can use it to apply back pressure.
-
-### combinedStream.end();
-
-Sets `combinedStream.writable` to false, emits an `'end'` event, and removes
-all streams from the queue.
-
-### combinedStream.destroy();
-
-Same as `combinedStream.end()`, except it emits a `'close'` event instead of
-`'end'`.
-
-## License
-
-combined-stream is licensed under the MIT license.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js
deleted file mode 100644
index 32849fd1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js
+++ /dev/null
@@ -1,185 +0,0 @@
-var util = require('util');
-var Stream = require('stream').Stream;
-var DelayedStream = require('delayed-stream');
-
-module.exports = CombinedStream;
-function CombinedStream() {
-  this.writable = false;
-  this.readable = true;
-  this.dataSize = 0;
-  this.maxDataSize = 2 * 1024 * 1024;
-  this.pauseStreams = true;
-
-  this._released = false;
-  this._streams = [];
-  this._currentStream = null;
-}
-util.inherits(CombinedStream, Stream);
-
-CombinedStream.create = function(options) {
-  var combinedStream = new this();
-
-  options = options || {};
-  for (var option in options) {
-    combinedStream[option] = options[option];
-  }
-
-  return combinedStream;
-};
-
-CombinedStream.isStreamLike = function(stream) {
-  return (typeof stream !== 'function')
-    && (typeof stream !== 'string')
-    && (typeof stream !== 'boolean')    
-    && (typeof stream !== 'number')
-    && (!Buffer.isBuffer(stream));
-};
-
-CombinedStream.prototype.append = function(stream) {
-  var isStreamLike = CombinedStream.isStreamLike(stream);
-
-  if (isStreamLike) {
-    if (!(stream instanceof DelayedStream)) {
-      stream.on('data', this._checkDataSize.bind(this));
-
-      stream = DelayedStream.create(stream, {
-        maxDataSize: Infinity,
-        pauseStream: this.pauseStreams,
-      });
-    }
-
-    this._handleErrors(stream);
-
-    if (this.pauseStreams) {
-      stream.pause();
-    }
-  }
-
-  this._streams.push(stream);
-  return this;
-};
-
-CombinedStream.prototype.pipe = function(dest, options) {
-  Stream.prototype.pipe.call(this, dest, options);
-  this.resume();
-};
-
-CombinedStream.prototype._getNext = function() {
-  this._currentStream = null;
-  var stream = this._streams.shift();
-
-
-  if (typeof stream == 'undefined') {
-    this.end();
-    return;
-  }
-
-  if (typeof stream !== 'function') {
-    this._pipeNext(stream);
-    return;
-  }
-
-  var getStream = stream;
-  getStream(function(stream) {
-    var isStreamLike = CombinedStream.isStreamLike(stream);
-    if (isStreamLike) {
-      stream.on('data', this._checkDataSize.bind(this));
-      this._handleErrors(stream);
-    }
-
-    this._pipeNext(stream);
-  }.bind(this));
-};
-
-CombinedStream.prototype._pipeNext = function(stream) {
-  this._currentStream = stream;
-
-  var isStreamLike = CombinedStream.isStreamLike(stream);
-  if (isStreamLike) {
-    stream.on('end', this._getNext.bind(this))
-    stream.pipe(this, {end: false});
-    return;
-  }
-
-  var value = stream;
-  this.write(value);
-  this._getNext();
-};
-
-CombinedStream.prototype._handleErrors = function(stream) {
-  var self = this;
-  stream.on('error', function(err) {
-    self._emitError(err);
-  });
-};
-
-CombinedStream.prototype.write = function(data) {
-  this.emit('data', data);
-};
-
-CombinedStream.prototype.pause = function() {
-  if (!this.pauseStreams) {
-    return;
-  }
-
-  this.emit('pause');
-};
-
-CombinedStream.prototype.resume = function() {
-  if (!this._released) {
-    this._released = true;
-    this.writable = true;
-    this._getNext();
-  }
-
-  this.emit('resume');
-};
-
-CombinedStream.prototype.end = function() {
-  this._reset();
-  this.emit('end');
-};
-
-CombinedStream.prototype.destroy = function() {
-  this._reset();
-  this.emit('close');
-};
-
-CombinedStream.prototype._reset = function() {
-  this.writable = false;
-  this._streams = [];
-  this._currentStream = null;
-};
-
-CombinedStream.prototype._checkDataSize = function() {
-  this._updateDataSize();
-  if (this.dataSize <= this.maxDataSize) {
-    return;
-  }
-
-  var message =
-    'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'
-  this._emitError(new Error(message));
-};
-
-CombinedStream.prototype._updateDataSize = function() {
-  this.dataSize = 0;
-
-  var self = this;
-  this._streams.forEach(function(stream) {
-    if (!stream.dataSize) {
-      return;
-    }
-
-    self.dataSize += stream.dataSize;
-  });
-
-  if (this._currentStream && this._currentStream.dataSize) {
-    this.dataSize += this._currentStream.dataSize;
-  }
-};
-
-CombinedStream.prototype._emitError = function(err) {
-  this._reset();
-  this.emit('error', err);
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore
deleted file mode 100644
index 2fedb26c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.un~
-/node_modules/*
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License
deleted file mode 100644
index 4804b7ab..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile
deleted file mode 100644
index b4ff85a3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-SHELL := /bin/bash
-
-test:
-	@./test/run.js
-
-.PHONY: test
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md
deleted file mode 100644
index 5cb5b35e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md
+++ /dev/null
@@ -1,154 +0,0 @@
-# delayed-stream
-
-Buffers events from a stream until you are ready to handle them.
-
-## Installation
-
-``` bash
-npm install delayed-stream
-```
-
-## Usage
-
-The following example shows how to write a http echo server that delays its
-response by 1000 ms.
-
-``` javascript
-var DelayedStream = require('delayed-stream');
-var http = require('http');
-
-http.createServer(function(req, res) {
-  var delayed = DelayedStream.create(req);
-
-  setTimeout(function() {
-    res.writeHead(200);
-    delayed.pipe(res);
-  }, 1000);
-});
-```
-
-If you are not using `Stream#pipe`, you can also manually release the buffered
-events by calling `delayedStream.resume()`:
-
-``` javascript
-var delayed = DelayedStream.create(req);
-
-setTimeout(function() {
-  // Emit all buffered events and resume underlaying source
-  delayed.resume();
-}, 1000);
-```
-
-## Implementation
-
-In order to use this meta stream properly, here are a few things you should
-know about the implementation.
-
-### Event Buffering / Proxying
-
-All events of the `source` stream are hijacked by overwriting the `source.emit`
-method. Until node implements a catch-all event listener, this is the only way.
-
-However, delayed-stream still continues to emit all events it captures on the
-`source`, regardless of whether you have released the delayed stream yet or
-not.
-
-Upon creation, delayed-stream captures all `source` events and stores them in
-an internal event buffer. Once `delayedStream.release()` is called, all
-buffered events are emitted on the `delayedStream`, and the event buffer is
-cleared. After that, delayed-stream merely acts as a proxy for the underlaying
-source.
-
-### Error handling
-
-Error events on `source` are buffered / proxied just like any other events.
-However, `delayedStream.create` attaches a no-op `'error'` listener to the
-`source`. This way you only have to handle errors on the `delayedStream`
-object, rather than in two places.
-
-### Buffer limits
-
-delayed-stream provides a `maxDataSize` property that can be used to limit
-the amount of data being buffered. In order to protect you from bad `source`
-streams that don't react to `source.pause()`, this feature is enabled by
-default.
-
-## API
-
-### DelayedStream.create(source, [options])
-
-Returns a new `delayedStream`. Available options are:
-
-* `pauseStream`
-* `maxDataSize`
-
-The description for those properties can be found below.
-
-### delayedStream.source
-
-The `source` stream managed by this object. This is useful if you are
-passing your `delayedStream` around, and you still want to access properties
-on the `source` object.
-
-### delayedStream.pauseStream = true
-
-Whether to pause the underlaying `source` when calling
-`DelayedStream.create()`. Modifying this property afterwards has no effect.
-
-### delayedStream.maxDataSize = 1024 * 1024
-
-The amount of data to buffer before emitting an `error`.
-
-If the underlaying source is emitting `Buffer` objects, the `maxDataSize`
-refers to bytes.
-
-If the underlaying source is emitting JavaScript strings, the size refers to
-characters.
-
-If you know what you are doing, you can set this property to `Infinity` to
-disable this feature. You can also modify this property during runtime.
-
-### delayedStream.maxDataSize = 1024 * 1024
-
-The amount of data to buffer before emitting an `error`.
-
-If the underlaying source is emitting `Buffer` objects, the `maxDataSize`
-refers to bytes.
-
-If the underlaying source is emitting JavaScript strings, the size refers to
-characters.
-
-If you know what you are doing, you can set this property to `Infinity` to
-disable this feature.
-
-### delayedStream.dataSize = 0
-
-The amount of data buffered so far.
-
-### delayedStream.readable
-
-An ECMA5 getter that returns the value of `source.readable`.
-
-### delayedStream.resume()
-
-If the `delayedStream` has not been released so far, `delayedStream.release()`
-is called.
-
-In either case, `source.resume()` is called.
-
-### delayedStream.pause()
-
-Calls `source.pause()`.
-
-### delayedStream.pipe(dest)
-
-Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.
-
-### delayedStream.release()
-
-Emits and clears all events that have been buffered up so far. This does not
-resume the underlaying source, use `delayedStream.resume()` instead.
-
-## License
-
-delayed-stream is licensed under the MIT license.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js
deleted file mode 100644
index 7c10d482..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js
+++ /dev/null
@@ -1,99 +0,0 @@
-var Stream = require('stream').Stream;
-var util = require('util');
-
-module.exports = DelayedStream;
-function DelayedStream() {
-  this.source = null;
-  this.dataSize = 0;
-  this.maxDataSize = 1024 * 1024;
-  this.pauseStream = true;
-
-  this._maxDataSizeExceeded = false;
-  this._released = false;
-  this._bufferedEvents = [];
-}
-util.inherits(DelayedStream, Stream);
-
-DelayedStream.create = function(source, options) {
-  var delayedStream = new this();
-
-  options = options || {};
-  for (var option in options) {
-    delayedStream[option] = options[option];
-  }
-
-  delayedStream.source = source;
-
-  var realEmit = source.emit;
-  source.emit = function() {
-    delayedStream._handleEmit(arguments);
-    return realEmit.apply(source, arguments);
-  };
-
-  source.on('error', function() {});
-  if (delayedStream.pauseStream) {
-    source.pause();
-  }
-
-  return delayedStream;
-};
-
-DelayedStream.prototype.__defineGetter__('readable', function() {
-  return this.source.readable;
-});
-
-DelayedStream.prototype.resume = function() {
-  if (!this._released) {
-    this.release();
-  }
-
-  this.source.resume();
-};
-
-DelayedStream.prototype.pause = function() {
-  this.source.pause();
-};
-
-DelayedStream.prototype.release = function() {
-  this._released = true;
-
-  this._bufferedEvents.forEach(function(args) {
-    this.emit.apply(this, args);
-  }.bind(this));
-  this._bufferedEvents = [];
-};
-
-DelayedStream.prototype.pipe = function() {
-  var r = Stream.prototype.pipe.apply(this, arguments);
-  this.resume();
-  return r;
-};
-
-DelayedStream.prototype._handleEmit = function(args) {
-  if (this._released) {
-    this.emit.apply(this, args);
-    return;
-  }
-
-  if (args[0] === 'data') {
-    this.dataSize += args[1].length;
-    this._checkIfMaxDataSizeExceeded();
-  }
-
-  this._bufferedEvents.push(args);
-};
-
-DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() {
-  if (this._maxDataSizeExceeded) {
-    return;
-  }
-
-  if (this.dataSize <= this.maxDataSize) {
-    return;
-  }
-
-  this._maxDataSizeExceeded = true;
-  var message =
-    'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'
-  this.emit('error', new Error(message));
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json
deleted file mode 100644
index 3328e9b6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "author": {
-    "name": "Felix Geisendörfer",
-    "email": "felix@debuggable.com",
-    "url": "http://debuggable.com/"
-  },
-  "name": "delayed-stream",
-  "description": "Buffers events from a stream until you are ready to handle them.",
-  "version": "0.0.5",
-  "homepage": "https://github.com/felixge/node-delayed-stream",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/felixge/node-delayed-stream.git"
-  },
-  "main": "./lib/delayed_stream",
-  "engines": {
-    "node": ">=0.4.0"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "fake": "0.2.0",
-    "far": "0.0.1"
-  },
-  "readme": "# delayed-stream\n\nBuffers events from a stream until you are ready to handle them.\n\n## Installation\n\n``` bash\nnpm install delayed-stream\n```\n\n## Usage\n\nThe following example shows how to write a http echo server that delays its\nresponse by 1000 ms.\n\n``` javascript\nvar DelayedStream = require('delayed-stream');\nvar http = require('http');\n\nhttp.createServer(function(req, res) {\n  var delayed = DelayedStream.create(req);\n\n  setTimeout(function() {\n    res.writeHead(200);\n    delayed.pipe(res);\n  }, 1000);\n});\n```\n\nIf you are not using `Stream#pipe`, you can also manually release the buffered\nevents by calling `delayedStream.resume()`:\n\n``` javascript\nvar delayed = DelayedStream.create(req);\n\nsetTimeout(function() {\n  // Emit all buffered events and resume underlaying source\n  delayed.resume();\n}, 1000);\n```\n\n## Implementation\n\nIn order to use this meta stream properly, here are a few things you should\nknow about the implementation.\n\n### Event Buffering / Proxying\n\nAll events of the `source` stream are hijacked by overwriting the `source.emit`\nmethod. Until node implements a catch-all event listener, this is the only way.\n\nHowever, delayed-stream still continues to emit all events it captures on the\n`source`, regardless of whether you have released the delayed stream yet or\nnot.\n\nUpon creation, delayed-stream captures all `source` events and stores them in\nan internal event buffer. Once `delayedStream.release()` is called, all\nbuffered events are emitted on the `delayedStream`, and the event buffer is\ncleared. After that, delayed-stream merely acts as a proxy for the underlaying\nsource.\n\n### Error handling\n\nError events on `source` are buffered / proxied just like any other events.\nHowever, `delayedStream.create` attaches a no-op `'error'` listener to the\n`source`. This way you only have to handle errors on the `delayedStream`\nobject, rather than in two places.\n\n### Buffer limits\n\ndelayed-stream provides a `maxDataSize` property that can be used to limit\nthe amount of data being buffered. In order to protect you from bad `source`\nstreams that don't react to `source.pause()`, this feature is enabled by\ndefault.\n\n## API\n\n### DelayedStream.create(source, [options])\n\nReturns a new `delayedStream`. Available options are:\n\n* `pauseStream`\n* `maxDataSize`\n\nThe description for those properties can be found below.\n\n### delayedStream.source\n\nThe `source` stream managed by this object. This is useful if you are\npassing your `delayedStream` around, and you still want to access properties\non the `source` object.\n\n### delayedStream.pauseStream = true\n\nWhether to pause the underlaying `source` when calling\n`DelayedStream.create()`. Modifying this property afterwards has no effect.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature. You can also modify this property during runtime.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature.\n\n### delayedStream.dataSize = 0\n\nThe amount of data buffered so far.\n\n### delayedStream.readable\n\nAn ECMA5 getter that returns the value of `source.readable`.\n\n### delayedStream.resume()\n\nIf the `delayedStream` has not been released so far, `delayedStream.release()`\nis called.\n\nIn either case, `source.resume()` is called.\n\n### delayedStream.pause()\n\nCalls `source.pause()`.\n\n### delayedStream.pipe(dest)\n\nCalls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.\n\n### delayedStream.release()\n\nEmits and clears all events that have been buffered up so far. This does not\nresume the underlaying source, use `delayedStream.resume()` instead.\n\n## License\n\ndelayed-stream is licensed under the MIT license.\n",
-  "readmeFilename": "Readme.md",
-  "bugs": {
-    "url": "https://github.com/felixge/node-delayed-stream/issues"
-  },
-  "_id": "delayed-stream@0.0.5",
-  "_shasum": "d4b1f43a93e8296dfe02694f4680bc37a313c73f",
-  "_from": "delayed-stream@0.0.5",
-  "_resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js
deleted file mode 100644
index 4d71b8a6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js
+++ /dev/null
@@ -1,6 +0,0 @@
-var common = module.exports;
-
-common.DelayedStream = require('..');
-common.assert = require('assert');
-common.fake = require('fake');
-common.PORT = 49252;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js
deleted file mode 100644
index 9ecad5b8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var DelayedStream = common.DelayedStream;
-var http = require('http');
-
-var UPLOAD = new Buffer(10 * 1024 * 1024);
-
-var server = http.createServer(function(req, res) {
-  var delayed = DelayedStream.create(req, {maxDataSize: UPLOAD.length});
-
-  setTimeout(function() {
-    res.writeHead(200);
-    delayed.pipe(res);
-  }, 10);
-});
-server.listen(common.PORT, function() {
-  var request = http.request({
-    method: 'POST',
-    port: common.PORT,
-  });
-
-  request.write(UPLOAD);
-  request.end();
-
-  request.on('response', function(res) {
-    var received = 0;
-    res
-      .on('data', function(chunk) {
-        received += chunk.length;
-      })
-      .on('end', function() {
-        assert.equal(received, UPLOAD.length);
-        server.close();
-      });
-  });
-});
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js
deleted file mode 100644
index 6f417f3e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js
+++ /dev/null
@@ -1,21 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var fake = common.fake.create();
-var DelayedStream = common.DelayedStream;
-var Stream = require('stream').Stream;
-
-(function testAutoPause() {
-  var source = new Stream();
-
-  fake.expect(source, 'pause', 1);
-  var delayedStream = DelayedStream.create(source);
-  fake.verify();
-})();
-
-(function testDisableAutoPause() {
-  var source = new Stream();
-  fake.expect(source, 'pause', 0);
-
-  var delayedStream = DelayedStream.create(source, {pauseStream: false});
-  fake.verify();
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js
deleted file mode 100644
index b50c3978..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var fake = common.fake.create();
-var DelayedStream = common.DelayedStream;
-var Stream = require('stream').Stream;
-
-(function testDelayEventsUntilResume() {
-  var source = new Stream();
-  var delayedStream = DelayedStream.create(source, {pauseStream: false});
-
-  fake.expect(source, 'pause');
-  delayedStream.pause();
-  fake.verify();
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js
deleted file mode 100644
index fc4047e0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js
+++ /dev/null
@@ -1,48 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var fake = common.fake.create();
-var DelayedStream = common.DelayedStream;
-var Stream = require('stream').Stream;
-
-(function testDelayEventsUntilResume() {
-  var source = new Stream();
-  var delayedStream = DelayedStream.create(source, {pauseStream: false});
-
-  // delayedStream must not emit until we resume
-  fake.expect(delayedStream, 'emit', 0);
-
-  // but our original source must emit
-  var params = [];
-  source.on('foo', function(param) {
-    params.push(param);
-  });
-
-  source.emit('foo', 1);
-  source.emit('foo', 2);
-
-  // Make sure delayedStream did not emit, and source did
-  assert.deepEqual(params, [1, 2]);
-  fake.verify();
-
-  // After resume, delayedStream must playback all events
-  fake
-    .stub(delayedStream, 'emit')
-    .times(Infinity)
-    .withArg(1, 'newListener');
-  fake.expect(delayedStream, 'emit', ['foo', 1]);
-  fake.expect(delayedStream, 'emit', ['foo', 2]);
-  fake.expect(source, 'resume');
-
-  delayedStream.resume();
-  fake.verify();
-
-  // Calling resume again will delegate to source
-  fake.expect(source, 'resume');
-  delayedStream.resume();
-  fake.verify();
-
-  // Emitting more events directly leads to them being emitted
-  fake.expect(delayedStream, 'emit', ['foo', 3]);
-  source.emit('foo', 3);
-  fake.verify();
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js
deleted file mode 100644
index a9d35e72..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js
+++ /dev/null
@@ -1,15 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var fake = common.fake.create();
-var DelayedStream = common.DelayedStream;
-var Stream = require('stream').Stream;
-
-(function testHandleSourceErrors() {
-  var source = new Stream();
-  var delayedStream = DelayedStream.create(source, {pauseStream: false});
-
-  // We deal with this by attaching a no-op listener to 'error' on the source
-  // when creating a new DelayedStream. This way error events on the source
-  // won't throw.
-  source.emit('error', new Error('something went wrong'));
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js
deleted file mode 100644
index 7638a2bf..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var fake = common.fake.create();
-var DelayedStream = common.DelayedStream;
-var Stream = require('stream').Stream;
-
-(function testMaxDataSize() {
-  var source = new Stream();
-  var delayedStream = DelayedStream.create(source, {maxDataSize: 1024, pauseStream: false});
-
-  source.emit('data', new Buffer(1024));
-
-  fake
-    .expect(delayedStream, 'emit')
-    .withArg(1, 'error');
-  source.emit('data', new Buffer(1));
-  fake.verify();
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js
deleted file mode 100644
index 7d312ab1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js
+++ /dev/null
@@ -1,13 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var fake = common.fake.create();
-var DelayedStream = common.DelayedStream;
-var Stream = require('stream').Stream;
-
-(function testPipeReleases() {
-  var source = new Stream();
-  var delayedStream = DelayedStream.create(source, {pauseStream: false});
-
-  fake.expect(delayedStream, 'resume');
-  delayedStream.pipe(new Stream());
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js
deleted file mode 100644
index d436163b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js
+++ /dev/null
@@ -1,13 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var fake = common.fake.create();
-var DelayedStream = common.DelayedStream;
-var Stream = require('stream').Stream;
-
-(function testProxyReadableProperty() {
-  var source = new Stream();
-  var delayedStream = DelayedStream.create(source, {pauseStream: false});
-
-  source.readable = fake.value('source.readable');
-  assert.strictEqual(delayedStream.readable, source.readable);
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js
deleted file mode 100755
index 0bb8e822..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env node
-var far = require('far').create();
-
-far.add(__dirname);
-far.include(/test-.*\.js$/);
-
-far.execute();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json
deleted file mode 100644
index 15d38744..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "author": {
-    "name": "Felix Geisendörfer",
-    "email": "felix@debuggable.com",
-    "url": "http://debuggable.com/"
-  },
-  "name": "combined-stream",
-  "description": "A stream that emits multiple other streams one after another.",
-  "version": "0.0.4",
-  "homepage": "https://github.com/felixge/node-combined-stream",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/felixge/node-combined-stream.git"
-  },
-  "main": "./lib/combined_stream",
-  "engines": {
-    "node": "*"
-  },
-  "dependencies": {
-    "delayed-stream": "0.0.5"
-  },
-  "devDependencies": {
-    "far": "0.0.1"
-  },
-  "readme": "# combined-stream\n\nA stream that emits multiple other streams one after another.\n\n## Installation\n\n``` bash\nnpm install combined-stream\n```\n\n## Usage\n\nHere is a simple example that shows how you can use combined-stream to combine\ntwo files into one:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nWhile the example above works great, it will pause all source streams until\nthey are needed. If you don't want that to happen, you can set `pauseStreams`\nto `false`:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create({pauseStreams: false});\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nHowever, what if you don't have all the source streams yet, or you don't want\nto allocate the resources (file descriptors, memory, etc.) for them right away?\nWell, in that case you can simply provide a callback that supplies the stream\nby calling a `next()` function:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(function(next) {\n  next(fs.createReadStream('file1.txt'));\n});\ncombinedStream.append(function(next) {\n  next(fs.createReadStream('file2.txt'));\n});\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\n## API\n\n### CombinedStream.create([options])\n\nReturns a new combined stream object. Available options are:\n\n* `maxDataSize`\n* `pauseStreams`\n\nThe effect of those options is described below.\n\n### combinedStream.pauseStreams = true\n\nWhether to apply back pressure to the underlaying streams. If set to `false`,\nthe underlaying streams will never be paused. If set to `true`, the\nunderlaying streams will be paused right after being appended, as well as when\n`delayedStream.pipe()` wants to throttle.\n\n### combinedStream.maxDataSize = 2 * 1024 * 1024\n\nThe maximum amount of bytes (or characters) to buffer for all source streams.\nIf this value is exceeded, `combinedStream` emits an `'error'` event.\n\n### combinedStream.dataSize = 0\n\nThe amount of bytes (or characters) currently buffered by `combinedStream`.\n\n### combinedStream.append(stream)\n\nAppends the given `stream` to the combinedStream object. If `pauseStreams` is\nset to `true, this stream will also be paused right away.\n\n`streams` can also be a function that takes one parameter called `next`. `next`\nis a function that must be invoked in order to provide the `next` stream, see\nexample above.\n\nRegardless of how the `stream` is appended, combined-stream always attaches an\n`'error'` listener to it, so you don't have to do that manually.\n\nSpecial case: `stream` can also be a String or Buffer.\n\n### combinedStream.write(data)\n\nYou should not call this, `combinedStream` takes care of piping the appended\nstreams into itself for you.\n\n### combinedStream.resume()\n\nCauses `combinedStream` to start drain the streams it manages. The function is\nidempotent, and also emits a `'resume'` event each time which usually goes to\nthe stream that is currently being drained.\n\n### combinedStream.pause();\n\nIf `combinedStream.pauseStreams` is set to `false`, this does nothing.\nOtherwise a `'pause'` event is emitted, this goes to the stream that is\ncurrently being drained, so you can use it to apply back pressure.\n\n### combinedStream.end();\n\nSets `combinedStream.writable` to false, emits an `'end'` event, and removes\nall streams from the queue.\n\n### combinedStream.destroy();\n\nSame as `combinedStream.end()`, except it emits a `'close'` event instead of\n`'end'`.\n\n## License\n\ncombined-stream is licensed under the MIT license.\n",
-  "readmeFilename": "Readme.md",
-  "bugs": {
-    "url": "https://github.com/felixge/node-combined-stream/issues"
-  },
-  "_id": "combined-stream@0.0.4",
-  "_shasum": "2d1a43347dbe9515a4a2796732e5b88473840b22",
-  "_from": "combined-stream@~0.0.4",
-  "_resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.4.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js
deleted file mode 100644
index 81543485..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js
+++ /dev/null
@@ -1,23 +0,0 @@
-var common = module.exports;
-
-var path = require('path');
-var fs = require('fs');
-var root = path.join(__dirname, '..');
-
-common.dir = {
-  fixture: root + '/test/fixture',
-  tmp: root + '/test/tmp',
-};
-
-// Create tmp directory if it does not exist
-// Not using fs.exists so as to be node 0.6.x compatible
-try {
-  fs.statSync(common.dir.tmp);
-}
-catch (e) {
-  // Dir does not exist
-  fs.mkdirSync(common.dir.tmp);
-}
-
-common.CombinedStream = require(root);
-common.assert = require('assert');
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt
deleted file mode 100644
index 50e0218d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt
+++ /dev/null
@@ -1,256 +0,0 @@
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
-10101010101010101010101010101010101010101010101010101010101010101010101010101010
-01010101010101010101010101010101010101010101010101010101010101010101010101010101
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt
deleted file mode 100644
index da1d821f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt
+++ /dev/null
@@ -1,256 +0,0 @@
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
-20202020202020202020202020202020202020202020202020202020202020202020202020202020
-02020202020202020202020202020202020202020202020202020202020202020202020202020202
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js
deleted file mode 100644
index 44ecabab..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js
+++ /dev/null
@@ -1,27 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-var fs = require('fs');
-
-var FILE1 = common.dir.fixture + '/file1.txt';
-var FILE2 = common.dir.fixture + '/file2.txt';
-var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
-
-(function testDelayedStreams() {
-  var combinedStream = CombinedStream.create();
-  combinedStream.append(function(next) {
-    next(fs.createReadStream(FILE1));
-  });
-  combinedStream.append(function(next) {
-    next(fs.createReadStream(FILE2));
-  });
-
-  var tmpFile = common.dir.tmp + '/combined.txt';
-  var dest = fs.createWriteStream(tmpFile);
-  combinedStream.pipe(dest);
-
-  dest.on('end', function() {
-    var written = fs.readFileSync(tmpFile, 'utf8');
-    assert.strictEqual(written, EXPECTED);
-  });
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js
deleted file mode 100644
index e3fbd184..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js
+++ /dev/null
@@ -1,34 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-
-(function testDataSizeGetter() {
-  var combinedStream = CombinedStream.create();
-
-  assert.strictEqual(combinedStream.dataSize, 0);
-
-  // Test one stream
-  combinedStream._streams.push({dataSize: 10});
-  combinedStream._updateDataSize();
-  assert.strictEqual(combinedStream.dataSize, 10);
-
-  // Test two streams
-  combinedStream._streams.push({dataSize: 23});
-  combinedStream._updateDataSize();
-  assert.strictEqual(combinedStream.dataSize, 33);
-
-  // Test currentStream
-  combinedStream._currentStream = {dataSize: 20};
-  combinedStream._updateDataSize();
-  assert.strictEqual(combinedStream.dataSize, 53);
-
-  // Test currentStream without dataSize
-  combinedStream._currentStream = {};
-  combinedStream._updateDataSize();
-  assert.strictEqual(combinedStream.dataSize, 33);
-
-  // Test stream function
-  combinedStream._streams.push(function() {});
-  combinedStream._updateDataSize();
-  assert.strictEqual(combinedStream.dataSize, 33);
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js
deleted file mode 100644
index c678575c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-var fs = require('fs');
-
-var FILE1 = common.dir.fixture + '/file1.txt';
-var BUFFER = new Buffer('Bacon is delicious');
-var FILE2 = common.dir.fixture + '/file2.txt';
-var STRING = 'The € kicks the $\'s ass!';
-
-var EXPECTED =
-  fs.readFileSync(FILE1)
-  + BUFFER
-  + fs.readFileSync(FILE2)
-  + STRING;
-var GOT;
-
-(function testDelayedStreams() {
-  var combinedStream = CombinedStream.create();
-  combinedStream.append(fs.createReadStream(FILE1));
-  combinedStream.append(BUFFER);
-  combinedStream.append(fs.createReadStream(FILE2));
-  combinedStream.append(function(next) {
-    next(STRING);
-  });
-
-  var tmpFile = common.dir.tmp + '/combined-file1-buffer-file2-string.txt';
-  var dest = fs.createWriteStream(tmpFile);
-  combinedStream.pipe(dest);
-
-  dest.on('close', function() {
-    GOT = fs.readFileSync(tmpFile, 'utf8');
-  });
-})();
-
-process.on('exit', function() {
-  assert.strictEqual(GOT, EXPECTED);
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js
deleted file mode 100644
index 263cfdf7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js
+++ /dev/null
@@ -1,35 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-var fs = require('fs');
-
-var FILE1 = common.dir.fixture + '/file1.txt';
-var FILE2 = common.dir.fixture + '/file2.txt';
-var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
-var GOT;
-
-(function testDelayedStreams() {
-  var combinedStream = CombinedStream.create();
-  combinedStream.append(fs.createReadStream(FILE1));
-  combinedStream.append(fs.createReadStream(FILE2));
-
-  var stream1 = combinedStream._streams[0];
-  var stream2 = combinedStream._streams[1];
-
-  stream1.on('end', function() {
-    assert.equal(stream2.dataSize, 0);
-  });
-
-  var tmpFile = common.dir.tmp + '/combined.txt';
-  var dest = fs.createWriteStream(tmpFile);
-  combinedStream.pipe(dest);
-
-  dest.on('close', function() {
-    GOT = fs.readFileSync(tmpFile, 'utf8');
-  });
-})();
-
-process.on('exit', function() {
-  console.error(GOT.length, EXPECTED.length);
-  assert.strictEqual(GOT, EXPECTED);
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js
deleted file mode 100644
index c3d288d0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-var util = require('util');
-var Stream = require('stream').Stream;
-
-var s = CombinedStream.create();
-
-
-function StringStream(){
-  this.writable=true;
-  this.str=""
-}
-util.inherits(StringStream,Stream);
-
-StringStream.prototype.write=function(chunk,encoding){
-  this.str+=chunk.toString();
-  this.emit('data',chunk);
-}
-
-StringStream.prototype.end=function(chunk,encoding){
-  this.emit('end');
-}
-
-StringStream.prototype.toString=function(){
-  return this.str;
-}
-
-
-s.append("foo.");
-s.append("");
-s.append("bar");
-
-var ss = new StringStream();
-
-s.pipe(ss);
-s.resume();
-
-assert.equal(ss.toString(),"foo.bar");
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js
deleted file mode 100644
index aefa36e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js
+++ /dev/null
@@ -1,17 +0,0 @@
-var fs = require('fs');
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-var FILE1 = common.dir.fixture + '/file1.txt';
-var fileStream = fs.createReadStream(FILE1);
-
-var foo = function(){};
-
-(function testIsStreamLike() {
-  assert(! CombinedStream.isStreamLike(true));
-  assert(! CombinedStream.isStreamLike("I am a string"));
-  assert(! CombinedStream.isStreamLike(7));
-  assert(! CombinedStream.isStreamLike(foo));
-
-  assert(CombinedStream.isStreamLike(fileStream));
-})();
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js
deleted file mode 100644
index 25f47a47..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-var fs = require('fs');
-
-var FILE1 = common.dir.fixture + '/file1.txt';
-var FILE2 = common.dir.fixture + '/file2.txt';
-var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
-
-(function testDelayedStreams() {
-  var combinedStream = CombinedStream.create({pauseStreams: false, maxDataSize: 20736});
-  combinedStream.append(fs.createReadStream(FILE1));
-  combinedStream.append(fs.createReadStream(FILE2));
-
-  var gotErr = null;
-  combinedStream.on('error', function(err) {
-    gotErr = err;
-  });
-
-  process.on('exit', function() {
-    assert.ok(gotErr);
-    assert.ok(gotErr.message.match(/bytes/));
-  });
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js
deleted file mode 100644
index 30a3a6f8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var common = require('../common');
-var assert = common.assert;
-var CombinedStream = common.CombinedStream;
-var fs = require('fs');
-
-var FILE1 = common.dir.fixture + '/file1.txt';
-var FILE2 = common.dir.fixture + '/file2.txt';
-var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
-
-(function testDelayedStreams() {
-  var combinedStream = CombinedStream.create({pauseStreams: false});
-  combinedStream.append(fs.createReadStream(FILE1));
-  combinedStream.append(fs.createReadStream(FILE2));
-
-  var stream1 = combinedStream._streams[0];
-  var stream2 = combinedStream._streams[1];
-
-  stream1.on('end', function() {
-    assert.ok(stream2.dataSize > 0);
-  });
-
-  var tmpFile = common.dir.tmp + '/combined.txt';
-  var dest = fs.createWriteStream(tmpFile);
-  combinedStream.pipe(dest);
-
-  dest.on('end', function() {
-    var written = fs.readFileSync(tmpFile, 'utf8');
-    assert.strictEqual(written, EXPECTED);
-  });
-})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js
deleted file mode 100755
index 0bb8e822..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env node
-var far = require('far').create();
-
-far.add(__dirname);
-far.include(/test-.*\.js$/);
-
-far.execute();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/package.json
deleted file mode 100644
index 1c157f12..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/form-data/package.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
-  "author": {
-    "name": "Felix Geisendörfer",
-    "email": "felix@debuggable.com",
-    "url": "http://debuggable.com/"
-  },
-  "name": "form-data",
-  "description": "A module to create readable \"multipart/form-data\" streams.  Can be used to submit forms and file uploads to other web applications.",
-  "version": "0.1.2",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/felixge/node-form-data.git"
-  },
-  "main": "./lib/form_data",
-  "scripts": {
-    "test": "node test/run.js"
-  },
-  "engines": {
-    "node": ">= 0.6"
-  },
-  "dependencies": {
-    "combined-stream": "~0.0.4",
-    "mime": "~1.2.11",
-    "async": "~0.2.9"
-  },
-  "licenses": [
-    {
-      "type": "MIT",
-      "url": "https://raw.github.com/felixge/node-form-data/master/License"
-    }
-  ],
-  "devDependencies": {
-    "fake": "~0.2.2",
-    "far": "~0.0.7",
-    "formidable": "~1.0.14",
-    "request": "~2.27.0"
-  },
-  "readme": "# Form-Data [![Build Status](https://travis-ci.org/felixge/node-form-data.png?branch=master)](https://travis-ci.org/felixge/node-form-data) [![Dependency Status](https://gemnasium.com/felixge/node-form-data.png)](https://gemnasium.com/felixge/node-form-data)\n\nA module to create readable ```\"multipart/form-data\"``` streams. Can be used to submit forms and file uploads to other web applications.\n\nThe API of this module is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd].\n\n[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface\n[streams2-thing]: http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions\n\n## Install\n\n```\nnpm install form-data\n```\n\n## Usage\n\nIn this example we are constructing a form with 3 fields that contain a string,\na buffer and a file stream.\n\n``` javascript\nvar FormData = require('form-data');\nvar fs = require('fs');\n\nvar form = new FormData();\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_file', fs.createReadStream('/foo/bar.jpg'));\n```\n\nAlso you can use http-response stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar http = require('http');\n\nvar form = new FormData();\n\nhttp.request('http://nodejs.org/images/logo.png', function(response) {\n  form.append('my_field', 'my value');\n  form.append('my_buffer', new Buffer(10));\n  form.append('my_logo', response);\n});\n```\n\nOr @mikeal's request stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar request = require('request');\n\nvar form = new FormData();\n\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_logo', request('http://nodejs.org/images/logo.png'));\n```\n\nIn order to submit this form to a web application, call ```submit(url, [callback])``` method:\n\n``` javascript\nform.submit('http://example.org/', function(err, res) {\n  // res – response object (http.IncomingMessage)  //\n  res.resume(); // for node-0.10.x\n});\n\n```\n\nFor more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods.\n\n### Alternative submission methods\n\nYou can use node's http client interface:\n\n``` javascript\nvar http = require('http');\n\nvar request = http.request({\n  method: 'post',\n  host: 'example.org',\n  path: '/upload',\n  headers: form.getHeaders()\n});\n\nform.pipe(request);\n\nrequest.on('response', function(res) {\n  console.log(res.statusCode);\n});\n```\n\nOr if you would prefer the `'Content-Length'` header to be set for you:\n\n``` javascript\nform.submit('example.org/upload', function(err, res) {\n  console.log(res.statusCode);\n});\n```\n\nTo use custom headers and pre-known length in parts:\n\n``` javascript\nvar CRLF = '\\r\\n';\nvar form = new FormData();\n\nvar options = {\n  header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,\n  knownLength: 1\n};\n\nform.append('my_buffer', buffer, options);\n\nform.submit('http://example.com/', function(err, res) {\n  if (err) throw err;\n  console.log('Done');\n});\n```\n\nForm-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide \"file\"-related information manually:\n\n``` javascript\nsomeModule.stream(function(err, stdout, stderr) {\n  if (err) throw err;\n\n  var form = new FormData();\n\n  form.append('file', stdout, {\n    filename: 'unicycle.jpg',\n    contentType: 'image/jpg',\n    knownLength: 19806\n  });\n\n  form.submit('http://example.com/', function(err, res) {\n    if (err) throw err;\n    console.log('Done');\n  });\n});\n```\n\nFor edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:\n\n``` javascript\nform.submit({\n  host: 'example.com',\n  path: '/probably.php?extra=params',\n  auth: 'username:password'\n}, function(err, res) {\n  console.log(res.statusCode);\n});\n```\n\n## Notes\n\n- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround.\n- If it feels like FormData hangs after submit and you're on ```node-0.10```, please check [Compatibility with Older Node Versions][streams2-thing]\n\n## TODO\n\n- Add new streams (0.10) support and try really hard not to break it for 0.8.x.\n\n## License\n\nForm-Data is licensed under the MIT license.\n",
-  "readmeFilename": "Readme.md",
-  "bugs": {
-    "url": "https://github.com/felixge/node-form-data/issues"
-  },
-  "homepage": "https://github.com/felixge/node-form-data",
-  "_id": "form-data@0.1.2",
-  "_shasum": "1143c21357911a78dd7913b189b4bab5d5d57445",
-  "_from": "form-data@~0.1.0",
-  "_resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.2.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.npmignore
deleted file mode 100644
index 77ba16cb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.travis.yml
deleted file mode 100755
index 047f7e3d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-
-node_js:
-  - 0.10
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/LICENSE
deleted file mode 100755
index e699a7bd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2012-2013, Eran Hammer.
-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 Eran Hammer 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 ERAN HAMMER 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/Makefile
deleted file mode 100755
index 5f339bf3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/Makefile
+++ /dev/null
@@ -1,10 +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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/README.md
deleted file mode 100755
index 010bac6d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/README.md
+++ /dev/null
@@ -1,627 +0,0 @@
-![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png)
-
-<img align="right" src="https://raw.github.com/hueniverse/hawk/master/images/logo.png" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial
-HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).
-
-Current version: **1.0**
-
-[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk)
-
-# Table of Content
-
-- [**Introduction**](#introduction)
-  - [Replay Protection](#replay-protection)
-  - [Usage Example](#usage-example)
-  - [Protocol Example](#protocol-example)
-    - [Payload Validation](#payload-validation)
-    - [Response Payload Validation](#response-payload-validation)
-  - [Browser Support and Considerations](#browser-support-and-considerations)
-<p></p>
-- [**Single URI Authorization**](#single-uri-authorization)
-  - [Usage Example](#bewit-usage-example)
-<p></p>
-- [**Security Considerations**](#security-considerations)
-  - [MAC Keys Transmission](#mac-keys-transmission)
-  - [Confidentiality of Requests](#confidentiality-of-requests)
-  - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers)
-  - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials)
-  - [Entropy of Keys](#entropy-of-keys)
-  - [Coverage Limitations](#coverage-limitations)
-  - [Future Time Manipulation](#future-time-manipulation)
-  - [Client Clock Poisoning](#client-clock-poisoning)
-  - [Bewit Limitations](#bewit-limitations)
-  - [Host Header Forgery](#host-header-forgery)
-<p></p>
-- [**Frequently Asked Questions**](#frequently-asked-questions)
-<p></p>
-- [**Acknowledgements**](#acknowledgements)
-
-# Introduction
-
-**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with
-partial cryptographic verification of the request and response, covering the HTTP method, request URI, host,
-and optionally the request payload.
-
-Similar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of
-client credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme,
-the key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is
-included in its place.
-
-However, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of
-replay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less
-"chattiness" (interaction with the server).
-
-Also unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because
-the client and server must both have access to the key material in the clear.
-
-The primary design goals of this scheme are to:
-* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources,
-* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where
-  to send an authenticated request), and
-* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client
-  failure to validate the server's identity as part of its TLS handshake.
-
-In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using
-a query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).
-
-The **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server,
-which is beyond the scope of this module. Typically, the shared credentials are established via an initial
-TLS-protected phase or derived from some other shared confidential information available to both the client
-and the server.
-
-
-## Replay Protection
-
-Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more 
-than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when 
-making requests. This gives the server enough information to prevent replay attacks.
-
-The nonce is generated by the client, and is a string unique across all requests with the same timestamp and
-key identifier combination. 
-
-The timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards
-are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks.
-By default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in
-practice translates to a maximum of 2 minutes as the skew can be positive or negative).
-
-Using a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client
-clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types
-(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response
-to a bad timestamp.
-
-There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a
-potential attack vector). Instead, the client only uses the server's time to calculate an offset used only
-for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing
-the number of round trips required to authenticate the first request.
-
-
-## Usage Example
-
-Server code:
-
-```javascript
-var Http = require('http');
-var Hawk = require('hawk');
-
-
-// Credentials lookup function
-
-var credentialsFunc = function (id, callback) {
-
-    var credentials = {
-        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-        algorithm: 'sha256',
-        user: 'Steve'
-    };
-
-    return callback(null, credentials);
-};
-
-// Create HTTP server
-
-var handler = function (req, res) {
-
-    // Authenticate incoming request
-
-    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-        // Prepare response
-
-        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
-        var headers = { 'Content-Type': 'text/plain' };
-
-        // Generate Server-Authorization response header
-
-        var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] });
-        headers['Server-Authorization'] = header;
-
-        // Send the response back
-
-        res.writeHead(!err ? 200 : 401, headers);
-        res.end(payload);
-    });
-};
-
-// Start server
-
-Http.createServer(handler).listen(8000, 'example.com');
-```
-
-Client code:
-
-```javascript
-var Request = require('request');
-var Hawk = require('hawk');
-
-
-// Client credentials
-
-var credentials = {
-    id: 'dh37fgj492je',
-    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-    algorithm: 'sha256'
-}
-
-// Request options
-
-var requestOptions = {
-    uri: 'http://example.com:8000/resource/1?b=1&a=2',
-    method: 'GET',
-    headers: {}
-};
-
-// Generate Authorization request header
-
-var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });
-requestOptions.headers.Authorization = header.field;
-
-// Send authenticated request
-
-Request(requestOptions, function (error, response, body) {
-
-    // Authenticate the server's response
-
-    var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });
-
-    // Output results
-
-    console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
-});
-```
-
-**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local
-machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.
-
-```javascript
-Hawk.sntp.start();
-```
-
-
-## Protocol Example
-
-The client attempts to access a protected resource without authentication, sending the following HTTP request to
-the resource server:
-
-```
-GET /resource/1?b=1&a=2 HTTP/1.1
-Host: example.com:8000
-```
-
-The resource server returns an authentication challenge.
-
-```
-HTTP/1.1 401 Unauthorized
-WWW-Authenticate: Hawk
-```
-
-The client has previously obtained a set of **Hawk** credentials for accessing resources on the "http://example.com/"
-server. The **Hawk** credentials issued to the client include the following attributes:
-
-* Key identifier: dh37fgj492je
-* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn
-* Algorithm: sha256
-
-The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,
-1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline
-character):
-
-```
-hawk.1.header
-1353832234
-j4h3g2
-GET
-/resource/1?b=1&a=2
-example.com
-8000
-
-some-app-ext-data
-
-```
-
-The request MAC is calculated using HMAC with the specified hash algorithm "sha256" and the key over the normalized request string.
-The result is base64-encoded to produce the request MAC:
-
-```
-6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=
-```
-
-The client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using
-the HTTP `Authorization` request header field:
-
-```
-GET /resource/1?b=1&a=2 HTTP/1.1
-Host: example.com:8000
-Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="
-```
-
-The server validates the request by calculating the request MAC again based on the request received and verifies the validity
-and scope of the **Hawk** credentials. If valid, the server responds with the requested resource.
-
-
-### Payload Validation
-
-**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash
-using the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):
-* `hawk.1.payload`
-* the content-type in lowercase, without any parameters (e.g. `application/json`)
-* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability)
-
-For example:
-
-* Payload: `Thank you for flying Hawk`
-* Content Type: `text/plain`
-* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=`
-
-Results in the following input to the payload hash function (newline terminated values):
-
-```
-hawk.1.payload
-text/plain
-Thank you for flying Hawk
-
-```
-
-Which produces the following hash value:
-
-```
-Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
-```
-
-The client constructs the normalized request string (newline terminated values):
-
-```
-hawk.1.header
-1353832234
-j4h3g2
-POST
-/resource/1?a=1&b=2
-example.com
-8000
-Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
-some-app-ext-data
-
-```
-
-Then calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data,
-and request MAC, with the request using the HTTP `Authorization` request header field:
-
-```
-POST /resource/1?a=1&b=2 HTTP/1.1
-Host: example.com:8000
-Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="
-```
-
-It is up to the server if and when it validates the payload for any given request, based solely on it's security policy
-and the nature of the data included.
-
-If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct
-the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value
-with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.
-
-However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed
-at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value
-provided by the client after validating the MAC.
-
-It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value
-included in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided
-by the client, the payload may be modified by an attacker.
-
-
-## Response Payload Validation
-
-**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the
-client to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header
-as a response header using the exact same syntax as the `Authorization` request header field.
-
-The header is contructed using the same process as the client's request header. The server uses the same credentials and other
-artifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with
-new values based on the server response. The rest as identical to those used by the client.
-
-The result MAC digest is included with the optional `hash` and `ext` values:
-
-```
-Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"
-```
-
-
-## Browser Support and Considerations
-
-A browser script is provided for including using a `<script>` tag in [lib/browser.js](/lib/browser.js).
-
-**Hawk** relies on the _Server-Authorization_ and _WWW-Authenticate_ headers in its response to communicate with the client.
-Therefore, in case of CORS requests, it is important to consider sending _Access-Control-Expose-Headers_ with the value
-_"WWW-Authenticate, Server-Authorization"_ on each response from your server. As explained in the
-[specifications](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header), it will indicate that these headers
-can safely be accessed by the client (using getResponseHeader() on the XmlHttpRequest object). Otherwise you will be met with a
-["simple response header"](http://www.w3.org/TR/cors/#simple-response-header) which excludes these fields and would prevent the
-Hawk client from authenticating the requests.You can read more about the why and how in this
-[article](http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server)
-
-
-# Single URI Authorization
-
-There are cases in which limited and short-term access to a protected resource is granted to a third party which does not
-have access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. **Hawk**
-provides limited support for such URIs in the form of a _bewit_ - a URI query parameter appended to the request URI which contains
-the necessary credentials to authenticate the request.
-
-Because of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests
-and for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same
-credentials as the client to maintain clear traceability as to who issued which credentials.
-
-In order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within
-the granted access timeframe. 
-
-
-## Bewit Usage Example
-
-Server code:
-
-```javascript
-var Http = require('http');
-var Hawk = require('hawk');
-
-
-// Credentials lookup function
-
-var credentialsFunc = function (id, callback) {
-
-    var credentials = {
-        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-        algorithm: 'sha256'
-    };
-
-    return callback(null, credentials);
-};
-
-// Create HTTP server
-
-var handler = function (req, res) {
-
-    Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-        res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });
-        res.end(!err ? 'Access granted' : 'Shoosh!');
-    });
-};
-
-Http.createServer(handler).listen(8000, 'example.com');
-```
-
-Bewit code generation:
-
-```javascript
-var Request = require('request');
-var Hawk = require('hawk');
-
-
-// Client credentials
-
-var credentials = {
-    id: 'dh37fgj492je',
-    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-    algorithm: 'sha256'
-}
-
-// Generate bewit
-
-var duration = 60 * 5;      // 5 Minutes
-var bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });
-var uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;
-```
-
-
-# Security Considerations
-
-The greatest sources of security risks are usually found not in **Hawk** but in the policies and procedures surrounding its use.
-Implementers are strongly encouraged to assess how this module addresses their security requirements. This section includes
-an incomplete list of security considerations that must be reviewed and understood before deploying **Hawk** on the server.
-Many of the protections provided in **Hawk** depends on whether and how they are used.
-
-### MAC Keys Transmission
-
-**Hawk** does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used
-to obtain **Hawk** credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.
-
-### Confidentiality of Requests
-
-While **Hawk** provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request
-confidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should
-carefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms
-to protect sensitive resources.
-
-### Spoofing by Counterfeit Servers
-
-**Hawk** provides limited verification of the server authenticity. When receiving a response back from the server, the server
-may choose to include a response `Server-Authorization` header which the client can use to verify the response. However, it is up to
-the server to determine when such measure is included, to up to the client to enforce that policy.
-
-A hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise
-incorrect responses. Service providers should consider such attacks when developing services using this protocol, and should
-require transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.
-
-### Plaintext Storage of Credentials
-
-The **Hawk** key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC,
-the server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which
-store only a one-way hash of user credentials.
-
-If an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able
-to perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized
-access.
-
-### Entropy of Keys
-
-Unless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request
-MAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to
-assign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the **Hawk**
-credentials are valid.
-
-For example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force
-attack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the
-longest key reasonable.
-
-It is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high
-quality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit
-patterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use
-cryptographically secure PRNGs to avoid these problems.
-
-### Coverage Limitations
-
-The request MAC only covers the HTTP `Host` header and optionally the `Content-Type` header. It does not cover any other headers
-which can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence
-or value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the
-`ext` feature to pass application-specific information via the `Authorization` header which is protected by the request MAC.
-
-The response authentication, when performed, only covers the response payload, content-type, and the request information 
-provided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or
-any other response header field (e.g. Location) which can affect the client's behaviour.
-
-### Future Time Manipulation
-
-The protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its
-current time when an invalid timestamp is received.
-
-If an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause
-the client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will
-not likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then
-be able to replay the request at the correct time without detection.
-
-The client must only use the time information provided by the server if:
-* it was delivered over a TLS connection and the server identity has been verified, or
-* the `tsm` MAC digest calculated using the same client credentials over the timestamp has been verified.
-
-### Client Clock Poisoning
-
-When receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use
-the time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with
-that particular server.
-
-### Bewit Limitations
-
-Special care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot
-be revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with
-access to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET
-requests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private
-and sensitive information.
-
-### Host Header Forgery
-
-Hawk validates the incoming request MAC against the incoming HTTP Host header. However, unless the optional `host` and `port`
-options are used with `server.authenticate()`, a malicous client can mint new host names pointing to the server's IP address and
-use that to craft an attack by sending a valid request that's meant for another hostname than the one used by the server. Server
-implementors must manually verify that the host header received matches their expectation (or use the options mentioned above).
-
-# Frequently Asked Questions
-
-### Where is the protocol specification?
-
-If you are looking for some prose explaining how all this works, **this is it**. **Hawk** is being developed as an open source
-project instead of a standard. In other words, the [code](/hueniverse/hawk/tree/master/lib) is the specification. Not sure about
-something? Open an issue!
-
-### Is it done?
-
-At if version 0.10.0, **Hawk** is feature-complete. However, until this module reaches version 1.0.0 it is considered experimental
-and is likely to change. This also means your feedback and contribution are very welcome. Feel free to open issues with questions
-and suggestions.
-
-### Where can I find **Hawk** implementations in other languages?
-
-**Hawk**'s only reference implementation is provided in JavaScript as a node.js module. However, others are actively porting it to other
-platforms. There is already a [PHP](https://github.com/alexbilbie/PHP-Hawk),
-[.NET](https://github.com/pcibraro/hawknet), and [JAVA](https://github.com/wealdtech/hawk) libraries available. The full list
-is maintained [here](https://github.com/hueniverse/hawk/issues?labels=port). Please add an issue if you are working on another
-port. A cross-platform test-suite is in the works.
-
-### Why isn't the algorithm part of the challenge or dynamically negotiated?
-
-The algorithm used is closely related to the key issued as different algorithms require different key sizes (and other
-requirements). While some keys can be used for multiple algorithm, the protocol is designed to closely bind the key and algorithm
-together as part of the issued credentials.
-
-### Why is Host and Content-Type the only headers covered by the request MAC?
-
-It is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no
-well-established way to normalize them. Many platforms change the case of header field names and values. The only
-straight-forward solution is to include the headers in some blob (say, base64 encoded JSON) and include that with the request,
-an approach taken by JWT and other such formats. However, that design violates the HTTP header boundaries, repeats information,
-and introduces other security issues because firewalls will not be aware of these "hidden" headers. In addition, any information
-repeated must be compared to the duplicated information in the header and therefore only moves the problem elsewhere.
-
-### Why not just use HTTP Digest?
-
-Digest requires pre-negotiation to establish a nonce. This means you can't just make a request - you must first send
-a protocol handshake to the server. This pattern has become unacceptable for most web services, especially mobile
-where extra round-trip are costly.
-
-### Why bother with all this nonce and timestamp business?
-
-**Hawk** is an attempt to find a reasonable, practical compromise between security and usability. OAuth 1.0 got timestamp
-and nonces halfway right but failed when it came to scalability and consistent developer experience. **Hawk** addresses
-it by requiring the client to sync its clock, but provides it with tools to accomplish it.
-
-In general, replay protection is a matter of application-specific threat model. It is less of an issue on a TLS-protected
-system where the clients are implemented using best practices and are under the control of the server. Instead of dropping
-replay protection, **Hawk** offers a required time window and an optional nonce verification. Together, it provides developers
-with the ability to decide how to enforce their security policy without impacting the client's implementation.
-
-### What are `app` and `dlg` in the authorization header and normalized mac string?
-
-The original motivation for **Hawk** was to replace the OAuth 1.0 use cases. This included both a simple client-server mode which
-this module is specifically designed for, and a delegated access mode which is being developed separately in
-[Oz](https://github.com/hueniverse/oz). In addition to the **Hawk** use cases, Oz requires another attribute: the application id `app`.
-This provides binding between the credentials and the application in a way that prevents an attacker from tricking an application
-to use credentials issued to someone else. It also has an optional 'delegated-by' attribute `dlg` which is the application id of the
-application the credentials were directly issued to. The goal of these two additions is to allow Oz to utilize **Hawk** directly,
-but with the additional security of delegated credentials.
-
-### What is the purpose of the static strings used in each normalized MAC input?
-
-When calculating a hash or MAC, a static prefix (tag) is added. The prefix is used to prevent MAC values from being
-used or reused for a purpose other than what they were created for (i.e. prevents switching MAC values between a request,
-response, and a bewit use cases). It also protects against expliots created after a potential change in how the protocol
-creates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it
-can create an exploit opportunity for cases where the nonce is similar in format to a timestamp.
-
-### Does **Hawk** have anything to do with OAuth?
-
-Short answer: no.
-
-**Hawk** was originally proposed as the OAuth MAC Token specification. However, the OAuth working group in its consistent
-incompetence failed to produce a final, usable solution to address one of the most popular use cases of OAuth 1.0 - using it
-to authenticate simple client-server transactions (i.e. two-legged). As you can guess, the OAuth working group is still hard
-at work to produce more garbage.
-
-**Hawk** provides a simple HTTP authentication scheme for making client-server requests. It does not address the OAuth use case
-of delegating access to a third party. If you are looking for an OAuth alternative, check out [Oz](https://github.com/hueniverse/oz).
-
-
-# Acknowledgements
-
-**Hawk** is a derivative work of the [HTTP MAC Authentication Scheme](http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) proposal
-co-authored by Ben Adida, Adam Barth, and Eran Hammer, which in turn was based on the OAuth 1.0 community specification.
-
-Special thanks to Ben Laurie for his always insightful feedback and advice.
-
-The **Hawk** logo was created by [Chris Carrasco](http://chriscarrasco.com).
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/example/usage.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/example/usage.js
deleted file mode 100755
index 8c063f6c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/example/usage.js
+++ /dev/null
@@ -1,78 +0,0 @@
-// Load modules
-
-var Http = require('http');
-var Request = require('request');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {
-    credentials: {
-        dh37fgj492je: {
-            id: 'dh37fgj492je',                                             // Required by Hawk.client.header 
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: 'sha256',
-            user: 'Steve'
-        }
-    }
-};
-
-
-// Credentials lookup function
-
-var credentialsFunc = function (id, callback) {
-
-    return callback(null, internals.credentials[id]);
-};
-
-
-// Create HTTP server
-
-var handler = function (req, res) {
-
-    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
-        var headers = {
-            'Content-Type': 'text/plain',
-            'Server-Authorization': Hawk.server.header(credentials, artifacts, { payload: payload, contentType: 'text/plain' })
-        };
-
-        res.writeHead(!err ? 200 : 401, headers);
-        res.end(payload);
-    });
-};
-
-Http.createServer(handler).listen(8000, '127.0.0.1');
-
-
-// Send unauthenticated request
-
-Request('http://127.0.0.1:8000/resource/1?b=1&a=2', function (error, response, body) {
-
-    console.log(response.statusCode + ': ' + body);
-});
-
-
-// Send authenticated request
-
-credentialsFunc('dh37fgj492je', function (err, credentials) {
-
-    var header = Hawk.client.header('http://127.0.0.1:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'and welcome!' });
-    var options = {
-        uri: 'http://127.0.0.1:8000/resource/1?b=1&a=2',
-        method: 'GET',
-        headers: {
-            authorization: header.field
-        }
-    };
-
-    Request(options, function (error, response, body) {
-
-        var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });
-        console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
-        process.exit(0);
-    });
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/images/hawk.png b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/images/hawk.png
deleted file mode 100755
index a0e15cda0144a7d7ed222e74a2ea4afbab32555c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6945
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
CLl2Sw

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/images/logo.png b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/images/logo.png
deleted file mode 100755
index b8ff5901718a8a5529d25602a4a581d2f68d67cb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 71732
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

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/index.js
deleted file mode 100755
index 4cc88b35..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('./lib');
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/browser.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/browser.js
deleted file mode 100755
index 27494f23..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/browser.js
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
-    HTTP Hawk Authentication Scheme
-    Copyright (c) 2012-2013, Eran Hammer <eran@hueniverse.com>
-    MIT Licensed
-*/
-
-
-// Declare namespace
-
-var hawk = {};
-
-
-// Export if used as a module
-
-if (typeof module !== "undefined" && module.exports) {
-    module.exports = hawk;
-}
-
-hawk.client = {
-
-    // Generate an Authorization header for a given request
-
-    /*
-        uri: 'http://example.com/resource?a=b'
-        method: HTTP verb (e.g. 'GET', 'POST')
-        options: {
-    
-            // Required
-    
-            credentials: {
-                id: 'dh37fgj492je',
-                key: 'aoijedoaijsdlaksjdl',
-                algorithm: 'sha256'                                 // 'sha1', 'sha256'
-            },
-    
-            // Optional
-    
-            ext: 'application-specific',                        // Application specific data sent via the ext attribute
-            timestamp: Date.now() / 1000,                       // A pre-calculated timestamp in seconds
-            nonce: '2334f34f',                                  // A pre-generated nonce
-            localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
-            payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
-            contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
-            hash: 'U4MKKSmiVxk37JCCrAVIjV=',                    // Pre-calculated payload hash
-            app: '24s23423f34dx',                               // Oz application id
-            dlg: '234sz34tww3sd'                                // Oz delegated-by application id
-        }
-    */
-
-    header: function (uri, method, options) {
-
-        var result = {
-            field: '',
-            artifacts: {}
-        };
-
-        // Validate inputs
-
-        if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
-            !method || typeof method !== 'string' ||
-            !options || typeof options !== 'object') {
-
-            return result;
-        }
-
-        // Application time
-
-        var timestamp = options.timestamp || Math.floor((hawk.utils.now() + (options.localtimeOffsetMsec || 0)) / 1000)
-
-        // Validate credentials
-
-        var credentials = options.credentials;
-        if (!credentials ||
-            !credentials.id ||
-            !credentials.key ||
-            !credentials.algorithm) {
-
-            // Invalid credential object
-            return result;
-        }
-
-        if (hawk.crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return result;
-        }
-
-        // Parse URI
-
-        if (typeof uri === 'string') {
-            uri = hawk.utils.parseUri(uri);
-        }
-
-        // Calculate signature
-
-        var artifacts = {
-            ts: timestamp,
-            nonce: options.nonce || hawk.utils.randomString(6),
-            method: method,
-            resource: uri.relative,
-            host: uri.hostname,
-            port: uri.port,
-            hash: options.hash,
-            ext: options.ext,
-            app: options.app,
-            dlg: options.dlg
-        };
-
-        result.artifacts = artifacts;
-
-        // Calculate payload hash
-
-        if (!artifacts.hash &&
-            options.hasOwnProperty('payload')) {
-
-            artifacts.hash = hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
-        }
-
-        var mac = hawk.crypto.calculateMac('header', credentials, artifacts);
-
-        // Construct header
-
-        var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== '';       // Other falsey values allowed
-        var header = 'Hawk id="' + credentials.id +
-                     '", ts="' + artifacts.ts +
-                     '", nonce="' + artifacts.nonce +
-                     (artifacts.hash ? '", hash="' + artifacts.hash : '') +
-                     (hasExt ? '", ext="' + hawk.utils.escapeHeaderAttribute(artifacts.ext) : '') +
-                     '", mac="' + mac + '"';
-
-        if (artifacts.app) {
-            header += ', app="' + artifacts.app +
-                      (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
-        }
-
-        result.field = header;
-
-        return result;
-    },
-
-
-    // Validate server response
-
-    /*
-        request:    object created via 'new XMLHttpRequest()' after response received
-        artifacts:  object recieved from header().artifacts
-        options: {
-            payload:    optional payload received
-            required:   specifies if a Server-Authorization header is required. Defaults to 'false'
-        }
-    */
-
-    authenticate: function (request, credentials, artifacts, options) {
-
-        options = options || {};
-
-        if (request.getResponseHeader('www-authenticate')) {
-
-            // Parse HTTP WWW-Authenticate header
-
-            var attributes = hawk.utils.parseAuthorizationHeader(request.getResponseHeader('www-authenticate'), ['ts', 'tsm', 'error']);
-            if (!attributes) {
-                return false;
-            }
-
-            if (attributes.ts) {
-                var tsm = hawk.crypto.calculateTsMac(attributes.ts, credentials);
-                if (tsm !== attributes.tsm) {
-                    return false;
-                }
-
-                hawk.utils.setNtpOffset(attributes.ts - Math.floor(Date.now() / 1000));     // Keep offset at 1 second precision
-            }
-        }
-
-        // Parse HTTP Server-Authorization header
-
-        if (!request.getResponseHeader('server-authorization') &&
-            !options.required) {
-
-            return true;
-        }
-
-        var attributes = hawk.utils.parseAuthorizationHeader(request.getResponseHeader('server-authorization'), ['mac', 'ext', 'hash']);
-        if (!attributes) {
-            return false;
-        }
-
-        var modArtifacts = {
-            ts: artifacts.ts,
-            nonce: artifacts.nonce,
-            method: artifacts.method,
-            resource: artifacts.resource,
-            host: artifacts.host,
-            port: artifacts.port,
-            hash: attributes.hash,
-            ext: attributes.ext,
-            app: artifacts.app,
-            dlg: artifacts.dlg
-        };
-
-        var mac = hawk.crypto.calculateMac('response', credentials, modArtifacts);
-        if (mac !== attributes.mac) {
-            return false;
-        }
-
-        if (!options.hasOwnProperty('payload')) {
-            return true;
-        }
-
-        if (!attributes.hash) {
-            return false;
-        }
-
-        var calculatedHash = hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, request.getResponseHeader('content-type'));
-        return (calculatedHash === attributes.hash);
-    },
-
-    message: function (host, port, message, options) {
-
-        // Validate inputs
-
-        if (!host || typeof host !== 'string' ||
-            !port || typeof port !== 'number' ||
-            message === null || message === undefined || typeof message !== 'string' ||
-            !options || typeof options !== 'object') {
-
-            return null;
-        }
-
-        // Application time
-
-        var timestamp = options.timestamp || Math.floor((hawk.utils.now() + (options.localtimeOffsetMsec || 0)) / 1000)
-
-        // Validate credentials
-
-        var credentials = options.credentials;
-        if (!credentials ||
-            !credentials.id ||
-            !credentials.key ||
-            !credentials.algorithm) {
-
-            // Invalid credential object
-            return null;
-        }
-
-        if (hawk.crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return null;
-        }
-
-        // Calculate signature
-
-        var artifacts = {
-            ts: timestamp,
-            nonce: options.nonce || hawk.utils.randomString(6),
-            host: host,
-            port: port,
-            hash: hawk.crypto.calculatePayloadHash(message, credentials.algorithm)
-        };
-
-        // Construct authorization
-
-        var result = {
-            id: credentials.id,
-            ts: artifacts.ts,
-            nonce: artifacts.nonce,
-            hash: artifacts.hash,
-            mac: hawk.crypto.calculateMac('message', credentials, artifacts)
-        };
-
-        return result;
-    }
-};
-
-
-hawk.crypto = {
-
-    headerVersion: '1',
-
-    algorithms: ['sha1', 'sha256'],
-
-    calculateMac: function (type, credentials, options) {
-
-        var normalized = hawk.crypto.generateNormalizedString(type, options);
-
-        var hmac = CryptoJS['Hmac' + credentials.algorithm.toUpperCase()](normalized, credentials.key);
-        return hmac.toString(CryptoJS.enc.Base64);
-    },
-
-    generateNormalizedString: function (type, options) {
-
-        var normalized = 'hawk.' + hawk.crypto.headerVersion + '.' + type + '\n' +
-                         options.ts + '\n' +
-                         options.nonce + '\n' +
-                         (options.method || '').toUpperCase() + '\n' +
-                         (options.resource || '') + '\n' +
-                         options.host.toLowerCase() + '\n' +
-                         options.port + '\n' +
-                         (options.hash || '') + '\n';
-
-        if (options.ext) {
-            normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n');
-        }
-
-        normalized += '\n';
-
-        if (options.app) {
-            normalized += options.app + '\n' +
-                          (options.dlg || '') + '\n';
-        }
-
-        return normalized;
-    },
-
-    calculatePayloadHash: function (payload, algorithm, contentType) {
-
-        var hash = CryptoJS.algo[algorithm.toUpperCase()].create();
-        hash.update('hawk.' + hawk.crypto.headerVersion + '.payload\n');
-        hash.update(hawk.utils.parseContentType(contentType) + '\n');
-        hash.update(payload || '');
-        hash.update('\n');
-        return hash.finalize().toString(CryptoJS.enc.Base64);
-    },
-
-    calculateTsMac: function (ts, credentials) {
-
-        var hash = CryptoJS['Hmac' + credentials.algorithm.toUpperCase()]('hawk.' + hawk.crypto.headerVersion + '.ts\n' + ts + '\n', credentials.key);
-        return hash.toString(CryptoJS.enc.Base64);
-    }
-};
-
-
-hawk.utils = {
-
-    storage: {                                      // localStorage compatible interface
-        _cache: {},
-        setItem: function (key, value) {
-
-            hawk.utils.storage._cache[key] = value;
-        },
-        getItem: function (key) {
-
-            return hawk.utils.storage._cache[key];
-        }
-    },
-
-    setStorage: function (storage) {
-
-        var ntpOffset = hawk.utils.getNtpOffset() || 0;
-        hawk.utils.storage = storage;
-        hawk.utils.setNtpOffset(ntpOffset);
-    },
-
-    setNtpOffset: function (offset) {
-
-        hawk.utils.storage.setItem('hawk_ntp_offset', offset);
-    },
-
-    getNtpOffset: function () {
-
-        return parseInt(hawk.utils.storage.getItem('hawk_ntp_offset') || '0', 10);
-    },
-
-    now: function () {
-
-        return Date.now() + hawk.utils.getNtpOffset();
-    },
-
-    escapeHeaderAttribute: function (attribute) {
-
-        return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');
-    },
-
-    parseContentType: function (header) {
-
-        if (!header) {
-            return '';
-        }
-
-        return header.split(';')[0].trim().toLowerCase();
-    },
-
-    parseAuthorizationHeader: function (header, keys) {
-
-        if (!header) {
-            return null;
-        }
-
-        var headerParts = header.match(/^(\w+)(?:\s+(.*))?$/);       // Header: scheme[ something]
-        if (!headerParts) {
-            return null;
-        }
-
-        var scheme = headerParts[1];
-        if (scheme.toLowerCase() !== 'hawk') {
-            return null;
-        }
-
-        var attributesString = headerParts[2];
-        if (!attributesString) {
-            return null;
-        }
-
-        var attributes = {};
-        var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
-
-            // Check valid attribute names
-
-            if (keys.indexOf($1) === -1) {
-                return;
-            }
-
-            // Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
-
-            if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {
-                return;
-            }
-
-            // Check for duplicates
-
-            if (attributes.hasOwnProperty($1)) {
-                return;
-            }
-
-            attributes[$1] = $2;
-            return '';
-        });
-
-        if (verify !== '') {
-            return null;
-        }
-
-        return attributes;
-    },
-
-    randomString: function (size) {
-
-        var randomSource = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
-        var len = randomSource.length;
-
-        var result = [];
-        for (var i = 0; i < size; ++i) {
-            result[i] = randomSource[Math.floor(Math.random() * len)];
-        }
-
-        return result.join('');
-    },
-
-    parseUri: function (input) {
-
-        // Based on: parseURI 1.2.2
-        // http://blog.stevenlevithan.com/archives/parseuri
-        // (c) Steven Levithan <stevenlevithan.com>
-        // MIT License
-
-        var keys = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'hostname', 'port', 'resource', 'relative', 'pathname', 'directory', 'file', 'query', 'fragment'];
-
-        var uriRegex = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?(((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?)(?:#(.*))?)/;
-        var uriByNumber = uriRegex.exec(input);
-        var uri = {};
-
-        var i = 15;
-        while (i--) {
-            uri[keys[i]] = uriByNumber[i] || '';
-        }
-
-        if (uri.port === null ||
-            uri.port === '') {
-
-            uri.port = (uri.protocol.toLowerCase() === 'http' ? '80' : (uri.protocol.toLowerCase() === 'https' ? '443' : ''));
-        }
-
-        return uri;
-    }
-};
-
-
-// Based on: Crypto-JS v3.1.2
-// Copyright (c) 2009-2013, Jeff Mott. All rights reserved.
-// http://code.google.com/p/crypto-js/
-// http://code.google.com/p/crypto-js/wiki/License
-
-var CryptoJS=CryptoJS||function(h,r){var k={},l=k.lib={},n=function(){},f=l.Base={extend:function(a){n.prototype=this;var b=new n;a&&b.mixIn(a);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},j=l.WordArray=f.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=r?b:4*a.length},toString:function(a){return(a||s).stringify(this)},concat:function(a){var b=this.words,d=a.words,c=this.sigBytes;a=a.sigBytes;this.clamp();if(c%4)for(var e=0;e<a;e++)b[c+e>>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((c+e)%4);else if(65535<d.length)for(e=0;e<a;e+=4)b[c+e>>>2]=d[e>>>2];else b.push.apply(b,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<<32-8*(b%4);a.length=h.ceil(b/4)},clone:function(){var a=f.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],d=0;d<a;d+=4)b.push(4294967296*h.random()|0);return new j.init(b,a)}}),m=k.enc={},s=m.Hex={stringify:function(a){var b=a.words;a=a.sigBytes;for(var d=[],c=0;c<a;c++){var e=b[c>>>2]>>>24-8*(c%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c+=2)d[c>>>3]|=parseInt(a.substr(c,2),16)<<24-4*(c%8);return new j.init(d,b/2)}},p=m.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var d=[],c=0;c<a;c++)d.push(String.fromCharCode(b[c>>>2]>>>24-8*(c%4)&255));return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c++)d[c>>>2]|=(a.charCodeAt(c)&255)<<24-8*(c%4);return new j.init(d,b)}},t=m.Utf8={stringify:function(a){try{return decodeURIComponent(escape(p.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return p.parse(unescape(encodeURIComponent(a)))}},q=l.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new j.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=t.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,d=b.words,c=b.sigBytes,e=this.blockSize,f=c/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;c=h.min(4*a,c);if(a){for(var g=0;g<a;g+=e)this._doProcessBlock(d,g);g=d.splice(0,a);b.sigBytes-=c}return new j.init(g,c)},clone:function(){var a=f.clone.call(this);a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=q.extend({cfg:f.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,d){return(new a.init(d)).finalize(b)}},_createHmacHelper:function(a){return function(b,d){return(new u.HMAC.init(a,d)).finalize(b)}}});var u=k.algo={};return k}(Math);
-(function () { var k = CryptoJS, b = k.lib, m = b.WordArray, l = b.Hasher, d = [], b = k.algo.SHA1 = l.extend({ _doReset: function () { this._hash = new m.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (n, p) { for (var a = this._hash.words, e = a[0], f = a[1], h = a[2], j = a[3], b = a[4], c = 0; 80 > c; c++) { if (16 > c) d[c] = n[p + c] | 0; else { var g = d[c - 3] ^ d[c - 8] ^ d[c - 14] ^ d[c - 16]; d[c] = g << 1 | g >>> 31 } g = (e << 5 | e >>> 27) + b + d[c]; g = 20 > c ? g + ((f & h | ~f & j) + 1518500249) : 40 > c ? g + ((f ^ h ^ j) + 1859775393) : 60 > c ? g + ((f & h | f & j | h & j) - 1894007588) : g + ((f ^ h ^ j) - 899497514); b = j; j = h; h = f << 30 | f >>> 2; f = e; e = g } a[0] = a[0] + e | 0; a[1] = a[1] + f | 0; a[2] = a[2] + h | 0; a[3] = a[3] + j | 0; a[4] = a[4] + b | 0 }, _doFinalize: function () { var b = this._data, d = b.words, a = 8 * this._nDataBytes, e = 8 * b.sigBytes; d[e >>> 5] |= 128 << 24 - e % 32; d[(e + 64 >>> 9 << 4) + 14] = Math.floor(a / 4294967296); d[(e + 64 >>> 9 << 4) + 15] = a; b.sigBytes = 4 * d.length; this._process(); return this._hash }, clone: function () { var b = l.clone.call(this); b._hash = this._hash.clone(); return b } }); k.SHA1 = l._createHelper(b); k.HmacSHA1 = l._createHmacHelper(b) })();
-(function (k) { for (var g = CryptoJS, h = g.lib, v = h.WordArray, j = h.Hasher, h = g.algo, s = [], t = [], u = function (q) { return 4294967296 * (q - (q | 0)) | 0 }, l = 2, b = 0; 64 > b;) { var d; a: { d = l; for (var w = k.sqrt(d), r = 2; r <= w; r++) if (!(d % r)) { d = !1; break a } d = !0 } d && (8 > b && (s[b] = u(k.pow(l, 0.5))), t[b] = u(k.pow(l, 1 / 3)), b++); l++ } var n = [], h = h.SHA256 = j.extend({ _doReset: function () { this._hash = new v.init(s.slice(0)) }, _doProcessBlock: function (q, h) { for (var a = this._hash.words, c = a[0], d = a[1], b = a[2], k = a[3], f = a[4], g = a[5], j = a[6], l = a[7], e = 0; 64 > e; e++) { if (16 > e) n[e] = q[h + e] | 0; else { var m = n[e - 15], p = n[e - 2]; n[e] = ((m << 25 | m >>> 7) ^ (m << 14 | m >>> 18) ^ m >>> 3) + n[e - 7] + ((p << 15 | p >>> 17) ^ (p << 13 | p >>> 19) ^ p >>> 10) + n[e - 16] } m = l + ((f << 26 | f >>> 6) ^ (f << 21 | f >>> 11) ^ (f << 7 | f >>> 25)) + (f & g ^ ~f & j) + t[e] + n[e]; p = ((c << 30 | c >>> 2) ^ (c << 19 | c >>> 13) ^ (c << 10 | c >>> 22)) + (c & d ^ c & b ^ d & b); l = j; j = g; g = f; f = k + m | 0; k = b; b = d; d = c; c = m + p | 0 } a[0] = a[0] + c | 0; a[1] = a[1] + d | 0; a[2] = a[2] + b | 0; a[3] = a[3] + k | 0; a[4] = a[4] + f | 0; a[5] = a[5] + g | 0; a[6] = a[6] + j | 0; a[7] = a[7] + l | 0 }, _doFinalize: function () { var d = this._data, b = d.words, a = 8 * this._nDataBytes, c = 8 * d.sigBytes; b[c >>> 5] |= 128 << 24 - c % 32; b[(c + 64 >>> 9 << 4) + 14] = k.floor(a / 4294967296); b[(c + 64 >>> 9 << 4) + 15] = a; d.sigBytes = 4 * b.length; this._process(); return this._hash }, clone: function () { var b = j.clone.call(this); b._hash = this._hash.clone(); return b } }); g.SHA256 = j._createHelper(h); g.HmacSHA256 = j._createHmacHelper(h) })(Math);
-(function(){var c=CryptoJS,k=c.enc.Utf8;c.algo.HMAC=c.lib.Base.extend({init:function(a,b){a=this._hasher=new a.init;"string"==typeof b&&(b=k.parse(b));var c=a.blockSize,e=4*c;b.sigBytes>e&&(b=a.finalize(b));b.clamp();for(var f=this._oKey=b.clone(),g=this._iKey=b.clone(),h=f.words,j=g.words,d=0;d<c;d++)h[d]^=1549556828,j[d]^=909522486;f.sigBytes=g.sigBytes=e;this.reset()},reset:function(){var a=this._hasher;a.reset();a.update(this._iKey)},update:function(a){this._hasher.update(a);return this},finalize:function(a){var b=this._hasher;a=b.finalize(a);b.reset();return b.finalize(this._oKey.clone().concat(a))}})})();
-(function(){var h=CryptoJS,j=h.lib.WordArray;h.enc.Base64={stringify:function(b){var e=b.words,f=b.sigBytes,c=this._map;b.clamp();b=[];for(var a=0;a<f;a+=3)for(var d=(e[a>>>2]>>>24-8*(a%4)&255)<<16|(e[a+1>>>2]>>>24-8*((a+1)%4)&255)<<8|e[a+2>>>2]>>>24-8*((a+2)%4)&255,g=0;4>g&&a+0.75*g<f;g++)b.push(c.charAt(d>>>6*(3-g)&63));if(e=c.charAt(64))for(;b.length%4;)b.push(e);return b.join("")},parse:function(b){var e=b.length,f=this._map,c=f.charAt(64);c&&(c=b.indexOf(c),-1!=c&&(e=c));for(var c=[],a=0,d=0;d<e;d++)if(d%4){var g=f.indexOf(b.charAt(d-1))<<2*(d%4),h=f.indexOf(b.charAt(d))>>>6-2*(d%4);c[a>>>2]|=(g|h)<<24-8*(a%4);a++}return j.create(c,a)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/client.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/client.js
deleted file mode 100755
index 41984582..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/client.js
+++ /dev/null
@@ -1,367 +0,0 @@
-// Load modules
-
-var Url = require('url');
-var Hoek = require('hoek');
-var Cryptiles = require('cryptiles');
-var Crypto = require('./crypto');
-var Utils = require('./utils');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Generate an Authorization header for a given request
-
-/*
-    uri: 'http://example.com/resource?a=b' or object from Url.parse()
-    method: HTTP verb (e.g. 'GET', 'POST')
-    options: {
-
-        // Required
-
-        credentials: {
-            id: 'dh37fgj492je',
-            key: 'aoijedoaijsdlaksjdl',
-            algorithm: 'sha256'                                 // 'sha1', 'sha256'
-        },
-
-        // Optional
-
-        ext: 'application-specific',                        // Application specific data sent via the ext attribute
-        timestamp: Date.now(),                              // A pre-calculated timestamp
-        nonce: '2334f34f',                                  // A pre-generated nonce
-        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
-        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
-        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
-        hash: 'U4MKKSmiVxk37JCCrAVIjV=',                    // Pre-calculated payload hash
-        app: '24s23423f34dx',                               // Oz application id
-        dlg: '234sz34tww3sd'                                // Oz delegated-by application id
-    }
-*/
-
-exports.header = function (uri, method, options) {
-
-    var result = {
-        field: '',
-        artifacts: {}
-    };
-
-    // Validate inputs
-
-    if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
-        !method || typeof method !== 'string' ||
-        !options || typeof options !== 'object') {
-
-        return result;
-    }
-
-    // Application time
-
-    var timestamp = options.timestamp || Math.floor((Utils.now() + (options.localtimeOffsetMsec || 0)) / 1000)
-
-    // Validate credentials
-
-    var credentials = options.credentials;
-    if (!credentials ||
-        !credentials.id ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        // Invalid credential object
-        return result;
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        return result;
-    }
-
-    // Parse URI
-
-    if (typeof uri === 'string') {
-        uri = Url.parse(uri);
-    }
-
-    // Calculate signature
-
-    var artifacts = {
-        ts: timestamp,
-        nonce: options.nonce || Cryptiles.randomString(6),
-        method: method,
-        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
-        host: uri.hostname,
-        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
-        hash: options.hash,
-        ext: options.ext,
-        app: options.app,
-        dlg: options.dlg
-    };
-
-    result.artifacts = artifacts;
-
-    // Calculate payload hash
-
-    if (!artifacts.hash &&
-        options.hasOwnProperty('payload')) {
-
-        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
-    }
-
-    var mac = Crypto.calculateMac('header', credentials, artifacts);
-
-    // Construct header
-
-    var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== '';       // Other falsey values allowed
-    var header = 'Hawk id="' + credentials.id +
-                 '", ts="' + artifacts.ts +
-                 '", nonce="' + artifacts.nonce +
-                 (artifacts.hash ? '", hash="' + artifacts.hash : '') +
-                 (hasExt ? '", ext="' + Utils.escapeHeaderAttribute(artifacts.ext) : '') +
-                 '", mac="' + mac + '"';
-
-    if (artifacts.app) {
-        header += ', app="' + artifacts.app +
-                  (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
-    }
-
-    result.field = header;
-
-    return result;
-};
-
-
-// Validate server response
-
-/*
-    res:        node's response object
-    artifacts:  object recieved from header().artifacts
-    options: {
-        payload:    optional payload received
-        required:   specifies if a Server-Authorization header is required. Defaults to 'false'
-    }
-*/
-
-exports.authenticate = function (res, credentials, artifacts, options) {
-
-    artifacts = Hoek.clone(artifacts);
-    options = options || {};
-
-    if (res.headers['www-authenticate']) {
-
-        // Parse HTTP WWW-Authenticate header
-
-        var attributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']);
-        if (attributes instanceof Error) {
-            return false;
-        }
-
-        if (attributes.ts) {
-            var tsm = Crypto.calculateTsMac(attributes.ts, credentials);
-            if (tsm !== attributes.tsm) {
-                return false;
-            }
-        }
-    }
-
-    // Parse HTTP Server-Authorization header
-
-    if (!res.headers['server-authorization'] &&
-        !options.required) {
-
-        return true;
-    }
-
-    var attributes = Utils.parseAuthorizationHeader(res.headers['server-authorization'], ['mac', 'ext', 'hash']);
-    if (attributes instanceof Error) {
-        return false;
-    }
-
-    artifacts.ext = attributes.ext;
-    artifacts.hash = attributes.hash;
-
-    var mac = Crypto.calculateMac('response', credentials, artifacts);
-    if (mac !== attributes.mac) {
-        return false;
-    }
-
-    if (!options.hasOwnProperty('payload')) {
-        return true;
-    }
-
-    if (!attributes.hash) {
-        return false;
-    }
-
-    var calculatedHash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, res.headers['content-type']);
-    return (calculatedHash === attributes.hash);
-};
-
-
-// Generate a bewit value for a given URI
-
-/*
- * credentials is an object with the following keys: 'id, 'key', 'algorithm'.
- * options is an object with the following optional keys: 'ext', 'localtimeOffsetMsec'
- */
-/*
-    uri: 'http://example.com/resource?a=b' or object from Url.parse()
-    options: {
-
-        // Required
-
-        credentials: {
-            id: 'dh37fgj492je',
-            key: 'aoijedoaijsdlaksjdl',
-            algorithm: 'sha256'                             // 'sha1', 'sha256'
-        },
-        ttlSec: 60 * 60,                                    // TTL in seconds
-
-        // Optional
-
-        ext: 'application-specific',                        // Application specific data sent via the ext attribute
-        localtimeOffsetMsec: 400                            // Time offset to sync with server time
-    };
-*/
-
-exports.getBewit = function (uri, options) {
-
-    // Validate inputs
-
-    if (!uri ||
-        (typeof uri !== 'string' && typeof uri !== 'object') ||
-        !options ||
-        typeof options !== 'object' ||
-        !options.ttlSec) {
-
-        return '';
-    }
-
-    options.ext = (options.ext === null || options.ext === undefined ? '' : options.ext);       // Zero is valid value
-
-    // Application time
-
-    var now = Utils.now() + (options.localtimeOffsetMsec || 0);
-
-    // Validate credentials
-
-    var credentials = options.credentials;
-    if (!credentials ||
-        !credentials.id ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        return '';
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        return '';
-    }
-
-    // Parse URI
-
-    if (typeof uri === 'string') {
-        uri = Url.parse(uri);
-    }
-
-    // Calculate signature
-
-    var exp = Math.floor(now / 1000) + options.ttlSec;
-    var mac = Crypto.calculateMac('bewit', credentials, {
-        ts: exp,
-        nonce: '',
-        method: 'GET',
-        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
-        host: uri.hostname,
-        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
-        ext: options.ext
-    });
-
-    // Construct bewit: id\exp\mac\ext
-
-    var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + options.ext;
-    return Utils.base64urlEncode(bewit);
-};
-
-
-// Generate an authorization string for a message
-
-/*
-    host: 'example.com',
-    port: 8000,
-    message: '{"some":"payload"}',                          // UTF-8 encoded string for body hash generation
-    options: {
-
-        // Required
-
-        credentials: {
-            id: 'dh37fgj492je',
-            key: 'aoijedoaijsdlaksjdl',
-            algorithm: 'sha256'                             // 'sha1', 'sha256'
-        },
-
-        // Optional
-
-        timestamp: Date.now(),                              // A pre-calculated timestamp
-        nonce: '2334f34f',                                  // A pre-generated nonce
-        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
-    }
-*/
-
-exports.message = function (host, port, message, options) {
-
-    // Validate inputs
-
-    if (!host || typeof host !== 'string' ||
-        !port || typeof port !== 'number' ||
-        message === null || message === undefined || typeof message !== 'string' ||
-        !options || typeof options !== 'object') {
-
-        return null;
-    }
-
-    // Application time
-
-    var timestamp = options.timestamp || Math.floor((Utils.now() + (options.localtimeOffsetMsec || 0)) / 1000)
-
-    // Validate credentials
-
-    var credentials = options.credentials;
-    if (!credentials ||
-        !credentials.id ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        // Invalid credential object
-        return null;
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        return null;
-    }
-
-    // Calculate signature
-
-    var artifacts = {
-        ts: timestamp,
-        nonce: options.nonce || Cryptiles.randomString(6),
-        host: host,
-        port: port,
-        hash: Crypto.calculatePayloadHash(message, credentials.algorithm)
-    };
-
-    // Construct authorization
-
-    var result = {
-        id: credentials.id,
-        ts: artifacts.ts,
-        nonce: artifacts.nonce,
-        hash: artifacts.hash,
-        mac: Crypto.calculateMac('message', credentials, artifacts)
-    };
-
-    return result;
-};
-
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/crypto.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/crypto.js
deleted file mode 100755
index 150340a3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/crypto.js
+++ /dev/null
@@ -1,111 +0,0 @@
-// Load modules
-
-var Crypto = require('crypto');
-var Url = require('url');
-var Utils = require('./utils');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// MAC normalization format version
-
-exports.headerVersion = '1';                        // Prevent comparison of mac values generated with different normalized string formats
-
-
-// Supported HMAC algorithms
-
-exports.algorithms = ['sha1', 'sha256'];
-
-
-// Calculate the request MAC
-
-/*
-    type: 'header',                                 // 'header', 'bewit', 'response'
-    credentials: {
-        key: 'aoijedoaijsdlaksjdl',
-        algorithm: 'sha256'                         // 'sha1', 'sha256'
-    },
-    options: {
-        method: 'GET',
-        resource: '/resource?a=1&b=2',
-        host: 'example.com',
-        port: 8080,
-        ts: 1357718381034,
-        nonce: 'd3d345f',
-        hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
-        ext: 'app-specific-data',
-        app: 'hf48hd83qwkj',                        // Application id (Oz)
-        dlg: 'd8djwekds9cj'                         // Delegated by application id (Oz), requires options.app
-    }
-*/
-
-exports.calculateMac = function (type, credentials, options) {
-
-    var normalized = exports.generateNormalizedString(type, options);
-
-    var hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
-    var digest = hmac.digest('base64');
-    return digest;
-};
-
-
-exports.generateNormalizedString = function (type, options) {
-
-    var normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' +
-                     options.ts + '\n' +
-                     options.nonce + '\n' +
-                     (options.method || '').toUpperCase() + '\n' +
-                     (options.resource || '') + '\n' +
-                     options.host.toLowerCase() + '\n' +
-                     options.port + '\n' +
-                     (options.hash || '') + '\n';
-
-    if (options.ext) {
-        normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n');
-    }
-
-    normalized += '\n';
-
-    if (options.app) {
-        normalized += options.app + '\n' +
-                      (options.dlg || '') + '\n';
-    }
-
-    return normalized;
-};
-
-
-exports.calculatePayloadHash = function (payload, algorithm, contentType) {
-
-    var hash = exports.initializePayloadHash(algorithm, contentType);
-    hash.update(payload || '');
-    return exports.finalizePayloadHash(hash);
-};
-
-
-exports.initializePayloadHash = function (algorithm, contentType) {
-
-    var hash = Crypto.createHash(algorithm);
-    hash.update('hawk.' + exports.headerVersion + '.payload\n');
-    hash.update(Utils.parseContentType(contentType) + '\n');
-    return hash;
-};
-
-
-exports.finalizePayloadHash = function (hash) {
-
-    hash.update('\n');
-    return hash.digest('base64');
-};
-
-
-exports.calculateTsMac = function (ts, credentials) {
-
-    var hmac = Crypto.createHmac(credentials.algorithm, credentials.key);
-    hmac.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n');
-    return hmac.digest('base64');
-};
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/index.js
deleted file mode 100755
index 1d713cb6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Export sub-modules
-
-exports.error = exports.Error = require('boom');
-exports.sntp = require('sntp');
-exports.server = require('./server');
-exports.client = require('./client');
-exports.crypto = require('./crypto');
-exports.utils = require('./utils');
-
-exports.uri = {
-    authenticate: exports.server.authenticateBewit,
-    getBewit: exports.client.getBewit
-};
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/server.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/server.js
deleted file mode 100755
index 478c47b3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/server.js
+++ /dev/null
@@ -1,524 +0,0 @@
-// Load modules
-
-var Boom = require('boom');
-var Hoek = require('hoek');
-var Cryptiles = require('cryptiles');
-var Crypto = require('./crypto');
-var Utils = require('./utils');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Hawk authentication
-
-/*
-   req:                 node's HTTP request object or an object as follows:
-  
-                        var request = {
-                            method: 'GET',
-                            url: '/resource/4?a=1&b=2',
-                            host: 'example.com',
-                            port: 8080,
-                            authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="'
-                        };
-  
-   credentialsFunc:     required function to lookup the set of Hawk credentials based on the provided credentials id.
-                        The credentials include the MAC key, MAC algorithm, and other attributes (such as username)
-                        needed by the application. This function is the equivalent of verifying the username and
-                        password in Basic authentication.
-  
-                        var credentialsFunc = function (id, callback) {
-    
-                            // Lookup credentials in database
-                            db.lookup(id, function (err, item) {
-    
-                                if (err || !item) {
-                                    return callback(err);
-                                }
-    
-                                var credentials = {
-                                    // Required
-                                    key: item.key,
-                                    algorithm: item.algorithm,
-                                    // Application specific
-                                    user: item.user
-                                };
-    
-                                return callback(null, credentials);
-                            });
-                        };
-  
-   options: {
-
-        hostHeaderName:        optional header field name, used to override the default 'Host' header when used
-                               behind a cache of a proxy. Apache2 changes the value of the 'Host' header while preserving
-                               the original (which is what the module must verify) in the 'x-forwarded-host' header field.
-                               Only used when passed a node Http.ServerRequest object.
-  
-        nonceFunc:             optional nonce validation function. The function signature is function(nonce, ts, callback)
-                               where 'callback' must be called using the signature function(err).
-  
-        timestampSkewSec:      optional number of seconds of permitted clock skew for incoming timestamps. Defaults to 60 seconds.
-                               Provides a +/- skew which means actual allowed window is double the number of seconds.
-  
-        localtimeOffsetMsec:   optional local clock time offset express in a number of milliseconds (positive or negative).
-                               Defaults to 0.
-  
-        payload:               optional payload for validation. The client calculates the hash value and includes it via the 'hash'
-                               header attribute. The server always ensures the value provided has been included in the request
-                               MAC. When this option is provided, it validates the hash value itself. Validation is done by calculating
-                               a hash value over the entire payload (assuming it has already be normalized to the same format and
-                               encoding used by the client to calculate the hash on request). If the payload is not available at the time
-                               of authentication, the authenticatePayload() method can be used by passing it the credentials and
-                               attributes.hash returned in the authenticate callback.
-
-        host:                  optional host name override. Only used when passed a node request object.
-        port:                  optional port override. Only used when passed a node request object.
-    }
-
-    callback: function (err, credentials, artifacts) { }
- */
-
-exports.authenticate = function (req, credentialsFunc, options, callback) {
-
-    callback = Utils.nextTick(callback);
-    
-    // Default options
-
-    options.nonceFunc = options.nonceFunc || function (nonce, ts, nonceCallback) { return nonceCallback(); };   // No validation
-    options.timestampSkewSec = options.timestampSkewSec || 60;                                                  // 60 seconds
-
-    // Application time
-
-    var now = Utils.now() + (options.localtimeOffsetMsec || 0);                 // Measure now before any other processing
-
-    // Convert node Http request object to a request configuration object
-
-    var request = Utils.parseRequest(req, options);
-    if (request instanceof Error) {
-        return callback(Boom.badRequest(request.message));
-    }
-
-    // Parse HTTP Authorization header
-
-    var attributes = Utils.parseAuthorizationHeader(request.authorization);
-    if (attributes instanceof Error) {
-        return callback(attributes);
-    }
-
-    // Construct artifacts container
-
-    var artifacts = {
-        method: request.method,
-        host: request.host,
-        port: request.port,
-        resource: request.url,
-        ts: attributes.ts,
-        nonce: attributes.nonce,
-        hash: attributes.hash,
-        ext: attributes.ext,
-        app: attributes.app,
-        dlg: attributes.dlg,
-        mac: attributes.mac,
-        id: attributes.id
-    };
-
-    // Verify required header attributes
-
-    if (!attributes.id ||
-        !attributes.ts ||
-        !attributes.nonce ||
-        !attributes.mac) {
-
-        return callback(Boom.badRequest('Missing attributes'), null, artifacts);
-    }
-
-    // Fetch Hawk credentials
-
-    credentialsFunc(attributes.id, function (err, credentials) {
-
-        if (err) {
-            return callback(err, credentials || null, artifacts);
-        }
-
-        if (!credentials) {
-            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, artifacts);
-        }
-
-        if (!credentials.key ||
-            !credentials.algorithm) {
-
-            return callback(Boom.internal('Invalid credentials'), credentials, artifacts);
-        }
-
-        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return callback(Boom.internal('Unknown algorithm'), credentials, artifacts);
-        }
-
-        // Calculate MAC
-
-        var mac = Crypto.calculateMac('header', credentials, artifacts);
-        if (!Cryptiles.fixedTimeComparison(mac, attributes.mac)) {
-            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, artifacts);
-        }
-
-        // Check payload hash
-
-        if (options.payload !== null &&
-            options.payload !== undefined) {       // '' is valid
-
-            if (!attributes.hash) {
-                return callback(Boom.unauthorized('Missing required payload hash', 'Hawk'), credentials, artifacts);
-            }
-
-            var hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, request.contentType);
-            if (!Cryptiles.fixedTimeComparison(hash, attributes.hash)) {
-                return callback(Boom.unauthorized('Bad payload hash', 'Hawk'), credentials, artifacts);
-            }
-        }
-
-        // Check nonce
-
-        options.nonceFunc(attributes.nonce, attributes.ts, function (err) {
-
-            if (err) {
-                return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials, artifacts);
-            }
-
-            // Check timestamp staleness
-
-            if (Math.abs((attributes.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
-                var fresh = Math.floor((Utils.now() + (options.localtimeOffsetMsec || 0)) / 1000);            // Get fresh now
-                var tsm = Crypto.calculateTsMac(fresh, credentials);
-                return callback(Boom.unauthorized('Stale timestamp', 'Hawk', { ts: fresh, tsm: tsm }), credentials, artifacts);
-            }
-
-            // Successful authentication
-
-            return callback(null, credentials, artifacts);
-        });
-    });
-};
-
-
-// Authenticate payload hash - used when payload cannot be provided during authenticate()
-
-/*
-    payload:        raw request payload
-    credentials:    from authenticate callback
-    artifacts:      from authenticate callback
-    contentType:    req.headers['content-type']
-*/
-
-exports.authenticatePayload = function (payload, credentials, artifacts, contentType) {
-
-    var calculatedHash = Crypto.calculatePayloadHash(payload, credentials.algorithm, contentType);
-    return Cryptiles.fixedTimeComparison(calculatedHash, artifacts.hash);
-};
-
-
-// Generate a Server-Authorization header for a given response
-
-/*
-    credentials: {},                                        // Object received from authenticate()
-    artifacts: {}                                           // Object received from authenticate(); 'mac', 'hash', and 'ext' - ignored
-    options: {
-        ext: 'application-specific',                        // Application specific data sent via the ext attribute
-        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
-        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
-        hash: 'U4MKKSmiVxk37JCCrAVIjV='                     // Pre-calculated payload hash
-    }
-*/
-
-exports.header = function (credentials, artifacts, options) {
-
-    // Prepare inputs
-
-    options = options || {};
-
-    if (!artifacts ||
-        typeof artifacts !== 'object' ||
-        typeof options !== 'object') {
-
-        return '';
-    }
-
-    artifacts = Hoek.clone(artifacts);
-    delete artifacts.mac;
-    artifacts.hash = options.hash;
-    artifacts.ext = options.ext;
-
-    // Validate credentials
-
-    if (!credentials ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        // Invalid credential object
-        return '';
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        return '';
-    }
-
-    // Calculate payload hash
-
-    if (!artifacts.hash &&
-        options.hasOwnProperty('payload')) {
-
-        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
-    }
-
-    var mac = Crypto.calculateMac('response', credentials, artifacts);
-
-    // Construct header
-
-    var header = 'Hawk mac="' + mac + '"' +
-                 (artifacts.hash ? ', hash="' + artifacts.hash + '"' : '');
-
-    if (artifacts.ext !== null &&
-        artifacts.ext !== undefined &&
-        artifacts.ext !== '') {                       // Other falsey values allowed
-
-        header += ', ext="' + Utils.escapeHeaderAttribute(artifacts.ext) + '"';
-    }
-
-    return header;
-};
-
-
-/*
- * Arguments and options are the same as authenticate() with the exception that the only supported options are:
- * 'hostHeaderName', 'localtimeOffsetMsec', 'host', 'port'
- */
-
-exports.authenticateBewit = function (req, credentialsFunc, options, callback) {
-
-    callback = Utils.nextTick(callback);
-
-    // Application time
-
-    var now = Utils.now() + (options.localtimeOffsetMsec || 0);
-
-    // Convert node Http request object to a request configuration object
-
-    var request = Utils.parseRequest(req, options);
-    if (request instanceof Error) {
-        return callback(Boom.badRequest(request.message));
-    }
-
-    // Extract bewit
-
-    //                                 1     2             3           4     
-    var resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/);
-    if (!resource) {
-        return callback(Boom.unauthorized(null, 'Hawk'));
-    }
-
-    // Bewit not empty
-
-    if (!resource[3]) {
-        return callback(Boom.unauthorized('Empty bewit', 'Hawk'));
-    }
-
-    // Verify method is GET
-
-    if (request.method !== 'GET' &&
-        request.method !== 'HEAD') {
-
-        return callback(Boom.unauthorized('Invalid method', 'Hawk'));
-    }
-
-    // No other authentication
-
-    if (request.authorization) {
-        return callback(Boom.badRequest('Multiple authentications', 'Hawk'));
-    }
-
-    // Parse bewit
-
-    var bewitString = Utils.base64urlDecode(resource[3]);
-    if (bewitString instanceof Error) {
-        return callback(Boom.badRequest('Invalid bewit encoding'));
-    }
-
-    // Bewit format: id\exp\mac\ext ('\' is used because it is a reserved header attribute character)
-
-    var bewitParts = bewitString.split('\\');
-    if (!bewitParts ||
-        bewitParts.length !== 4) {
-
-        return callback(Boom.badRequest('Invalid bewit structure'));
-    }
-
-    var bewit = {
-        id: bewitParts[0],
-        exp: parseInt(bewitParts[1], 10),
-        mac: bewitParts[2],
-        ext: bewitParts[3] || ''
-    };
-
-    if (!bewit.id ||
-        !bewit.exp ||
-        !bewit.mac) {
-
-        return callback(Boom.badRequest('Missing bewit attributes'));
-    }
-
-    // Construct URL without bewit
-
-    var url = resource[1];
-    if (resource[4]) {
-        url += resource[2] + resource[4];
-    }
-
-    // Check expiration
-
-    if (bewit.exp * 1000 <= now) {
-        return callback(Boom.unauthorized('Access expired', 'Hawk'), null, bewit);
-    }
-
-    // Fetch Hawk credentials
-
-    credentialsFunc(bewit.id, function (err, credentials) {
-
-        if (err) {
-            return callback(err, credentials || null, bewit.ext);
-        }
-
-        if (!credentials) {
-            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, bewit);
-        }
-
-        if (!credentials.key ||
-            !credentials.algorithm) {
-
-            return callback(Boom.internal('Invalid credentials'), credentials, bewit);
-        }
-
-        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return callback(Boom.internal('Unknown algorithm'), credentials, bewit);
-        }
-
-        // Calculate MAC
-
-        var mac = Crypto.calculateMac('bewit', credentials, {
-            ts: bewit.exp,
-            nonce: '',
-            method: 'GET',
-            resource: url,
-            host: request.host,
-            port: request.port,
-            ext: bewit.ext
-        });
-
-        if (!Cryptiles.fixedTimeComparison(mac, bewit.mac)) {
-            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, bewit);
-        }
-
-        // Successful authentication
-
-        return callback(null, credentials, bewit);
-    });
-};
-
-
-/*
- *  options are the same as authenticate() with the exception that the only supported options are:
- * 'nonceFunc', 'timestampSkewSec', 'localtimeOffsetMsec'
- */
-
-exports.authenticateMessage = function (host, port, message, authorization, credentialsFunc, options, callback) {
-
-    callback = Utils.nextTick(callback);
-    
-    // Default options
-
-    options.nonceFunc = options.nonceFunc || function (nonce, ts, nonceCallback) { return nonceCallback(); };   // No validation
-    options.timestampSkewSec = options.timestampSkewSec || 60;                                                  // 60 seconds
-
-    // Application time
-
-    var now = Utils.now() + (options.localtimeOffsetMsec || 0);                 // Measure now before any other processing
-
-    // Validate authorization
-    
-    if (!authorization.id ||
-        !authorization.ts ||
-        !authorization.nonce ||
-        !authorization.hash ||
-        !authorization.mac) {
-        
-            return callback(Boom.badRequest('Invalid authorization'))
-    }
-
-    // Fetch Hawk credentials
-
-    credentialsFunc(authorization.id, function (err, credentials) {
-
-        if (err) {
-            return callback(err, credentials || null);
-        }
-
-        if (!credentials) {
-            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'));
-        }
-
-        if (!credentials.key ||
-            !credentials.algorithm) {
-
-            return callback(Boom.internal('Invalid credentials'), credentials);
-        }
-
-        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return callback(Boom.internal('Unknown algorithm'), credentials);
-        }
-
-        // Construct artifacts container
-
-        var artifacts = {
-            ts: authorization.ts,
-            nonce: authorization.nonce,
-            host: host,
-            port: port,
-            hash: authorization.hash
-        };
-
-        // Calculate MAC
-
-        var mac = Crypto.calculateMac('message', credentials, artifacts);
-        if (!Cryptiles.fixedTimeComparison(mac, authorization.mac)) {
-            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials);
-        }
-
-        // Check payload hash
-
-        var hash = Crypto.calculatePayloadHash(message, credentials.algorithm);
-        if (!Cryptiles.fixedTimeComparison(hash, authorization.hash)) {
-            return callback(Boom.unauthorized('Bad message hash', 'Hawk'), credentials);
-        }
-
-        // Check nonce
-
-        options.nonceFunc(authorization.nonce, authorization.ts, function (err) {
-
-            if (err) {
-                return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials);
-            }
-
-            // Check timestamp staleness
-
-            if (Math.abs((authorization.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
-                return callback(Boom.unauthorized('Stale timestamp'), credentials);
-            }
-
-            // Successful authentication
-
-            return callback(null, credentials);
-        });
-    });
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/utils.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/utils.js
deleted file mode 100755
index c8938fe8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/lib/utils.js
+++ /dev/null
@@ -1,183 +0,0 @@
-// Load modules
-
-var Hoek = require('hoek');
-var Sntp = require('sntp');
-var Boom = require('boom');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Import Hoek Utilities
-
-internals.import = function () {
-
-    for (var i in Hoek) {
-        if (Hoek.hasOwnProperty(i)) {
-            exports[i] = Hoek[i];
-        }
-    }
-};
-
-internals.import();
-
-
-// Hawk version
-
-exports.version = function () {
-
-    return exports.loadPackage(__dirname + '/..').version;
-};
-
-
-// Extract host and port from request
-
-exports.parseHost = function (req, hostHeaderName) {
-
-    hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
-    var hostHeader = req.headers[hostHeaderName];
-    if (!hostHeader) {
-        return null;
-    }
-
-    var hostHeaderRegex;
-    if (hostHeader[0] === '[') {
-        hostHeaderRegex = /^(?:(?:\r\n)?\s)*(\[[^\]]+\])(?::(\d+))?(?:(?:\r\n)?\s)*$/;      // IPv6
-    }
-    else {
-        hostHeaderRegex = /^(?:(?:\r\n)?\s)*([^:]+)(?::(\d+))?(?:(?:\r\n)?\s)*$/;           // IPv4, hostname
-    }
-    
-    var hostParts = hostHeader.match(hostHeaderRegex);
-
-    if (!hostParts ||
-        hostParts.length !== 3 ||
-        !hostParts[1]) {
-
-        return null;
-    }
-
-    return {
-        name: hostParts[1],
-        port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))
-    };
-};
-
-
-// Parse Content-Type header content
-
-exports.parseContentType = function (header) {
-
-    if (!header) {
-        return '';
-    }
-
-    return header.split(';')[0].trim().toLowerCase();
-};
-
-
-// Convert node's  to request configuration object
-
-exports.parseRequest = function (req, options) {
-
-    if (!req.headers) {
-        return req;
-    }
-    
-    // Obtain host and port information
-
-    if (!options.host || !options.port) {
-        var host = exports.parseHost(req, options.hostHeaderName);
-        if (!host) {
-            return new Error('Invalid Host header');
-        }
-    }
-
-    var request = {
-        method: req.method,
-        url: req.url,
-        host: options.host || host.name,
-        port: options.port || host.port,
-        authorization: req.headers.authorization,
-        contentType: req.headers['content-type'] || ''
-    };
-
-    return request;
-};
-
-
-exports.now = function () {
-
-    return Sntp.now();
-};
-
-
-// Parse Hawk HTTP Authorization header
-
-exports.parseAuthorizationHeader = function (header, keys) {
-
-    keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];
-
-    if (!header) {
-        return Boom.unauthorized(null, 'Hawk');
-    }
-
-    var headerParts = header.match(/^(\w+)(?:\s+(.*))?$/);       // Header: scheme[ something]
-    if (!headerParts) {
-        return Boom.badRequest('Invalid header syntax');
-    }
-
-    var scheme = headerParts[1];
-    if (scheme.toLowerCase() !== 'hawk') {
-        return Boom.unauthorized(null, 'Hawk');
-    }
-
-    var attributesString = headerParts[2];
-    if (!attributesString) {
-        return Boom.badRequest('Invalid header syntax');
-    }
-
-    var attributes = {};
-    var errorMessage = '';
-    var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
-
-        // Check valid attribute names
-
-        if (keys.indexOf($1) === -1) {
-            errorMessage = 'Unknown attribute: ' + $1;
-            return;
-        }
-
-        // Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
-
-        if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {
-            errorMessage = 'Bad attribute value: ' + $1;
-            return;
-        }
-
-        // Check for duplicates
-
-        if (attributes.hasOwnProperty($1)) {
-            errorMessage = 'Duplicate attribute: ' + $1;
-            return;
-        }
-
-        attributes[$1] = $2;
-        return '';
-    });
-
-    if (verify !== '') {
-        return Boom.badRequest(errorMessage || 'Bad header format');
-    }
-
-    return attributes;
-};
-
-
-exports.unauthorized = function (message) {
-
-    return Boom.unauthorized(message, 'Hawk');
-};
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore
deleted file mode 100644
index 77ba16cb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml
deleted file mode 100755
index 047f7e3d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-
-node_js:
-  - 0.10
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE
deleted file mode 100755
index 911b97ee..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2012-2013, Walmart.
-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 Walmart 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 WALMART 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/Makefile
deleted file mode 100755
index 884ec6db..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/README.md
deleted file mode 100755
index 1970b1c4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
-![boom Logo](https://raw.github.com/spumko/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)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/images/boom.png b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/images/boom.png
deleted file mode 100755
index 373bc13455bc0a71a6a4538158aee59c6994b761..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 29479
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

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/index.js
deleted file mode 100755
index 4cc88b35..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('./lib');
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js
deleted file mode 100755
index 0bbeed95..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js
+++ /dev/null
@@ -1,207 +0,0 @@
-// Load modules
-
-var Http = require('http');
-var NodeUtil = require('util');
-var Hoek = require('hoek');
-
-
-// Declare internals
-
-var internals = {};
-
-
-exports = module.exports = internals.Boom = function (/* (new Error) or (code, message) */) {
-
-    var self = this;
-
-    Hoek.assert(this.constructor === internals.Boom, 'Error must be instantiated using new');
-
-    Error.call(this);
-    this.isBoom = true;
-
-    this.response = {
-        code: 0,
-        payload: {},
-        headers: {}
-        // type: 'content-type'
-    };
-
-    if (arguments[0] instanceof Error) {
-
-        // Error
-
-        var error = arguments[0];
-
-        this.data = error;
-        this.response.code = error.code || 500;
-        if (error.message) {
-            this.message = error.message;
-        }
-    }
-    else {
-
-        // code, message
-
-        var code = arguments[0];
-        var message = arguments[1];
-
-        Hoek.assert(!isNaN(parseFloat(code)) && isFinite(code) && code >= 400, 'First argument must be a number (400+)');
-
-        this.response.code = code;
-        if (message) {
-            this.message = message;
-        }
-    }
-
-    // Response format
-
-    this.reformat();
-
-    return this;
-};
-
-NodeUtil.inherits(internals.Boom, Error);
-
-
-internals.Boom.prototype.reformat = function () {
-
-    this.response.payload.code = this.response.code;
-    this.response.payload.error = Http.STATUS_CODES[this.response.code] || 'Unknown';
-    if (this.message) {
-        this.response.payload.message = Hoek.escapeHtml(this.message);         // Prevent XSS from error message
-    }
-};
-
-
-// Utilities
-
-internals.Boom.badRequest = function (message) {
-
-    return new internals.Boom(400, message);
-};
-
-
-internals.Boom.unauthorized = function (message, scheme, attributes) {          // Or function (message, wwwAuthenticate[])
-
-    var err = new internals.Boom(401, message);
-
-    if (!scheme) {
-        return err;
-    }
-
-    var wwwAuthenticate = '';
-
-    if (typeof scheme === 'string') {
-
-        // function (message, scheme, attributes)
-
-        wwwAuthenticate = scheme;
-        if (attributes) {
-            var names = Object.keys(attributes);
-            for (var i = 0, il = names.length; i < il; ++i) {
-                if (i) {
-                    wwwAuthenticate += ',';
-                }
-
-                var value = attributes[names[i]];
-                if (value === null ||
-                    value === undefined) {              // Value can be zero
-
-                    value = '';
-                }
-                wwwAuthenticate += ' ' + names[i] + '="' + Hoek.escapeHeaderAttribute(value.toString()) + '"';
-            }
-        }
-
-        if (message) {
-            if (attributes) {
-                wwwAuthenticate += ',';
-            }
-            wwwAuthenticate += ' error="' + Hoek.escapeHeaderAttribute(message) + '"';
-        }
-        else {
-            err.isMissing = true;
-        }
-    }
-    else {
-
-        // function (message, wwwAuthenticate[])
-
-        var wwwArray = scheme;
-        for (var i = 0, il = wwwArray.length; i < il; ++i) {
-            if (i) {
-                wwwAuthenticate += ', ';
-            }
-
-            wwwAuthenticate += wwwArray[i];
-        }
-    }
-
-    err.response.headers['WWW-Authenticate'] = wwwAuthenticate;
-
-    return err;
-};
-
-
-internals.Boom.clientTimeout = function (message) {
-
-    return new internals.Boom(408, message);
-};
-
-
-internals.Boom.serverTimeout = function (message) {
-
-    return new internals.Boom(503, message);
-};
-
-
-internals.Boom.forbidden = function (message) {
-
-    return new internals.Boom(403, message);
-};
-
-
-internals.Boom.notFound = function (message) {
-
-    return new internals.Boom(404, message);
-};
-
-
-internals.Boom.internal = function (message, data) {
-
-    var err = new internals.Boom(500, message);
-
-    if (data && data.stack) {
-        err.trace = data.stack.split('\n');
-        err.outterTrace = Hoek.displayStack(1);
-    }
-    else {
-        err.trace = Hoek.displayStack(1);
-    }
-
-    err.data = data;
-    err.response.payload.message = 'An internal server error occurred';                     // Hide actual error from user
-
-    return err;
-};
-
-
-internals.Boom.passThrough = function (code, payload, contentType, headers) {
-
-    var err = new internals.Boom(500, 'Pass-through');                                      // 500 code is only used to initialize
-
-    err.data = {
-        code: code,
-        payload: payload,
-        type: contentType
-    };
-
-    err.response.code = code;
-    err.response.type = contentType;
-    err.response.headers = headers;
-    err.response.payload = payload;
-
-    return err;
-};
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/package.json
deleted file mode 100755
index 572ebb76..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/package.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
-  "name": "boom",
-  "description": "HTTP-friendly error objects",
-  "version": "0.4.2",
-  "author": {
-    "name": "Eran Hammer",
-    "email": "eran@hueniverse.com",
-    "url": "http://hueniverse.com"
-  },
-  "contributors": [],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/spumko/boom"
-  },
-  "main": "index",
-  "keywords": [
-    "error",
-    "http"
-  ],
-  "engines": {
-    "node": ">=0.8.0"
-  },
-  "dependencies": {
-    "hoek": "0.9.x"
-  },
-  "devDependencies": {
-    "lab": "0.1.x",
-    "complexity-report": "0.x.x"
-  },
-  "scripts": {
-    "test": "make test-cov"
-  },
-  "licenses": [
-    {
-      "type": "BSD",
-      "url": "http://github.com/spumko/boom/raw/master/LICENSE"
-    }
-  ],
-  "readme": "<a href=\"https://github.com/spumko\"><img src=\"https://raw.github.com/spumko/spumko/master/images/from.png\" align=\"right\" /></a>\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"
-  },
-  "homepage": "https://github.com/spumko/boom",
-  "_id": "boom@0.4.2",
-  "_shasum": "7a636e9ded4efcefb19cef4947a3c67dfaee911b",
-  "_from": "boom@0.4.x",
-  "_resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js
deleted file mode 100755
index a20c1c34..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js
+++ /dev/null
@@ -1,245 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Boom = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Boom', function () {
-
-    it('returns an error with info when constructed using another error', 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: {}
-        });
-        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 code', function (done) {
-
-            expect(Boom.badRequest().response.code).to.equal(400);
-            done();
-        });
-
-        it('sets the message with the passed in message', function (done) {
-
-            expect(Boom.badRequest('my message').message).to.equal('my message');
-            done();
-        });
-    });
-
-    describe('#unauthorized', function () {
-
-        it('returns a 401 error code', function (done) {
-
-            var err = Boom.unauthorized();
-            expect(err.response.code).to.equal(401);
-            expect(err.response.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.response.code).to.equal(401);
-            expect(err.response.headers['WWW-Authenticate']).to.equal('Test error="boom"');
-            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.response.code).to.equal(401);
-            expect(err.response.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"');
-            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.response.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"');
-            done();
-        });
-    });
-
-    describe('#clientTimeout', function () {
-
-        it('returns a 408 error code', function (done) {
-
-            expect(Boom.clientTimeout().response.code).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('#serverTimeout', function () {
-
-        it('returns a 503 error code', function (done) {
-
-            expect(Boom.serverTimeout().response.code).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 code', function (done) {
-
-            expect(Boom.forbidden().response.code).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 code', function (done) {
-
-            expect(Boom.notFound().response.code).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 code', function (done) {
-
-            expect(Boom.internal().response.code).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.response.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('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('#passThrough', function () {
-
-        it('returns a pass-through error', function (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('#reformat', function () {
-
-        it('encodes any HTML markup in the response payload', function (done) {
-
-            var boom = new Boom(new Error('<script>alert(1)</script>'));
-            expect(boom.response.payload.message).to.not.contain('<script>');
-            done();
-        });
-    });
-});
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore
deleted file mode 100644
index b3bb5176..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml
deleted file mode 100755
index 40ca59ee..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-
-node_js:
-  - 0.10
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE
deleted file mode 100755
index e699a7bd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2012-2013, Eran Hammer.
-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 Eran Hammer 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 ERAN HAMMER 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile
deleted file mode 100755
index 9e7138c2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-test:
-	@./node_modules/.bin/lab
-test-cov: 
-	@./node_modules/.bin/lab -r threshold -t 100
-test-cov-html:
-	@./node_modules/.bin/lab -r html -o coverage.html
-complexity:
-	@./node_modules/.bin/cr -o complexity.md -f markdown lib
-
-.PHONY: test test-cov test-cov-html complexity
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md
deleted file mode 100644
index 6a900a49..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-cryptiles
-=========
-
-General purpose crypto utilities
-
-[![Build Status](https://secure.travis-ci.org/hueniverse/cryptiles.png)](http://travis-ci.org/hueniverse/cryptiles)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js
deleted file mode 100755
index 4cc88b35..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('./lib');
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js
deleted file mode 100755
index dcf2bc38..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// Load modules
-
-var Crypto = require('crypto');
-var Boom = require('boom');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Generate a cryptographically strong pseudo-random data
-
-exports.randomString = function (size) {
-
-    var buffer = exports.randomBits((size + 1) * 6);
-    if (buffer instanceof Error) {
-        return buffer;
-    }
-
-    var string = buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
-    return string.slice(0, size);
-};
-
-
-exports.randomBits = function (bits) {
-
-    if (!bits ||
-        bits < 0) {
-
-        return Boom.internal('Invalid random bits count');
-    }
-
-    var bytes = Math.ceil(bits / 8);
-    try {
-        return Crypto.randomBytes(bytes);
-    }
-    catch (err) {
-        return Boom.internal('Failed generating random bits: ' + err.message);
-    }
-};
-
-
-// Compare two strings using fixed time algorithm (to prevent time-based analysis of MAC digest match)
-
-exports.fixedTimeComparison = function (a, b) {
-
-    if (typeof a !== 'string' ||
-        typeof b !== 'string') {
-
-        return false;
-    }
-
-    var mismatch = (a.length === b.length ? 0 : 1);
-    if (mismatch) {
-        b = a;
-    }
-
-    for (var i = 0, il = a.length; i < il; ++i) {
-        var ac = a.charCodeAt(i);
-        var bc = b.charCodeAt(i);
-        mismatch += (ac === bc ? 0 : 1);
-    }
-
-    return (mismatch === 0);
-};
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json
deleted file mode 100755
index 9d0d44d9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-  "name": "cryptiles",
-  "description": "General purpose crypto utilities",
-  "version": "0.2.2",
-  "author": {
-    "name": "Eran Hammer",
-    "email": "eran@hueniverse.com",
-    "url": "http://hueniverse.com"
-  },
-  "contributors": [],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/hueniverse/cryptiles"
-  },
-  "main": "index",
-  "keywords": [
-    "cryptography",
-    "security",
-    "utilites"
-  ],
-  "engines": {
-    "node": ">=0.8.0"
-  },
-  "dependencies": {
-    "boom": "0.4.x"
-  },
-  "devDependencies": {
-    "lab": "0.1.x",
-    "complexity-report": "0.x.x"
-  },
-  "scripts": {
-    "test": "make test-cov"
-  },
-  "licenses": [
-    {
-      "type": "BSD",
-      "url": "http://github.com/hueniverse/cryptiles/raw/master/LICENSE"
-    }
-  ],
-  "readme": "cryptiles\n=========\n\nGeneral purpose crypto utilities\n\n[![Build Status](https://secure.travis-ci.org/hueniverse/cryptiles.png)](http://travis-ci.org/hueniverse/cryptiles)\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/hueniverse/cryptiles/issues"
-  },
-  "homepage": "https://github.com/hueniverse/cryptiles",
-  "_id": "cryptiles@0.2.2",
-  "_shasum": "ed91ff1f17ad13d3748288594f8a48a0d26f325c",
-  "_from": "cryptiles@0.2.x",
-  "_resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js
deleted file mode 100755
index 58aaa70b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js
+++ /dev/null
@@ -1,101 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Cryptiles = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-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();
-        });
-    });
-});
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore
deleted file mode 100644
index 9966e5e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml
deleted file mode 100755
index 40ca59ee..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-
-node_js:
-  - 0.10
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE
deleted file mode 100755
index 394adcff..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE
+++ /dev/null
@@ -1,33 +0,0 @@
-Copyright (c) 2011-2013, Walmart.
-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 Walmart 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 WALMART 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.
-
-
-                                  *   *   *
-
-
-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.
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile
deleted file mode 100755
index e605d6c0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile
+++ /dev/null
@@ -1,10 +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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/README.md
deleted file mode 100755
index ac64e2fd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/README.md
+++ /dev/null
@@ -1,436 +0,0 @@
-<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
-![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)
-
-General purpose node utilities
-
-[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)
-
-# Table of Contents
-
-* [Introduction](#introduction "Introduction")
-* [Object](#object "Object")
-  * [clone](#cloneobj "clone")
-  * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge")
-  * [applyToDefaults](#applytodefaultsdefaults-options "applyToDefaults")
-  * [unique](#uniquearray-key "unique")
-  * [mapToObject](#maptoobjectarray-key "mapToObject")
-  * [intersect](#intersectarray1-array2 "intersect")
-  * [matchKeys](#matchkeysobj-keys "matchKeys")
-  * [flatten](#flattenarray-target "flatten")
-  * [removeKeys](#removekeysobject-keys "removeKeys")
-  * [reach](#reachobj-chain "reach")
-  * [inheritAsync](#inheritasyncself-obj-keys "inheritAsync")
-  * [rename](#renameobj-from-to "rename")
-* [Timer](#timer "Timer")
-* [Binary Encoding/Decoding](#binary "Binary Encoding/Decoding")
-  * [base64urlEncode](#binary64urlEncodevalue "binary64urlEncode")
-  * [base64urlDecode](#binary64urlDecodevalue "binary64urlDecode")
-* [Escaping Characters](#escaped "Escaping Characters")
-  * [escapeHtml](#escapeHtmlstring "escapeHtml")
-  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute "escapeHeaderAttribute")
-  * [escapeRegex](#escapeRegexstring "escapeRegex")
-* [Errors](#errors "Errors")
-  * [assert](#assertmessage "assert")
-  * [abort](#abortmessage "abort")
-  * [displayStack](#displayStackslice "displayStack")
-  * [callStack](#callStackslice "callStack")
-  * [toss](#tosscondition "toss")
-* [Load files](#load-files "Load Files")
-  * [loadPackage](#loadPackagedir "loadpackage")
-  * [loadDirModules](#loadDirModulespath-excludefiles-target "loaddirmodules")
-
-
-
-# Introduction
-
-The *Hoek* general purpose node utilities library is used to aid in a variety of manners. 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). 
-
-```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
-```
-
-### merge(target, source, isNullOverride, isMergeArrays)
-isNullOverride, isMergeArrays default to true
-
-Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
-
-
-```javascript
-
-var target = {a: 1, b : 2}
-var source = {a: 0, c: 5}
-var source2 = {a: null, c: 5}
-
-var targetArray = [1, 2, 3];
-var sourceArray = [4, 5];
-
-var newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}
-newTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}
-newTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}
-
-newTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]
-newTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]
-
-
-
-
-```
-
-### applyToDefaults(defaults, options)
-
-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};
-
-
-```
-
-### 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]
-
-```
-
-### matchKeys(obj, keys) 
-
-Find which keys are present
-
-```javascript
-
-var obj = {a: 1, b: 2, c: 3};
-var keys = ["a", "e"];
-
-Hoek.matchKeys(obj, keys) // returns ["a"]
-
-```
-
-### flatten(array, target)
-
-Flatten an array
-
-```javascript
-
-var array = [1, 2, 3];
-var target = [4, 5]; 
-
-var flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];
-
-```
-
-### removeKeys(object, keys)
-
-Remove keys
-
-```javascript
-
-var object = {a: 1, b: 2, c: 3, d: 4};
-
-var keys = ["a", "b"];
-
-Hoek.removeKeys(object, keys) // object is now {c: 3, d: 4}
-
-```
-
-### reach(obj, chain)
-
-Converts an object key chain string to reference
-
-```javascript
-
-var chain = 'a.b.c';
-var obj = {a : {b : { c : 1}}};
-
-Hoek.reach(obj, chain) // returns 1
-
-```
-
-### inheritAsync(self, obj, keys) 
-
-Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
-
-```javascript
-
-var targetFunc = function () { };
-
-var proto = {
-                a: function () {
-                    return 'a!';
-                },
-                b: function () {
-                    return 'b!';
-                },
-                c: function () {
-                    throw new Error('c!');
-                }
-            };
-
-var keys = ['a', 'c'];
-
-Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
-
-var target = new targetFunc();
-
-target.a(function(err, result){console.log(result)}         // returns 'a!'       
-
-target.c(function(err, result){console.log(result)}         // returns undefined
-
-target.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'
-
-```
-
-### rename(obj, from, to)
-
-Rename a key of an object
-
-```javascript
-
-var obj = {a : 1, b : 2};
-
-Hoek.rename(obj, "a", "c");     // obj is now {c : 1, b : 2}
-
-```
-
-
-# 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
-
-
-example : 
-
-
-var timerObj = new Hoek.Timer();
-console.log("Time is now: " + timerObj.ts)
-console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds')
-
-```
-
-# 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 = {
-    '&': '&amp;',
-    '<': '&lt;',
-    '>': '&gt;',
-    '"': '&quot;',
-    "'": '&#x27;',
-    '`': '&#x60;'
-};
-
-```
-
-### escapeHtml(string)
-
-```javascript
-
-var string = '<html> hey </html>';
-var escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;
-
-```
-
-### 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(message)
-
-```javascript
-
-var a = 1, b =2;
-
-Hoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b
-
-```
-
-### 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 ] ]
-
-
-```
-
-### toss(condition)
-
-toss(condition /*, [message], callback */)
-
-Return an error as first argument of a callback
-
-
-# Load Files
-
-### loadPackage(dir)
-
-Load and parse package.json process root or given directory
-
-```javascript
-
-var pack = Hoek.loadPackage();  // pack.name === 'hoek'
-
-```
-
-### loadDirModules(path, excludeFiles, target) 
-
-Loads modules from a given path; option to exclude files (array).
-
-
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/images/hoek.png b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/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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

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/index.js
deleted file mode 100755
index 4cc88b35..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('./lib');
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js
deleted file mode 100755
index 666b3dc8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js
+++ /dev/null
@@ -1,132 +0,0 @@
-// Declare internals
-
-var internals = {};
-
-
-exports.escapeJavaScript = function (input) {
-
-    if (!input) {
-        return '';
-    }
-
-    var escaped = '';
-
-    for (var i = 0, il = input.length; i < il; ++i) {
-
-        var charCode = input.charCodeAt(i);
-
-        if (internals.isSafe(charCode)) {
-            escaped += input[i];
-        }
-        else {
-            escaped += internals.escapeJavaScriptChar(charCode);
-        }
-    }
-
-    return escaped;
-};
-
-
-exports.escapeHtml = function (input) {
-
-    if (!input) {
-        return '';
-    }
-
-    var escaped = '';
-
-    for (var i = 0, il = input.length; i < il; ++i) {
-
-        var charCode = input.charCodeAt(i);
-
-        if (internals.isSafe(charCode)) {
-            escaped += input[i];
-        }
-        else {
-            escaped += internals.escapeHtmlChar(charCode);
-        }
-    }
-
-    return escaped;
-};
-
-
-internals.escapeJavaScriptChar = function (charCode) {
-
-    if (charCode >= 256) {
-        return '\\u' + internals.padLeft('' + charCode, 4);
-    }
-
-    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
-    return '\\x' + internals.padLeft(hexValue, 2);
-};
-
-
-internals.escapeHtmlChar = function (charCode) {
-
-    var namedEscape = internals.namedHtml[charCode];
-    if (typeof namedEscape !== 'undefined') {
-        return namedEscape;
-    }
-
-    if (charCode >= 256) {
-        return '&#' + charCode + ';';
-    }
-
-    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
-    return '&#x' + internals.padLeft(hexValue, 2) + ';';
-};
-
-
-internals.padLeft = function (str, len) {
-
-    while (str.length < len) {
-        str = '0' + str;
-    }
-
-    return str;
-};
-
-
-internals.isSafe = function (charCode) {
-
-    return (typeof internals.safeCharCodes[charCode] !== 'undefined');
-};
-
-
-internals.namedHtml = {
-    '38': '&amp;',
-    '60': '&lt;',
-    '62': '&gt;',
-    '34': '&quot;',
-    '160': '&nbsp;',
-    '162': '&cent;',
-    '163': '&pound;',
-    '164': '&curren;',
-    '169': '&copy;',
-    '174': '&reg;'
-};
-
-
-internals.safeCharCodes = (function () {
-
-    var safe = {};
-
-    for (var i = 32; i < 123; ++i) {
-
-        if ((i >= 97 && i <= 122) ||         // a-z
-            (i >= 65 && i <= 90) ||          // A-Z
-            (i >= 48 && i <= 57) ||          // 0-9
-            i === 32 ||                      // space
-            i === 46 ||                      // .
-            i === 44 ||                      // ,
-            i === 45 ||                      // -
-            i === 58 ||                      // :
-            i === 95) {                      // _
-
-            safe[i] = null;
-        }
-    }
-
-    return safe;
-}());
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js
deleted file mode 100755
index 806260d2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js
+++ /dev/null
@@ -1,585 +0,0 @@
-// Load modules
-
-var Fs = require('fs');
-var Escape = require('./escape');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Clone object or array
-
-exports.clone = function (obj, seen) {
-
-    if (typeof obj !== 'object' ||
-        obj === null) {
-
-        return obj;
-    }
-
-    seen = seen || { orig: [], copy: [] };
-
-    var lookup = seen.orig.indexOf(obj);
-    if (lookup !== -1) {
-        return seen.copy[lookup];
-    }
-
-    var newObj = (obj instanceof Array) ? [] : {};
-
-    seen.orig.push(obj);
-    seen.copy.push(newObj);
-
-    for (var i in obj) {
-        if (obj.hasOwnProperty(i)) {
-            if (obj[i] instanceof Buffer) {
-                newObj[i] = new Buffer(obj[i]);
-            }
-            else if (obj[i] instanceof Date) {
-                newObj[i] = new Date(obj[i].getTime());
-            }
-            else if (obj[i] instanceof RegExp) {
-                var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
-                newObj[i] = new RegExp(obj[i].source, flags);
-            }
-            else {
-                newObj[i] = exports.clone(obj[i], seen);
-            }
-        }
-    }
-
-    return newObj;
-};
-
-
-// Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
-
-exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
-
-    exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
-    exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
-
-    if (!source) {
-        return target;
-    }
-
-    if (source instanceof Array) {
-        exports.assert(target instanceof Array, 'Cannot merge array onto an object');
-        if (isMergeArrays === false) {                                                  // isMergeArrays defaults to true
-            target.length = 0;                                                          // Must not change target assignment
-        }
-
-        for (var i = 0, il = source.length; i < il; ++i) {
-            target.push(source[i]);
-        }
-
-        return target;
-    }
-
-    var keys = Object.keys(source);
-    for (var k = 0, kl = keys.length; k < kl; ++k) {
-        var key = keys[k];
-        var value = source[key];
-        if (value &&
-            typeof value === 'object') {
-
-            if (!target[key] ||
-                typeof target[key] !== 'object') {
-
-                target[key] = exports.clone(value);
-            }
-            else {
-                exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
-            }
-        }
-        else {
-            if (value !== null && value !== undefined) {            // Explicit to preserve empty strings
-                target[key] = value;
-            }
-            else if (isNullOverride !== false) {                    // Defaults to true
-                target[key] = value;
-            }
-        }
-    }
-
-    return target;
-};
-
-
-// Apply options to a copy of the defaults
-
-exports.applyToDefaults = function (defaults, options) {
-
-    exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
-    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
-
-    if (!options) {                                                 // If no options, return null
-        return null;
-    }
-
-    var copy = exports.clone(defaults);
-
-    if (options === true) {                                         // If options is set to true, use defaults
-        return copy;
-    }
-
-    return exports.merge(copy, options, false, false);
-};
-
-
-// Remove duplicate items from array
-
-exports.unique = function (array, key) {
-
-    var index = {};
-    var result = [];
-
-    for (var i = 0, il = array.length; i < il; ++i) {
-        var id = (key ? array[i][key] : array[i]);
-        if (index[id] !== true) {
-
-            result.push(array[i]);
-            index[id] = true;
-        }
-    }
-
-    return result;
-};
-
-
-// Convert array into object
-
-exports.mapToObject = function (array, key) {
-
-    if (!array) {
-        return null;
-    }
-
-    var obj = {};
-    for (var i = 0, il = array.length; i < il; ++i) {
-        if (key) {
-            if (array[i][key]) {
-                obj[array[i][key]] = true;
-            }
-        }
-        else {
-            obj[array[i]] = true;
-        }
-    }
-
-    return obj;
-};
-
-
-// Find the common unique items in two arrays
-
-exports.intersect = function (array1, array2, justFirst) {
-
-    if (!array1 || !array2) {
-        return [];
-    }
-
-    var common = [];
-    var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
-    var found = {};
-    for (var i = 0, il = array2.length; i < il; ++i) {
-        if (hash[array2[i]] && !found[array2[i]]) {
-            if (justFirst) {
-                return array2[i];
-            }
-
-            common.push(array2[i]);
-            found[array2[i]] = true;
-        }
-    }
-
-    return (justFirst ? null : common);
-};
-
-
-// Find which keys are present
-
-exports.matchKeys = function (obj, keys) {
-
-    var matched = [];
-    for (var i = 0, il = keys.length; i < il; ++i) {
-        if (obj.hasOwnProperty(keys[i])) {
-            matched.push(keys[i]);
-        }
-    }
-    return matched;
-};
-
-
-// Flatten array
-
-exports.flatten = function (array, target) {
-
-    var result = target || [];
-
-    for (var i = 0, il = array.length; i < il; ++i) {
-        if (Array.isArray(array[i])) {
-            exports.flatten(array[i], result);
-        }
-        else {
-            result.push(array[i]);
-        }
-    }
-
-    return result;
-};
-
-
-// Remove keys
-
-exports.removeKeys = function (object, keys) {
-
-    for (var i = 0, il = keys.length; i < il; i++) {
-        delete object[keys[i]];
-    }
-};
-
-
-// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
-
-exports.reach = function (obj, chain) {
-
-    var path = chain.split('.');
-    var ref = obj;
-    for (var i = 0, il = path.length; i < il; ++i) {
-        if (ref) {
-            ref = ref[path[i]];
-        }
-    }
-
-    return ref;
-};
-
-
-// Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
-
-exports.inheritAsync = function (self, obj, keys) {
-
-    keys = keys || null;
-
-    for (var i in obj) {
-        if (obj.hasOwnProperty(i)) {
-            if (keys instanceof Array &&
-                keys.indexOf(i) < 0) {
-
-                continue;
-            }
-
-            self.prototype[i] = (function (fn) {
-
-                return function (next) {
-
-                    var result = null;
-                    try {
-                        result = fn();
-                    }
-                    catch (err) {
-                        return next(err);
-                    }
-
-                    return next(null, result);
-                };
-            })(obj[i]);
-        }
-    }
-};
-
-
-exports.formatStack = function (stack) {
-
-    var trace = [];
-    for (var i = 0, il = stack.length; i < il; ++i) {
-        var item = stack[i];
-        trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
-    }
-
-    return trace;
-};
-
-
-exports.formatTrace = function (trace) {
-
-    var display = [];
-
-    for (var i = 0, il = trace.length; i < il; ++i) {
-        var row = trace[i];
-        display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
-    }
-
-    return display;
-};
-
-
-exports.callStack = function (slice) {
-
-    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
-
-    var v8 = Error.prepareStackTrace;
-    Error.prepareStackTrace = function (err, stack) {
-
-        return stack;
-    };
-
-    var capture = {};
-    Error.captureStackTrace(capture, arguments.callee);
-    var stack = capture.stack;
-
-    Error.prepareStackTrace = v8;
-
-    var trace = exports.formatStack(stack);
-
-    if (slice) {
-        return trace.slice(slice);
-    }
-
-    return trace;
-};
-
-
-exports.displayStack = function (slice) {
-
-    var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
-
-    return exports.formatTrace(trace);
-};
-
-
-exports.abortThrow = false;
-
-
-exports.abort = function (message, hideStack) {
-
-    if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
-        throw new Error(message || 'Unknown error');
-    }
-
-    var stack = '';
-    if (!hideStack) {
-        stack = exports.displayStack(1).join('\n\t');
-    }
-    console.log('ABORT: ' + message + '\n\t' + stack);
-    process.exit(1);
-};
-
-
-exports.assert = function (condition /*, msg1, msg2, msg3 */) {
-
-    if (condition) {
-        return;
-    }
-
-    var msgs = Array.prototype.slice.call(arguments, 1);
-    msgs = msgs.map(function (msg) {
-
-        return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : JSON.stringify(msg);
-    });
-    throw new Error(msgs.join(' ') || 'Unknown error');
-};
-
-
-exports.loadDirModules = function (path, excludeFiles, target) {      // target(filename, name, capName)
-
-    var exclude = {};
-    for (var i = 0, il = excludeFiles.length; i < il; ++i) {
-        exclude[excludeFiles[i] + '.js'] = true;
-    }
-
-    var files = Fs.readdirSync(path);
-    for (i = 0, il = files.length; i < il; ++i) {
-        var filename = files[i];
-        if (/\.js$/.test(filename) &&
-            !exclude[filename]) {
-
-            var name = filename.substr(0, filename.lastIndexOf('.'));
-            var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();
-
-            if (typeof target !== 'function') {
-                target[capName] = require(path + '/' + name);
-            }
-            else {
-                target(path + '/' + name, name, capName);
-            }
-        }
-    }
-};
-
-
-exports.rename = function (obj, from, to) {
-
-    obj[to] = obj[from];
-    delete obj[from];
-};
-
-
-exports.Timer = function () {
-
-    this.reset();
-};
-
-
-exports.Timer.prototype.reset = function () {
-
-    this.ts = Date.now();
-};
-
-
-exports.Timer.prototype.elapsed = function () {
-
-    return Date.now() - this.ts;
-};
-
-
-// Load and parse package.json process root or given directory
-
-exports.loadPackage = function (dir) {
-
-    var result = {};
-    var filepath = (dir || process.env.PWD) + '/package.json';
-    if (Fs.existsSync(filepath)) {
-        try {
-            result = JSON.parse(Fs.readFileSync(filepath));
-        }
-        catch (e) { }
-    }
-
-    return result;
-};
-
-
-// Escape string for Regex construction
-
-exports.escapeRegex = function (string) {
-
-    // Escape ^$.*+-?=!:|\/()[]{},
-    return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
-};
-
-
-// Return an error as first argument of a callback
-
-exports.toss = function (condition /*, [message], next */) {
-
-    var message = (arguments.length === 3 ? arguments[1] : '');
-    var next = (arguments.length === 3 ? arguments[2] : arguments[1]);
-
-    var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));
-
-    if (condition instanceof Error ||
-        !condition) {
-
-        return next(err);
-    }
-};
-
-
-// Base64url (RFC 4648) encode
-
-exports.base64urlEncode = function (value) {
-
-    return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
-};
-
-
-// Base64url (RFC 4648) decode
-
-exports.base64urlDecode = function (encoded) {
-
-    if (encoded &&
-        !encoded.match(/^[\w\-]*$/)) {
-
-        return new Error('Invalid character');
-    }
-
-    try {
-        return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
-    }
-    catch (err) {
-        return err;
-    }
-};
-
-
-// Escape attribute value for use in HTTP header
-
-exports.escapeHeaderAttribute = function (attribute) {
-
-    // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
-
-    exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');
-
-    return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');                             // Escape quotes and slash
-};
-
-
-exports.escapeHtml = function (string) {
-
-    return Escape.escapeHtml(string);
-};
-
-
-exports.escapeJavaScript = function (string) {
-
-    return Escape.escapeJavaScript(string);
-};
-
-
-/*
-var event = {
-    timestamp: now.getTime(),
-    tags: ['tag'],
-    data: { some: 'data' }
-};
-*/
-
-exports.consoleFunc = console.log;
-
-exports.printEvent = function (event) {
-
-    var pad = function (value) {
-
-        return (value < 10 ? '0' : '') + value;
-    };
-
-    var now = new Date(event.timestamp);
-    var timestring = (now.getYear() - 100).toString() +
-        pad(now.getMonth() + 1) +
-        pad(now.getDate()) +
-        '/' +
-        pad(now.getHours()) +
-        pad(now.getMinutes()) +
-        pad(now.getSeconds()) +
-        '.' +
-        now.getMilliseconds();
-
-    var data = event.data;
-    if (typeof event.data !== 'string') {
-        try {
-            data = JSON.stringify(event.data);
-        }
-        catch (e) {
-            data = 'JSON Error: ' + e.message;
-        }
-    }
-
-    var output = timestring + ', ' + event.tags[0] + ', ' + data;
-    exports.consoleFunc(output);
-};
-
-
-exports.nextTick = function (callback) {
-
-    return function () {
-
-        var args = arguments;
-        process.nextTick(function () {
-
-            callback.apply(null, args);
-        });
-    };
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/package.json
deleted file mode 100755
index 9930eed3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/package.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "name": "hoek",
-  "description": "General purpose node utilities",
-  "version": "0.9.1",
-  "author": {
-    "name": "Eran Hammer",
-    "email": "eran@hueniverse.com",
-    "url": "http://hueniverse.com"
-  },
-  "contributors": [
-    {
-      "name": "Van Nguyen",
-      "email": "the.gol.effect@gmail.com"
-    }
-  ],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/spumko/hoek"
-  },
-  "main": "index",
-  "keywords": [
-    "utilities"
-  ],
-  "engines": {
-    "node": ">=0.8.0"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "lab": "0.1.x",
-    "complexity-report": "0.x.x"
-  },
-  "scripts": {
-    "test": "make test-cov"
-  },
-  "licenses": [
-    {
-      "type": "BSD",
-      "url": "http://github.com/spumko/hoek/raw/master/LICENSE"
-    }
-  ],
-  "readme": "<a href=\"https://github.com/spumko\"><img src=\"https://raw.github.com/spumko/spumko/master/images/from.png\" align=\"right\" /></a>\r\n![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)\r\n\r\nGeneral purpose node utilities\r\n\r\n[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)\r\n\r\n# Table of Contents\r\n\r\n* [Introduction](#introduction \"Introduction\")\r\n* [Object](#object \"Object\")\r\n  * [clone](#cloneobj \"clone\")\r\n  * [merge](#mergetarget-source-isnulloverride-ismergearrays \"merge\")\r\n  * [applyToDefaults](#applytodefaultsdefaults-options \"applyToDefaults\")\r\n  * [unique](#uniquearray-key \"unique\")\r\n  * [mapToObject](#maptoobjectarray-key \"mapToObject\")\r\n  * [intersect](#intersectarray1-array2 \"intersect\")\r\n  * [matchKeys](#matchkeysobj-keys \"matchKeys\")\r\n  * [flatten](#flattenarray-target \"flatten\")\r\n  * [removeKeys](#removekeysobject-keys \"removeKeys\")\r\n  * [reach](#reachobj-chain \"reach\")\r\n  * [inheritAsync](#inheritasyncself-obj-keys \"inheritAsync\")\r\n  * [rename](#renameobj-from-to \"rename\")\r\n* [Timer](#timer \"Timer\")\r\n* [Binary Encoding/Decoding](#binary \"Binary Encoding/Decoding\")\r\n  * [base64urlEncode](#binary64urlEncodevalue \"binary64urlEncode\")\r\n  * [base64urlDecode](#binary64urlDecodevalue \"binary64urlDecode\")\r\n* [Escaping Characters](#escaped \"Escaping Characters\")\r\n  * [escapeHtml](#escapeHtmlstring \"escapeHtml\")\r\n  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute \"escapeHeaderAttribute\")\r\n  * [escapeRegex](#escapeRegexstring \"escapeRegex\")\r\n* [Errors](#errors \"Errors\")\r\n  * [assert](#assertmessage \"assert\")\r\n  * [abort](#abortmessage \"abort\")\r\n  * [displayStack](#displayStackslice \"displayStack\")\r\n  * [callStack](#callStackslice \"callStack\")\r\n  * [toss](#tosscondition \"toss\")\r\n* [Load files](#load-files \"Load Files\")\r\n  * [loadPackage](#loadPackagedir \"loadpackage\")\r\n  * [loadDirModules](#loadDirModulespath-excludefiles-target \"loaddirmodules\")\r\n\r\n\r\n\r\n# Introduction\r\n\r\nThe *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. \r\n\r\nFor example, to use Hoek to set configuration with default options:\r\n```javascript\r\nvar Hoek = require('hoek');\r\n\r\nvar default = {url : \"www.github.com\", port : \"8000\", debug : true}\r\n\r\nvar config = Hoek.applyToDefaults(default, {port : \"3000\", admin : true});\r\n\r\n// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }\r\n```\r\n\r\nUnder 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.\r\n\r\n## Object\r\n\r\nHoek provides several helpful methods for objects and arrays.\r\n\r\n### clone(obj)\r\n\r\nThis method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects). \r\n\r\n```javascript\r\n\r\nvar nestedObj = {\r\n        w: /^something$/ig,\r\n        x: {\r\n            a: [1, 2, 3],\r\n            b: 123456,\r\n            c: new Date()\r\n        },\r\n        y: 'y',\r\n        z: new Date()\r\n    };\r\n\r\nvar copy = Hoek.clone(nestedObj);\r\n\r\ncopy.x.b = 100;\r\n\r\nconsole.log(copy.y)        // results in 'y'\r\nconsole.log(nestedObj.x.b) // results in 123456\r\nconsole.log(copy.x.b)      // results in 100\r\n```\r\n\r\n### merge(target, source, isNullOverride, isMergeArrays)\r\nisNullOverride, isMergeArrays default to true\r\n\r\nMerge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied\r\n\r\n\r\n```javascript\r\n\r\nvar target = {a: 1, b : 2}\r\nvar source = {a: 0, c: 5}\r\nvar source2 = {a: null, c: 5}\r\n\r\nvar targetArray = [1, 2, 3];\r\nvar sourceArray = [4, 5];\r\n\r\nvar newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}\r\n\r\nnewTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]\r\nnewTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]\r\n\r\n\r\n\r\n\r\n```\r\n\r\n### applyToDefaults(defaults, options)\r\n\r\nApply options to a copy of the defaults\r\n\r\n```javascript\r\n\r\nvar defaults = {host: \"localhost\", port: 8000};\r\nvar options = {port: 8080};\r\n\r\nvar config = Hoek.applyToDefaults(defaults, options); // results in {host: \"localhost\", port: 8080};\r\n\r\n\r\n```\r\n\r\n### unique(array, key)\r\n\r\nRemove duplicate items from Array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 2, 3, 3, 4, 5, 6];\r\n\r\nvar newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];\r\n\r\narray = [{id: 1}, {id: 1}, {id: 2}];\r\n\r\nnewArray = Hoek.unique(array, \"id\") // results in [{id: 1}, {id: 2}]\r\n\r\n```\r\n\r\n### mapToObject(array, key)\r\n\r\nConvert an Array into an Object\r\n\r\n```javascript\r\n\r\nvar array = [1,2,3];\r\nvar newObject = Hoek.mapToObject(array); // results in [{\"1\": true}, {\"2\": true}, {\"3\": true}]\r\n\r\narray = [{id: 1}, {id: 2}];\r\nnewObject = Hoek.mapToObject(array, \"id\") // results in [{\"id\": 1}, {\"id\": 2}]\r\n\r\n```\r\n### intersect(array1, array2)\r\n\r\nFind the common unique items in two arrays\r\n\r\n```javascript\r\n\r\nvar array1 = [1, 2, 3];\r\nvar array2 = [1, 4, 5];\r\n\r\nvar newArray = Hoek.intersect(array1, array2) // results in [1]\r\n\r\n```\r\n\r\n### matchKeys(obj, keys) \r\n\r\nFind which keys are present\r\n\r\n```javascript\r\n\r\nvar obj = {a: 1, b: 2, c: 3};\r\nvar keys = [\"a\", \"e\"];\r\n\r\nHoek.matchKeys(obj, keys) // returns [\"a\"]\r\n\r\n```\r\n\r\n### flatten(array, target)\r\n\r\nFlatten an array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 3];\r\nvar target = [4, 5]; \r\n\r\nvar flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];\r\n\r\n```\r\n\r\n### removeKeys(object, keys)\r\n\r\nRemove keys\r\n\r\n```javascript\r\n\r\nvar object = {a: 1, b: 2, c: 3, d: 4};\r\n\r\nvar keys = [\"a\", \"b\"];\r\n\r\nHoek.removeKeys(object, keys) // object is now {c: 3, d: 4}\r\n\r\n```\r\n\r\n### reach(obj, chain)\r\n\r\nConverts an object key chain string to reference\r\n\r\n```javascript\r\n\r\nvar chain = 'a.b.c';\r\nvar obj = {a : {b : { c : 1}}};\r\n\r\nHoek.reach(obj, chain) // returns 1\r\n\r\n```\r\n\r\n### inheritAsync(self, obj, keys) \r\n\r\nInherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors\r\n\r\n```javascript\r\n\r\nvar targetFunc = function () { };\r\n\r\nvar proto = {\r\n                a: function () {\r\n                    return 'a!';\r\n                },\r\n                b: function () {\r\n                    return 'b!';\r\n                },\r\n                c: function () {\r\n                    throw new Error('c!');\r\n                }\r\n            };\r\n\r\nvar keys = ['a', 'c'];\r\n\r\nHoek.inheritAsync(targetFunc, proto, ['a', 'c']);\r\n\r\nvar target = new targetFunc();\r\n\r\ntarget.a(function(err, result){console.log(result)}         // returns 'a!'       \r\n\r\ntarget.c(function(err, result){console.log(result)}         // returns undefined\r\n\r\ntarget.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'\r\n\r\n```\r\n\r\n### rename(obj, from, to)\r\n\r\nRename a key of an object\r\n\r\n```javascript\r\n\r\nvar obj = {a : 1, b : 2};\r\n\r\nHoek.rename(obj, \"a\", \"c\");     // obj is now {c : 1, b : 2}\r\n\r\n```\r\n\r\n\r\n# Timer\r\n\r\nA Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.\r\n\r\n```javascript\r\n\r\n\r\nexample : \r\n\r\n\r\nvar timerObj = new Hoek.Timer();\r\nconsole.log(\"Time is now: \" + timerObj.ts)\r\nconsole.log(\"Elapsed time from initialization: \" + timerObj.elapsed() + 'milliseconds')\r\n\r\n```\r\n\r\n# Binary Encoding/Decoding\r\n\r\n### base64urlEncode(value)\r\n\r\nEncodes value in Base64 or URL encoding\r\n\r\n### base64urlDecode(value)\r\n\r\nDecodes data in Base64 or URL encoding.\r\n# Escaping Characters\r\n\r\nHoek provides convenient methods for escaping html characters. The escaped characters are as followed:\r\n\r\n```javascript\r\n\r\ninternals.htmlEscaped = {\r\n    '&': '&amp;',\r\n    '<': '&lt;',\r\n    '>': '&gt;',\r\n    '\"': '&quot;',\r\n    \"'\": '&#x27;',\r\n    '`': '&#x60;'\r\n};\r\n\r\n```\r\n\r\n### escapeHtml(string)\r\n\r\n```javascript\r\n\r\nvar string = '<html> hey </html>';\r\nvar escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;\r\n\r\n```\r\n\r\n### escapeHeaderAttribute(attribute)\r\n\r\nEscape attribute value for use in HTTP header\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeHeaderAttribute('I said \"go w\\\\o me\"');  //returns I said \\\"go w\\\\o me\\\"\r\n\r\n\r\n```\r\n\r\n\r\n### escapeRegex(string)\r\n\r\nEscape string for Regex construction\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\\\/`\"(>)[<]d{}s,');  // returns 4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`\"\\(>\\)\\[<\\]d\\{\\}s\\,\r\n\r\n\r\n\r\n```\r\n\r\n# Errors\r\n\r\n### assert(message)\r\n\r\n```javascript\r\n\r\nvar a = 1, b =2;\r\n\r\nHoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b\r\n\r\n```\r\n\r\n### abort(message)\r\n\r\nFirst checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,\r\ndisplays most recent stack and then exits process.\r\n\r\n\r\n\r\n### displayStack(slice)\r\n\r\nDisplays the trace stack\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.displayStack();\r\nconsole.log(stack) // returns something like:\r\n\r\n[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',\r\n  'Module._compile (module.js:449:26)',\r\n  'Module._extensions..js (module.js:467:10)',\r\n  'Module.load (module.js:356:32)',\r\n  'Module._load (module.js:312:12)',\r\n  'Module.runMain (module.js:492:10)',\r\n  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]\r\n\r\n```\r\n\r\n### callStack(slice)\r\n\r\nReturns a trace stack array.\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.callStack();\r\nconsole.log(stack)  // returns something like:\r\n\r\n[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],\r\n  [ 'module.js', 449, 26, 'Module._compile', false ],\r\n  [ 'module.js', 467, 10, 'Module._extensions..js', false ],\r\n  [ 'module.js', 356, 32, 'Module.load', false ],\r\n  [ 'module.js', 312, 12, 'Module._load', false ],\r\n  [ 'module.js', 492, 10, 'Module.runMain', false ],\r\n  [ 'node.js',\r\n    244,\r\n    9,\r\n    'startup.processNextTick.process._tickCallback',\r\n    false ] ]\r\n\r\n\r\n```\r\n\r\n### toss(condition)\r\n\r\ntoss(condition /*, [message], callback */)\r\n\r\nReturn an error as first argument of a callback\r\n\r\n\r\n# Load Files\r\n\r\n### loadPackage(dir)\r\n\r\nLoad and parse package.json process root or given directory\r\n\r\n```javascript\r\n\r\nvar pack = Hoek.loadPackage();  // pack.name === 'hoek'\r\n\r\n```\r\n\r\n### loadDirModules(path, excludeFiles, target) \r\n\r\nLoads modules from a given path; option to exclude files (array).\r\n\r\n\r\n\r\n\r\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/spumko/hoek/issues"
-  },
-  "homepage": "https://github.com/spumko/hoek",
-  "_id": "hoek@0.9.1",
-  "_shasum": "3d322462badf07716ea7eb85baf88079cddce505",
-  "_from": "hoek@0.9.x",
-  "_resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js
deleted file mode 100644
index 4dddd77d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js
+++ /dev/null
@@ -1,86 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Hoek = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hoek', function () {
-
-    describe('#escapeJavaScript', function () {
-
-        it('encodes / characters', function (done) {
-
-            var encoded = Hoek.escapeJavaScript('<script>alert(1)</script>');
-            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('<script>alert(1)</script>');
-            expect(encoded).to.equal('&lt;script&gt;alert&#x28;1&#x29;&lt;&#x2f;script&gt;');
-            done();
-        });
-
-        it('encodes < and > as named characters', function (done) {
-
-            var encoded = Hoek.escapeHtml('<script><>');
-            expect(encoded).to.equal('&lt;script&gt;&lt;&gt;');
-            done();
-        });
-
-        it('encodes large unicode characters', function (done) {
-
-            var encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000));
-            expect(encoded).to.equal('&#500;&#1000;');
-            done();
-        });
-
-        it('doesn\'t throw an exception when passed null', function (done) {
-
-            var encoded = Hoek.escapeHtml(null);
-            expect(encoded).to.equal('');
-            done();
-        });
-    });
-});
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js
deleted file mode 100755
index c40e3ad9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js
+++ /dev/null
@@ -1,1078 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Hoek = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hoek', function () {
-
-    var nestedObj = {
-        v: [7,8,9],
-        w: /^something$/igm,
-        x: {
-            a: [1, 2, 3],
-            b: 123456,
-            c: new Date(),
-            d: /hi/igm,
-            e: /hello/
-        },
-        y: 'y',
-        z: new Date()
-    };
-
-    var dupsArray = [nestedObj, { z: 'z' }, nestedObj];
-    var reducedDupsArray = [nestedObj, { z: 'z' }];
-
-    describe('#clone', function () {
-
-        it('should clone a nested object', function (done) {
-
-            var a = nestedObj;
-            var b = Hoek.clone(a);
-
-            expect(a).to.deep.equal(b);
-            expect(a.z.getTime()).to.equal(b.z.getTime());
-            done();
-        });
-
-        it('should clone a null object', function (done) {
-
-            var b = Hoek.clone(null);
-
-            expect(b).to.equal(null);
-            done();
-        });
-
-        it('should not convert undefined properties to null', function (done) {
-
-            var obj = { something: undefined };
-            var b = Hoek.clone(obj);
-
-            expect(typeof b.something).to.equal('undefined');
-            done();
-        });
-
-        it('should not throw on circular reference', function (done) {
-
-            var a = {};
-            a.x = a;
-
-            var test = (function () {
-
-                var b = Hoek.clone(a);
-            });
-
-            expect(test).to.not.throw();
-            done();
-        });
-
-        it('should properly clone circular reference', function (done) {
-
-            var x = {
-                'z': new Date()
-            };
-            x.y = x;
-
-            var b = Hoek.clone(x);
-            expect(Object.keys(b.y)).to.deep.equal(Object.keys(x))
-            expect(b.z).to.not.equal(x.z);
-            expect(b.y).to.not.equal(x.y);
-            expect(b.y.z).to.not.equal(x.y.z);
-            expect(b.y).to.equal(b);
-            expect(b.y.y.y.y).to.equal(b);
-            done();
-        });
-
-        it('should properly clone deeply nested object', function (done) {
-
-            var a = {
-                x: {
-                    y: {
-                        a: [1, 2, 3],
-                        b: 123456,
-                        c: new Date(),
-                        d: /hi/igm,
-                        e: /hello/
-                    },
-                }
-            };
-
-            var b = Hoek.clone(a);
-
-            expect(a).to.deep.equal(b);
-            expect(a.x.y.c.getTime()).to.equal(b.x.y.c.getTime());
-            done();
-        });
-
-        it('should properly clone arrays', function (done) {
-
-            var a = [1,2,3];
-
-            var b = Hoek.clone(a);
-
-            expect(a).to.deep.equal(b);
-            done();
-        });
-
-        it('should perform actual copy for shallow keys (no pass by reference)', function (done) {
-
-            var x = Hoek.clone(nestedObj);
-            var y = Hoek.clone(nestedObj);
-
-            // Date
-            expect(x.z).to.not.equal(nestedObj.z);
-            expect(x.z).to.not.equal(y.z);
-
-            // Regex
-            expect(x.w).to.not.equal(nestedObj.w);
-            expect(x.w).to.not.equal(y.w);
-
-            // Array
-            expect(x.v).to.not.equal(nestedObj.v);
-            expect(x.v).to.not.equal(y.v);
-
-            // Immutable(s)
-            x.y = 5;
-            expect(x.y).to.not.equal(nestedObj.y);
-            expect(x.y).to.not.equal(y.y);
-
-            done();
-        });
-
-        it('should perform actual copy for deep keys (no pass by reference)', function (done) {
-
-            var x = Hoek.clone(nestedObj);
-            var y = Hoek.clone(nestedObj);
-
-            expect(x.x.c).to.not.equal(nestedObj.x.c);
-            expect(x.x.c).to.not.equal(y.x.c);
-
-            expect(x.x.c.getTime()).to.equal(nestedObj.x.c.getTime());
-            expect(x.x.c.getTime()).to.equal(y.x.c.getTime());
-            done();
-        });
-
-        it('copies functions with properties', function (done) {
-
-            var a = {
-                x: function () { return 1; },
-                y: {}
-            };
-            a.x.z = 'string in function';
-            a.x.v = function () { return 2; };
-            a.y.u = a.x;
-
-            var b = Hoek.clone(a);
-            expect(b.x()).to.equal(1);
-            expect(b.x.v()).to.equal(2);
-            expect(b.y.u).to.equal(b.x);
-            expect(b.x.z).to.equal('string in function');
-            done();
-        });
-
-        it('should copy a buffer', function(done){
-            var tls = {
-                key: new Buffer([1,2,3,4,5]),
-                cert: new Buffer([1,2,3,4,5,6,10])
-            }
-
-            copiedTls = Hoek.clone(tls);
-            expect(Buffer.isBuffer(copiedTls.key)).to.equal(true);
-            expect(JSON.stringify(copiedTls.key)).to.equal(JSON.stringify(tls.key))
-            expect(Buffer.isBuffer(copiedTls.cert)).to.equal(true);
-            expect(JSON.stringify(copiedTls.cert)).to.equal(JSON.stringify(tls.cert))
-            done();
-        });
-    });
-
-    describe('#merge', function () {
-
-        it('does not throw if source is null', function (done) {
-
-            var a = {};
-            var b = null;
-            var c = null;
-
-            expect(function () {
-
-                c = Hoek.merge(a, b);
-            }).to.not.throw();
-
-            expect(c).to.equal(a);
-            done();
-        });
-
-        it('does not throw if source is undefined', function (done) {
-
-            var a = {};
-            var b = undefined;
-            var c = null;
-
-            expect(function () {
-
-                c = Hoek.merge(a, b);
-            }).to.not.throw();
-
-            expect(c).to.equal(a);
-            done();
-        });
-
-        it('throws if source is not an object', function (done) {
-
-            expect(function () {
-
-                var a = {};
-                var b = 0;
-
-                Hoek.merge(a, b);
-            }).to.throw('Invalid source value: must be null, undefined, or an object');
-            done();
-        });
-
-        it('throws if target is not an object', function (done) {
-
-            expect(function () {
-
-                var a = 0;
-                var b = {};
-
-                Hoek.merge(a, b);
-            }).to.throw('Invalid target value: must be an object');
-            done();
-        });
-
-        it('throws if target is not an array and source is', function (done) {
-
-            expect(function () {
-
-                var a = {};
-                var b = [1, 2];
-
-                Hoek.merge(a, b);
-            }).to.throw('Cannot merge array onto an object');
-            done();
-        });
-
-        it('returns the same object when merging arrays', function (done) {
-
-            var a = [];
-            var b = [1, 2];
-
-            expect(Hoek.merge(a, b)).to.equal(a);
-            done();
-        });
-
-        it('should combine an empty object with a non-empty object', function (done) {
-
-            var a = {};
-            var b = nestedObj;
-
-            var c = Hoek.merge(a, b);
-            expect(a).to.deep.equal(b);
-            expect(c).to.deep.equal(b);
-            done();
-        });
-
-        it('should override values in target', function (done) {
-
-            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
-            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
-
-            var c = Hoek.merge(a, b);
-            expect(c.x).to.equal(null);
-            expect(c.y).to.equal(2);
-            expect(c.z).to.equal(4);
-            expect(c.v).to.equal(0);
-            expect(c.m).to.equal('123');
-            expect(c.t).to.deep.equal({ u: 6 });
-            done();
-        });
-
-        it('should override values in target (flip)', function (done) {
-
-            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
-            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
-
-            var d = Hoek.merge(b, a);
-            expect(d.x).to.equal(1);
-            expect(d.y).to.equal(2);
-            expect(d.z).to.equal(3);
-            expect(d.v).to.equal(5);
-            expect(d.m).to.equal('abc');
-            expect(d.t).to.deep.equal('test');
-            done();
-        });
-    });
-
-    describe('#applyToDefaults', function () {
-
-        var defaults = {
-            a: 1,
-            b: 2,
-            c: {
-                d: 3,
-                e: [5, 6]
-            },
-            f: 6,
-            g: 'test'
-        };
-
-        it('should return null if options is false', function (done) {
-
-            var result = Hoek.applyToDefaults(defaults, false);
-            expect(result).to.equal(null);
-            done();
-        });
-
-        it('should return a copy of defaults if options is true', function (done) {
-
-            var result = Hoek.applyToDefaults(defaults, true);
-            expect(result).to.deep.equal(result);
-            done();
-        });
-
-        it('should apply object to defaults', function (done) {
-
-            var obj = {
-                a: null,
-                c: {
-                    e: [4]
-                },
-                f: 0,
-                g: {
-                    h: 5
-                }
-            };
-
-            var result = Hoek.applyToDefaults(defaults, obj);
-            expect(result.c.e).to.deep.equal([4]);
-            expect(result.a).to.equal(1);
-            expect(result.b).to.equal(2);
-            expect(result.f).to.equal(0);
-            expect(result.g).to.deep.equal({ h: 5 });
-            done();
-        });
-    });
-
-    describe('#unique', function () {
-
-        it('should ensure uniqueness within array of objects based on subkey', function (done) {
-
-            var a = Hoek.unique(dupsArray, 'x');
-            expect(a).to.deep.equal(reducedDupsArray);
-            done();
-        });
-
-        it('removes duplicated without key', function (done) {
-
-            expect(Hoek.unique([1, 2, 3, 4, 2, 1, 5])).to.deep.equal([1, 2, 3, 4, 5]);
-            done();
-        });
-    });
-
-    describe('#mapToObject', function () {
-
-        it('should return null on null array', function (done) {
-
-            var a = Hoek.mapToObject(null);
-            expect(a).to.equal(null);
-            done();
-        });
-
-        it('should convert basic array to existential object', function (done) {
-
-            var keys = [1, 2, 3, 4];
-            var a = Hoek.mapToObject(keys);
-            for (var i in keys) {
-                expect(a[keys[i]]).to.equal(true);
-            }
-            done();
-        });
-
-        it('should convert array of objects to existential object', function (done) {
-
-            var keys = [{ x: 1 }, { x: 2 }, { x: 3 }];
-            var subkey = 'x';
-            var a = Hoek.mapToObject(keys, subkey);
-            for (var i in keys) {
-                expect(a[keys[i][subkey]]).to.equal(true);
-            }
-            done();
-        });
-    });
-
-    describe('#intersect', function () {
-
-        it('should return the common objects of two arrays', function (done) {
-
-            var array1 = [1, 2, 3, 4, 4, 5, 5];
-            var array2 = [5, 4, 5, 6, 7];
-            var common = Hoek.intersect(array1, array2);
-            expect(common.length).to.equal(2);
-            done();
-        });
-
-        it('should return just the first common object of two arrays', function (done) {
-
-            var array1 = [1, 2, 3, 4, 4, 5, 5];
-            var array2 = [5, 4, 5, 6, 7];
-            var common = Hoek.intersect(array1, array2, true);
-            expect(common).to.equal(5);
-            done();
-        });
-
-        it('should return an empty array if either input is null', function (done) {
-
-            expect(Hoek.intersect([1], null).length).to.equal(0);
-            expect(Hoek.intersect(null, [1]).length).to.equal(0);
-            done();
-        });
-
-        it('should return the common objects of object and array', function (done) {
-
-            var array1 = [1, 2, 3, 4, 4, 5, 5];
-            var array2 = [5, 4, 5, 6, 7];
-            var common = Hoek.intersect(Hoek.mapToObject(array1), array2);
-            expect(common.length).to.equal(2);
-            done();
-        });
-    });
-
-    describe('#matchKeys', function () {
-
-        it('should match the existing object keys', function (done) {
-
-            var obj = {
-                a: 1,
-                b: 2,
-                c: 3,
-                d: null
-            };
-
-            expect(Hoek.matchKeys(obj, ['b', 'c', 'd', 'e'])).to.deep.equal(['b', 'c', 'd']);
-            done();
-        });
-    });
-
-    describe('#flatten', function () {
-
-        it('should return a flat array', function (done) {
-
-            var result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]);
-            expect(result.length).to.equal(13);
-            expect(result).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
-            done();
-        });
-    });
-
-    describe('#removeKeys', function () {
-
-        var objWithHiddenKeys = {
-            location: {
-                name: 'San Bruno'
-            },
-            company: {
-                name: '@WalmartLabs'
-            }
-        };
-
-        it('should delete params with definition\'s hide set to true', function (done) {
-
-            var a = Hoek.removeKeys(objWithHiddenKeys, ['location']);
-            expect(objWithHiddenKeys.location).to.not.exist;
-            expect(objWithHiddenKeys.company).to.exist;
-            done();
-        });
-    });
-
-    describe('#reach', function () {
-
-        var obj = {
-            a: {
-                b: {
-                    c: {
-                        d: 1,
-                        e: 2
-                    },
-                    f: 'hello'
-                },
-                g: {
-                    h: 3
-                }
-            },
-            i: function () { }
-        };
-
-        it('returns a valid member', function (done) {
-
-            expect(Hoek.reach(obj, 'a.b.c.d')).to.equal(1);
-            done();
-        });
-
-        it('returns null on null object', function (done) {
-
-            expect(Hoek.reach(null, 'a.b.c.d')).to.not.exist;
-            done();
-        });
-
-        it('returns null on missing member', function (done) {
-
-            expect(Hoek.reach(obj, 'a.b.c.d.x')).to.not.exist;
-            done();
-        });
-
-        it('returns null on invalid member', function (done) {
-
-            expect(Hoek.reach(obj, 'a.b.c.d-.x')).to.not.exist;
-            done();
-        });
-
-        it('returns function member', function (done) {
-
-            expect(typeof Hoek.reach(obj, 'i')).to.equal('function');
-            done();
-        });
-    });
-
-    describe('#inheritAsync', function () {
-
-        it('should inherit selected methods and wrap in async call', function (done) {
-
-            var proto = {
-                a: function () {
-                    return 'a!';
-                },
-                b: function () {
-                    return 'b!';
-                },
-                c: function () {
-                    throw new Error('c!');
-                }
-            };
-
-            var targetFunc = function () { };
-            targetFunc.prototype.c = function () {
-
-                return 'oops';
-            };
-
-            Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
-            var target = new targetFunc();
-
-            expect(typeof target.a).to.equal('function');
-            expect(typeof target.c).to.equal('function');
-            expect(target.b).to.not.exist;
-
-            target.a(function (err, result) {
-
-                expect(err).to.not.exist;
-                expect(result).to.equal('a!');
-
-                target.c(function (err, result) {
-
-                    expect(result).to.not.exist;
-                    expect(err.message).to.equal('c!');
-                    done();
-                });
-            });
-        });
-    });
-
-    describe('#callStack', function () {
-
-        it('should return the full call stack', function (done) {
-
-            var stack = Hoek.callStack();
-            expect(stack[0][0]).to.contain('index.js');
-            expect(stack[0][2]).to.equal(30);
-            done();
-        });
-    });
-
-    describe('#displayStack ', function () {
-
-        it('should return the full call stack for display', function (done) {
-
-            var stack = Hoek.displayStack();
-            expect(stack[0]).to.contain('test/index.js:');
-            done();
-        });
-
-        it('should include constructor functions correctly', function (done) {
-
-            var Something = function (next) {
-
-                next();
-            };
-
-            var something = new Something(function () {
-
-                var stack = Hoek.displayStack();
-                expect(stack[1]).to.contain('new Something');
-                done();
-            });
-        });
-    });
-
-    describe('#abort', function () {
-
-        it('should exit process when not in test mode', function (done) {
-
-            var env = process.env.NODE_ENV;
-            var write = process.stdout.write;
-            var exit = process.exit;
-
-            process.env.NODE_ENV = 'nottatest';
-            process.stdout.write = function () { };
-            process.exit = function (state) {
-
-                process.exit = exit;
-                process.env.NODE_ENV = env;
-                process.stdout.write = write;
-
-                expect(state).to.equal(1);
-                done();
-            };
-
-            Hoek.abort('Boom');
-        });
-
-        it('should throw when not in test mode and abortThrow is true', function (done) {
-
-            var env = process.env.NODE_ENV;
-            process.env.NODE_ENV = 'nottatest';
-            Hoek.abortThrow = true;
-
-            var fn = function () {
-
-                Hoek.abort('my error message');
-            };
-
-            expect(fn).to.throw('my error message');
-            Hoek.abortThrow = false;
-            process.env.NODE_ENV = env;
-
-            done();
-        });
-
-
-        it('should respect hideStack argument', function (done) {
-
-            var env = process.env.NODE_ENV;
-            var write = process.stdout.write;
-            var exit = process.exit;
-            var output = '';
-
-            process.exit = function () { };
-            process.env.NODE_ENV = '';
-            process.stdout.write = function (message) {
-
-                output = message;
-            };
-
-            Hoek.abort('my error message', true);
-
-            process.env.NODE_ENV = env;
-            process.stdout.write = write;
-            process.exit = exit;
-
-            expect(output).to.equal('ABORT: my error message\n\t\n');
-
-            done();
-        });
-
-        it('should default to showing stack', function (done) {
-
-            var env = process.env.NODE_ENV;
-            var write = process.stdout.write;
-            var exit = process.exit;
-            var output = '';
-
-            process.exit = function () { };
-            process.env.NODE_ENV = '';
-            process.stdout.write = function (message) {
-
-                output = message;
-            };
-
-            Hoek.abort('my error message');
-
-            process.env.NODE_ENV = env;
-            process.stdout.write = write;
-            process.exit = exit;
-
-            expect(output).to.contain('index.js');
-
-            done();
-        });
-    });
-
-    describe('#assert', function () {
-
-        it('should throw an Error when using assert in a test', function (done) {
-
-            var fn = function () {
-
-                Hoek.assert(false, 'my error message');
-            };
-
-            expect(fn).to.throw('my error message');
-            done();
-        });
-
-        it('should throw an Error when using assert in a test with no message', function (done) {
-
-            var fn = function () {
-
-                Hoek.assert(false);
-            };
-
-            expect(fn).to.throw('Unknown error');
-            done();
-        });
-
-        it('should throw an Error when using assert in a test with multipart message', function (done) {
-
-            var fn = function () {
-
-                Hoek.assert(false, 'This', 'is', 'my message');
-            };
-
-            expect(fn).to.throw('This is my message');
-            done();
-        });
-
-        it('should throw an Error when using assert in a test with object message', function (done) {
-
-            var fn = function () {
-
-                Hoek.assert(false, 'This', 'is', { spinal: 'tap' });
-            };
-
-            expect(fn).to.throw('This is {"spinal":"tap"}');
-            done();
-        });
-
-        it('should throw an Error when using assert in a test with error object message', function (done) {
-
-            var fn = function () {
-
-                Hoek.assert(false, new Error('This is spinal tap'));
-            };
-
-            expect(fn).to.throw('This is spinal tap');
-            done();
-        });
-    });
-
-    describe('#loadDirModules', function () {
-
-        it('should load modules from directory', function (done) {
-
-            var target = {};
-            Hoek.loadDirModules(__dirname + '/modules', ['test2'], target);
-            expect(target.Test1.x).to.equal(1);
-            expect(target.Test2).to.not.exist;
-            expect(target.Test3.z).to.equal(3);
-            done();
-        });
-
-        it('should list modules from directory into function', function (done) {
-
-            var target = {};
-            Hoek.loadDirModules(__dirname + '/modules', ['test2'], function (path, name, capName) {
-
-                target[name] = capName;
-            });
-
-            expect(target.test1).to.equal('Test1');
-            expect(target.test2).to.not.exist;
-            expect(target.test3).to.equal('Test3');
-            done();
-        });
-    });
-
-    describe('#rename', function () {
-
-        it('should rename object key', function (done) {
-
-            var a = { b: 'c' };
-            Hoek.rename(a, 'b', 'x');
-            expect(a.b).to.not.exist;
-            expect(a.x).to.equal('c');
-            done();
-        });
-    });
-
-    describe('Timer', function () {
-
-        it('should return time elapsed', function (done) {
-
-            var timer = new Hoek.Timer();
-            setTimeout(function () {
-
-                expect(timer.elapsed()).to.be.above(9);
-                done();
-            }, 12);
-        });
-    });
-
-    describe('#loadPackage', function () {
-
-        it('should', function (done) {
-
-            var pack = Hoek.loadPackage();
-            expect(pack.name).to.equal('hoek');
-            done();
-        });
-    });
-
-    describe('#escapeRegex', function () {
-
-        it('should escape all special regular expression characters', function (done) {
-
-            var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');
-            expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,');
-            done();
-        });
-    });
-
-    describe('#toss', function () {
-
-        it('should call callback with new error', function (done) {
-
-            var callback = function (err) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('bug');
-                done();
-            };
-
-            Hoek.toss(true, 'feature', callback);
-            Hoek.toss(false, 'bug', callback);
-        });
-
-        it('should call callback with new error and no message', function (done) {
-
-            Hoek.toss(false, function (err) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('');
-                done();
-            });
-        });
-
-        it('should call callback with error condition', function (done) {
-
-            Hoek.toss(new Error('boom'), function (err) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('boom');
-                done();
-            });
-        });
-
-        it('should call callback with new error using message with error condition', function (done) {
-
-            Hoek.toss(new Error('ka'), 'boom', function (err) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('boom');
-                done();
-            });
-        });
-
-        it('should call callback with new error using passed error with error condition', function (done) {
-
-            Hoek.toss(new Error('ka'), new Error('boom'), function (err) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('boom');
-                done();
-            });
-        });
-    });
-
-    describe('Base64Url', function () {
-
-        var base64str = 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w';
-        var str = unescape('%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF');
-
-        describe('#base64urlEncode', function () {
-
-            it('should base64 URL-safe a string', function (done) {
-
-                expect(Hoek.base64urlEncode(str)).to.equal(base64str);
-                done();
-            });
-        });
-
-        describe('#base64urlDecode', function () {
-
-            it('should un-base64 URL-safe a string', function (done) {
-
-                expect(Hoek.base64urlDecode(base64str)).to.equal(str);
-                done();
-            });
-
-            it('should return error on undefined input', function (done) {
-
-                expect(Hoek.base64urlDecode().message).to.exist;
-                done();
-            });
-
-            it('should return error on invalid input', function (done) {
-
-                expect(Hoek.base64urlDecode('*').message).to.exist;
-                done();
-            });
-        });
-    });
-
-    describe('#escapeHeaderAttribute', function () {
-
-        it('should not alter ascii values', function (done) {
-
-            var a = Hoek.escapeHeaderAttribute('My Value');
-            expect(a).to.equal('My Value');
-            done();
-        });
-
-        it('should escape all special HTTP header attribute characters', function (done) {
-
-            var a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92));
-            expect(a).to.equal('I said go!!!#\\"\\\\');
-            done();
-        });
-
-        it('should throw on large unicode characters', function (done) {
-
-            var fn = function () {
-
-                Hoek.escapeHeaderAttribute('this is a test' + String.fromCharCode(500) + String.fromCharCode(300));
-            };
-
-            expect(fn).to.throw(Error);
-            done();
-        });
-
-        it('should throw on CRLF to prevent response splitting', function (done) {
-
-            var fn = function () {
-
-                Hoek.escapeHeaderAttribute('this is a test\r\n');
-            };
-
-            expect(fn).to.throw(Error);
-            done();
-        });
-    });
-
-    describe('#escapeHtml', function () {
-
-        it('should escape all special HTML characters', function (done) {
-
-            var a = Hoek.escapeHtml('&<>"\'`');
-            expect(a).to.equal('&amp;&lt;&gt;&quot;&#x27;&#x60;');
-            done();
-        });
-
-        it('should return empty string on falsy input', function (done) {
-
-            var a = Hoek.escapeHtml('');
-            expect(a).to.equal('');
-            done();
-        });
-
-        it('should return unchanged string on no reserved input', function (done) {
-
-            var a = Hoek.escapeHtml('abc');
-            expect(a).to.equal('abc');
-            done();
-        });
-    });
-
-    describe('#printEvent', function () {
-
-        it('outputs event as string', function (done) {
-
-            var event = {
-                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
-                tags: ['a', 'b', 'c'],
-                data: { some: 'data' }
-            };
-
-            Hoek.consoleFunc = function (string) {
-
-                Hoek.consoleFunc = console.log;
-                expect(string).to.equal('130201/063045.123, a, {"some":"data"}');
-                done();
-            };
-
-            Hoek.printEvent(event);
-        });
-
-        it('outputs JSON error', function (done) {
-
-            var event = {
-                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
-                tags: ['a', 'b', 'c'],
-                data: { some: 'data' }
-            };
-
-            event.data.a = event.data;
-
-            Hoek.consoleFunc = function (string) {
-
-                Hoek.consoleFunc = console.log;
-                expect(string).to.equal('130201/063045.123, a, JSON Error: Converting circular structure to JSON');
-                done();
-            };
-
-            Hoek.printEvent(event);
-        });
-    });
-
-    describe('#nextTick', function () {
-
-        it('calls the provided callback on nextTick', function (done) {
-
-            var a = 0;
-
-            var inc = function (step, next) {
-
-                a += step;
-                next();
-            };
-
-            var ticked = Hoek.nextTick(inc);
-
-            ticked(5, function () {
-
-                expect(a).to.equal(6);
-                done();
-            });
-
-            expect(a).to.equal(0);
-            inc(1, function () {
-
-                expect(a).to.equal(1);
-            });
-        });
-    });
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js
deleted file mode 100755
index 3f41e601..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js
+++ /dev/null
@@ -1 +0,0 @@
-exports.x = 1;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js
deleted file mode 100755
index 38556b27..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js
+++ /dev/null
@@ -1 +0,0 @@
-exports.y = 2;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js
deleted file mode 100755
index 436b860b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js
+++ /dev/null
@@ -1 +0,0 @@
-exports.z = 3;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.npmignore
deleted file mode 100644
index 77ba16cb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml
deleted file mode 100755
index 047f7e3d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-
-node_js:
-  - 0.10
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE
deleted file mode 100755
index e699a7bd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (c) 2012-2013, Eran Hammer.
-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 Eran Hammer 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 ERAN HAMMER 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile
deleted file mode 100755
index 9e7138c2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-test:
-	@./node_modules/.bin/lab
-test-cov: 
-	@./node_modules/.bin/lab -r threshold -t 100
-test-cov-html:
-	@./node_modules/.bin/lab -r html -o coverage.html
-complexity:
-	@./node_modules/.bin/cr -o complexity.md -f markdown lib
-
-.PHONY: test test-cov test-cov-html complexity
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/README.md
deleted file mode 100755
index 98a6e025..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/README.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# sntp
-
-An SNTP v4 client (RFC4330) for node. Simpy connects to the NTP or SNTP server requested and returns the server time
-along with the roundtrip duration and clock offset. To adjust the local time to the NTP time, add the returned `t` offset
-to the local time.
-
-[![Build Status](https://secure.travis-ci.org/hueniverse/sntp.png)](http://travis-ci.org/hueniverse/sntp)
-
-# Usage
-
-```javascript
-var Sntp = require('sntp');
-
-// All options are optional
-
-var options = {
-    host: 'nist1-sj.ustiming.org',  // Defaults to pool.ntp.org
-    port: 123,                      // Defaults to 123 (NTP)
-    resolveReference: true,         // Default to false (not resolving)
-    timeout: 1000                   // Defaults to zero (no timeout)
-};
-
-// Request server time
-
-Sntp.time(options, function (err, time) {
-
-    if (err) {
-        console.log('Failed: ' + err.message);
-        process.exit(1);
-    }
-
-    console.log('Local clock is off by: ' + time.t + ' milliseconds');
-    process.exit(0);
-});
-```
-
-If an application needs to maintain continuous time synchronization, the module provides a stateful method for
-querying the current offset only when the last one is too old (defaults to daily).
-
-```javascript
-// Request offset once
-
-Sntp.offset(function (err, offset) {
-
-    console.log(offset);                    // New (served fresh)
-
-    // Request offset again
-
-    Sntp.offset(function (err, offset) {
-
-        console.log(offset);                // Identical (served from cache)
-    });
-});
-```
-
-To set a background offset refresh, start the interval and use the provided now() method. If for any reason the
-client fails to obtain an up-to-date offset, the current system clock is used.
-
-```javascript
-var before = Sntp.now();                    // System time without offset
-
-Sntp.start(function () {
-
-    var now = Sntp.now();                   // With offset
-    Sntp.stop();
-});
-```
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js
deleted file mode 100755
index 0303f6dc..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js
+++ /dev/null
@@ -1,16 +0,0 @@
-var Sntp = require('../lib');
-
-// Request offset once
-
-Sntp.offset(function (err, offset) {
-
-    console.log(offset);                    // New (served fresh)
-
-    // Request offset again
-
-    Sntp.offset(function (err, offset) {
-
-        console.log(offset);                // Identical (served from cache)
-    });
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js
deleted file mode 100755
index bd70d0e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var Sntp = require('../lib');
-
-// All options are optional
-
-var options = {
-    host: 'nist1-sj.ustiming.org',  // Defaults to pool.ntp.org
-    port: 123,                      // Defaults to 123 (NTP)
-    resolveReference: true,         // Default to false (not resolving)
-    timeout: 1000                   // Defaults to zero (no timeout)
-};
-
-// Request server time
-
-Sntp.time(options, function (err, time) {
-
-    if (err) {
-        console.log('Failed: ' + err.message);
-        process.exit(1);
-    }
-
-    console.log(time);
-    console.log('Local clock is off by: ' + time.t + ' milliseconds');
-    process.exit(0);
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/index.js
deleted file mode 100755
index 4cc88b35..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('./lib');
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js
deleted file mode 100755
index e492cd93..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js
+++ /dev/null
@@ -1,409 +0,0 @@
-// Load modules
-
-var Dgram = require('dgram');
-var Dns = require('dns');
-var Hoek = require('hoek');
-
-
-// Declare internals
-
-var internals = {};
-
-
-exports.time = function (options, callback) {
-
-    if (arguments.length !== 2) {
-        callback = arguments[0];
-        options = {};
-    }
-
-    var settings = Hoek.clone(options);
-    settings.host = settings.host || 'pool.ntp.org';
-    settings.port = settings.port || 123;
-    settings.resolveReference = settings.resolveReference || false;
-
-    // Declare variables used by callback
-
-    var timeoutId = 0;
-    var sent = 0;
-
-    // Ensure callback is only called once
-
-    var isFinished = false;
-    var finish = function (err, result) {
-
-        if (timeoutId) {
-            clearTimeout(timeoutId);
-            timeoutId = 0;
-        }
-
-        if (!isFinished) {
-            isFinished = true;
-            socket.removeAllListeners();
-            socket.close();
-            return callback(err, result);
-        }
-    };
-
-    // Create UDP socket
-
-    var socket = Dgram.createSocket('udp4');
-
-    socket.once('error', function (err) {
-
-        return finish(err);
-    });
-
-    // Listen to incoming messages
-
-    socket.on('message', function (buffer, rinfo) {
-
-        var received = Date.now();
-
-        var message = new internals.NtpMessage(buffer);
-        if (!message.isValid) {
-            return finish(new Error('Invalid server response'), message);
-        }
-
-        if (message.originateTimestamp !== sent) {
-            return finish(new Error('Wrong originate timestamp'), message);
-        }
-
-        // Timestamp Name          ID   When Generated
-        // ------------------------------------------------------------
-        // Originate Timestamp     T1   time request sent by client
-        // Receive Timestamp       T2   time request received by server
-        // Transmit Timestamp      T3   time reply sent by server
-        // Destination Timestamp   T4   time reply received by client
-        //
-        // The roundtrip delay d and system clock offset t are defined as:
-        //
-        // d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2
-
-        var T1 = message.originateTimestamp;
-        var T2 = message.receiveTimestamp;
-        var T3 = message.transmitTimestamp;
-        var T4 = received;
-
-        message.d = (T4 - T1) - (T3 - T2);
-        message.t = ((T2 - T1) + (T3 - T4)) / 2;
-        message.receivedLocally = received;
-
-        if (!settings.resolveReference ||
-            message.stratum !== 'secondary') {
-
-            return finish(null, message);
-        }
-
-        // Resolve reference IP address
-
-        Dns.reverse(message.referenceId, function (err, domains) {
-
-            if (!err) {
-                message.referenceHost = domains[0];
-            }
-
-            return finish(null, message);
-        });
-    });
-
-    // Set timeout
-
-    if (settings.timeout) {
-        timeoutId = setTimeout(function () {
-
-            timeoutId = 0;
-            return finish(new Error('Timeout'));
-        }, settings.timeout);
-    }
-
-    // Construct NTP message
-
-    var message = new Buffer(48);
-    for (var i = 0; i < 48; i++) {                      // Zero message
-        message[i] = 0;
-    }
-
-    message[0] = (0 << 6) + (4 << 3) + (3 << 0)         // Set version number to 4 and Mode to 3 (client)
-    sent = Date.now();
-    internals.fromMsecs(sent, message, 40);               // Set transmit timestamp (returns as originate)
-
-    // Send NTP request
-
-    socket.send(message, 0, message.length, settings.port, settings.host, function (err, bytes) {
-
-        if (err ||
-            bytes !== 48) {
-
-            return finish(err || new Error('Could not send entire message'));
-        }
-    });
-};
-
-
-internals.NtpMessage = function (buffer) {
-
-    this.isValid = false;
-
-    // Validate
-
-    if (buffer.length !== 48) {
-        return;
-    }
-
-    // Leap indicator
-
-    var li = (buffer[0] >> 6);
-    switch (li) {
-        case 0: this.leapIndicator = 'no-warning'; break;
-        case 1: this.leapIndicator = 'last-minute-61'; break;
-        case 2: this.leapIndicator = 'last-minute-59'; break;
-        case 3: this.leapIndicator = 'alarm'; break;
-    }
-
-    // Version
-
-    var vn = ((buffer[0] & 0x38) >> 3);
-    this.version = vn;
-
-    // Mode
-
-    var mode = (buffer[0] & 0x7);
-    switch (mode) {
-        case 1: this.mode = 'symmetric-active'; break;
-        case 2: this.mode = 'symmetric-passive'; break;
-        case 3: this.mode = 'client'; break;
-        case 4: this.mode = 'server'; break;
-        case 5: this.mode = 'broadcast'; break;
-        case 0:
-        case 6:
-        case 7: this.mode = 'reserved'; break;
-    }
-
-    // Stratum
-
-    var stratum = buffer[1];
-    if (stratum === 0) {
-        this.stratum = 'death';
-    }
-    else if (stratum === 1) {
-        this.stratum = 'primary';
-    }
-    else if (stratum <= 15) {
-        this.stratum = 'secondary';
-    }
-    else {
-        this.stratum = 'reserved';
-    }
-
-    // Poll interval (msec)
-
-    this.pollInterval = Math.round(Math.pow(2, buffer[2])) * 1000;
-
-    // Precision (msecs)
-
-    this.precision = Math.pow(2, buffer[3]) * 1000;
-
-    // Root delay (msecs)
-
-    var rootDelay = 256 * (256 * (256 * buffer[4] + buffer[5]) + buffer[6]) + buffer[7];
-    this.rootDelay = 1000 * (rootDelay / 0x10000);
-
-    // Root dispersion (msecs)
-
-    this.rootDispersion = ((buffer[8] << 8) + buffer[9] + ((buffer[10] << 8) + buffer[11]) / Math.pow(2, 16)) * 1000;
-
-    // Reference identifier
-
-    this.referenceId = '';
-    switch (this.stratum) {
-        case 'death':
-        case 'primary':
-            this.referenceId = String.fromCharCode(buffer[12]) + String.fromCharCode(buffer[13]) + String.fromCharCode(buffer[14]) + String.fromCharCode(buffer[15]);
-            break;
-        case 'secondary':
-            this.referenceId = '' + buffer[12] + '.' + buffer[13] + '.' + buffer[14] + '.' + buffer[15];
-            break;
-    }
-
-    // Reference timestamp
-
-    this.referenceTimestamp = internals.toMsecs(buffer, 16);
-
-    // Originate timestamp
-
-    this.originateTimestamp = internals.toMsecs(buffer, 24);
-
-    // Receive timestamp
-
-    this.receiveTimestamp = internals.toMsecs(buffer, 32);
-
-    // Transmit timestamp
-
-    this.transmitTimestamp = internals.toMsecs(buffer, 40);
-
-    // Validate
-
-    if (this.version === 4 &&
-        this.stratum !== 'reserved' &&
-        this.mode === 'server' &&
-        this.originateTimestamp &&
-        this.receiveTimestamp &&
-        this.transmitTimestamp) {
-
-        this.isValid = true;
-    }
-
-    return this;
-};
-
-
-internals.toMsecs = function (buffer, offset) {
-
-    var seconds = 0;
-    var fraction = 0;
-
-    for (var i = 0; i < 4; ++i) {
-        seconds = (seconds * 256) + buffer[offset + i];
-    }
-
-    for (i = 4; i < 8; ++i) {
-        fraction = (fraction * 256) + buffer[offset + i];
-    }
-
-    return ((seconds - 2208988800 + (fraction / Math.pow(2, 32))) * 1000);
-};
-
-
-internals.fromMsecs = function (ts, buffer, offset) {
-
-    var seconds = Math.floor(ts / 1000) + 2208988800;
-    var fraction = Math.round((ts % 1000) / 1000 * Math.pow(2, 32));
-
-    buffer[offset + 0] = (seconds & 0xFF000000) >> 24;
-    buffer[offset + 1] = (seconds & 0x00FF0000) >> 16;
-    buffer[offset + 2] = (seconds & 0x0000FF00) >> 8;
-    buffer[offset + 3] = (seconds & 0x000000FF);
-
-    buffer[offset + 4] = (fraction & 0xFF000000) >> 24;
-    buffer[offset + 5] = (fraction & 0x00FF0000) >> 16;
-    buffer[offset + 6] = (fraction & 0x0000FF00) >> 8;
-    buffer[offset + 7] = (fraction & 0x000000FF);
-};
-
-
-// Offset singleton
-
-internals.last = {
-    offset: 0,
-    expires: 0,
-    host: '',
-    port: 0
-};
-
-
-exports.offset = function (options, callback) {
-
-    if (arguments.length !== 2) {
-        callback = arguments[0];
-        options = {};
-    }
-
-    var now = Date.now();
-    var clockSyncRefresh = options.clockSyncRefresh || 24 * 60 * 60 * 1000;                    // Daily
-
-    if (internals.last.offset &&
-        internals.last.host === options.host &&
-        internals.last.port === options.port &&
-        now < internals.last.expires) {
-
-        process.nextTick(function () {
-                
-            callback(null, internals.last.offset);
-        });
-
-        return;
-    }
-
-    exports.time(options, function (err, time) {
-
-        if (err) {
-            return callback(err, 0);
-        }
-
-        internals.last = {
-            offset: Math.round(time.t),
-            expires: now + clockSyncRefresh,
-            host: options.host,
-            port: options.port
-        };
-
-        return callback(null, internals.last.offset);
-    });
-};
-
-
-// Now singleton
-
-internals.now = {
-    intervalId: 0
-};
-
-
-exports.start = function (options, callback) {
-
-    if (arguments.length !== 2) {
-        callback = arguments[0];
-        options = {};
-    }
-
-    if (internals.now.intervalId) {
-        process.nextTick(function () {
-            
-            callback();
-        });
-        
-        return;
-    }
-
-    exports.offset(options, function (err, offset) {
-
-        internals.now.intervalId = setInterval(function () {
-
-            exports.offset(options, function () { });
-        }, options.clockSyncRefresh || 24 * 60 * 60 * 1000);                                // Daily
-
-        return callback();
-    });
-};
-
-
-exports.stop = function () {
-
-    if (!internals.now.intervalId) {
-        return;
-    }
-
-    clearInterval(internals.now.intervalId);
-    internals.now.intervalId = 0;
-};
-
-
-exports.isLive = function () {
-
-    return !!internals.now.intervalId;
-};
-
-
-exports.now = function () {
-
-    var now = Date.now();
-    if (!exports.isLive() ||
-        now >= internals.last.expires) {
-
-        return now;
-    }
-
-    return now + internals.last.offset;
-};
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/package.json
deleted file mode 100755
index b0f82152..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/package.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-  "name": "sntp",
-  "description": "SNTP Client",
-  "version": "0.2.4",
-  "author": {
-    "name": "Eran Hammer",
-    "email": "eran@hueniverse.com",
-    "url": "http://hueniverse.com"
-  },
-  "contributors": [],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/hueniverse/sntp"
-  },
-  "main": "index",
-  "keywords": [
-    "sntp",
-    "ntp",
-    "time"
-  ],
-  "engines": {
-    "node": ">=0.8.0"
-  },
-  "dependencies": {
-    "hoek": "0.9.x"
-  },
-  "devDependencies": {
-    "lab": "0.1.x",
-    "complexity-report": "0.x.x"
-  },
-  "scripts": {
-    "test": "make test-cov"
-  },
-  "licenses": [
-    {
-      "type": "BSD",
-      "url": "http://github.com/hueniverse/sntp/raw/master/LICENSE"
-    }
-  ],
-  "readme": "# sntp\n\nAn SNTP v4 client (RFC4330) for node. Simpy connects to the NTP or SNTP server requested and returns the server time\nalong with the roundtrip duration and clock offset. To adjust the local time to the NTP time, add the returned `t` offset\nto the local time.\n\n[![Build Status](https://secure.travis-ci.org/hueniverse/sntp.png)](http://travis-ci.org/hueniverse/sntp)\n\n# Usage\n\n```javascript\nvar Sntp = require('sntp');\n\n// All options are optional\n\nvar options = {\n    host: 'nist1-sj.ustiming.org',  // Defaults to pool.ntp.org\n    port: 123,                      // Defaults to 123 (NTP)\n    resolveReference: true,         // Default to false (not resolving)\n    timeout: 1000                   // Defaults to zero (no timeout)\n};\n\n// Request server time\n\nSntp.time(options, function (err, time) {\n\n    if (err) {\n        console.log('Failed: ' + err.message);\n        process.exit(1);\n    }\n\n    console.log('Local clock is off by: ' + time.t + ' milliseconds');\n    process.exit(0);\n});\n```\n\nIf an application needs to maintain continuous time synchronization, the module provides a stateful method for\nquerying the current offset only when the last one is too old (defaults to daily).\n\n```javascript\n// Request offset once\n\nSntp.offset(function (err, offset) {\n\n    console.log(offset);                    // New (served fresh)\n\n    // Request offset again\n\n    Sntp.offset(function (err, offset) {\n\n        console.log(offset);                // Identical (served from cache)\n    });\n});\n```\n\nTo set a background offset refresh, start the interval and use the provided now() method. If for any reason the\nclient fails to obtain an up-to-date offset, the current system clock is used.\n\n```javascript\nvar before = Sntp.now();                    // System time without offset\n\nSntp.start(function () {\n\n    var now = Sntp.now();                   // With offset\n    Sntp.stop();\n});\n```\n\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/hueniverse/sntp/issues"
-  },
-  "homepage": "https://github.com/hueniverse/sntp",
-  "_id": "sntp@0.2.4",
-  "_shasum": "fb885f18b0f3aad189f824862536bceeec750900",
-  "_from": "sntp@0.2.x",
-  "_resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js
deleted file mode 100755
index 38a55346..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js
+++ /dev/null
@@ -1,359 +0,0 @@
-// Load modules
-
-var Dgram = require('dgram');
-var Lab = require('lab');
-var Sntp = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('SNTP', function () {
-
-    describe('#time', function () {
-
-        it('returns consistent result over multiple tries', function (done) {
-
-            Sntp.time(function (err, time) {
-
-                expect(err).to.not.exist;
-                expect(time).to.exist;
-                var t1 = time.t;
-
-                Sntp.time(function (err, time) {
-
-                    expect(err).to.not.exist;
-                    expect(time).to.exist;
-                    var t2 = time.t;
-                    expect(Math.abs(t1 - t2)).is.below(200);
-                    done();
-                });
-            });
-        });
-
-        it('resolves reference IP', function (done) {
-
-            Sntp.time({ host: 'ntp.exnet.com', resolveReference: true }, function (err, time) {
-
-                expect(err).to.not.exist;
-                expect(time).to.exist;
-                expect(time.referenceHost).to.exist;
-                done();
-            });
-        });
-
-        it('times out on no response', function (done) {
-
-            Sntp.time({ port: 124, timeout: 100 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time).to.not.exist;
-                expect(err.message).to.equal('Timeout');
-                done();
-            });
-        });
-
-        it('errors on error event', function (done) {
-
-            var orig = Dgram.createSocket;
-            Dgram.createSocket = function (type) {
-
-                Dgram.createSocket = orig;
-                var socket = Dgram.createSocket(type);
-                process.nextTick(function () { socket.emit('error', new Error('Fake')) });
-                return socket;
-            };
-
-            Sntp.time(function (err, time) {
-
-                expect(err).to.exist;
-                expect(time).to.not.exist;
-                expect(err.message).to.equal('Fake');
-                done();
-            });
-        });
-
-        it('times out on invalid host', function (done) {
-
-            Sntp.time({ host: 'error', timeout: 10000 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time).to.not.exist;
-                expect(err.message).to.equal('getaddrinfo ENOTFOUND');
-                done();
-            });
-        });
-
-        it('fails on bad response buffer size', function (done) {
-
-            var server = Dgram.createSocket('udp4');
-            server.on('message', function (message, remote) {
-                var message = new Buffer(10);
-                server.send(message, 0, message.length, remote.port, remote.address, function (err, bytes) {
-
-                    server.close();
-                });
-            });
-
-            server.bind(49123);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Invalid server response');
-                done();
-            });
-        });
-
-        var messup = function (bytes) {
-
-            var server = Dgram.createSocket('udp4');
-            server.on('message', function (message, remote) {
-
-                var message = new Buffer([
-                    0x24, 0x01, 0x00, 0xe3,
-                    0x00, 0x00, 0x00, 0x00,
-                    0x00, 0x00, 0x00, 0x00,
-                    0x41, 0x43, 0x54, 0x53,
-                    0xd4, 0xa8, 0x2d, 0xc7,
-                    0x1c, 0x5d, 0x49, 0x1b,
-                    0xd4, 0xa8, 0x2d, 0xe6,
-                    0x67, 0xef, 0x9d, 0xb2,
-                    0xd4, 0xa8, 0x2d, 0xe6,
-                    0x71, 0xed, 0xb5, 0xfb,
-                    0xd4, 0xa8, 0x2d, 0xe6,
-                    0x71, 0xee, 0x6c, 0xc5
-                ]);
-
-                for (var i = 0, il = bytes.length; i < il; ++i) {
-                    message[bytes[i][0]] = bytes[i][1];
-                }
-
-                server.send(message, 0, message.length, remote.port, remote.address, function (err, bytes) {
-
-                    server.close();
-                });
-            });
-
-            server.bind(49123);
-        };
-
-        it('fails on bad version', function (done) {
-
-            messup([[0, (0 << 6) + (3 << 3) + (4 << 0)]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time.version).to.equal(3);
-                expect(err.message).to.equal('Invalid server response');
-                done();
-            });
-        });
-
-        it('fails on bad originate timestamp and alarm li', function (done) {
-
-            messup([[0, (3 << 6) + (4 << 3) + (4 << 0)]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Wrong originate timestamp');
-                expect(time.leapIndicator).to.equal('alarm');
-                done();
-            });
-        });
-
-        it('returns time with death stratum and last61 li', function (done) {
-
-            messup([[0, (1 << 6) + (4 << 3) + (4 << 0)], [1, 0]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(time.stratum).to.equal('death');
-                expect(time.leapIndicator).to.equal('last-minute-61');
-                done();
-            });
-        });
-
-        it('returns time with reserved stratum and last59 li', function (done) {
-
-            messup([[0, (2 << 6) + (4 << 3) + (4 << 0)], [1, 0x1f]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(time.stratum).to.equal('reserved');
-                expect(time.leapIndicator).to.equal('last-minute-59');
-                done();
-            });
-        });
-
-        it('fails on bad mode (symmetric-active)', function (done) {
-
-            messup([[0, (0 << 6) + (4 << 3) + (1 << 0)]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time.mode).to.equal('symmetric-active');
-                done();
-            });
-        });
-
-        it('fails on bad mode (symmetric-passive)', function (done) {
-
-            messup([[0, (0 << 6) + (4 << 3) + (2 << 0)]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time.mode).to.equal('symmetric-passive');
-                done();
-            });
-        });
-
-        it('fails on bad mode (client)', function (done) {
-
-            messup([[0, (0 << 6) + (4 << 3) + (3 << 0)]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time.mode).to.equal('client');
-                done();
-            });
-        });
-
-        it('fails on bad mode (broadcast)', function (done) {
-
-            messup([[0, (0 << 6) + (4 << 3) + (5 << 0)]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time.mode).to.equal('broadcast');
-                done();
-            });
-        });
-
-        it('fails on bad mode (reserved)', function (done) {
-
-            messup([[0, (0 << 6) + (4 << 3) + (6 << 0)]]);
-
-            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
-
-                expect(err).to.exist;
-                expect(time.mode).to.equal('reserved');
-                done();
-            });
-        });
-    });
-
-    describe('#offset', function () {
-
-        it('gets the current offset', function (done) {
-
-            Sntp.offset(function (err, offset) {
-
-                expect(err).to.not.exist;
-                expect(offset).to.not.equal(0);
-                done();
-            });
-        });
-
-        it('gets the current offset from cache', function (done) {
-
-            Sntp.offset(function (err, offset) {
-
-                expect(err).to.not.exist;
-                expect(offset).to.not.equal(0);
-                var offset1 = offset;
-                Sntp.offset({}, function (err, offset) {
-
-                    expect(err).to.not.exist;
-                    expect(offset).to.equal(offset1);
-                    done();
-                });
-            });
-        });
-
-        it('fails getting the current offset on invalid server', function (done) {
-
-            Sntp.offset({ host: 'error' }, function (err, offset) {
-
-                expect(err).to.exist;
-                expect(offset).to.equal(0);
-                done();
-            });
-        });
-    });
-
-    describe('#now', function () {
-
-        it('starts auto-sync, gets now, then stops', function (done) {
-
-            Sntp.stop();
-
-            var before = Sntp.now();
-            expect(before).to.equal(Date.now());
-
-            Sntp.start(function () {
-
-                var now = Sntp.now();
-                expect(now).to.not.equal(Date.now());
-                Sntp.stop();
-
-                done();
-            });
-        });
-
-        it('starts twice', function (done) {
-
-            Sntp.start(function () {
-
-                Sntp.start(function () {
-
-                    var now = Sntp.now();
-                    expect(now).to.not.equal(Date.now());
-                    Sntp.stop();
-
-                    done();
-                });
-            });
-        });
-
-        it('starts auto-sync, gets now, waits, gets again after timeout', function (done) {
-
-            Sntp.stop();
-
-            var before = Sntp.now();
-            expect(before).to.equal(Date.now());
-
-            Sntp.start({ clockSyncRefresh: 100 }, function () {
-
-                var now = Sntp.now();
-                expect(now).to.not.equal(Date.now());
-                expect(now).to.equal(Sntp.now());
-
-                setTimeout(function () {
-
-                    expect(Sntp.now()).to.not.equal(now);
-                    Sntp.stop();
-                    done();
-                }, 110);
-            });
-        });
-    });
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/package.json
deleted file mode 100755
index 36cab85e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
-  "name": "hawk",
-  "description": "HTTP Hawk Authentication Scheme",
-  "version": "1.0.0",
-  "author": {
-    "name": "Eran Hammer",
-    "email": "eran@hueniverse.com",
-    "url": "http://hueniverse.com"
-  },
-  "contributors": [],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/hueniverse/hawk"
-  },
-  "main": "index",
-  "keywords": [
-    "http",
-    "authentication",
-    "scheme",
-    "hawk"
-  ],
-  "engines": {
-    "node": ">=0.8.0"
-  },
-  "dependencies": {
-    "hoek": "0.9.x",
-    "boom": "0.4.x",
-    "cryptiles": "0.2.x",
-    "sntp": "0.2.x"
-  },
-  "devDependencies": {
-    "lab": "0.1.x",
-    "complexity-report": "0.x.x",
-    "localStorage": "1.0.x"
-  },
-  "scripts": {
-    "test": "make test-cov"
-  },
-  "licenses": [
-    {
-      "type": "BSD",
-      "url": "http://github.com/hueniverse/hawk/raw/master/LICENSE"
-    }
-  ],
-  "readme": "![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png)\n\n<img align=\"right\" src=\"https://raw.github.com/hueniverse/hawk/master/images/logo.png\" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial\nHTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).\n\nCurrent version: **1.0**\n\n[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk)\n\n# Table of Content\n\n- [**Introduction**](#introduction)\n  - [Replay Protection](#replay-protection)\n  - [Usage Example](#usage-example)\n  - [Protocol Example](#protocol-example)\n    - [Payload Validation](#payload-validation)\n    - [Response Payload Validation](#response-payload-validation)\n  - [Browser Support and Considerations](#browser-support-and-considerations)\n<p></p>\n- [**Single URI Authorization**](#single-uri-authorization)\n  - [Usage Example](#bewit-usage-example)\n<p></p>\n- [**Security Considerations**](#security-considerations)\n  - [MAC Keys Transmission](#mac-keys-transmission)\n  - [Confidentiality of Requests](#confidentiality-of-requests)\n  - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers)\n  - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials)\n  - [Entropy of Keys](#entropy-of-keys)\n  - [Coverage Limitations](#coverage-limitations)\n  - [Future Time Manipulation](#future-time-manipulation)\n  - [Client Clock Poisoning](#client-clock-poisoning)\n  - [Bewit Limitations](#bewit-limitations)\n  - [Host Header Forgery](#host-header-forgery)\n<p></p>\n- [**Frequently Asked Questions**](#frequently-asked-questions)\n<p></p>\n- [**Acknowledgements**](#acknowledgements)\n\n# Introduction\n\n**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with\npartial cryptographic verification of the request and response, covering the HTTP method, request URI, host,\nand optionally the request payload.\n\nSimilar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of\nclient credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme,\nthe key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is\nincluded in its place.\n\nHowever, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of\nreplay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less\n\"chattiness\" (interaction with the server).\n\nAlso unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because\nthe client and server must both have access to the key material in the clear.\n\nThe primary design goals of this scheme are to:\n* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources,\n* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where\n  to send an authenticated request), and\n* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client\n  failure to validate the server's identity as part of its TLS handshake.\n\nIn addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using\na query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).\n\nThe **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server,\nwhich is beyond the scope of this module. Typically, the shared credentials are established via an initial\nTLS-protected phase or derived from some other shared confidential information available to both the client\nand the server.\n\n\n## Replay Protection\n\nWithout replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more \nthan once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when \nmaking requests. This gives the server enough information to prevent replay attacks.\n\nThe nonce is generated by the client, and is a string unique across all requests with the same timestamp and\nkey identifier combination. \n\nThe timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards\nare rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks.\nBy default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in\npractice translates to a maximum of 2 minutes as the skew can be positive or negative).\n\nUsing a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client\nclock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types\n(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response\nto a bad timestamp.\n\nThere is no expectation that the client will adjust its system clock to match the server (in fact, this would be a\npotential attack vector). Instead, the client only uses the server's time to calculate an offset used only\nfor communications with that particular server. The protocol rewards clients with synchronized clocks by reducing\nthe number of round trips required to authenticate the first request.\n\n\n## Usage Example\n\nServer code:\n\n```javascript\nvar Http = require('http');\nvar Hawk = require('hawk');\n\n\n// Credentials lookup function\n\nvar credentialsFunc = function (id, callback) {\n\n    var credentials = {\n        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\n        algorithm: 'sha256',\n        user: 'Steve'\n    };\n\n    return callback(null, credentials);\n};\n\n// Create HTTP server\n\nvar handler = function (req, res) {\n\n    // Authenticate incoming request\n\n    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {\n\n        // Prepare response\n\n        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');\n        var headers = { 'Content-Type': 'text/plain' };\n\n        // Generate Server-Authorization response header\n\n        var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] });\n        headers['Server-Authorization'] = header;\n\n        // Send the response back\n\n        res.writeHead(!err ? 200 : 401, headers);\n        res.end(payload);\n    });\n};\n\n// Start server\n\nHttp.createServer(handler).listen(8000, 'example.com');\n```\n\nClient code:\n\n```javascript\nvar Request = require('request');\nvar Hawk = require('hawk');\n\n\n// Client credentials\n\nvar credentials = {\n    id: 'dh37fgj492je',\n    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\n    algorithm: 'sha256'\n}\n\n// Request options\n\nvar requestOptions = {\n    uri: 'http://example.com:8000/resource/1?b=1&a=2',\n    method: 'GET',\n    headers: {}\n};\n\n// Generate Authorization request header\n\nvar header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });\nrequestOptions.headers.Authorization = header.field;\n\n// Send authenticated request\n\nRequest(requestOptions, function (error, response, body) {\n\n    // Authenticate the server's response\n\n    var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });\n\n    // Output results\n\n    console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));\n});\n```\n\n**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local\nmachine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.\n\n```javascript\nHawk.sntp.start();\n```\n\n\n## Protocol Example\n\nThe client attempts to access a protected resource without authentication, sending the following HTTP request to\nthe resource server:\n\n```\nGET /resource/1?b=1&a=2 HTTP/1.1\nHost: example.com:8000\n```\n\nThe resource server returns an authentication challenge.\n\n```\nHTTP/1.1 401 Unauthorized\nWWW-Authenticate: Hawk\n```\n\nThe client has previously obtained a set of **Hawk** credentials for accessing resources on the \"http://example.com/\"\nserver. The **Hawk** credentials issued to the client include the following attributes:\n\n* Key identifier: dh37fgj492je\n* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn\n* Algorithm: sha256\n\nThe client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,\n1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline\ncharacter):\n\n```\nhawk.1.header\n1353832234\nj4h3g2\nGET\n/resource/1?b=1&a=2\nexample.com\n8000\n\nsome-app-ext-data\n\n```\n\nThe request MAC is calculated using HMAC with the specified hash algorithm \"sha256\" and the key over the normalized request string.\nThe result is base64-encoded to produce the request MAC:\n\n```\n6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=\n```\n\nThe client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using\nthe HTTP `Authorization` request header field:\n\n```\nGET /resource/1?b=1&a=2 HTTP/1.1\nHost: example.com:8000\nAuthorization: Hawk id=\"dh37fgj492je\", ts=\"1353832234\", nonce=\"j4h3g2\", ext=\"some-app-ext-data\", mac=\"6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=\"\n```\n\nThe server validates the request by calculating the request MAC again based on the request received and verifies the validity\nand scope of the **Hawk** credentials. If valid, the server responds with the requested resource.\n\n\n### Payload Validation\n\n**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash\nusing the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):\n* `hawk.1.payload`\n* the content-type in lowercase, without any parameters (e.g. `application/json`)\n* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability)\n\nFor example:\n\n* Payload: `Thank you for flying Hawk`\n* Content Type: `text/plain`\n* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=`\n\nResults in the following input to the payload hash function (newline terminated values):\n\n```\nhawk.1.payload\ntext/plain\nThank you for flying Hawk\n\n```\n\nWhich produces the following hash value:\n\n```\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\n```\n\nThe client constructs the normalized request string (newline terminated values):\n\n```\nhawk.1.header\n1353832234\nj4h3g2\nPOST\n/resource/1?a=1&b=2\nexample.com\n8000\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\nsome-app-ext-data\n\n```\n\nThen calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data,\nand request MAC, with the request using the HTTP `Authorization` request header field:\n\n```\nPOST /resource/1?a=1&b=2 HTTP/1.1\nHost: example.com:8000\nAuthorization: Hawk id=\"dh37fgj492je\", ts=\"1353832234\", nonce=\"j4h3g2\", hash=\"Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\", ext=\"some-app-ext-data\", mac=\"aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw=\"\n```\n\nIt is up to the server if and when it validates the payload for any given request, based solely on it's security policy\nand the nature of the data included.\n\nIf the payload is available at the time of authentication, the server uses the hash value provided by the client to construct\nthe normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value\nwith the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.\n\nHowever, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed\nat a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value\nprovided by the client after validating the MAC.\n\nIt is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value\nincluded in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided\nby the client, the payload may be modified by an attacker.\n\n\n## Response Payload Validation\n\n**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the\nclient to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header\nas a response header using the exact same syntax as the `Authorization` request header field.\n\nThe header is contructed using the same process as the client's request header. The server uses the same credentials and other\nartifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with\nnew values based on the server response. The rest as identical to those used by the client.\n\nThe result MAC digest is included with the optional `hash` and `ext` values:\n\n```\nServer-Authorization: Hawk mac=\"XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"\n```\n\n\n## Browser Support and Considerations\n\nA browser script is provided for including using a `<script>` tag in [lib/browser.js](/lib/browser.js).\n\n**Hawk** relies on the _Server-Authorization_ and _WWW-Authenticate_ headers in its response to communicate with the client.\nTherefore, in case of CORS requests, it is important to consider sending _Access-Control-Expose-Headers_ with the value\n_\"WWW-Authenticate, Server-Authorization\"_ on each response from your server. As explained in the\n[specifications](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header), it will indicate that these headers\ncan safely be accessed by the client (using getResponseHeader() on the XmlHttpRequest object). Otherwise you will be met with a\n[\"simple response header\"](http://www.w3.org/TR/cors/#simple-response-header) which excludes these fields and would prevent the\nHawk client from authenticating the requests.You can read more about the why and how in this\n[article](http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server)\n\n\n# Single URI Authorization\n\nThere are cases in which limited and short-term access to a protected resource is granted to a third party which does not\nhave access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. **Hawk**\nprovides limited support for such URIs in the form of a _bewit_ - a URI query parameter appended to the request URI which contains\nthe necessary credentials to authenticate the request.\n\nBecause of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests\nand for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same\ncredentials as the client to maintain clear traceability as to who issued which credentials.\n\nIn order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within\nthe granted access timeframe. \n\n\n## Bewit Usage Example\n\nServer code:\n\n```javascript\nvar Http = require('http');\nvar Hawk = require('hawk');\n\n\n// Credentials lookup function\n\nvar credentialsFunc = function (id, callback) {\n\n    var credentials = {\n        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\n        algorithm: 'sha256'\n    };\n\n    return callback(null, credentials);\n};\n\n// Create HTTP server\n\nvar handler = function (req, res) {\n\n    Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {\n\n        res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });\n        res.end(!err ? 'Access granted' : 'Shoosh!');\n    });\n};\n\nHttp.createServer(handler).listen(8000, 'example.com');\n```\n\nBewit code generation:\n\n```javascript\nvar Request = require('request');\nvar Hawk = require('hawk');\n\n\n// Client credentials\n\nvar credentials = {\n    id: 'dh37fgj492je',\n    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\n    algorithm: 'sha256'\n}\n\n// Generate bewit\n\nvar duration = 60 * 5;      // 5 Minutes\nvar bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });\nvar uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;\n```\n\n\n# Security Considerations\n\nThe greatest sources of security risks are usually found not in **Hawk** but in the policies and procedures surrounding its use.\nImplementers are strongly encouraged to assess how this module addresses their security requirements. This section includes\nan incomplete list of security considerations that must be reviewed and understood before deploying **Hawk** on the server.\nMany of the protections provided in **Hawk** depends on whether and how they are used.\n\n### MAC Keys Transmission\n\n**Hawk** does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used\nto obtain **Hawk** credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.\n\n### Confidentiality of Requests\n\nWhile **Hawk** provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request\nconfidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should\ncarefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms\nto protect sensitive resources.\n\n### Spoofing by Counterfeit Servers\n\n**Hawk** provides limited verification of the server authenticity. When receiving a response back from the server, the server\nmay choose to include a response `Server-Authorization` header which the client can use to verify the response. However, it is up to\nthe server to determine when such measure is included, to up to the client to enforce that policy.\n\nA hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise\nincorrect responses. Service providers should consider such attacks when developing services using this protocol, and should\nrequire transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.\n\n### Plaintext Storage of Credentials\n\nThe **Hawk** key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC,\nthe server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which\nstore only a one-way hash of user credentials.\n\nIf an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able\nto perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized\naccess.\n\n### Entropy of Keys\n\nUnless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request\nMAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to\nassign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the **Hawk**\ncredentials are valid.\n\nFor example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force\nattack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the\nlongest key reasonable.\n\nIt is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high\nquality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit\npatterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use\ncryptographically secure PRNGs to avoid these problems.\n\n### Coverage Limitations\n\nThe request MAC only covers the HTTP `Host` header and optionally the `Content-Type` header. It does not cover any other headers\nwhich can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence\nor value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the\n`ext` feature to pass application-specific information via the `Authorization` header which is protected by the request MAC.\n\nThe response authentication, when performed, only covers the response payload, content-type, and the request information \nprovided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or\nany other response header field (e.g. Location) which can affect the client's behaviour.\n\n### Future Time Manipulation\n\nThe protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its\ncurrent time when an invalid timestamp is received.\n\nIf an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause\nthe client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will\nnot likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then\nbe able to replay the request at the correct time without detection.\n\nThe client must only use the time information provided by the server if:\n* it was delivered over a TLS connection and the server identity has been verified, or\n* the `tsm` MAC digest calculated using the same client credentials over the timestamp has been verified.\n\n### Client Clock Poisoning\n\nWhen receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use\nthe time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with\nthat particular server.\n\n### Bewit Limitations\n\nSpecial care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot\nbe revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with\naccess to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET\nrequests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private\nand sensitive information.\n\n### Host Header Forgery\n\nHawk validates the incoming request MAC against the incoming HTTP Host header. However, unless the optional `host` and `port`\noptions are used with `server.authenticate()`, a malicous client can mint new host names pointing to the server's IP address and\nuse that to craft an attack by sending a valid request that's meant for another hostname than the one used by the server. Server\nimplementors must manually verify that the host header received matches their expectation (or use the options mentioned above).\n\n# Frequently Asked Questions\n\n### Where is the protocol specification?\n\nIf you are looking for some prose explaining how all this works, **this is it**. **Hawk** is being developed as an open source\nproject instead of a standard. In other words, the [code](/hueniverse/hawk/tree/master/lib) is the specification. Not sure about\nsomething? Open an issue!\n\n### Is it done?\n\nAt if version 0.10.0, **Hawk** is feature-complete. However, until this module reaches version 1.0.0 it is considered experimental\nand is likely to change. This also means your feedback and contribution are very welcome. Feel free to open issues with questions\nand suggestions.\n\n### Where can I find **Hawk** implementations in other languages?\n\n**Hawk**'s only reference implementation is provided in JavaScript as a node.js module. However, others are actively porting it to other\nplatforms. There is already a [PHP](https://github.com/alexbilbie/PHP-Hawk),\n[.NET](https://github.com/pcibraro/hawknet), and [JAVA](https://github.com/wealdtech/hawk) libraries available. The full list\nis maintained [here](https://github.com/hueniverse/hawk/issues?labels=port). Please add an issue if you are working on another\nport. A cross-platform test-suite is in the works.\n\n### Why isn't the algorithm part of the challenge or dynamically negotiated?\n\nThe algorithm used is closely related to the key issued as different algorithms require different key sizes (and other\nrequirements). While some keys can be used for multiple algorithm, the protocol is designed to closely bind the key and algorithm\ntogether as part of the issued credentials.\n\n### Why is Host and Content-Type the only headers covered by the request MAC?\n\nIt is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no\nwell-established way to normalize them. Many platforms change the case of header field names and values. The only\nstraight-forward solution is to include the headers in some blob (say, base64 encoded JSON) and include that with the request,\nan approach taken by JWT and other such formats. However, that design violates the HTTP header boundaries, repeats information,\nand introduces other security issues because firewalls will not be aware of these \"hidden\" headers. In addition, any information\nrepeated must be compared to the duplicated information in the header and therefore only moves the problem elsewhere.\n\n### Why not just use HTTP Digest?\n\nDigest requires pre-negotiation to establish a nonce. This means you can't just make a request - you must first send\na protocol handshake to the server. This pattern has become unacceptable for most web services, especially mobile\nwhere extra round-trip are costly.\n\n### Why bother with all this nonce and timestamp business?\n\n**Hawk** is an attempt to find a reasonable, practical compromise between security and usability. OAuth 1.0 got timestamp\nand nonces halfway right but failed when it came to scalability and consistent developer experience. **Hawk** addresses\nit by requiring the client to sync its clock, but provides it with tools to accomplish it.\n\nIn general, replay protection is a matter of application-specific threat model. It is less of an issue on a TLS-protected\nsystem where the clients are implemented using best practices and are under the control of the server. Instead of dropping\nreplay protection, **Hawk** offers a required time window and an optional nonce verification. Together, it provides developers\nwith the ability to decide how to enforce their security policy without impacting the client's implementation.\n\n### What are `app` and `dlg` in the authorization header and normalized mac string?\n\nThe original motivation for **Hawk** was to replace the OAuth 1.0 use cases. This included both a simple client-server mode which\nthis module is specifically designed for, and a delegated access mode which is being developed separately in\n[Oz](https://github.com/hueniverse/oz). In addition to the **Hawk** use cases, Oz requires another attribute: the application id `app`.\nThis provides binding between the credentials and the application in a way that prevents an attacker from tricking an application\nto use credentials issued to someone else. It also has an optional 'delegated-by' attribute `dlg` which is the application id of the\napplication the credentials were directly issued to. The goal of these two additions is to allow Oz to utilize **Hawk** directly,\nbut with the additional security of delegated credentials.\n\n### What is the purpose of the static strings used in each normalized MAC input?\n\nWhen calculating a hash or MAC, a static prefix (tag) is added. The prefix is used to prevent MAC values from being\nused or reused for a purpose other than what they were created for (i.e. prevents switching MAC values between a request,\nresponse, and a bewit use cases). It also protects against expliots created after a potential change in how the protocol\ncreates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it\ncan create an exploit opportunity for cases where the nonce is similar in format to a timestamp.\n\n### Does **Hawk** have anything to do with OAuth?\n\nShort answer: no.\n\n**Hawk** was originally proposed as the OAuth MAC Token specification. However, the OAuth working group in its consistent\nincompetence failed to produce a final, usable solution to address one of the most popular use cases of OAuth 1.0 - using it\nto authenticate simple client-server transactions (i.e. two-legged). As you can guess, the OAuth working group is still hard\nat work to produce more garbage.\n\n**Hawk** provides a simple HTTP authentication scheme for making client-server requests. It does not address the OAuth use case\nof delegating access to a third party. If you are looking for an OAuth alternative, check out [Oz](https://github.com/hueniverse/oz).\n\n\n# Acknowledgements\n\n**Hawk** is a derivative work of the [HTTP MAC Authentication Scheme](http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) proposal\nco-authored by Ben Adida, Adam Barth, and Eran Hammer, which in turn was based on the OAuth 1.0 community specification.\n\nSpecial thanks to Ben Laurie for his always insightful feedback and advice.\n\nThe **Hawk** logo was created by [Chris Carrasco](http://chriscarrasco.com).\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/hueniverse/hawk/issues"
-  },
-  "homepage": "https://github.com/hueniverse/hawk",
-  "_id": "hawk@1.0.0",
-  "_shasum": "b90bb169807285411da7ffcb8dd2598502d3b52d",
-  "_from": "hawk@~1.0.0",
-  "_resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/browser.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/browser.js
deleted file mode 100755
index b25a10fd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/browser.js
+++ /dev/null
@@ -1,771 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Hoek = require('hoek');
-var Hawk = require('../lib');
-var Browser = require('../lib/browser');
-var LocalStorage = require('localStorage');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Browser', function () {
-
-    var credentialsFunc = function (id, callback) {
-
-        var credentials = {
-            id: id,
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: (id === '1' ? 'sha1' : 'sha256'),
-            user: 'steve'
-        };
-
-        return callback(null, credentials);
-    };
-
-    it('should generate a header then successfully parse it (configuration)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
-            expect(req.authorization).to.exist;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (node request)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-                expect(res.headers['server-authorization']).to.exist;
-
-                expect(Browser.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (no server header options)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
-                expect(res.headers['server-authorization']).to.exist;
-
-                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (no server header)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('should generate a header with stale ts and successfully authenticate on second call', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            Browser.utils.setNtpOffset(60 * 60 * 1000);
-            var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' });
-            req.authorization = header.field;
-            expect(req.authorization).to.exist;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Stale timestamp');
-
-                var res = {
-                    headers: {
-                        'www-authenticate': err.response.headers['WWW-Authenticate']
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
-                expect(Browser.client.authenticate(res, credentials, header.artifacts)).to.equal(true);
-                expect(Browser.utils.getNtpOffset()).to.equal(0);
-
-                req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
-                expect(req.authorization).to.exist;
-
-                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    expect(artifacts.ext).to.equal('some-app-data');
-                    done();
-                });
-            });
-        });
-    });
-
-    it('should generate a header with stale ts and successfully authenticate on second call (manual localStorage)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-            Browser.utils.setStorage(LocalStorage)
-
-            Browser.utils.setNtpOffset(60 * 60 * 1000);
-            var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' });
-            req.authorization = header.field;
-            expect(req.authorization).to.exist;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Stale timestamp');
-
-                var res = {
-                    headers: {
-                        'www-authenticate': err.response.headers['WWW-Authenticate']
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                expect(parseInt(LocalStorage.getItem('hawk_ntp_offset'))).to.equal(60 * 60 * 1000);
-                expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
-                expect(Browser.client.authenticate(res, credentials, header.artifacts)).to.equal(true);
-                expect(Browser.utils.getNtpOffset()).to.equal(0);
-                expect(parseInt(LocalStorage.getItem('hawk_ntp_offset'))).to.equal(0);
-
-                req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
-                expect(req.authorization).to.exist;
-
-                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    expect(artifacts.ext).to.equal('some-app-data');
-                    done();
-                });
-            });
-        });
-    });
-
-    it('should generate a header then fails to parse it (missing server header hash)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
-                expect(res.headers['server-authorization']).to.exist;
-
-                expect(Browser.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(false);
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (with hash)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it then validate payload', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload('hola!', credentials, artifacts)).to.be.true;
-                expect(Hawk.server.authenticatePayload('hello!', credentials, artifacts)).to.be.false;
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (app)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(artifacts.app).to.equal('asd23ased');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (app, dlg)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased', dlg: '23434szr3q4d' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(artifacts.app).to.equal('asd23ased');
-                expect(artifacts.dlg).to.equal('23434szr3q4d');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then fail authentication due to bad hash', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Bad payload hash');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header for one resource then fail to authenticate another', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
-            req.url = '/something/else';
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.exist;
-                expect(credentials).to.exist;
-                done();
-            });
-        });
-    });
-
-    describe('client', function () {
-
-        describe('#header', function () {
-
-            it('should return a valid authorization header (sha1)', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'sha1'
-                };
-
-                var header = Browser.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' }).field;
-                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
-                done();
-            });
-
-            it('should return a valid authorization header (sha256)', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'sha256'
-                };
-
-                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
-                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
-                done();
-            });
-
-            it('should return a valid authorization header (no ext)', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'sha256'
-                };
-
-                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
-                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
-                done();
-            });
-
-            it('should return an empty authorization header on missing options', function (done) {
-
-                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST').field;
-                expect(header).to.equal('');
-                done();
-            });
-
-            it('should return an empty authorization header on invalid credentials', function (done) {
-
-                var credentials = {
-                    key: '2983d45yun89q',
-                    algorithm: 'sha256'
-                };
-
-                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }).field;
-                expect(header).to.equal('');
-                done();
-            });
-
-            it('should return an empty authorization header on invalid algorithm', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'hmac-sha-0'
-                };
-
-                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 }).field;
-                expect(header).to.equal('');
-                done();
-            });
-        });
-
-        describe('#authenticate', function () {
-
-            it('should return false on invalid header', function (done) {
-
-                var res = {
-                    headers: {
-                        'server-authorization': 'Hawk mac="abc", bad="xyz"'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                expect(Browser.client.authenticate(res, {})).to.equal(false);
-                done();
-            });
-
-            it('should return false on invalid mac', function (done) {
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain',
-                        'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                var artifacts = {
-                    method: 'POST',
-                    host: 'example.com',
-                    port: '8080',
-                    resource: '/resource/4?filter=a',
-                    ts: '1362336900',
-                    nonce: 'eb5S_L',
-                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                    ext: 'some-app-data',
-                    app: undefined,
-                    dlg: undefined,
-                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
-                    id: '123456'
-                };
-
-                var credentials = {
-                    id: '123456',
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'sha256',
-                    user: 'steve'
-                };
-
-                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(false);
-                done();
-            });
-
-            it('should return true on ignoring hash', function (done) {
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain',
-                        'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                var artifacts = {
-                    method: 'POST',
-                    host: 'example.com',
-                    port: '8080',
-                    resource: '/resource/4?filter=a',
-                    ts: '1362336900',
-                    nonce: 'eb5S_L',
-                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                    ext: 'some-app-data',
-                    app: undefined,
-                    dlg: undefined,
-                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
-                    id: '123456'
-                };
-
-                var credentials = {
-                    id: '123456',
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'sha256',
-                    user: 'steve'
-                };
-
-                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
-                done();
-            });
-
-            it('should fail on invalid WWW-Authenticate header format', function (done) {
-
-                var res = {
-                    headers: {
-                        'www-authenticate': 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                expect(Browser.client.authenticate(res, {})).to.equal(false);
-                done();
-            });
-
-            it('should fail on invalid WWW-Authenticate header format', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'sha256',
-                    user: 'steve'
-                };
-
-                var res = {
-                    headers: {
-                        'www-authenticate': 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"'
-                    },
-                    getResponseHeader: function (header) {
-
-                        return res.headers[header.toLowerCase()];
-                    }
-                };
-
-                expect(Browser.client.authenticate(res, credentials)).to.equal(false);
-                done();
-            });
-        });
-
-        describe('#message', function () {
-            it('should generate an authorization then successfully parse it', function (done) {
-
-                credentialsFunc('123456', function (err, credentials) {
-
-                    var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: credentials });
-                    expect(auth).to.exist;
-
-                    Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) {
-
-                        expect(err).to.not.exist;
-                        expect(credentials.user).to.equal('steve');
-                        done();
-                    });
-                });
-            });
-
-            it('should fail on missing host', function (done) {
-
-                credentialsFunc('123456', function (err, credentials) {
-
-                    var auth = Browser.client.message(null, 8080, 'some message', { credentials: credentials });
-                    expect(auth).to.not.exist;
-                    done();
-                });
-            });
-
-            it('should fail on missing credentials', function (done) {
-
-                var auth = Browser.client.message('example.com', 8080, 'some message', {});
-                expect(auth).to.not.exist;
-                done();
-            });
-
-            it('should fail on invalid algorithm', function (done) {
-
-                credentialsFunc('123456', function (err, credentials) {
-
-                    var creds = Hoek.clone(credentials);
-                    creds.algorithm = 'blah';
-                    var auth = Browser.client.message('example.com', 8080, 'some message', { credentials: creds });
-                    expect(auth).to.not.exist;
-                    done();
-                });
-            });
-        });
-    });
-
-    describe('#parseAuthorizationHeader', function (done) {
-
-        it('returns null on missing header', function (done) {
-
-            expect(Browser.utils.parseAuthorizationHeader()).to.equal(null);
-            done();
-        });
-
-        it('returns null on bad header syntax (structure)', function (done) {
-
-            expect(Browser.utils.parseAuthorizationHeader('Hawk')).to.equal(null);
-            done();
-        });
-
-        it('returns null on bad header syntax (parts)', function (done) {
-
-            expect(Browser.utils.parseAuthorizationHeader(' ')).to.equal(null);
-            done();
-        });
-
-        it('returns null on bad scheme name', function (done) {
-
-            expect(Browser.utils.parseAuthorizationHeader('Basic asdasd')).to.equal(null);
-            done();
-        });
-
-        it('returns null on bad attribute value', function (done) {
-
-            expect(Browser.utils.parseAuthorizationHeader('Hawk test="\t"', ['test'])).to.equal(null);
-            done();
-        });
-
-        it('returns null on duplicated attribute', function (done) {
-
-            expect(Browser.utils.parseAuthorizationHeader('Hawk test="a", test="b"', ['test'])).to.equal(null);
-            done();
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/client.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/client.js
deleted file mode 100755
index bcc4222a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/client.js
+++ /dev/null
@@ -1,206 +0,0 @@
-// Load modules
-
-var Url = require('url');
-var Lab = require('lab');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    describe('client', function () {
-
-        describe('#header', function () {
-
-            it('should return a valid authorization header (sha1)', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'sha1'
-                };
-
-                var header = Hawk.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' }).field;
-                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
-                done();
-            });
-
-            it('should return a valid authorization header (sha256)', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'sha256'
-                };
-
-                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
-                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
-                done();
-            });
-
-            it('should return a valid authorization header (no ext)', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'sha256'
-                };
-
-                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
-                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
-                done();
-            });
-
-            it('should return an empty authorization header on missing options', function (done) {
-
-                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST').field;
-                expect(header).to.equal('');
-                done();
-            });
-
-            it('should return an empty authorization header on invalid credentials', function (done) {
-
-                var credentials = {
-                    key: '2983d45yun89q',
-                    algorithm: 'sha256'
-                };
-
-                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }).field;
-                expect(header).to.equal('');
-                done();
-            });
-
-            it('should return an empty authorization header on invalid algorithm', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: '2983d45yun89q',
-                    algorithm: 'hmac-sha-0'
-                };
-
-                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 }).field;
-                expect(header).to.equal('');
-                done();
-            });
-        });
-
-        describe('#authenticate', function () {
-
-            it('should return false on invalid header', function (done) {
-
-                var res = {
-                    headers: {
-                        'server-authorization': 'Hawk mac="abc", bad="xyz"'
-                    }
-                };
-
-                expect(Hawk.client.authenticate(res, {})).to.equal(false);
-                done();
-            });
-
-            it('should return false on invalid mac', function (done) {
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain',
-                        'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
-                    }
-                };
-
-                var artifacts = {
-                    method: 'POST',
-                    host: 'example.com',
-                    port: '8080',
-                    resource: '/resource/4?filter=a',
-                    ts: '1362336900',
-                    nonce: 'eb5S_L',
-                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                    ext: 'some-app-data',
-                    app: undefined,
-                    dlg: undefined,
-                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
-                    id: '123456'
-                };
-
-                var credentials = {
-                    id: '123456',
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'sha256',
-                    user: 'steve'
-                };
-
-                expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(false);
-                done();
-            });
-
-            it('should return true on ignoring hash', function (done) {
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain',
-                        'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
-                    }
-                };
-
-                var artifacts = {
-                    method: 'POST',
-                    host: 'example.com',
-                    port: '8080',
-                    resource: '/resource/4?filter=a',
-                    ts: '1362336900',
-                    nonce: 'eb5S_L',
-                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                    ext: 'some-app-data',
-                    app: undefined,
-                    dlg: undefined,
-                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
-                    id: '123456'
-                };
-
-                var credentials = {
-                    id: '123456',
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'sha256',
-                    user: 'steve'
-                };
-
-                expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
-                done();
-            });
-
-            it('should fail on invalid WWW-Authenticate header format', function (done) {
-
-                var header = 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"';
-                expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(false);
-                done();
-            });
-
-            it('should fail on invalid WWW-Authenticate header format', function (done) {
-
-                var credentials = {
-                    id: '123456',
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'sha256',
-                    user: 'steve'
-                };
-
-                var header = 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"';
-                expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, credentials)).to.equal(false);
-                done();
-            });
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/crypto.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/crypto.js
deleted file mode 100755
index b62c2177..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/crypto.js
+++ /dev/null
@@ -1,86 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    describe('Crypto', function () {
-
-        describe('#generateNormalizedString', function () {
-
-            it('should return a valid normalized string', function (done) {
-
-                expect(Hawk.crypto.generateNormalizedString('header', {
-                    credentials: {
-                        key: 'dasdfasdf',
-                        algorithm: 'sha256'
-                    },
-                    ts: 1357747017,
-                    nonce: 'k3k4j5',
-                    method: 'GET',
-                    resource: '/resource/something',
-                    host: 'example.com',
-                    port: 8080
-                })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\n\n');
-
-                done();
-            });
-
-            it('should return a valid normalized string (ext)', function (done) {
-
-                expect(Hawk.crypto.generateNormalizedString('header', {
-                    credentials: {
-                        key: 'dasdfasdf',
-                        algorithm: 'sha256'
-                    },
-                    ts: 1357747017,
-                    nonce: 'k3k4j5',
-                    method: 'GET',
-                    resource: '/resource/something',
-                    host: 'example.com',
-                    port: 8080,
-                    ext: 'this is some app data'
-                })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\nthis is some app data\n');
-
-                done();
-            });
-
-            it('should return a valid normalized string (payload + ext)', function (done) {
-
-                expect(Hawk.crypto.generateNormalizedString('header', {
-                    credentials: {
-                        key: 'dasdfasdf',
-                        algorithm: 'sha256'
-                    },
-                    ts: 1357747017,
-                    nonce: 'k3k4j5',
-                    method: 'GET',
-                    resource: '/resource/something',
-                    host: 'example.com',
-                    port: 8080,
-                    hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
-                    ext: 'this is some app data'
-                })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\nU4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=\nthis is some app data\n');
-
-                done();
-            });
-        });
-    });
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/index.js
deleted file mode 100755
index ba837388..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/index.js
+++ /dev/null
@@ -1,316 +0,0 @@
-// Load modules
-
-var Url = require('url');
-var Lab = require('lab');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    var credentialsFunc = function (id, callback) {
-
-        var credentials = {
-            id: id,
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: (id === '1' ? 'sha1' : 'sha256'),
-            user: 'steve'
-        };
-
-        return callback(null, credentials);
-    };
-
-    it('should generate a header then successfully parse it (configuration)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Hawk.client.header(Url.parse('http://example.com:8080/resource/4?filter=a'), req.method, { credentials: credentials, ext: 'some-app-data' }).field;
-            expect(req.authorization).to.exist;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (node request)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-                expect(res.headers['server-authorization']).to.exist;
-
-                expect(Hawk.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (no server header options)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
-                expect(res.headers['server-authorization']).to.exist;
-
-                expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then fails to parse it (missing server header hash)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
-                expect(res.headers['server-authorization']).to.exist;
-
-                expect(Hawk.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(false);
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (with hash)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it then validate payload', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload('hola!', credentials, artifacts)).to.be.true;
-                expect(Hawk.server.authenticatePayload('hello!', credentials, artifacts)).to.be.false;
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (app)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(artifacts.app).to.equal('asd23ased');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then successfully parse it (app, dlg)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased', dlg: '23434szr3q4d' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(artifacts.app).to.equal('asd23ased');
-                expect(artifacts.dlg).to.equal('23434szr3q4d');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header then fail authentication due to bad hash', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Bad payload hash');
-                done();
-            });
-        });
-    });
-
-    it('should generate a header for one resource then fail to authenticate another', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
-            req.url = '/something/else';
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.exist;
-                expect(credentials).to.exist;
-                done();
-            });
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/message.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/message.js
deleted file mode 100755
index 04b91d41..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/message.js
+++ /dev/null
@@ -1,246 +0,0 @@
-// Load modules
-
-var Url = require('url');
-var Lab = require('lab');
-var Hoek = require('hoek');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    var credentialsFunc = function (id, callback) {
-
-        var credentials = {
-            id: id,
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: (id === '1' ? 'sha1' : 'sha256'),
-            user: 'steve'
-        };
-
-        return callback(null, credentials);
-    };
-
-    it('should generate an authorization then successfully parse it', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on mismatching host', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            Hawk.server.authenticateMessage('example1.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Bad mac');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on stale timestamp', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Stale timestamp');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on invalid authorization', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-            delete auth.id;
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Invalid authorization');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on bad hash', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message1', auth, credentialsFunc, {}, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Bad message hash');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on nonce error', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { nonceFunc: function (nonce, ts, callback) { callback (new Error('kaboom')); } }, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Invalid nonce');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on credentials error', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            var errFunc = function (id, callback) {
-
-                callback(new Error('kablooey'));
-            };
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('kablooey');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on missing credentials', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            var errFunc = function (id, callback) {
-
-                callback();
-            };
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Unknown credentials');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on invalid credentials', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            var errFunc = function (id, callback) {
-
-                callback(null, {});
-            };
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Invalid credentials');
-                done();
-            });
-        });
-    });
-
-    it('should fail authorization on invalid credentials algorithm', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials });
-            expect(auth).to.exist;
-
-            var errFunc = function (id, callback) {
-
-                callback(null, { key: '123', algorithm: '456' });
-            };
-
-            Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Unknown algorithm');
-                done();
-            });
-        });
-    });
-
-    it('should fail on missing host', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var auth = Hawk.client.message(null, 8080, 'some message', { credentials: credentials });
-            expect(auth).to.not.exist;
-            done();
-        });
-    });
-
-    it('should fail on missing credentials', function (done) {
-
-        var auth = Hawk.client.message('example.com', 8080, 'some message', {});
-        expect(auth).to.not.exist;
-        done();
-    });
-
-    it('should fail on invalid algorithm', function (done) {
-
-        credentialsFunc('123456', function (err, credentials) {
-
-            var creds = Hoek.clone(credentials);
-            creds.algorithm = 'blah';
-            var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: creds });
-            expect(auth).to.not.exist;
-            done();
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/readme.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/readme.js
deleted file mode 100755
index f39e033d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/readme.js
+++ /dev/null
@@ -1,98 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Hoek = require('hoek');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    describe('README', function () {
-
-        describe('core', function () {
-
-            var credentials = {
-                id: 'dh37fgj492je',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256'
-            };
-
-            var options = {
-                credentials: credentials,
-                timestamp: 1353832234,
-                nonce: 'j4h3g2',
-                ext: 'some-app-ext-data'
-            };
-
-            it('should generate a header protocol example', function (done) {
-
-                var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', options).field;
-
-                expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="');
-                done();
-            });
-
-            it('should generate a normalized string protocol example', function (done) {
-
-                var normalized = Hawk.crypto.generateNormalizedString('header', {
-                    credentials: credentials,
-                    ts: options.timestamp,
-                    nonce: options.nonce,
-                    method: 'GET',
-                    resource: '/resource?a=1&b=2',
-                    host: 'example.com',
-                    port: 8000,
-                    ext: options.ext
-                });
-
-                expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nGET\n/resource?a=1&b=2\nexample.com\n8000\n\nsome-app-ext-data\n');
-                done();
-            });
-
-            var payloadOptions = Hoek.clone(options);
-            payloadOptions.payload = 'Thank you for flying Hawk';
-            payloadOptions.contentType = 'text/plain';
-
-            it('should generate a header protocol example (with payload)', function (done) {
-
-                var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'POST', payloadOptions).field;
-
-                expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="');
-                done();
-            });
-
-            it('should generate a normalized string protocol example (with payload)', function (done) {
-
-                var normalized = Hawk.crypto.generateNormalizedString('header', {
-                    credentials: credentials,
-                    ts: options.timestamp,
-                    nonce: options.nonce,
-                    method: 'POST',
-                    resource: '/resource?a=1&b=2',
-                    host: 'example.com',
-                    port: 8000,
-                    hash: Hawk.crypto.calculatePayloadHash(payloadOptions.payload, credentials.algorithm, payloadOptions.contentType),
-                    ext: options.ext
-                });
-
-                expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nPOST\n/resource?a=1&b=2\nexample.com\n8000\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\nsome-app-ext-data\n');
-                done();
-            });
-        });
-    });
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/server.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/server.js
deleted file mode 100755
index 3e92427a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/server.js
+++ /dev/null
@@ -1,686 +0,0 @@
-// Load modules
-
-var Url = require('url');
-var Lab = require('lab');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    describe('server', function () {
-
-        var credentialsFunc = function (id, callback) {
-
-            var credentials = {
-                id: id,
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: (id === '1' ? 'sha1' : 'sha256'),
-                user: 'steve'
-            };
-
-            return callback(null, credentials);
-        };
-
-        describe('#authenticate', function () {
-
-            it('should parse a valid authentication header (sha1)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    done();
-                });
-            });
-
-            it('should parse a valid authentication header (sha256)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/1?b=1&a=2',
-                    host: 'example.com',
-                    port: 8000,
-                    authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    done();
-                });
-            });
-
-            it('should parse a valid authentication header (host override)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: 'example1.com:8080',
-                        authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
-                    }
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    done();
-                });
-            });
-
-            it('should parse a valid authentication header (host port override)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: 'example1.com:80',
-                        authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
-                    }
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', port: 8080, localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    done();
-                });
-            });
-
-            it('should parse a valid authentication header (POST with payload)', function (done) {
-
-                var req = {
-                    method: 'POST',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123456", ts="1357926341", nonce="1AwuJD", hash="qAiXIVv+yjDATneWxZP2YCTa9aHRgQdnH9b3Wc+o3dg=", ext="some-app-data", mac="UeYcj5UoTVaAWXNvJfLVia7kU3VabxCqrccXP8sUGC4="'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    done();
-                });
-            });
-
-            it('should fail on missing hash', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/1?b=1&a=2',
-                    host: 'example.com',
-                    port: 8000,
-                    authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Missing required payload hash');
-                    done();
-                });
-            });
-
-            it('should fail on a stale timestamp', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123456", ts="1362337299", nonce="UzmxSs", ext="some-app-data", mac="wnNUxchvvryMH2RxckTdZ/gY3ijzvccx4keVvELC61w="'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Stale timestamp');
-                    var header = err.response.headers['WWW-Authenticate'];
-                    var ts = header.match(/^Hawk ts\=\"(\d+)\"\, tsm\=\"([^\"]+)\"\, error=\"Stale timestamp\"$/);
-                    var now = Hawk.utils.now();
-                    expect(parseInt(ts[1], 10) * 1000).to.be.within(now - 1000, now + 1000);
-
-                    var res = {
-                        headers: {
-                            'www-authenticate': header
-                        }
-                    };
-
-                    expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
-                    done();
-                });
-            });
-
-            it('should fail on a replay', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"'
-                };
-
-                var memoryCache = {};
-                var options = {
-                    localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(),
-                    nonceFunc: function (nonce, ts, callback) {
-
-                        if (memoryCache[nonce]) {
-                            return callback(new Error());
-                        }
-
-                        memoryCache[nonce] = true;
-                        return callback();
-                    }
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-
-                    Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) {
-
-                        expect(err).to.exist;
-                        expect(err.response.payload.message).to.equal('Invalid nonce');
-                        done();
-                    });
-                });
-            });
-
-            it('should fail on an invalid authentication header: wrong scheme', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Basic asdasdasdasd'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.not.exist;
-                    done();
-                });
-            });
-
-            it('should fail on an invalid authentication header: no scheme', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: '!@#'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Invalid header syntax');
-                    done();
-                });
-            });
-
-            it('should fail on an missing authorization header', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.isMissing).to.equal(true);
-                    done();
-                });
-            });
-
-            it('should fail on an missing host header', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                    }
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Invalid Host header');
-                    done();
-                });
-            });
-
-            it('should fail on an missing authorization attribute (id)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Missing attributes');
-                    done();
-                });
-            });
-
-            it('should fail on an missing authorization attribute (ts)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Missing attributes');
-                    done();
-                });
-            });
-
-            it('should fail on an missing authorization attribute (nonce)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Missing attributes');
-                    done();
-                });
-            });
-
-            it('should fail on an missing authorization attribute (mac)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Missing attributes');
-                    done();
-                });
-            });
-
-            it('should fail on an unknown authorization attribute', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", x="3", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Unknown attribute: x');
-                    done();
-                });
-            });
-
-            it('should fail on an bad authorization header format', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123\\", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Bad header format');
-                    done();
-                });
-            });
-
-            it('should fail on an bad authorization attribute value', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="\t", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Bad attribute value: id');
-                    done();
-                });
-            });
-
-            it('should fail on an empty authorization attribute value', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Bad attribute value: id');
-                    done();
-                });
-            });
-
-            it('should fail on duplicated authorization attribute key', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", id="456", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Duplicate attribute: id');
-                    done();
-                });
-            });
-
-            it('should fail on an invalid authorization header format', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk'
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Invalid header syntax');
-                    done();
-                });
-            });
-
-            it('should fail on an bad host header (missing host)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: ':8080',
-                        authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                    }
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Invalid Host header');
-                    done();
-                });
-            });
-
-            it('should fail on an bad host header (pad port)', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: 'example.com:something',
-                        authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                    }
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Invalid Host header');
-                    done();
-                });
-            });
-
-            it('should fail on credentialsFunc error', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                var credentialsFunc = function (id, callback) {
-
-                    return callback(new Error('Unknown user'));
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.message).to.equal('Unknown user');
-                    done();
-                });
-            });
-
-            it('should fail on missing credentials', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                var credentialsFunc = function (id, callback) {
-
-                    return callback(null, null);
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Unknown credentials');
-                    done();
-                });
-            });
-
-            it('should fail on invalid credentials', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                var credentialsFunc = function (id, callback) {
-
-                    var credentials = {
-                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                        user: 'steve'
-                    };
-
-                    return callback(null, credentials);
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.message).to.equal('Invalid credentials');
-                    expect(err.response.payload.message).to.equal('An internal server error occurred');
-                    done();
-                });
-            });
-
-            it('should fail on unknown credentials algorithm', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                var credentialsFunc = function (id, callback) {
-
-                    var credentials = {
-                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                        algorithm: 'hmac-sha-0',
-                        user: 'steve'
-                    };
-
-                    return callback(null, credentials);
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.message).to.equal('Unknown algorithm');
-                    expect(err.response.payload.message).to.equal('An internal server error occurred');
-                    done();
-                });
-            });
-
-            it('should fail on unknown bad mac', function (done) {
-
-                var req = {
-                    method: 'GET',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080,
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcU4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                };
-
-                var credentialsFunc = function (id, callback) {
-
-                    var credentials = {
-                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                        algorithm: 'sha256',
-                        user: 'steve'
-                    };
-
-                    return callback(null, credentials);
-                };
-
-                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Bad mac');
-                    done();
-                });
-            });
-        });
-
-        describe('#header', function () {
-
-            it('should return an empty authorization header on missing options', function (done) {
-
-                var header = Hawk.server.header();
-                expect(header).to.equal('');
-                done();
-            });
-
-            it('should return an empty authorization header on missing credentials', function (done) {
-
-                var header = Hawk.server.header(null, {});
-                expect(header).to.equal('');
-                done();
-            });
-
-            it('should return an empty authorization header on invalid credentials', function (done) {
-
-                var credentials = {
-                    key: '2983d45yun89q'
-                };
-
-                var header = Hawk.server.header(credentials);
-                expect(header).to.equal('');
-                done();
-            });
-
-            it('should return an empty authorization header on invalid algorithm', function (done) {
-
-                var artifacts = {
-                    id: '123456'
-                };
-
-                var credentials = {
-                    key: '2983d45yun89q',
-                    algorithm: 'hmac-sha-0'
-                };
-
-                var header = Hawk.server.header(credentials, artifacts);
-                expect(header).to.equal('');
-                done();
-            });
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/uri.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/uri.js
deleted file mode 100755
index 44ffd7fb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/uri.js
+++ /dev/null
@@ -1,456 +0,0 @@
-// Load modules
-
-var Http = require('http');
-var Lab = require('lab');
-var Hawk = require('../lib');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    describe('Uri', function () {
-
-        var credentialsFunc = function (id, callback) {
-
-            var credentials = {
-                id: id,
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            return callback(null, credentials);
-        };
-
-        it('should generate a bewit then successfully authenticate it', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?a=1&b=2',
-                host: 'example.com',
-                port: 80
-            };
-
-            credentialsFunc('123456', function (err, credentials) {
-
-                var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' });
-                req.url += '&bewit=' + bewit;
-
-                Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    expect(attributes.ext).to.equal('some-app-data');
-                    done();
-                });
-            });
-        });
-
-        it('should generate a bewit then successfully authenticate it (no ext)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?a=1&b=2',
-                host: 'example.com',
-                port: 80
-            };
-
-            credentialsFunc('123456', function (err, credentials) {
-
-                var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100 });
-                req.url += '&bewit=' + bewit;
-
-                Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                    expect(err).to.not.exist;
-                    expect(credentials.user).to.equal('steve');
-                    done();
-                });
-            });
-        });
-
-        it('should successfully authenticate a request (last param)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(attributes.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-
-        it('should successfully authenticate a request (first param)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ&a=1&b=2',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(attributes.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-
-        it('should successfully authenticate a request (only param)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.not.exist;
-                expect(credentials.user).to.equal('steve');
-                expect(attributes.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-
-        it('should fail on multiple authentication', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Basic asdasdasdasd'
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Multiple authentications');
-                done();
-            });
-        });
-
-        it('should fail on method other than GET', function (done) {
-
-            credentialsFunc('123456', function (err, credentials) {
-
-                var req = {
-                    method: 'POST',
-                    url: '/resource/4?filter=a',
-                    host: 'example.com',
-                    port: 8080
-                };
-
-                var exp = Math.floor(Hawk.utils.now() / 1000) + 60;
-                var ext = 'some-app-data';
-                var mac = Hawk.crypto.calculateMac('bewit', credentials, {
-                    timestamp: exp,
-                    nonce: '',
-                    method: req.method,
-                    resource: req.url,
-                    host: req.host,
-                    port: req.port,
-                    ext: ext
-                });
-
-                var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + ext;
-
-                req.url += '&bewit=' + Hawk.utils.base64urlEncode(bewit);
-
-                Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                    expect(err).to.exist;
-                    expect(err.response.payload.message).to.equal('Invalid method');
-                    done();
-                });
-            });
-        });
-
-        it('should fail on invalid host header', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-                headers: {
-                    host: 'example.com:something'
-                }
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Invalid Host header');
-                done();
-            });
-        });
-
-        it('should fail on empty bewit', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Empty bewit');
-                expect(err.isMissing).to.not.exist;
-                done();
-            });
-        });
-
-        it('should fail on invalid bewit', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=*',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Invalid bewit encoding');
-                expect(err.isMissing).to.not.exist;
-                done();
-            });
-        });
-
-        it('should fail on missing bewit', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.not.exist;
-                expect(err.isMissing).to.equal(true);
-                done();
-            });
-        });
-
-        it('should fail on invalid bewit structure', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=abc',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Invalid bewit structure');
-                done();
-            });
-        });
-
-        it('should fail on empty bewit attribute', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=YVxcY1xk',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Missing bewit attributes');
-                done();
-            });
-        });
-
-        it('should fail on expired access', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDEzNTY0MTg1ODNcWk1wZlMwWU5KNHV0WHpOMmRucTRydEk3NXNXTjFjeWVITTcrL0tNZFdVQT1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Access expired');
-                done();
-            });
-        });
-
-        it('should fail on credentials function error', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, function (id, callback) { callback(Hawk.error.badRequest('Boom')); }, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Boom');
-                done();
-            });
-        });
-
-        it('should fail on null credentials function response', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, function (id, callback) { callback(null, null); }, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Unknown credentials');
-                done();
-            });
-        });
-
-        it('should fail on invalid credentials function response', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, function (id, callback) { callback(null, {}); }, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Invalid credentials');
-                done();
-            });
-        });
-
-        it('should fail on invalid credentials function response (unknown algorithm)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, function (id, callback) { callback(null, { key: 'xxx', algorithm: 'xxx' }); }, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.message).to.equal('Unknown algorithm');
-                done();
-            });
-        });
-
-        it('should fail on expired access', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.uri.authenticate(req, function (id, callback) { callback(null, { key: 'xxx', algorithm: 'sha256' }); }, {}, function (err, credentials, attributes) {
-
-                expect(err).to.exist;
-                expect(err.response.payload.message).to.equal('Bad mac');
-                done();
-            });
-        });
-    });
-
-    describe('#getBewit', function () {
-
-        it('should return a valid bewit value', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
-            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
-            done();
-        });
-
-        it('should return an empty bewit on invalid credentials', function (done) {
-
-            var credentials = {
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('should return an empty bewit on invalid algorithm', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'hmac-sha-0'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('should return an empty bewit on missing options', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'hmac-sha-0'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow');
-            expect(bewit).to.equal('');
-            done();
-        });
-    });
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/utils.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/utils.js
deleted file mode 100755
index 0f5fef77..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/hawk/test/utils.js
+++ /dev/null
@@ -1,120 +0,0 @@
-// Load modules
-
-var Lab = require('lab');
-var Hawk = require('../lib');
-var Package = require('../package.json');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
-
-
-describe('Hawk', function () {
-
-    describe('Utils', function () {
-
-        describe('#parseHost', function () {
-
-            it('returns port 80 for non tls node request', function (done) {
-
-                var req = {
-                    method: 'POST',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: 'example.com',
-                        'content-type': 'text/plain;x=y'
-                    }
-                };
-
-                expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(80);
-                done();
-            });
-
-            it('returns port 443 for non tls node request', function (done) {
-
-                var req = {
-                    method: 'POST',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: 'example.com',
-                        'content-type': 'text/plain;x=y'
-                    },
-                    connection: {
-                        encrypted: true
-                    }
-                };
-
-                expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443);
-                done();
-            });
-
-            it('returns port 443 for non tls node request (IPv6)', function (done) {
-
-                var req = {
-                    method: 'POST',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: '[123:123:123]',
-                        'content-type': 'text/plain;x=y'
-                    },
-                    connection: {
-                        encrypted: true
-                    }
-                };
-
-                expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443);
-                done();
-            });
-
-            it('parses IPv6 headers', function (done) {
-
-                var req = {
-                    method: 'POST',
-                    url: '/resource/4?filter=a',
-                    headers: {
-                        host: '[123:123:123]:8000',
-                        'content-type': 'text/plain;x=y'
-                    },
-                    connection: {
-                        encrypted: true
-                    }
-                };
-
-                var host = Hawk.utils.parseHost(req, 'Host');
-                expect(host.port).to.equal('8000');
-                expect(host.name).to.equal('[123:123:123]');
-                done();
-            });
-        });
-
-        describe('#version', function () {
-
-            it('returns the correct package version number', function (done) {
-
-                expect(Hawk.utils.version()).to.equal(Package.version);
-                done();
-            });
-        });
-
-        describe('#unauthorized', function () {
-
-            it('returns a hawk 401', function (done) {
-
-                expect(Hawk.utils.unauthorized('kaboom').response.headers['WWW-Authenticate']).to.equal('Hawk error="kaboom"');
-                done();
-            });
-        });
-    });
-});
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.dir-locals.el b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.dir-locals.el
deleted file mode 100644
index 3bc9235f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.dir-locals.el
+++ /dev/null
@@ -1,6 +0,0 @@
-((nil . ((indent-tabs-mode . nil)
-         (tab-width . 8)
-         (fill-column . 80)))
- (js-mode . ((js-indent-level . 2)
-             (indent-tabs-mode . nil)
-             )))
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.npmignore
deleted file mode 100644
index c143fb3a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/.npmignore
+++ /dev/null
@@ -1,7 +0,0 @@
-.gitmodules
-deps
-docs
-Makefile
-node_modules
-test
-tools
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/LICENSE
deleted file mode 100644
index f6d947d2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/LICENSE
+++ /dev/null
@@ -1,18 +0,0 @@
-Copyright Joyent, Inc. All rights reserved.
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/README.md
deleted file mode 100644
index 0c707149..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/README.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# node-http-signature
-
-node-http-signature is a node.js library that has client and server components
-for Joyent's [HTTP Signature Scheme](http_signing.md).
-
-## Usage
-
-Note the example below signs a request with the same key/cert used to start an
-HTTP server. This is almost certainly not what you actaully want, but is just
-used to illustrate the API calls; you will need to provide your own key
-management in addition to this library.
-
-### Client
-
-    var fs = require('fs');
-    var https = require('https');
-    var httpSignature = require('http-signature');
-
-    var key = fs.readFileSync('./key.pem', 'ascii');
-
-    var options = {
-      host: 'localhost',
-      port: 8443,
-      path: '/',
-      method: 'GET',
-      headers: {}
-    };
-
-    // Adds a 'Date' header in, signs it, and adds the
-    // 'Authorization' header in.
-    var req = https.request(options, function(res) {
-      console.log(res.statusCode);
-    });
-
-
-    httpSignature.sign(req, {
-      key: key,
-      keyId: './cert.pem'
-    });
-
-    req.end();
-
-### Server
-
-    var fs = require('fs');
-    var https = require('https');
-    var httpSignature = require('http-signature');
-
-    var options = {
-      key: fs.readFileSync('./key.pem'),
-      cert: fs.readFileSync('./cert.pem')
-    };
-
-    https.createServer(options, function (req, res) {
-      var rc = 200;
-      var parsed = httpSignature.parseRequest(req);
-      var pub = fs.readFileSync(parsed.keyId, 'ascii');
-      if (!httpSignature.verifySignature(parsed, pub))
-        rc = 401;
-
-      res.writeHead(rc);
-      res.end();
-    }).listen(8443);
-
-## Installation
-
-    npm install http-signature
-
-## License
-
-MIT.
-
-## Bugs
-
-See <https://github.com/joyent/node-http-signature/issues>.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/http_signing.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/http_signing.md
deleted file mode 100644
index ba7321da..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/http_signing.md
+++ /dev/null
@@ -1,296 +0,0 @@
-# Abstract
-
-This document describes a way to add origin authentication, message integrity,
-and replay resistance to HTTP REST requests.  It is intended to be used over
-the HTTPS protocol.
-
-# Copyright Notice
-
-Copyright (c) 2011 Joyent, Inc. and the persons identified as document authors.
-All rights reserved.
-
-Code Components extracted from this document must include MIT License text.
-
-# Introduction
-
-This protocol is intended to provide a standard way for clients to sign HTTP
-requests.  RFC2617 (HTTP Authentication) defines Basic and Digest authentication
-mechanisms, and RFC5246 (TLS 1.2) defines client-auth, both of which are widely
-employed on the Internet today.  However, it is common place that the burdens of
-PKI prevent web service operators from deploying that methodoloy, and so many
-fall back to Basic authentication, which has poor security characteristics.
-
-Additionally, OAuth provides a fully-specified alternative for authorization
-of web service requests, but is not (always) ideal for machine to machine
-communication, as the key acquisition steps (generally) imply a fixed
-infrastructure that may not make sense to a service provider (e.g., symmetric
-keys).
-
-Several web service providers have invented their own schemes for signing
-HTTP requests, but to date, none have been placed in the public domain as a
-standard.  This document serves that purpose.  There are no techniques in this
-proposal that are novel beyond previous art, however, this aims to be a simple
-mechanism for signing these requests.
-
-# Signature Authentication Scheme
-
-The "signature" authentication scheme is based on the model that the client must
-authenticate itself with a digital signature produced by either a private
-asymmetric key (e.g., RSA) or a shared symmetric key (e.g., HMAC).  The scheme
-is parameterized enough such that it is not bound to any particular key type or
-signing algorithm.  However, it does explicitly assume that clients can send an
-HTTP `Date` header.
-
-## Authorization Header
-
-The client is expected to send an Authorization header (as defined in RFC 2617)
-with the following parameterization:
-
-    credentials := "Signature" params
-    params := 1#(keyId | algorithm | [headers] | [ext] | signature)
-    digitalSignature := plain-string
-
-    keyId := "keyId" "=" <"> plain-string <">
-    algorithm := "algorithm" "=" <"> plain-string <">
-    headers := "headers" "=" <"> 1#headers-value <">
-    ext := "ext" "=" <"> plain-string <">
-    signature := "signature" "=" <"> plain-string <">
-
-    headers-value := plain-string
-    plain-string   = 1*( %x20-21 / %x23-5B / %x5D-7E )
-
-### Signature Parameters
-
-#### keyId
-
-REQUIRED.  The `keyId` field is an opaque string that the server can use to look
-up the component they need to validate the signature.  It could be an SSH key
-fingerprint, an LDAP DN, etc.  Management of keys and assignment of `keyId` is
-out of scope for this document.
-
-#### algorithm
-
-REQUIRED. The `algorithm` parameter is used if the client and server agree on a
-non-standard digital signature algorithm.  The full list of supported signature
-mechanisms is listed below.
-
-#### headers
-
-OPTIONAL.  The `headers` parameter is used to specify the list of HTTP headers
-used to sign the request.  If specified, it should be a quoted list of HTTP
-header names, separated by a single space character.  By default, only one
-HTTP header is signed, which is the `Date` header.  Note that the list MUST be
-specified in the order the values are concatenated together during signing. To
-include the HTTP request line in the signature calculation, use the special
-`request-line` value.  While this is overloading the definition of `headers` in
-HTTP linguism, the request-line is defined in RFC 2616, and as the outlier from
-headers in useful signature calculation, it is deemed simpler to simply use
-`request-line` than to add a separate parameter for it.
-
-#### extensions
-
-OPTIONAL.  The `extensions` parameter is used to include additional information
-which is covered by the request.  The content and format of the string is out of
-scope for this document, and expected to be specified by implementors.
-
-#### signature
-
-REQUIRED.  The `signature` parameter is a `Base64` encoded digital signature
-generated by the client. The client uses the `algorithm` and `headers` request
-parameters to form a canonicalized `signing string`.  This `signing string` is
-then signed with the key associated with `keyId` and the algorithm
-corresponding to `algorithm`.  The `signature` parameter is then set to the
-`Base64` encoding of the signature.
-
-### Signing String Composition
-
-In order to generate the string that is signed with a key, the client MUST take
-the values of each HTTP header specified by `headers` in the order they appear.
-
-1. If the header name is not `request-line` then append the lowercased header
-   name followed with an ASCII colon `:` and an ASCII space ` `.
-2. If the header name is `request-line` then appened the HTTP request line,
-   otherwise append the header value.
-3. If value is not the last value then append an ASCII newline `\n`. The string
-   MUST NOT include a trailing ASCII newline.
-
-# Example Requests
-
-All requests refer to the following request (body ommitted):
-
-    POST /foo HTTP/1.1
-    Host: example.org
-    Date: Tue, 07 Jun 2011 20:51:35 GMT
-    Content-Type: application/json
-    Content-MD5: h0auK8hnYJKmHTLhKtMTkQ==
-    Content-Length: 123
-
-The "rsa-key-1" keyId refers to a private key known to the client and a public
-key known to the server. The "hmac-key-1" keyId refers to key known to the
-client and server.
-
-## Default parameterization
-
-The authorization header and signature would be generated as:
-
-    Authorization: Signature keyId="rsa-key-1",algorithm="rsa-sha256",signature="Base64(RSA-SHA256(signing string))"
-
-The client would compose the signing string as:
-
-    date: Tue, 07 Jun 2011 20:51:35 GMT
-
-## Header List
-
-The authorization header and signature would be generated as:
-
-    Authorization: Signature keyId="rsa-key-1",algorithm="rsa-sha256",headers="request-line date content-type content-md5",signature="Base64(RSA-SHA256(signing string))"
-
-The client would compose the signing string as (`+ "\n"` inserted for
-readability):
-
-    POST /foo HTTP/1.1 + "\n"
-    date: Tue, 07 Jun 2011 20:51:35 GMT + "\n"
-    content-type: application/json + "\n"
-    content-md5: h0auK8hnYJKmHTLhKtMTkQ==
-
-## Algorithm
-
-The authorization header and signature would be generated as:
-
-    Authorization: Signature keyId="hmac-key-1",algorithm="hmac-sha1",signature="Base64(HMAC-SHA1(signing string))"
-
-The client would compose the signing string as:
-
-    date: Tue, 07 Jun 2011 20:51:35 GMT
-
-# Signing Algorithms
-
-Currently supported algorithm names are:
-
-* rsa-sha1
-* rsa-sha256
-* rsa-sha512
-* dsa-sha1
-* hmac-sha1
-* hmac-sha256
-* hmac-sha512
-
-# Security Considerations
-
-## Default Parameters
-
-Note the default parameterization of the `Signature` scheme is only safe if all
-requests are carried over a secure transport (i.e., TLS).  Sending the default
-scheme over a non-secure transport will leave the request vulnerable to
-spoofing, tampering, replay/repudiaton, and integrity violations (if using the
-STRIDE threat-modeling methodology).
-
-## Insecure Transports
-
-If sending the request over plain HTTP, service providers SHOULD require clients
-to sign ALL HTTP headers, and the `request-line`.  Additionally, service
-providers SHOULD require `Content-MD5` calculations to be performed to ensure
-against any tampering from clients.
-
-## Nonces
-
-Nonces are out of scope for this document simply because many service providers
-fail to implement them correctly, or do not adopt security specfiications
-because of the infrastructure complexity.  Given the `header` parameterization,
-a service provider is fully enabled to add nonce semantics into this scheme by
-using something like an `x-request-nonce` header, and ensuring it is signed
-with the `Date` header.
-
-## Clock Skew
-
-As the default scheme is to sign the `Date` header, service providers SHOULD
-protect against logged replay attacks by enforcing a clock skew.  The server
-SHOULD be synchronized with NTP, and the recommendation in this specification
-is to allow 300s of clock skew (in either direction).
-
-## Required Headers to Sign
-
-It is out of scope for this document to dictate what headers a service provider
-will want to enforce, but service providers SHOULD at minimum include the
-`Date` header.
-
-# References
-
-## Normative References
-
-* [RFC2616] Hypertext Transfer Protocol -- HTTP/1.1
-* [RFC2617] HTTP Authentication: Basic and Digest Access Authentication
-* [RFC5246] The Transport Layer Security (TLS) Protocol Version 1.2
-
-## Informative References
-
-    Name: Mark Cavage (editor)
-    Company: Joyent, Inc.
-    Email: mark.cavage@joyent.com
-    URI: http://www.joyent.com
-
-# Appendix A - Test Values
-
-The following test data uses the RSA (2048b) keys, which we will refer
-to as `keyId=Test` in the following samples:
-
-   -----BEGIN PUBLIC KEY-----
-   MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
-   6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6
-   Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw
-   oYi+1hqp1fIekaxsyQIDAQAB
-   -----END PUBLIC KEY-----
-
-    -----BEGIN RSA PRIVATE KEY-----
-    MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF
-    NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F
-    UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB
-    AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA
-    QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK
-    kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg
-    f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u
-    412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc
-    mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7
-    kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA
-    gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW
-    G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI
-    7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==
-    -----END RSA PRIVATE KEY-----
-
-And all examples use this request:
-
-    POST /foo?param=value&pet=dog HTTP/1.1
-    Host: example.com
-    Date: Thu, 05 Jan 2012 21:31:40 GMT
-    Content-Type: application/json
-    Content-MD5: Sd/dVLAcvNLSq16eXua5uQ==
-    Content-Length: 18
-
-    {"hello": "world"}
-
-### Default
-
-The string to sign would be:
-
-    date: Thu, 05 Jan 2012 21:31:40 GMT
-
-The Authorization header would be:
-
-    Authorization: Signature keyId="Test",algorithm="rsa-sha256",signature="JldXnt8W9t643M2Sce10gqCh/+E7QIYLiI+bSjnFBGCti7s+mPPvOjVb72sbd1FjeOUwPTDpKbrQQORrm+xBYfAwCxF3LBSSzORvyJ5nRFCFxfJ3nlQD6Kdxhw8wrVZX5nSem4A/W3C8qH5uhFTRwF4ruRjh+ENHWuovPgO/HGQ="
-
-### All Headers
-
-Parameterized to include all headers, the string to sign would be (`+ "\n"`
-inserted for readability):
-
-    POST /foo?param=value&pet=dog HTTP/1.1 + "\n"
-    host: example.com + "\n"
-    date: Thu, 05 Jan 2012 21:31:40 GMT + "\n"
-    content-type: application/json + "\n"
-    content-md5: Sd/dVLAcvNLSq16eXua5uQ== + "\n"
-    content-length: 18
-
-The Authorization header would be:
-
-    Authorization: Signature keyId="Test",algorithm="rsa-sha256",headers="request-line host date content-type content-md5 content-length",signature="Gm7W/r+e90REDpWytALMrft4MqZxCmslOTOvwJX17ViEBA5E65QqvWI0vIH3l/vSsGiaMVmuUgzYsJLYMLcm5dGrv1+a+0fCoUdVKPZWHyImQEqpLkopVwqEH67LVECFBqFTAKlQgBn676zrfXQbb+b/VebAsNUtvQMe6cTjnDY="
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/index.js
deleted file mode 100644
index 3ac70b77..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2011 Joyent, Inc.  All rights reserved.
-
-var parser = require('./parser');
-var signer = require('./signer');
-var verify = require('./verify');
-var util = require('./util');
-
-
-
-///--- API
-
-module.exports = {
-
-  parse: parser.parseRequest,
-  parseRequest: parser.parseRequest,
-
-  sign: signer.signRequest,
-  signRequest: signer.signRequest,
-
-  sshKeyToPEM: util.sshKeyToPEM,
-  sshKeyFingerprint: util.fingerprint,
-
-  verify: verify.verifySignature,
-  verifySignature: verify.verifySignature
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/parser.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/parser.js
deleted file mode 100644
index fd9ac102..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/parser.js
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright 2012 Joyent, Inc.  All rights reserved.
-
-var assert = require('assert-plus');
-var util = require('util');
-
-
-
-///--- Globals
-
-var Algorithms = {
-  'rsa-sha1': true,
-  'rsa-sha256': true,
-  'rsa-sha512': true,
-  'dsa-sha1': true,
-  'hmac-sha1': true,
-  'hmac-sha256': true,
-  'hmac-sha512': true
-};
-
-var State = {
-  New: 0,
-  Params: 1
-};
-
-var ParamsState = {
-  Name: 0,
-  Quote: 1,
-  Value: 2,
-  Comma: 3
-};
-
-
-
-///--- Specific Errors
-
-function HttpSignatureError(message, caller) {
-  if (Error.captureStackTrace)
-    Error.captureStackTrace(this, caller || HttpSignatureError);
-
-  this.message = message;
-  this.name = caller.name;
-}
-util.inherits(HttpSignatureError, Error);
-
-function ExpiredRequestError(message) {
-  HttpSignatureError.call(this, message, ExpiredRequestError);
-}
-util.inherits(ExpiredRequestError, HttpSignatureError);
-
-
-function InvalidHeaderError(message) {
-  HttpSignatureError.call(this, message, InvalidHeaderError);
-}
-util.inherits(InvalidHeaderError, HttpSignatureError);
-
-
-function InvalidParamsError(message) {
-  HttpSignatureError.call(this, message, InvalidParamsError);
-}
-util.inherits(InvalidParamsError, HttpSignatureError);
-
-
-function MissingHeaderError(message) {
-  HttpSignatureError.call(this, message, MissingHeaderError);
-}
-util.inherits(MissingHeaderError, HttpSignatureError);
-
-
-
-///--- Exported API
-
-module.exports = {
-
-  /**
-   * Parses the 'Authorization' header out of an http.ServerRequest object.
-   *
-   * Note that this API will fully validate the Authorization header, and throw
-   * on any error.  It will not however check the signature, or the keyId format
-   * as those are specific to your environment.  You can use the options object
-   * to pass in extra constraints.
-   *
-   * As a response object you can expect this:
-   *
-   *     {
-   *       "scheme": "Signature",
-   *       "params": {
-   *         "keyId": "foo",
-   *         "algorithm": "rsa-sha256",
-   *         "headers": [
-   *           "date" or "x-date",
-   *           "content-md5"
-   *         ],
-   *         "signature": "base64"
-   *       },
-   *       "signingString": "ready to be passed to crypto.verify()"
-   *     }
-   *
-   * @param {Object} request an http.ServerRequest.
-   * @param {Object} options an optional options object with:
-   *                   - clockSkew: allowed clock skew in seconds (default 300).
-   *                   - headers: required header names (def: date or x-date)
-   *                   - algorithms: algorithms to support (default: all).
-   * @return {Object} parsed out object (see above).
-   * @throws {TypeError} on invalid input.
-   * @throws {InvalidHeaderError} on an invalid Authorization header error.
-   * @throws {InvalidParamsError} if the params in the scheme are invalid.
-   * @throws {MissingHeaderError} if the params indicate a header not present,
-   *                              either in the request headers from the params,
-   *                              or not in the params from a required header
-   *                              in options.
-   * @throws {ExpiredRequestError} if the value of date or x-date exceeds skew.
-   */
-  parseRequest: function parseRequest(request, options) {
-    assert.object(request, 'request');
-    assert.object(request.headers, 'request.headers');
-    if (options === undefined) {
-      options = {};
-    }
-    if (options.headers === undefined) {
-      options.headers = [request.headers['x-date'] ? 'x-date' : 'date'];
-    }
-    assert.object(options, 'options');
-    assert.arrayOfString(options.headers, 'options.headers');
-    assert.optionalNumber(options.clockSkew, 'options.clockSkew');
-
-    if (!request.headers.authorization)
-      throw new MissingHeaderError('no authorization header present in ' +
-                                   'the request');
-
-    options.clockSkew = options.clockSkew || 300;
-
-
-    var i = 0;
-    var state = State.New;
-    var substate = ParamsState.Name;
-    var tmpName = '';
-    var tmpValue = '';
-
-    var parsed = {
-      scheme: '',
-      params: {},
-      signingString: '',
-
-      get algorithm() {
-        return this.params.algorithm.toUpperCase();
-      },
-
-      get keyId() {
-        return this.params.keyId;
-      }
-
-    };
-
-    var authz = request.headers.authorization;
-    for (i = 0; i < authz.length; i++) {
-      var c = authz.charAt(i);
-
-      switch (Number(state)) {
-
-      case State.New:
-        if (c !== ' ') parsed.scheme += c;
-        else state = State.Params;
-        break;
-
-      case State.Params:
-        switch (Number(substate)) {
-
-        case ParamsState.Name:
-          var code = c.charCodeAt(0);
-          // restricted name of A-Z / a-z
-          if ((code >= 0x41 && code <= 0x5a) || // A-Z
-              (code >= 0x61 && code <= 0x7a)) { // a-z
-            tmpName += c;
-          } else if (c === '=') {
-            if (tmpName.length === 0)
-              throw new InvalidHeaderError('bad param format');
-            substate = ParamsState.Quote;
-          } else {
-            throw new InvalidHeaderError('bad param format');
-          }
-          break;
-
-        case ParamsState.Quote:
-          if (c === '"') {
-            tmpValue = '';
-            substate = ParamsState.Value;
-          } else {
-            throw new InvalidHeaderError('bad param format');
-          }
-          break;
-
-        case ParamsState.Value:
-          if (c === '"') {
-            parsed.params[tmpName] = tmpValue;
-            substate = ParamsState.Comma;
-          } else {
-            tmpValue += c;
-          }
-          break;
-
-        case ParamsState.Comma:
-          if (c === ',') {
-            tmpName = '';
-            substate = ParamsState.Name;
-          } else {
-            throw new InvalidHeaderError('bad param format');
-          }
-          break;
-
-        default:
-          throw new Error('Invalid substate');
-        }
-        break;
-
-      default:
-        throw new Error('Invalid substate');
-      }
-
-    }
-
-    if (!parsed.params.headers || parsed.params.headers === '') {
-      if (request.headers['x-date']) {
-        parsed.params.headers = ['x-date'];
-      } else {
-        parsed.params.headers = ['date'];
-      }
-    } else {
-      parsed.params.headers = parsed.params.headers.split(' ');
-    }
-
-    // Minimally validate the parsed object
-    if (!parsed.scheme || parsed.scheme !== 'Signature')
-      throw new InvalidHeaderError('scheme was not "Signature"');
-
-    if (!parsed.params.keyId)
-      throw new InvalidHeaderError('keyId was not specified');
-
-    if (!parsed.params.algorithm)
-      throw new InvalidHeaderError('algorithm was not specified');
-
-    if (!parsed.params.signature)
-      throw new InvalidHeaderError('signature was not specified');
-
-    // Check the algorithm against the official list
-    parsed.params.algorithm = parsed.params.algorithm.toLowerCase();
-    if (!Algorithms[parsed.params.algorithm])
-      throw new InvalidParamsError(parsed.params.algorithm +
-                                   ' is not supported');
-
-    // Build the signingString
-    for (i = 0; i < parsed.params.headers.length; i++) {
-      var h = parsed.params.headers[i].toLowerCase();
-      parsed.params.headers[i] = h;
-
-      if (h !== 'request-line') {
-        var value = request.headers[h];
-        if (!value)
-          throw new MissingHeaderError(h + ' was not in the request');
-        parsed.signingString += h + ': ' + value;
-      } else {
-        parsed.signingString +=
-          request.method + ' ' + request.url + ' HTTP/' + request.httpVersion;
-      }
-
-      if ((i + 1) < parsed.params.headers.length)
-        parsed.signingString += '\n';
-    }
-
-    // Check against the constraints
-    var date;
-    if (request.headers.date || request.headers['x-date']) {
-        if (request.headers['x-date']) {
-          date = new Date(request.headers['x-date']);
-        } else {
-          date = new Date(request.headers.date);
-        }
-      var now = new Date();
-      var skew = Math.abs(now.getTime() - date.getTime());
-
-      if (skew > options.clockSkew * 1000) {
-        throw new ExpiredRequestError('clock skew of ' +
-                                      (skew / 1000) +
-                                      's was greater than ' +
-                                      options.clockSkew + 's');
-      }
-    }
-
-    options.headers.forEach(function (hdr) {
-      // Remember that we already checked any headers in the params
-      // were in the request, so if this passes we're good.
-      if (parsed.params.headers.indexOf(hdr) < 0)
-        throw new MissingHeaderError(hdr + ' was not a signed header');
-    });
-
-    if (options.algorithms) {
-      if (options.algorithms.indexOf(parsed.params.algorithm) === -1)
-        throw new InvalidParamsError(parsed.params.algorithm +
-                                     ' is not a supported algorithm');
-    }
-
-    return parsed;
-  }
-
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/signer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/signer.js
deleted file mode 100644
index 8095f0d1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/signer.js
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2012 Joyent, Inc.  All rights reserved.
-
-var assert = require('assert-plus');
-var crypto = require('crypto');
-var http = require('http');
-
-var sprintf = require('util').format;
-
-
-
-///--- Globals
-
-var Algorithms = {
-  'rsa-sha1': true,
-  'rsa-sha256': true,
-  'rsa-sha512': true,
-  'dsa-sha1': true,
-  'hmac-sha1': true,
-  'hmac-sha256': true,
-  'hmac-sha512': true
-};
-
-var Authorization =
-  'Signature keyId="%s",algorithm="%s",headers="%s",signature="%s"';
-
-
-
-///--- Specific Errors
-
-function MissingHeaderError(message) {
-    this.name = 'MissingHeaderError';
-    this.message = message;
-    this.stack = (new Error()).stack;
-}
-MissingHeaderError.prototype = new Error();
-
-
-function InvalidAlgorithmError(message) {
-    this.name = 'InvalidAlgorithmError';
-    this.message = message;
-    this.stack = (new Error()).stack;
-}
-InvalidAlgorithmError.prototype = new Error();
-
-
-
-///--- Internal Functions
-
-function _pad(val) {
-  if (parseInt(val, 10) < 10) {
-    val = '0' + val;
-  }
-  return val;
-}
-
-
-function _rfc1123() {
-  var date = new Date();
-
-  var months = ['Jan',
-                'Feb',
-                'Mar',
-                'Apr',
-                'May',
-                'Jun',
-                'Jul',
-                'Aug',
-                'Sep',
-                'Oct',
-                'Nov',
-                'Dec'];
-  var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
-  return days[date.getUTCDay()] + ', ' +
-    _pad(date.getUTCDate()) + ' ' +
-    months[date.getUTCMonth()] + ' ' +
-    date.getUTCFullYear() + ' ' +
-    _pad(date.getUTCHours()) + ':' +
-    _pad(date.getUTCMinutes()) + ':' +
-    _pad(date.getUTCSeconds()) +
-    ' GMT';
-}
-
-
-
-///--- Exported API
-
-module.exports = {
-
-  /**
-   * Adds an 'Authorization' header to an http.ClientRequest object.
-   *
-   * Note that this API will add a Date header if it's not already set. Any
-   * other headers in the options.headers array MUST be present, or this
-   * will throw.
-   *
-   * You shouldn't need to check the return type; it's just there if you want
-   * to be pedantic.
-   *
-   * @param {Object} request an instance of http.ClientRequest.
-   * @param {Object} options signing parameters object:
-   *                   - {String} keyId required.
-   *                   - {String} key required (either a PEM or HMAC key).
-   *                   - {Array} headers optional; defaults to ['date'].
-   *                   - {String} algorithm optional; defaults to 'rsa-sha256'.
-   *                   - {String} httpVersion optional; defaults to '1.1'.
-   * @return {Boolean} true if Authorization (and optionally Date) were added.
-   * @throws {TypeError} on bad parameter types (input).
-   * @throws {InvalidAlgorithmError} if algorithm was bad.
-   * @throws {MissingHeaderError} if a header to be signed was specified but
-   *                              was not present.
-   */
-  signRequest: function signRequest(request, options) {
-    assert.object(request, 'request');
-    assert.object(options, 'options');
-    assert.optionalString(options.algorithm, 'options.algorithm');
-    assert.string(options.keyId, 'options.keyId');
-    assert.optionalArrayOfString(options.headers, 'options.headers');
-    assert.optionalString(options.httpVersion, 'options.httpVersion');
-
-    if (!request.getHeader('Date'))
-      request.setHeader('Date', _rfc1123());
-    if (!options.headers)
-      options.headers = ['date'];
-    if (!options.algorithm)
-      options.algorithm = 'rsa-sha256';
-    if (!options.httpVersion)
-      options.httpVersion = '1.1';
-
-    options.algorithm = options.algorithm.toLowerCase();
-
-    if (!Algorithms[options.algorithm])
-      throw new InvalidAlgorithmError(options.algorithm + ' is not supported');
-
-    var i;
-    var stringToSign = '';
-    for (i = 0; i < options.headers.length; i++) {
-      if (typeof (options.headers[i]) !== 'string')
-        throw new TypeError('options.headers must be an array of Strings');
-
-      var h = options.headers[i].toLowerCase();
-
-      if (h !== 'request-line') {
-        var value = request.getHeader(h);
-        if (!value) {
-          throw new MissingHeaderError(h + ' was not in the request');
-        }
-        stringToSign += h + ': ' + value;
-      } else {
-        value =
-        stringToSign +=
-          request.method + ' ' + request.path + ' HTTP/' + options.httpVersion;
-      }
-
-      if ((i + 1) < options.headers.length)
-        stringToSign += '\n';
-    }
-
-    var alg = options.algorithm.match(/(hmac|rsa)-(\w+)/);
-    var signature;
-    if (alg[1] === 'hmac') {
-      var hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
-      hmac.update(stringToSign);
-      signature = hmac.digest('base64');
-    } else {
-      var signer = crypto.createSign(options.algorithm.toUpperCase());
-      signer.update(stringToSign);
-      signature = signer.sign(options.key, 'base64');
-    }
-
-    request.setHeader('Authorization', sprintf(Authorization,
-                                               options.keyId,
-                                               options.algorithm,
-                                               options.headers.join(' '),
-                                               signature));
-
-    return true;
-  }
-
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/util.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/util.js
deleted file mode 100644
index 30bbf045..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/util.js
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2012 Joyent, Inc.  All rights reserved.
-
-var assert = require('assert-plus');
-var crypto = require('crypto');
-
-var asn1 = require('asn1');
-var ctype = require('ctype');
-
-
-
-///--- Helpers
-
-function readNext(buffer, offset) {
-  var len = ctype.ruint32(buffer, 'big', offset);
-  offset += 4;
-
-  var newOffset = offset + len;
-
-  return {
-    data: buffer.slice(offset, newOffset),
-    offset: newOffset
-  };
-}
-
-
-function writeInt(writer, buffer) {
-  writer.writeByte(0x02); // ASN1.Integer
-  writer.writeLength(buffer.length);
-
-  for (var i = 0; i < buffer.length; i++)
-    writer.writeByte(buffer[i]);
-
-  return writer;
-}
-
-
-function rsaToPEM(key) {
-  var buffer;
-  var der;
-  var exponent;
-  var i;
-  var modulus;
-  var newKey = '';
-  var offset = 0;
-  var type;
-  var tmp;
-
-  try {
-    buffer = new Buffer(key.split(' ')[1], 'base64');
-
-    tmp = readNext(buffer, offset);
-    type = tmp.data.toString();
-    offset = tmp.offset;
-
-    if (type !== 'ssh-rsa')
-      throw new Error('Invalid ssh key type: ' + type);
-
-    tmp = readNext(buffer, offset);
-    exponent = tmp.data;
-    offset = tmp.offset;
-
-    tmp = readNext(buffer, offset);
-    modulus = tmp.data;
-  } catch (e) {
-    throw new Error('Invalid ssh key: ' + key);
-  }
-
-  // DER is a subset of BER
-  der = new asn1.BerWriter();
-
-  der.startSequence();
-
-  der.startSequence();
-  der.writeOID('1.2.840.113549.1.1.1');
-  der.writeNull();
-  der.endSequence();
-
-  der.startSequence(0x03); // bit string
-  der.writeByte(0x00);
-
-  // Actual key
-  der.startSequence();
-  writeInt(der, modulus);
-  writeInt(der, exponent);
-  der.endSequence();
-
-  // bit string
-  der.endSequence();
-
-  der.endSequence();
-
-  tmp = der.buffer.toString('base64');
-  for (i = 0; i < tmp.length; i++) {
-    if ((i % 64) === 0)
-      newKey += '\n';
-    newKey += tmp.charAt(i);
-  }
-
-  if (!/\\n$/.test(newKey))
-    newKey += '\n';
-
-  return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';
-}
-
-
-function dsaToPEM(key) {
-  var buffer;
-  var offset = 0;
-  var tmp;
-  var der;
-  var newKey = '';
-
-  var type;
-  var p;
-  var q;
-  var g;
-  var y;
-
-  try {
-    buffer = new Buffer(key.split(' ')[1], 'base64');
-
-    tmp = readNext(buffer, offset);
-    type = tmp.data.toString();
-    offset = tmp.offset;
-
-    /* JSSTYLED */
-    if (!/^ssh-ds[as].*/.test(type))
-      throw new Error('Invalid ssh key type: ' + type);
-
-    tmp = readNext(buffer, offset);
-    p = tmp.data;
-    offset = tmp.offset;
-
-    tmp = readNext(buffer, offset);
-    q = tmp.data;
-    offset = tmp.offset;
-
-    tmp = readNext(buffer, offset);
-    g = tmp.data;
-    offset = tmp.offset;
-
-    tmp = readNext(buffer, offset);
-    y = tmp.data;
-  } catch (e) {
-    console.log(e.stack);
-    throw new Error('Invalid ssh key: ' + key);
-  }
-
-  // DER is a subset of BER
-  der = new asn1.BerWriter();
-
-  der.startSequence();
-
-  der.startSequence();
-  der.writeOID('1.2.840.10040.4.1');
-
-  der.startSequence();
-  writeInt(der, p);
-  writeInt(der, q);
-  writeInt(der, g);
-  der.endSequence();
-
-  der.endSequence();
-
-  der.startSequence(0x03); // bit string
-  der.writeByte(0x00);
-  writeInt(der, y);
-  der.endSequence();
-
-  der.endSequence();
-
-  tmp = der.buffer.toString('base64');
-  for (var i = 0; i < tmp.length; i++) {
-    if ((i % 64) === 0)
-      newKey += '\n';
-    newKey += tmp.charAt(i);
-  }
-
-  if (!/\\n$/.test(newKey))
-    newKey += '\n';
-
-  return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';
-}
-
-
-///--- API
-
-module.exports = {
-
-  /**
-   * Converts an OpenSSH public key (rsa only) to a PKCS#8 PEM file.
-   *
-   * The intent of this module is to interoperate with OpenSSL only,
-   * specifically the node crypto module's `verify` method.
-   *
-   * @param {String} key an OpenSSH public key.
-   * @return {String} PEM encoded form of the RSA public key.
-   * @throws {TypeError} on bad input.
-   * @throws {Error} on invalid ssh key formatted data.
-   */
-  sshKeyToPEM: function sshKeyToPEM(key) {
-    assert.string(key, 'ssh_key');
-
-    /* JSSTYLED */
-    if (/^ssh-rsa.*/.test(key))
-      return rsaToPEM(key);
-
-    /* JSSTYLED */
-    if (/^ssh-ds[as].*/.test(key))
-      return dsaToPEM(key);
-
-    throw new Error('Only RSA and DSA public keys are allowed');
-  },
-
-
-  /**
-   * Generates an OpenSSH fingerprint from an ssh public key.
-   *
-   * @param {String} key an OpenSSH public key.
-   * @return {String} key fingerprint.
-   * @throws {TypeError} on bad input.
-   * @throws {Error} if what you passed doesn't look like an ssh public key.
-   */
-  fingerprint: function fingerprint(key) {
-    assert.string(key, 'ssh_key');
-
-    var pieces = key.split(' ');
-    if (!pieces || !pieces.length || pieces.length < 2)
-      throw new Error('invalid ssh key');
-
-    var data = new Buffer(pieces[1], 'base64');
-
-    var hash = crypto.createHash('md5');
-    hash.update(data);
-    var digest = hash.digest('hex');
-
-    var fp = '';
-    for (var i = 0; i < digest.length; i++) {
-      if (i && i % 2 === 0)
-        fp += ':';
-
-      fp += digest[i];
-    }
-
-    return fp;
-  }
-
-
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/verify.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/verify.js
deleted file mode 100644
index 5bf95896..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/lib/verify.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2011 Joyent, Inc.  All rights reserved.
-
-var assert = require('assert-plus');
-var crypto = require('crypto');
-
-
-
-///--- Exported API
-
-module.exports = {
-
-  /**
-   * Simply wraps up the node crypto operations for you, and returns
-   * true or false.  You are expected to pass in an object that was
-   * returned from `parse()`.
-   *
-   * @param {Object} parsedSignature the object you got from `parse`.
-   * @param {String} key either an RSA private key PEM or HMAC secret.
-   * @return {Boolean} true if valid, false otherwise.
-   * @throws {TypeError} if you pass in bad arguments.
-   */
-  verifySignature: function verifySignature(parsedSignature, key) {
-    assert.object(parsedSignature, 'parsedSignature');
-    assert.string(key, 'key');
-
-    var alg = parsedSignature.algorithm.match(/(HMAC|RSA|DSA)-(\w+)/);
-    if (!alg || alg.length !== 3)
-      throw new TypeError('parsedSignature: unsupported algorithm ' +
-                          parsedSignature.algorithm);
-
-    if (alg[1] === 'HMAC') {
-      var hmac = crypto.createHmac(alg[2].toUpperCase(), key);
-      hmac.update(parsedSignature.signingString);
-      return (hmac.digest('base64') === parsedSignature.params.signature);
-    } else {
-      var verify = crypto.createVerify(alg[0]);
-      verify.update(parsedSignature.signingString);
-      return verify.verify(key, parsedSignature.params.signature, 'base64');
-    }
-  }
-
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore
deleted file mode 100644
index eb03e3e1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules
-*.log
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE
deleted file mode 100644
index 9b5dcdb7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2011 Mark Cavage, All rights reserved.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md
deleted file mode 100644
index 7cebf7a2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md
+++ /dev/null
@@ -1,50 +0,0 @@
-node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS.
-Currently BER encoding is supported; at some point I'll likely have to do DER.
-
-## Usage
-
-Mostly, if you're *actually* needing to read and write ASN.1, you probably don't
-need this readme to explain what and why.  If you have no idea what ASN.1 is,
-see this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
-
-The source is pretty much self-explanatory, and has read/write methods for the
-common types out there.
-
-### Decoding
-
-The following reads an ASN.1 sequence with a boolean.
-
-    var Ber = require('asn1').Ber;
-
-    var reader = new Ber.Reader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff]));
-
-    reader.readSequence();
-    console.log('Sequence len: ' + reader.length);
-    if (reader.peek() === Ber.Boolean)
-      console.log(reader.readBoolean());
-
-### Encoding
-
-The following generates the same payload as above.
-
-    var Ber = require('asn1').Ber;
-
-    var writer = new Ber.Writer();
-
-    writer.startSequence();
-    writer.writeBoolean(true);
-    writer.endSequence();
-
-    console.log(writer.buffer);
-
-## Installation
-
-    npm install asn1
-
-## License
-
-MIT.
-
-## Bugs
-
-See <https://github.com/mcavage/node-asn1/issues>.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js
deleted file mode 100644
index ff21d4fa..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-
-module.exports = {
-
-  newInvalidAsn1Error: function(msg) {
-    var e = new Error();
-    e.name = 'InvalidAsn1Error';
-    e.message = msg || '';
-    return e;
-  }
-
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js
deleted file mode 100644
index 4fb90aea..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-var errors = require('./errors');
-var types = require('./types');
-
-var Reader = require('./reader');
-var Writer = require('./writer');
-
-
-///--- Exports
-
-module.exports = {
-
-  Reader: Reader,
-
-  Writer: Writer
-
-};
-
-for (var t in types) {
-  if (types.hasOwnProperty(t))
-    module.exports[t] = types[t];
-}
-for (var e in errors) {
-  if (errors.hasOwnProperty(e))
-    module.exports[e] = errors[e];
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js
deleted file mode 100644
index bd3357a6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-var assert = require('assert');
-
-var ASN1 = require('./types');
-var errors = require('./errors');
-
-
-///--- Globals
-
-var newInvalidAsn1Error = errors.newInvalidAsn1Error;
-
-
-
-///--- API
-
-function Reader(data) {
-  if (!data || !Buffer.isBuffer(data))
-    throw new TypeError('data must be a node Buffer');
-
-  this._buf = data;
-  this._size = data.length;
-
-  // These hold the "current" state
-  this._len = 0;
-  this._offset = 0;
-
-  var self = this;
-  this.__defineGetter__('length', function() { return self._len; });
-  this.__defineGetter__('offset', function() { return self._offset; });
-  this.__defineGetter__('remain', function() {
-    return self._size - self._offset;
-  });
-  this.__defineGetter__('buffer', function() {
-    return self._buf.slice(self._offset);
-  });
-}
-
-
-/**
- * Reads a single byte and advances offset; you can pass in `true` to make this
- * a "peek" operation (i.e., get the byte, but don't advance the offset).
- *
- * @param {Boolean} peek true means don't move offset.
- * @return {Number} the next byte, null if not enough data.
- */
-Reader.prototype.readByte = function(peek) {
-  if (this._size - this._offset < 1)
-    return null;
-
-  var b = this._buf[this._offset] & 0xff;
-
-  if (!peek)
-    this._offset += 1;
-
-  return b;
-};
-
-
-Reader.prototype.peek = function() {
-  return this.readByte(true);
-};
-
-
-/**
- * Reads a (potentially) variable length off the BER buffer.  This call is
- * not really meant to be called directly, as callers have to manipulate
- * the internal buffer afterwards.
- *
- * As a result of this call, you can call `Reader.length`, until the
- * next thing called that does a readLength.
- *
- * @return {Number} the amount of offset to advance the buffer.
- * @throws {InvalidAsn1Error} on bad ASN.1
- */
-Reader.prototype.readLength = function(offset) {
-  if (offset === undefined)
-    offset = this._offset;
-
-  if (offset >= this._size)
-    return null;
-
-  var lenB = this._buf[offset++] & 0xff;
-  if (lenB === null)
-    return null;
-
-  if ((lenB & 0x80) == 0x80) {
-    lenB &= 0x7f;
-
-    if (lenB == 0)
-      throw newInvalidAsn1Error('Indefinite length not supported');
-
-    if (lenB > 4)
-      throw newInvalidAsn1Error('encoding too long');
-
-    if (this._size - offset < lenB)
-      return null;
-
-    this._len = 0;
-    for (var i = 0; i < lenB; i++)
-      this._len = (this._len << 8) + (this._buf[offset++] & 0xff);
-
-  } else {
-    // Wasn't a variable length
-    this._len = lenB;
-  }
-
-  return offset;
-};
-
-
-/**
- * Parses the next sequence in this BER buffer.
- *
- * To get the length of the sequence, call `Reader.length`.
- *
- * @return {Number} the sequence's tag.
- */
-Reader.prototype.readSequence = function(tag) {
-  var seq = this.peek();
-  if (seq === null)
-    return null;
-  if (tag !== undefined && tag !== seq)
-    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
-                              ': got 0x' + seq.toString(16));
-
-  var o = this.readLength(this._offset + 1); // stored in `length`
-  if (o === null)
-    return null;
-
-  this._offset = o;
-  return seq;
-};
-
-
-Reader.prototype.readInt = function() {
-  return this._readTag(ASN1.Integer);
-};
-
-
-Reader.prototype.readBoolean = function() {
-  return (this._readTag(ASN1.Boolean) === 0 ? false : true);
-};
-
-
-Reader.prototype.readEnumeration = function() {
-  return this._readTag(ASN1.Enumeration);
-};
-
-
-Reader.prototype.readString = function(tag, retbuf) {
-  if (!tag)
-    tag = ASN1.OctetString;
-
-  var b = this.peek();
-  if (b === null)
-    return null;
-
-  if (b !== tag)
-    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
-                              ': got 0x' + b.toString(16));
-
-  var o = this.readLength(this._offset + 1); // stored in `length`
-
-  if (o === null)
-    return null;
-
-  if (this.length > this._size - o)
-    return null;
-
-  this._offset = o;
-
-  if (this.length === 0)
-    return '';
-
-  var str = this._buf.slice(this._offset, this._offset + this.length);
-  this._offset += this.length;
-
-  return retbuf ? str : str.toString('utf8');
-};
-
-Reader.prototype.readOID = function(tag) {
-  if (!tag)
-    tag = ASN1.OID;
-
-  var b = this.peek();
-  if (b === null)
-    return null;
-
-  if (b !== tag)
-    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
-                              ': got 0x' + b.toString(16));
-
-  var o = this.readLength(this._offset + 1); // stored in `length`
-  if (o === null)
-    return null;
-
-  if (this.length > this._size - o)
-    return null;
-
-  this._offset = o;
-
-  var values = [];
-  var value = 0;
-
-  for (var i = 0; i < this.length; i++) {
-    var byte = this._buf[this._offset++] & 0xff;
-
-    value <<= 7;
-    value += byte & 0x7f;
-    if ((byte & 0x80) == 0) {
-      values.push(value);
-      value = 0;
-    }
-  }
-
-  value = values.shift();
-  values.unshift(value % 40);
-  values.unshift((value / 40) >> 0);
-
-  return values.join('.');
-};
-
-
-Reader.prototype._readTag = function(tag) {
-  assert.ok(tag !== undefined);
-
-  var b = this.peek();
-
-  if (b === null)
-    return null;
-
-  if (b !== tag)
-    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
-                              ': got 0x' + b.toString(16));
-
-  var o = this.readLength(this._offset + 1); // stored in `length`
-  if (o === null)
-    return null;
-
-  if (this.length > 4)
-    throw newInvalidAsn1Error('Integer too long: ' + this.length);
-
-  if (this.length > this._size - o)
-    return null;
-  this._offset = o;
-
-  var fb = this._buf[this._offset++];
-  var value = 0;
-
-  value = fb & 0x7F;
-  for (var i = 1; i < this.length; i++) {
-    value <<= 8;
-    value |= (this._buf[this._offset++] & 0xff);
-  }
-
-  if ((fb & 0x80) == 0x80)
-    value = -value;
-
-  return value;
-};
-
-
-
-///--- Exported API
-
-module.exports = Reader;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js
deleted file mode 100644
index 8aea0001..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-
-module.exports = {
-  EOC: 0,
-  Boolean: 1,
-  Integer: 2,
-  BitString: 3,
-  OctetString: 4,
-  Null: 5,
-  OID: 6,
-  ObjectDescriptor: 7,
-  External: 8,
-  Real: 9, // float
-  Enumeration: 10,
-  PDV: 11,
-  Utf8String: 12,
-  RelativeOID: 13,
-  Sequence: 16,
-  Set: 17,
-  NumericString: 18,
-  PrintableString: 19,
-  T61String: 20,
-  VideotexString: 21,
-  IA5String: 22,
-  UTCTime: 23,
-  GeneralizedTime: 24,
-  GraphicString: 25,
-  VisibleString: 26,
-  GeneralString: 28,
-  UniversalString: 29,
-  CharacterString: 30,
-  BMPString: 31,
-  Constructor: 32,
-  Context: 128
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js
deleted file mode 100644
index 7b445cc6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-var assert = require('assert');
-var ASN1 = require('./types');
-var errors = require('./errors');
-
-
-///--- Globals
-
-var newInvalidAsn1Error = errors.newInvalidAsn1Error;
-
-var DEFAULT_OPTS = {
-  size: 1024,
-  growthFactor: 8
-};
-
-
-///--- Helpers
-
-function merge(from, to) {
-  assert.ok(from);
-  assert.equal(typeof(from), 'object');
-  assert.ok(to);
-  assert.equal(typeof(to), 'object');
-
-  var keys = Object.getOwnPropertyNames(from);
-  keys.forEach(function(key) {
-    if (to[key])
-      return;
-
-    var value = Object.getOwnPropertyDescriptor(from, key);
-    Object.defineProperty(to, key, value);
-  });
-
-  return to;
-}
-
-
-
-///--- API
-
-function Writer(options) {
-  options = merge(DEFAULT_OPTS, options || {});
-
-  this._buf = new Buffer(options.size || 1024);
-  this._size = this._buf.length;
-  this._offset = 0;
-  this._options = options;
-
-  // A list of offsets in the buffer where we need to insert
-  // sequence tag/len pairs.
-  this._seq = [];
-
-  var self = this;
-  this.__defineGetter__('buffer', function() {
-    if (self._seq.length)
-      throw new InvalidAsn1Error(self._seq.length + ' unended sequence(s)');
-
-    return self._buf.slice(0, self._offset);
-  });
-}
-
-
-Writer.prototype.writeByte = function(b) {
-  if (typeof(b) !== 'number')
-    throw new TypeError('argument must be a Number');
-
-  this._ensure(1);
-  this._buf[this._offset++] = b;
-};
-
-
-Writer.prototype.writeInt = function(i, tag) {
-  if (typeof(i) !== 'number')
-    throw new TypeError('argument must be a Number');
-  if (typeof(tag) !== 'number')
-    tag = ASN1.Integer;
-
-  var sz = 4;
-
-  while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000)) &&
-         (sz > 1)) {
-    sz--;
-    i <<= 8;
-  }
-
-  if (sz > 4)
-    throw new InvalidAsn1Error('BER ints cannot be > 0xffffffff');
-
-  this._ensure(2 + sz);
-  this._buf[this._offset++] = tag;
-  this._buf[this._offset++] = sz;
-
-  while (sz-- > 0) {
-    this._buf[this._offset++] = ((i & 0xff000000) >> 24);
-    i <<= 8;
-  }
-
-};
-
-
-Writer.prototype.writeNull = function() {
-  this.writeByte(ASN1.Null);
-  this.writeByte(0x00);
-};
-
-
-Writer.prototype.writeEnumeration = function(i, tag) {
-  if (typeof(i) !== 'number')
-    throw new TypeError('argument must be a Number');
-  if (typeof(tag) !== 'number')
-    tag = ASN1.Enumeration;
-
-  return this.writeInt(i, tag);
-};
-
-
-Writer.prototype.writeBoolean = function(b, tag) {
-  if (typeof(b) !== 'boolean')
-    throw new TypeError('argument must be a Boolean');
-  if (typeof(tag) !== 'number')
-    tag = ASN1.Boolean;
-
-  this._ensure(3);
-  this._buf[this._offset++] = tag;
-  this._buf[this._offset++] = 0x01;
-  this._buf[this._offset++] = b ? 0xff : 0x00;
-};
-
-
-Writer.prototype.writeString = function(s, tag) {
-  if (typeof(s) !== 'string')
-    throw new TypeError('argument must be a string (was: ' + typeof(s) + ')');
-  if (typeof(tag) !== 'number')
-    tag = ASN1.OctetString;
-
-  var len = Buffer.byteLength(s);
-  this.writeByte(tag);
-  this.writeLength(len);
-  if (len) {
-    this._ensure(len);
-    this._buf.write(s, this._offset);
-    this._offset += len;
-  }
-};
-
-
-Writer.prototype.writeBuffer = function(buf, tag) {
-  if (typeof(tag) !== 'number')
-    throw new TypeError('tag must be a number');
-  if (!Buffer.isBuffer(buf))
-    throw new TypeError('argument must be a buffer');
-
-  this.writeByte(tag);
-  this.writeLength(buf.length);
-  this._ensure(buf.length);
-  buf.copy(this._buf, this._offset, 0, buf.length);
-  this._offset += buf.length;
-};
-
-
-Writer.prototype.writeStringArray = function(strings) {
-  if ((!strings instanceof Array))
-    throw new TypeError('argument must be an Array[String]');
-
-  var self = this;
-  strings.forEach(function(s) {
-    self.writeString(s);
-  });
-};
-
-// This is really to solve DER cases, but whatever for now
-Writer.prototype.writeOID = function(s, tag) {
-  if (typeof(s) !== 'string')
-    throw new TypeError('argument must be a string');
-  if (typeof(tag) !== 'number')
-    tag = ASN1.OID;
-
-  if (!/^([0-9]+\.){3,}[0-9]+$/.test(s))
-    throw new Error('argument is not a valid OID string');
-
-  function encodeOctet(bytes, octet) {
-    if (octet < 128) {
-        bytes.push(octet);
-    } else if (octet < 16384) {
-        bytes.push((octet >>> 7) | 0x80);
-        bytes.push(octet & 0x7F);
-    } else if (octet < 2097152) {
-      bytes.push((octet >>> 14) | 0x80);
-      bytes.push(((octet >>> 7) | 0x80) & 0xFF);
-      bytes.push(octet & 0x7F);
-    } else if (octet < 268435456) {
-      bytes.push((octet >>> 21) | 0x80);
-      bytes.push(((octet >>> 14) | 0x80) & 0xFF);
-      bytes.push(((octet >>> 7) | 0x80) & 0xFF);
-      bytes.push(octet & 0x7F);
-    } else {
-      bytes.push(((octet >>> 28) | 0x80) & 0xFF);
-      bytes.push(((octet >>> 21) | 0x80) & 0xFF);
-      bytes.push(((octet >>> 14) | 0x80) & 0xFF);
-      bytes.push(((octet >>> 7) | 0x80) & 0xFF);
-      bytes.push(octet & 0x7F);
-    }
-  }
-
-  var tmp = s.split('.');
-  var bytes = [];
-  bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10));
-  tmp.slice(2).forEach(function(b) {
-    encodeOctet(bytes, parseInt(b, 10));
-  });
-
-  var self = this;
-  this._ensure(2 + bytes.length);
-  this.writeByte(tag);
-  this.writeLength(bytes.length);
-  bytes.forEach(function(b) {
-    self.writeByte(b);
-  });
-};
-
-
-Writer.prototype.writeLength = function(len) {
-  if (typeof(len) !== 'number')
-    throw new TypeError('argument must be a Number');
-
-  this._ensure(4);
-
-  if (len <= 0x7f) {
-    this._buf[this._offset++] = len;
-  } else if (len <= 0xff) {
-    this._buf[this._offset++] = 0x81;
-    this._buf[this._offset++] = len;
-  } else if (len <= 0xffff) {
-    this._buf[this._offset++] = 0x82;
-    this._buf[this._offset++] = len >> 8;
-    this._buf[this._offset++] = len;
-  } else if (len <= 0xffffff) {
-    this._shift(start, len, 1);
-    this._buf[this._offset++] = 0x83;
-    this._buf[this._offset++] = len >> 16;
-    this._buf[this._offset++] = len >> 8;
-    this._buf[this._offset++] = len;
-  } else {
-    throw new InvalidAsn1ERror('Length too long (> 4 bytes)');
-  }
-};
-
-Writer.prototype.startSequence = function(tag) {
-  if (typeof(tag) !== 'number')
-    tag = ASN1.Sequence | ASN1.Constructor;
-
-  this.writeByte(tag);
-  this._seq.push(this._offset);
-  this._ensure(3);
-  this._offset += 3;
-};
-
-
-Writer.prototype.endSequence = function() {
-  var seq = this._seq.pop();
-  var start = seq + 3;
-  var len = this._offset - start;
-
-  if (len <= 0x7f) {
-    this._shift(start, len, -2);
-    this._buf[seq] = len;
-  } else if (len <= 0xff) {
-    this._shift(start, len, -1);
-    this._buf[seq] = 0x81;
-    this._buf[seq + 1] = len;
-  } else if (len <= 0xffff) {
-    this._buf[seq] = 0x82;
-    this._buf[seq + 1] = len >> 8;
-    this._buf[seq + 2] = len;
-  } else if (len <= 0xffffff) {
-    this._shift(start, len, 1);
-    this._buf[seq] = 0x83;
-    this._buf[seq + 1] = len >> 16;
-    this._buf[seq + 2] = len >> 8;
-    this._buf[seq + 3] = len;
-  } else {
-    throw new InvalidAsn1Error('Sequence too long');
-  }
-};
-
-
-Writer.prototype._shift = function(start, len, shift) {
-  assert.ok(start !== undefined);
-  assert.ok(len !== undefined);
-  assert.ok(shift);
-
-  this._buf.copy(this._buf, start + shift, start, start + len);
-  this._offset += shift;
-};
-
-Writer.prototype._ensure = function(len) {
-  assert.ok(len);
-
-  if (this._size - this._offset < len) {
-    var sz = this._size * this._options.growthFactor;
-    if (sz - this._offset < len)
-      sz += len;
-
-    var buf = new Buffer(sz);
-
-    this._buf.copy(buf, 0, 0, this._offset);
-    this._buf = buf;
-    this._size = sz;
-  }
-};
-
-
-
-///--- Exported API
-
-module.exports = Writer;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js
deleted file mode 100644
index d1766e7a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-// If you have no idea what ASN.1 or BER is, see this:
-// ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
-
-var Ber = require('./ber/index');
-
-
-
-///--- Exported API
-
-module.exports = {
-
-  Ber: Ber,
-
-  BerReader: Ber.Reader,
-
-  BerWriter: Ber.Writer
-
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json
deleted file mode 100644
index d42d3ecb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
-  "author": {
-    "name": "Mark Cavage",
-    "email": "mcavage@gmail.com"
-  },
-  "contributors": [
-    {
-      "name": "David Gwynne",
-      "email": "loki@animata.net"
-    },
-    {
-      "name": "Yunong Xiao",
-      "email": "yunong@joyent.com"
-    }
-  ],
-  "name": "asn1",
-  "description": "Contains parsers and serializers for ASN.1 (currently BER only)",
-  "version": "0.1.11",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/mcavage/node-asn1.git"
-  },
-  "main": "lib/index.js",
-  "engines": {
-    "node": ">=0.4.9"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "tap": "0.1.4"
-  },
-  "scripts": {
-    "pretest": "which gjslint; if [[ \"$?\" = 0 ]] ; then  gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi",
-    "test": "tap ./tst"
-  },
-  "readme": "node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS.\nCurrently BER encoding is supported; at some point I'll likely have to do DER.\n\n## Usage\n\nMostly, if you're *actually* needing to read and write ASN.1, you probably don't\nneed this readme to explain what and why.  If you have no idea what ASN.1 is,\nsee this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc\n\nThe source is pretty much self-explanatory, and has read/write methods for the\ncommon types out there.\n\n### Decoding\n\nThe following reads an ASN.1 sequence with a boolean.\n\n    var Ber = require('asn1').Ber;\n\n    var reader = new Ber.Reader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff]));\n\n    reader.readSequence();\n    console.log('Sequence len: ' + reader.length);\n    if (reader.peek() === Ber.Boolean)\n      console.log(reader.readBoolean());\n\n### Encoding\n\nThe following generates the same payload as above.\n\n    var Ber = require('asn1').Ber;\n\n    var writer = new Ber.Writer();\n\n    writer.startSequence();\n    writer.writeBoolean(true);\n    writer.endSequence();\n\n    console.log(writer.buffer);\n\n## Installation\n\n    npm install asn1\n\n## License\n\nMIT.\n\n## Bugs\n\nSee <https://github.com/mcavage/node-asn1/issues>.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/mcavage/node-asn1/issues"
-  },
-  "homepage": "https://github.com/mcavage/node-asn1",
-  "_id": "asn1@0.1.11",
-  "_shasum": "559be18376d08a4ec4dbe80877d27818639b2df7",
-  "_from": "asn1@0.1.11",
-  "_resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js
deleted file mode 100644
index 0b78b474..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-var test = require('tap').test;
-
-
-
-///--- Globals
-
-var BerReader;
-
-
-
-///--- Tests
-
-test('load library', function(t) {
-  BerReader = require('../../lib/index').BerReader;
-  t.ok(BerReader);
-  try {
-    new BerReader();
-    t.fail('Should have thrown');
-  } catch (e) {
-    t.ok(e instanceof TypeError, 'Should have been a type error');
-  }
-  t.end();
-});
-
-
-test('read byte', function(t) {
-  var reader = new BerReader(new Buffer([0xde]));
-  t.ok(reader);
-  t.equal(reader.readByte(), 0xde, 'wrong value');
-  t.end();
-});
-
-
-test('read 1 byte int', function(t) {
-  var reader = new BerReader(new Buffer([0x02, 0x01, 0x03]));
-  t.ok(reader);
-  t.equal(reader.readInt(), 0x03, 'wrong value');
-  t.equal(reader.length, 0x01, 'wrong length');
-  t.end();
-});
-
-
-test('read 2 byte int', function(t) {
-  var reader = new BerReader(new Buffer([0x02, 0x02, 0x7e, 0xde]));
-  t.ok(reader);
-  t.equal(reader.readInt(), 0x7ede, 'wrong value');
-  t.equal(reader.length, 0x02, 'wrong length');
-  t.end();
-});
-
-
-test('read 3 byte int', function(t) {
-  var reader = new BerReader(new Buffer([0x02, 0x03, 0x7e, 0xde, 0x03]));
-  t.ok(reader);
-  t.equal(reader.readInt(), 0x7ede03, 'wrong value');
-  t.equal(reader.length, 0x03, 'wrong length');
-  t.end();
-});
-
-
-test('read 4 byte int', function(t) {
-  var reader = new BerReader(new Buffer([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01]));
-  t.ok(reader);
-  t.equal(reader.readInt(), 0x7ede0301, 'wrong value');
-  t.equal(reader.length, 0x04, 'wrong length');
-  t.end();
-});
-
-
-test('read boolean true', function(t) {
-  var reader = new BerReader(new Buffer([0x01, 0x01, 0xff]));
-  t.ok(reader);
-  t.equal(reader.readBoolean(), true, 'wrong value');
-  t.equal(reader.length, 0x01, 'wrong length');
-  t.end();
-});
-
-
-test('read boolean false', function(t) {
-  var reader = new BerReader(new Buffer([0x01, 0x01, 0x00]));
-  t.ok(reader);
-  t.equal(reader.readBoolean(), false, 'wrong value');
-  t.equal(reader.length, 0x01, 'wrong length');
-  t.end();
-});
-
-
-test('read enumeration', function(t) {
-  var reader = new BerReader(new Buffer([0x0a, 0x01, 0x20]));
-  t.ok(reader);
-  t.equal(reader.readEnumeration(), 0x20, 'wrong value');
-  t.equal(reader.length, 0x01, 'wrong length');
-  t.end();
-});
-
-
-test('read string', function(t) {
-  var dn = 'cn=foo,ou=unit,o=test';
-  var buf = new Buffer(dn.length + 2);
-  buf[0] = 0x04;
-  buf[1] = Buffer.byteLength(dn);
-  buf.write(dn, 2);
-  var reader = new BerReader(buf);
-  t.ok(reader);
-  t.equal(reader.readString(), dn, 'wrong value');
-  t.equal(reader.length, dn.length, 'wrong length');
-  t.end();
-});
-
-
-test('read sequence', function(t) {
-  var reader = new BerReader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff]));
-  t.ok(reader);
-  t.equal(reader.readSequence(), 0x30, 'wrong value');
-  t.equal(reader.length, 0x03, 'wrong length');
-  t.equal(reader.readBoolean(), true, 'wrong value');
-  t.equal(reader.length, 0x01, 'wrong length');
-  t.end();
-});
-
-
-test('anonymous LDAPv3 bind', function(t) {
-  var BIND = new Buffer(14);
-  BIND[0] = 0x30;  // Sequence
-  BIND[1] = 12;    // len
-  BIND[2] = 0x02;  // ASN.1 Integer
-  BIND[3] = 1;     // len
-  BIND[4] = 0x04;  // msgid (make up 4)
-  BIND[5] = 0x60;  // Bind Request
-  BIND[6] = 7;     // len
-  BIND[7] = 0x02;  // ASN.1 Integer
-  BIND[8] = 1;     // len
-  BIND[9] = 0x03;  // v3
-  BIND[10] = 0x04; // String (bind dn)
-  BIND[11] = 0;    // len
-  BIND[12] = 0x80; // ContextSpecific (choice)
-  BIND[13] = 0;    // simple bind
-
-  // Start testing ^^
-  var ber = new BerReader(BIND);
-  t.equal(ber.readSequence(), 48, 'Not an ASN.1 Sequence');
-  t.equal(ber.length, 12, 'Message length should be 12');
-  t.equal(ber.readInt(), 4, 'Message id should have been 4');
-  t.equal(ber.readSequence(), 96, 'Bind Request should have been 96');
-  t.equal(ber.length, 7, 'Bind length should have been 7');
-  t.equal(ber.readInt(), 3, 'LDAP version should have been 3');
-  t.equal(ber.readString(), '', 'Bind DN should have been empty');
-  t.equal(ber.length, 0, 'string length should have been 0');
-  t.equal(ber.readByte(), 0x80, 'Should have been ContextSpecific (choice)');
-  t.equal(ber.readByte(), 0, 'Should have been simple bind');
-  t.equal(null, ber.readByte(), 'Should be out of data');
-  t.end();
-});
-
-
-test('long string', function(t) {
-  var buf = new Buffer(256);
-  var o;
-  var s =
-    '2;649;CN=Red Hat CS 71GA Demo,O=Red Hat CS 71GA Demo,C=US;' +
-    'CN=RHCS Agent - admin01,UID=admin01,O=redhat,C=US [1] This is ' +
-    'Teena Vradmin\'s description.';
-  buf[0] = 0x04;
-  buf[1] = 0x81;
-  buf[2] = 0x94;
-  buf.write(s, 3);
-  var ber = new BerReader(buf.slice(0, 3 + s.length));
-  t.equal(ber.readString(), s);
-  t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js
deleted file mode 100644
index add0b9fd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
-
-var test = require('tap').test;
-var sys = require('sys');
-
-///--- Globals
-
-var BerWriter;
-
-var BerReader;
-
-
-///--- Tests
-
-test('load library', function(t) {
-  BerWriter = require('../../lib/index').BerWriter;
-  t.ok(BerWriter);
-  t.ok(new BerWriter());
-  t.end();
-});
-
-
-test('write byte', function(t) {
-  var writer = new BerWriter();
-
-  writer.writeByte(0xC2);
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 1, 'Wrong length');
-  t.equal(ber[0], 0xC2, 'value wrong');
-
-  t.end();
-});
-
-
-test('write 1 byte int', function(t) {
-  var writer = new BerWriter();
-
-  writer.writeInt(0x7f);
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 3, 'Wrong length for an int: ' + ber.length);
-  t.equal(ber[0], 0x02, 'ASN.1 tag wrong (2) -> ' + ber[0]);
-  t.equal(ber[1], 0x01, 'length wrong(1) -> ' + ber[1]);
-  t.equal(ber[2], 0x7f, 'value wrong(3) -> ' + ber[2]);
-
-  t.end();
-});
-
-
-test('write 2 byte int', function(t) {
-  var writer = new BerWriter();
-
-  writer.writeInt(0x7ffe);
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 4, 'Wrong length for an int');
-  t.equal(ber[0], 0x02, 'ASN.1 tag wrong');
-  t.equal(ber[1], 0x02, 'length wrong');
-  t.equal(ber[2], 0x7f, 'value wrong (byte 1)');
-  t.equal(ber[3], 0xfe, 'value wrong (byte 2)');
-
-  t.end();
-});
-
-
-test('write 3 byte int', function(t) {
-  var writer = new BerWriter();
-
-  writer.writeInt(0x7ffffe);
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 5, 'Wrong length for an int');
-  t.equal(ber[0], 0x02, 'ASN.1 tag wrong');
-  t.equal(ber[1], 0x03, 'length wrong');
-  t.equal(ber[2], 0x7f, 'value wrong (byte 1)');
-  t.equal(ber[3], 0xff, 'value wrong (byte 2)');
-  t.equal(ber[4], 0xfe, 'value wrong (byte 3)');
-
-  t.end();
-});
-
-
-test('write 4 byte int', function(t) {
-  var writer = new BerWriter();
-
-  writer.writeInt(0x7ffffffe);
-  var ber = writer.buffer;
-
-  t.ok(ber);
-
-  t.equal(ber.length, 6, 'Wrong length for an int');
-  t.equal(ber[0], 0x02, 'ASN.1 tag wrong');
-  t.equal(ber[1], 0x04, 'length wrong');
-  t.equal(ber[2], 0x7f, 'value wrong (byte 1)');
-  t.equal(ber[3], 0xff, 'value wrong (byte 2)');
-  t.equal(ber[4], 0xff, 'value wrong (byte 3)');
-  t.equal(ber[5], 0xfe, 'value wrong (byte 4)');
-
-  t.end();
-});
-
-
-test('write boolean', function(t) {
-  var writer = new BerWriter();
-
-  writer.writeBoolean(true);
-  writer.writeBoolean(false);
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 6, 'Wrong length');
-  t.equal(ber[0], 0x01, 'tag wrong');
-  t.equal(ber[1], 0x01, 'length wrong');
-  t.equal(ber[2], 0xff, 'value wrong');
-  t.equal(ber[3], 0x01, 'tag wrong');
-  t.equal(ber[4], 0x01, 'length wrong');
-  t.equal(ber[5], 0x00, 'value wrong');
-
-  t.end();
-});
-
-
-test('write string', function(t) {
-  var writer = new BerWriter();
-  writer.writeString('hello world');
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 13, 'wrong length');
-  t.equal(ber[0], 0x04, 'wrong tag');
-  t.equal(ber[1], 11, 'wrong length');
-  t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value');
-
-  t.end();
-});
-
-test('write buffer', function(t) {
-  var writer = new BerWriter();
-  // write some stuff to start with
-  writer.writeString('hello world');
-  var ber = writer.buffer;
-  var buf = new Buffer([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01,
-     0xff, 0x01, 0x01, 0xff]);
-  writer.writeBuffer(buf.slice(2, buf.length), 0x04);
-  ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 26, 'wrong length');
-  t.equal(ber[0], 0x04, 'wrong tag');
-  t.equal(ber[1], 11, 'wrong length');
-  t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value');
-  t.equal(ber[13], buf[0], 'wrong tag');
-  t.equal(ber[14], buf[1], 'wrong length');
-  for (var i = 13, j = 0; i < ber.length && j < buf.length; i++, j++) {
-    t.equal(ber[i], buf[j], 'buffer contents not identical');
-  }
-  t.end();
-});
-
-test('write string array', function(t) {
-  var writer = new BerWriter();
-  writer.writeStringArray(['hello world', 'fubar!']);
-  var ber = writer.buffer;
-
-  t.ok(ber);
-
-  t.equal(ber.length, 21, 'wrong length');
-  t.equal(ber[0], 0x04, 'wrong tag');
-  t.equal(ber[1], 11, 'wrong length');
-  t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value');
-
-  t.equal(ber[13], 0x04, 'wrong tag');
-  t.equal(ber[14], 6, 'wrong length');
-  t.equal(ber.slice(15).toString('utf8'), 'fubar!', 'wrong value');
-
-  t.end();
-});
-
-
-test('resize internal buffer', function(t) {
-  var writer = new BerWriter({size: 2});
-  writer.writeString('hello world');
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 13, 'wrong length');
-  t.equal(ber[0], 0x04, 'wrong tag');
-  t.equal(ber[1], 11, 'wrong length');
-  t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value');
-
-  t.end();
-});
-
-
-test('sequence', function(t) {
-  var writer = new BerWriter({size: 25});
-  writer.startSequence();
-  writer.writeString('hello world');
-  writer.endSequence();
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  console.log(ber);
-  t.equal(ber.length, 15, 'wrong length');
-  t.equal(ber[0], 0x30, 'wrong tag');
-  t.equal(ber[1], 13, 'wrong length');
-  t.equal(ber[2], 0x04, 'wrong tag');
-  t.equal(ber[3], 11, 'wrong length');
-  t.equal(ber.slice(4).toString('utf8'), 'hello world', 'wrong value');
-
-  t.end();
-});
-
-
-test('nested sequence', function(t) {
-  var writer = new BerWriter({size: 25});
-  writer.startSequence();
-  writer.writeString('hello world');
-  writer.startSequence();
-  writer.writeString('hello world');
-  writer.endSequence();
-  writer.endSequence();
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 30, 'wrong length');
-  t.equal(ber[0], 0x30, 'wrong tag');
-  t.equal(ber[1], 28, 'wrong length');
-  t.equal(ber[2], 0x04, 'wrong tag');
-  t.equal(ber[3], 11, 'wrong length');
-  t.equal(ber.slice(4, 15).toString('utf8'), 'hello world', 'wrong value');
-  t.equal(ber[15], 0x30, 'wrong tag');
-  t.equal(ber[16], 13, 'wrong length');
-  t.equal(ber[17], 0x04, 'wrong tag');
-  t.equal(ber[18], 11, 'wrong length');
-  t.equal(ber.slice(19, 30).toString('utf8'), 'hello world', 'wrong value');
-
-  t.end();
-});
-
-
-test('LDAP bind message', function(t) {
-  var dn = 'cn=foo,ou=unit,o=test';
-  var writer = new BerWriter();
-  writer.startSequence();
-  writer.writeInt(3);             // msgid = 3
-  writer.startSequence(0x60);     // ldap bind
-  writer.writeInt(3);             // ldap v3
-  writer.writeString(dn);
-  writer.writeByte(0x80);
-  writer.writeByte(0x00);
-  writer.endSequence();
-  writer.endSequence();
-  var ber = writer.buffer;
-
-  t.ok(ber);
-  t.equal(ber.length, 35, 'wrong length (buffer)');
-  t.equal(ber[0], 0x30, 'wrong tag');
-  t.equal(ber[1], 33, 'wrong length');
-  t.equal(ber[2], 0x02, 'wrong tag');
-  t.equal(ber[3], 1, 'wrong length');
-  t.equal(ber[4], 0x03, 'wrong value');
-  t.equal(ber[5], 0x60, 'wrong tag');
-  t.equal(ber[6], 28, 'wrong length');
-  t.equal(ber[7], 0x02, 'wrong tag');
-  t.equal(ber[8], 1, 'wrong length');
-  t.equal(ber[9], 0x03, 'wrong value');
-  t.equal(ber[10], 0x04, 'wrong tag');
-  t.equal(ber[11], dn.length, 'wrong length');
-  t.equal(ber.slice(12, 33).toString('utf8'), dn, 'wrong value');
-  t.equal(ber[33], 0x80, 'wrong tag');
-  t.equal(ber[34], 0x00, 'wrong len');
-
-  t.end();
-});
-
-
-test('Write OID', function(t) {
-  var oid = '1.2.840.113549.1.1.1';
-  var writer = new BerWriter();
-  writer.writeOID(oid);
-
-  var ber = writer.buffer;
-  t.ok(ber);
-  console.log(require('util').inspect(ber));
-  console.log(require('util').inspect(new Buffer([0x06, 0x09, 0x2a, 0x86,
-                                                  0x48, 0x86, 0xf7, 0x0d,
-                                                  0x01, 0x01, 0x01])));
-
-  t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md
deleted file mode 100644
index c0c3a530..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# node-assert-plus
-
-This library is a super small wrapper over node's assert module that has two
-things: (1) the ability to disable assertions with the environment variable
-NODE_NDEBUG, and (2) some API wrappers for argument testing.  Like
-`assert.string(myArg, 'myArg')`.  As a simple example, most of my code looks
-like this:
-
-    var assert = require('assert-plus');
-
-    function fooAccount(options, callback) {
-	    assert.object(options, 'options');
-		assert.number(options.id, 'options.id);
-		assert.bool(options.isManager, 'options.isManager');
-		assert.string(options.name, 'options.name');
-		assert.arrayOfString(options.email, 'options.email');
-		assert.func(callback, 'callback');
-
-        // Do stuff
-		callback(null, {});
-    }
-
-# API
-
-All methods that *aren't* part of node's core assert API are simply assumed to
-take an argument, and then a string 'name' that's not a message; `AssertionError`
-will be thrown if the assertion fails with a message like:
-
-    AssertionError: foo (string) is required
-	at test (/home/mark/work/foo/foo.js:3:9)
-	at Object.<anonymous> (/home/mark/work/foo/foo.js:15:1)
-	at Module._compile (module.js:446:26)
-	at Object..js (module.js:464:10)
-	at Module.load (module.js:353:31)
-	at Function._load (module.js:311:12)
-	at Array.0 (module.js:484:10)
-	at EventEmitter._tickCallback (node.js:190:38)
-
-from:
-
-    function test(foo) {
-	    assert.string(foo, 'foo');
-    }
-
-There you go.  You can check that arrays are of a homogenous type with `Arrayof$Type`:
-
-    function test(foo) {
-	    assert.arrayOfString(foo, 'foo');
-    }
-
-You can assert IFF an argument is not `undefined` (i.e., an optional arg):
-
-    assert.optionalString(foo, 'foo');
-
-Lastly, you can opt-out of assertion checking altogether by setting the
-environment variable `NODE_NDEBUG=1`.  This is pseudo-useful if you have
-lots of assertions, and don't want to pay `typeof ()` taxes to v8 in
-production.
-
-The complete list of APIs is:
-
-* assert.bool
-* assert.buffer
-* assert.func
-* assert.number
-* assert.object
-* assert.string
-* assert.arrayOfBool
-* assert.arrayOfFunc
-* assert.arrayOfNumber
-* assert.arrayOfObject
-* assert.arrayOfString
-* assert.optionalBool
-* assert.optionalBuffer
-* assert.optionalFunc
-* assert.optionalNumber
-* assert.optionalObject
-* assert.optionalString
-* assert.optionalArrayOfBool
-* assert.optionalArrayOfFunc
-* assert.optionalArrayOfNumber
-* assert.optionalArrayOfObject
-* assert.optionalArrayOfString
-* assert.AssertionError
-* assert.fail
-* assert.ok
-* assert.equal
-* assert.notEqual
-* assert.deepEqual
-* assert.notDeepEqual
-* assert.strictEqual
-* assert.notStrictEqual
-* assert.throws
-* assert.doesNotThrow
-* assert.ifError
-
-# Installation
-
-    npm install assert-plus
-
-## License
-
-The MIT License (MIT)
-Copyright (c) 2012 Mark Cavage
-
-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.
-
-## Bugs
-
-See <https://github.com/mcavage/node-assert-plus/issues>.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js
deleted file mode 100644
index 70583f12..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) 2012, Mark Cavage. All rights reserved.
-
-var assert = require('assert');
-var Stream = require('stream').Stream;
-var util = require('util');
-
-
-
-///--- Globals
-
-var NDEBUG = process.env.NODE_NDEBUG || false;
-
-
-
-///--- Messages
-
-var ARRAY_TYPE_REQUIRED = '%s ([%s]) required';
-var TYPE_REQUIRED = '%s (%s) is required';
-
-
-
-///--- Internal
-
-function capitalize(str) {
-        return (str.charAt(0).toUpperCase() + str.slice(1));
-}
-
-function uncapitalize(str) {
-        return (str.charAt(0).toLowerCase() + str.slice(1));
-}
-
-function _() {
-        return (util.format.apply(util, arguments));
-}
-
-
-function _assert(arg, type, name, stackFunc) {
-        if (!NDEBUG) {
-                name = name || type;
-                stackFunc = stackFunc || _assert.caller;
-                var t = typeof (arg);
-
-                if (t !== type) {
-                        throw new assert.AssertionError({
-                                message: _(TYPE_REQUIRED, name, type),
-                                actual: t,
-                                expected: type,
-                                operator: '===',
-                                stackStartFunction: stackFunc
-                        });
-                }
-        }
-}
-
-
-
-///--- API
-
-function array(arr, type, name) {
-        if (!NDEBUG) {
-                name = name || type;
-
-                if (!Array.isArray(arr)) {
-                        throw new assert.AssertionError({
-                                message: _(ARRAY_TYPE_REQUIRED, name, type),
-                                actual: typeof (arr),
-                                expected: 'array',
-                                operator: 'Array.isArray',
-                                stackStartFunction: array.caller
-                        });
-                }
-
-                for (var i = 0; i < arr.length; i++) {
-                        _assert(arr[i], type, name, array);
-                }
-        }
-}
-
-
-function bool(arg, name) {
-        _assert(arg, 'boolean', name, bool);
-}
-
-
-function buffer(arg, name) {
-        if (!Buffer.isBuffer(arg)) {
-                throw new assert.AssertionError({
-                        message: _(TYPE_REQUIRED, name, type),
-                        actual: typeof (arg),
-                        expected: 'buffer',
-                        operator: 'Buffer.isBuffer',
-                        stackStartFunction: buffer
-                });
-        }
-}
-
-
-function func(arg, name) {
-        _assert(arg, 'function', name);
-}
-
-
-function number(arg, name) {
-        _assert(arg, 'number', name);
-}
-
-
-function object(arg, name) {
-        _assert(arg, 'object', name);
-}
-
-
-function stream(arg, name) {
-        if (!(arg instanceof Stream)) {
-                throw new assert.AssertionError({
-                        message: _(TYPE_REQUIRED, name, type),
-                        actual: typeof (arg),
-                        expected: 'Stream',
-                        operator: 'instanceof',
-                        stackStartFunction: buffer
-                });
-        }
-}
-
-
-function string(arg, name) {
-        _assert(arg, 'string', name);
-}
-
-
-
-///--- Exports
-
-module.exports = {
-        bool: bool,
-        buffer: buffer,
-        func: func,
-        number: number,
-        object: object,
-        stream: stream,
-        string: string
-};
-
-
-Object.keys(module.exports).forEach(function (k) {
-        if (k === 'buffer')
-                return;
-
-        var name = 'arrayOf' + capitalize(k);
-
-        if (k === 'bool')
-                k = 'boolean';
-        if (k === 'func')
-                k = 'function';
-        module.exports[name] = function (arg, name) {
-                array(arg, k, name);
-        };
-});
-
-Object.keys(module.exports).forEach(function (k) {
-        var _name = 'optional' + capitalize(k);
-        var s = uncapitalize(k.replace('arrayOf', ''));
-        if (s === 'bool')
-                s = 'boolean';
-        if (s === 'func')
-                s = 'function';
-
-        if (k.indexOf('arrayOf') !== -1) {
-          module.exports[_name] = function (arg, name) {
-                  if (!NDEBUG && arg !== undefined) {
-                          array(arg, s, name);
-                  }
-          };
-        } else {
-          module.exports[_name] = function (arg, name) {
-                  if (!NDEBUG && arg !== undefined) {
-                          _assert(arg, s, name);
-                  }
-          };
-        }
-});
-
-
-// Reexport built-in assertions
-Object.keys(assert).forEach(function (k) {
-        if (k === 'AssertionError') {
-                module.exports[k] = assert[k];
-                return;
-        }
-
-        module.exports[k] = function () {
-                if (!NDEBUG) {
-                        assert[k].apply(assert[k], arguments);
-                }
-        };
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json
deleted file mode 100644
index 94c40b08..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "author": {
-    "name": "Mark Cavage",
-    "email": "mcavage@gmail.com"
-  },
-  "name": "assert-plus",
-  "description": "Extra assertions on top of node's assert module",
-  "version": "0.1.2",
-  "main": "./assert.js",
-  "dependencies": {},
-  "devDependencies": {},
-  "optionalDependencies": {},
-  "engines": {
-    "node": ">=0.6"
-  },
-  "readme": "# node-assert-plus\n\nThis library is a super small wrapper over node's assert module that has two\nthings: (1) the ability to disable assertions with the environment variable\nNODE_NDEBUG, and (2) some API wrappers for argument testing.  Like\n`assert.string(myArg, 'myArg')`.  As a simple example, most of my code looks\nlike this:\n\n    var assert = require('assert-plus');\n\n    function fooAccount(options, callback) {\n\t    assert.object(options, 'options');\n\t\tassert.number(options.id, 'options.id);\n\t\tassert.bool(options.isManager, 'options.isManager');\n\t\tassert.string(options.name, 'options.name');\n\t\tassert.arrayOfString(options.email, 'options.email');\n\t\tassert.func(callback, 'callback');\n\n        // Do stuff\n\t\tcallback(null, {});\n    }\n\n# API\n\nAll methods that *aren't* part of node's core assert API are simply assumed to\ntake an argument, and then a string 'name' that's not a message; `AssertionError`\nwill be thrown if the assertion fails with a message like:\n\n    AssertionError: foo (string) is required\n\tat test (/home/mark/work/foo/foo.js:3:9)\n\tat Object.<anonymous> (/home/mark/work/foo/foo.js:15:1)\n\tat Module._compile (module.js:446:26)\n\tat Object..js (module.js:464:10)\n\tat Module.load (module.js:353:31)\n\tat Function._load (module.js:311:12)\n\tat Array.0 (module.js:484:10)\n\tat EventEmitter._tickCallback (node.js:190:38)\n\nfrom:\n\n    function test(foo) {\n\t    assert.string(foo, 'foo');\n    }\n\nThere you go.  You can check that arrays are of a homogenous type with `Arrayof$Type`:\n\n    function test(foo) {\n\t    assert.arrayOfString(foo, 'foo');\n    }\n\nYou can assert IFF an argument is not `undefined` (i.e., an optional arg):\n\n    assert.optionalString(foo, 'foo');\n\nLastly, you can opt-out of assertion checking altogether by setting the\nenvironment variable `NODE_NDEBUG=1`.  This is pseudo-useful if you have\nlots of assertions, and don't want to pay `typeof ()` taxes to v8 in\nproduction.\n\nThe complete list of APIs is:\n\n* assert.bool\n* assert.buffer\n* assert.func\n* assert.number\n* assert.object\n* assert.string\n* assert.arrayOfBool\n* assert.arrayOfFunc\n* assert.arrayOfNumber\n* assert.arrayOfObject\n* assert.arrayOfString\n* assert.optionalBool\n* assert.optionalBuffer\n* assert.optionalFunc\n* assert.optionalNumber\n* assert.optionalObject\n* assert.optionalString\n* assert.optionalArrayOfBool\n* assert.optionalArrayOfFunc\n* assert.optionalArrayOfNumber\n* assert.optionalArrayOfObject\n* assert.optionalArrayOfString\n* assert.AssertionError\n* assert.fail\n* assert.ok\n* assert.equal\n* assert.notEqual\n* assert.deepEqual\n* assert.notDeepEqual\n* assert.strictEqual\n* assert.notStrictEqual\n* assert.throws\n* assert.doesNotThrow\n* assert.ifError\n\n# Installation\n\n    npm install assert-plus\n\n## License\n\nThe MIT License (MIT)\nCopyright (c) 2012 Mark Cavage\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n## Bugs\n\nSee <https://github.com/mcavage/node-assert-plus/issues>.\n",
-  "readmeFilename": "README.md",
-  "_id": "assert-plus@0.1.2",
-  "_shasum": "d93ffdbb67ac5507779be316a7d65146417beef8",
-  "_from": "assert-plus@0.1.2",
-  "_resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG
deleted file mode 100644
index 078c03ca..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG
+++ /dev/null
@@ -1,71 +0,0 @@
-This contains tickets fixed in each version release in reverse chronological
-order. There is one ticket per line. Each commits message has the tickets fixed
-in it. The commit message also has the corresponding github issue. i.e. CTYPE-42
-would be issue 42. Each issue can be found at:
-https://github.com/rmustacc/node-ctype/issues/%d.
-
-CTYPE v0.5.2
-CTYPE-46 Release 0.5.2
-CTYPE-45 error in setEndian logic
-
-v0.5.1
-CTYPE-44 Release 0.5.1
-Contributed by Terin Stock:
-CTYPE-41 CTypeParser.writeStruct should return its offset
-Contributed by Terin Stock:
-CTYPE-42 int64_t returns wrong size
-
-v0.5.0
-CTYPE-40 Release 0.5.0
-CTYPE-39 want > 0.6 engine support
-
-v0.4.0
-CTYPE-37 Release v0.4.0
-CTYPE-6 want additional entry point for write
-CTYPE-20 Add 64-bit int support into core parser
-CTYPE-31 Fix bounds errors node/2129
-CTYPE-33 Update copyright holders
-CTYPE-34 ctf.js confuses sign bit.
-CTYPE-35 Make the README more useful for getting started
-CTYPE-36 want manual page on ctio functions
-
-v0.3.1
-CTYPE-29 Release 0.3.1
-CTYPE-28 Want v0.6 npm support
-
-v0.3.0
-CTYPE-27 Release v0.3.0
-CTYPE-26 Want alternate default char behavior
-
-v0.2.1
-CTYPE-25 Release v0.2.1
-CTYPE-24 Writing structs is busted
-
-v0.2.0:
-CTYPE-23 Release v0.2.0
-CTYPE-21 Add support for CTF JSON data
-CTYPE-22 Add Javascriptlint profile
-CTYPE-15 Pull in ctio updates from node/master
-
-v0.1.0:
-CTYPE-18 Bump version to v0.1.0
-CTYPE-17 Fix nested structures
-CTYPE-16 Remove extraneous logging
-CTYPE-14 toAbs64 and toApprox64 are not exported
-
-v0.0.3:
-CTYPE-12 Bump version to v0.0.3
-CTYPE-11 fix typo in wuint64
-CTYPE-10 Integrate jsstyle
-
-v0.0.2:
-CTYPE-8 dump npm version to v0.0.2
-CTYPE-9 want changelog
-CTYPE-7 fix typo in detypes.
-
-v0.0.1:
-CTYPE-5 Missing from NPM registry
-CTYPE-4 int16_t calls wrong read function
-CTYPE-3 API example types are missing quotes as strings
-CTYPE-2 doc missing 64-bit functions
-CTYPE-1 Need license
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE
deleted file mode 100644
index 22ced3e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-The following license applies to all files unless the file is specified below.
-Each file specified below has its license information embedded in it:
-
-tools/jsstyle
-
-Copyright 2011, Robert Mustacchi. All rights reserved.
-Copyright 2011, Joyent, Inc. All rights reserved.
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README
deleted file mode 100644
index 4efd7ee5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README
+++ /dev/null
@@ -1,82 +0,0 @@
-Node-CType is a way to read and write binary data in structured and easy to use
-format. Its name comes from the C header file.
-
-To get started, simply clone the repository or use npm to install it. Once it is
-there, simply require it.
-
-git clone git://github.com/rmustacc/node-ctype
-npm install ctype
-var mod_ctype = require('ctype')
-
-
-There are two APIs that you can use, depending on what abstraction you'd like.
-The low level API let's you read and write individual integers and floats from
-buffers. The higher level API let's you read and write structures of these. To
-illustrate this, let's looks look at how we would read and write a binary
-encoded x,y point.
-
-In C we would define this structure as follows:
-
-typedef struct point {
-	uint16_t	p_x;
-	uint16_t	p_y;
-} point_t;
-
-To read a binary encoded point from a Buffer, we first need to create a CType
-parser (where we specify the endian and other options) and add the typedef.
-
-var parser = new mod_ctype.Parser({ endian: 'big' });
-parser.typedef('point_t', [
-	{ x: { type: 'uint16_t' } },
-	{ y: { type: 'uint16_t' } }
-]);
-
-From here, given a buffer buf and an offset into it, we can read a point.
-
-var out = parser.readData([ { point: { type: 'point_t' } } ], buffer, 0);
-console.log(out);
-{ point: { x: 23, y: 42 } }
-
-Another way to get the same information would be to use the low level methods.
-Note that these require you to manually deal with the offset. Here's how we'd
-get the same values of x and y from the buffer.
-
-var x = mod_ctype.ruint16(buf, 'big', 0);
-var y = mod_ctype.ruint16(buf, 'big', 2);
-console.log(x + ', ' + y);
-23, 42
-
-The true power of this API comes from the ability to define and nest typedefs,
-just as you would in C. By default, the following types are defined by default.
-Note that they return a Number, unless indicated otherwise.
-
-    * int8_t
-    * int16_t
-    * int32_t
-    * int64_t (returns an array where val[0] << 32 + val[1] would be the value)
-    * uint8_t
-    * uint16_t
-    * uint32_t
-    * uint64_t (returns an array where val[0] << 32 + val[1] would be the value)
-    * float
-    * double
-    * char (either returns a buffer with that character or a uint8_t)
-    * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)
-
-
-ctf2json integration:
-
-Node-CType supports consuming the output of ctf2json. Once you read in a JSON file,
-all you have to do to add all the definitions it contains is:
-
-var data, parser;
-data = JSON.parse(parsedJSONData);
-parser = mod_ctype.parseCTF(data, { endian: 'big' });
-
-For more documentation, see the file README.old. Full documentation is in the
-process of being rewritten as a series of manual pages which will be available
-in the repository and online for viewing.
-
-To read the ctio manual page simple run, from the root of the workspace:
-
-man -Mman -s 3ctype ctio
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README.old b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README.old
deleted file mode 100644
index 9326b725..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/README.old
+++ /dev/null
@@ -1,298 +0,0 @@
-This library provides a way to read and write binary data.
-
-Node CType is a way to read and write binary data in structured and easy to use
-formats. It's name comes from the header file, though it does not share as much
-with it as it perhaps should.
-
-There are two levels of the API. One is the raw API which everything is built on
-top of, while the other provides a much nicer abstraction and is built entirely
-by using the lower level API. The hope is that the low level API is both clear
-and useful. The low level API gets it's names from stdint.h (a rather
-appropriate source). The lower level API is presented at the end of this
-document.
-
-Standard CType API
-
-The CType interface is presented as a parser object that controls the
-endianness combined with a series of methods to change that value, parse and
-write out buffers, and a way to provide typedefs.  Standard Types
-
-The CType parser supports the following basic types which return Numbers except
-as indicated:
-
-    * int8_t
-    * int16_t
-    * int32_t
-    * int64_t (returns an array where val[0] << 32 + val[1] would be the value)
-    * uint8_t
-    * uint16_t
-    * uint32_t
-    * uint64_t (returns an array where val[0] << 32 + val[1] would be the value)
-    * float
-    * double
-    * char (returns a buffer with just that single character)
-    * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)
-
-Specifying Structs
-
-The CType parser also supports the notion of structs. A struct is an array of
-JSON objects that defines an order of keys which have types and values. One
-would build a struct to represent a point (x,y) as follows:
-
-[
-    { x: { type: 'int16_t' }},
-    { y: { type: 'int16_t' }}
-]
-
-When this is passed into the read routine, it would read the first two bytes
-(as defined by int16_t) to determine the Number to use for X, and then it would
-read the next two bytes to determine the value of Y. When read this could
-return something like:
-
-{
-    x: 42,
-    y: -23
-}
-
-When someone wants to write values, we use the same format as above, but with
-additional value field:
-
-[
-    { x: { type: 'int16_t', value: 42 }},
-    { y: { type: 'int16_t', value: -23 }}
-]
-
-Now, the structure above may be optionally annotated with offsets. This tells
-us to rather than read continuously we should read the given value at the
-specified offset. If an offset is provided, it is is effectively the equivalent
-of lseek(offset, SEEK_SET). Thus, subsequent values will be read from that
-offset and incremented by the appropriate value. As an example:
-
-[
-    { x: { type: 'int16_t' }},
-    { y: { type: 'int16_t', offset: 20 }},
-    { z: { type: 'int16_t' }}
-]
-
-We would read x from the first starting offset given to us, for the sake of
-example, let's assume that's 0. After reading x, the next offset to read from
-would be 2; however, y specifies an offset, thus we jump directly to that
-offset and read y from byte 20. We would then read z from byte 22.
-
-The same offsets may be used when writing values.
-
-Typedef
-
-The basic set of types while covers the basics, is somewhat limiting. To make
-this richer, there is functionality to typedef something like in C. One can use
-typedef to add a new name to an existing type or to define a name to refer to a
-struct. Thus the following are all examples of a typedef:
-
-typedef('size_t', 'uint32_t');
-typedef('ssize_t', 'int32_t');
-typedef('point_t', [
-    { x: { type: 'int16_t' }},
-    { y: { type: 'int16_t' }}
-]);
-
-Once something has been typedef'd it can be used in any of the definitions
-previously shown.
-
-One cannot remove a typedef once created, this is analogous to C.
-
-The set of defined types can be printed with lstypes. The format of this output
-is subject to change, but likely will look something like:
-
-> lstypes();
-{
-    size_t: 'uint32_t',
-    ssize_t: 'int32_t',
-    point_t: [
-        { x: { type: 'int16_t' }},
-        { y: { type: 'int16_t' }}
-    ]
-}
-
-Specifying arrays
-
-Arrays can be specified by appending []s to a type. Arrays must have the size
-specified. The size must be specified and it can be done in one of two ways:
-
-    * An explicit non-zero integer size
-    * A name of a previously declared variable in the struct whose value is a
-      number.
-
-Note, that when using the name of a variable, it should be the string name for
-the key. This is only valid inside structs and the value must be declared
-before the value with the array. The following are examples:
-
-[
-    { ip_addr4: { type: 'uint8_t[4]' }},
-    { len: { type: 'uint32_t' }},
-    { data: { type: 'uint8_t[len]' }}
-]
-
-Arrays are permitted in typedefs; however, they must have a declared integer
-size. The following are examples of valid and invalid arrays:
-
-typedef('path', 'char[1024]'); /* Good */
-typedef('path', 'char[len]');  /* Bad! */
-
-64 bit values:
-
-Unfortunately Javascript represents values with a double, so you lose precision
-and the ability to represent Integers roughly beyond 2^53. To alleviate this, I
-propose the following for returning 64 bit integers when read:
-
-value[2]: Each entry is a 32 bit number which can be reconstructed to the
-original by the following formula:
-
-value[0] << 32 + value[1] (Note this will not work in Javascript)
-
-CTF JSON data:
-
-node-ctype can also handle JSON data that mathces the format described in the
-documentation of the tool ctf2json. Given the JSON data which specifies type
-information, it will transform that into a parser that understands all of the
-types defined inside of it. This is useful for more complicated structures that
-have a lot of typedefs.
-
-Interface overview
-
-The following is the header-file like interface to the parser object:
-
-/*
- * Create a new instance of the parser. Each parser has its own store of
- * typedefs and endianness. Conf is an object with the following values:
- *
- *      endian          Either 'big' or 'little' do determine the endianness we
- *                      want to read from or write to.
- *
- */
-function CTypeParser(conf);
-
-/*
- * Parses the CTF JSON data and creates a parser that understands all of those
- * types.
- *
- *	data		Parsed JSON data that maches that CTF JSON
- *			specification.
- *
- *	conf		The configuration object to create a new CTypeParser
- *			from.
- */
-CTypeParser parseCTF(data, conf);
-
-/*
- * This is what we were born to do. We read the data from a buffer and return it
- * in an object whose keys match the values from the object.
- *
- *      def             The array definition of the data to read in
- *
- *      buffer          The buffer to read data from
- *
- *      offset          The offset to start writing to
- *
- * Returns an object where each key corresponds to an entry in def and the value
- * is the read value.
- */
-Object CTypeParser.readData(<Type Definition>, buffer, offset);
-
-/*
- * This is the second half of what we were born to do, write out the data
- * itself.
- *
- *      def             The array definition of the data to write out with
- *                      values
- *
- *      buffer          The buffer to write to
- *
- *      offset          The offset in the buffer to write to
- */
-void CTypeParser.writeData(<Type Definition>, buffer, offset);
-
-/*
- * A user has requested to add a type, let us honor their request. Yet, if their
- * request doth spurn us, send them unto the Hells which Dante describes.
- *
- *      name            The string for the type definition we're adding
- *
- *      value           Either a string that is a type/array name or an object
- *                      that describes a struct.
- */
-void CTypeParser.prototype.typedef(name, value);
-
-Object CTypeParser.prototype.lstypes();
-
-/*
- * Get the endian value for the current parser
- */
-String CTypeParser.prototype.getEndian();
-
-/*
- * Sets the current endian value for the Parser. If the value is not valid,
- * throws an Error.
- *
- *      endian          Either 'big' or 'little' do determine the endianness we
- *                      want to read from or write to.
- *
- */
-void CTypeParser.protoype.setEndian(String);
-
-/*
- * Attempts to convert an array of two integers returned from rsint64 / ruint64
- * into an absolute 64 bit number. If however the value would exceed 2^52 this
- * will instead throw an error. The mantissa in a double is a 52 bit number and
- * rather than potentially give you a value that is an approximation this will
- * error. If you would rather an approximation, please see toApprox64.
- *
- *	val		An array of two 32-bit integers
- */
-Number function toAbs64(val)
-
-/*
- * Will return the 64 bit value as returned in an array from rsint64 / ruint64
- * to a value as close as it can. Note that Javascript stores all numbers as a
- * double and the mantissa only has 52 bits. Thus this version may approximate
- * the value.
- *
- *	val		An array of two 32-bit integers
- */
-Number function toApprox64(val)
-
-Low Level API
-
-The following function are provided at the low level:
-
-Read unsigned integers from a buffer:
-Number ruint8(buffer, endian, offset);
-Number ruint16(buffer, endian, offset);
-Number ruint32(buffer, endian, offset);
-Number[] ruint64(buffer, endian, offset);
-
-Read signed integers from a buffer:
-Number rsint8(buffer, endian, offset);
-Number rsint16(buffer, endian, offset);
-Number rsint32(buffer, endian, offset);
-Number[] rsint64(buffer, endian, offset);
-
-Read floating point numbers from a buffer:
-Number rfloat(buffer, endian, offset);   /* IEEE-754 Single precision */
-Number rdouble(buffer, endian, offset);  /* IEEE-754 Double precision */
-
-Write unsigned integers to a buffer:
-void wuint8(Number, endian, buffer, offset);
-void wuint16(Number, endian, buffer, offset);
-void wuint32(Number, endian, buffer, offset);
-void wuint64(Number[], endian, buffer, offset);
-
-Write signed integers from a buffer:
-void wsint8(Number, endian, buffer, offset);
-void wsint16(Number, endian, buffer, offset);
-void wsint32(Number, endian, buffer, offset);
-void wsint64(Number[], endian, buffer offset);
-
-Write floating point numbers from a buffer:
-void wfloat(Number, buffer, endian, offset);   /* IEEE-754 Single precision */
-void wdouble(Number, buffer, endian, offset);  /* IEEE-754 Double precision */
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js
deleted file mode 100644
index 66d5f735..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * ctf.js
- *
- * Understand and parse all of the different JSON formats of CTF data and
- * translate that into a series of node-ctype friendly pieces. The reason for
- * the abstraction is to handle different changes in the file format.
- *
- * We have to be careful here that we don't end up using a name that is already
- * a built in type.
- */
-var mod_assert = require('assert');
-var ASSERT = mod_assert.ok;
-
-var ctf_versions = [ '1.0' ];
-var ctf_entries = [ 'integer', 'float', 'typedef', 'struct' ];
-var ctf_deftypes = [ 'int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t',
-    'uint32_t', 'float', 'double' ];
-
-function ctfParseInteger(entry, ctype)
-{
-	var name, sign, len, type;
-
-	name = entry['name'];
-	if (!('signed' in entry['integer']))
-		throw (new Error('Malformed CTF JSON: integer missing ' +
-		    'signed value'));
-
-
-	if (!('length' in entry['integer']))
-		throw (new Error('Malformed CTF JSON: integer missing ' +
-		    'length value'));
-
-	sign = entry['integer']['signed'];
-	len = entry['integer']['length'];
-	type = null;
-
-	if (sign && len == 1)
-		type = 'int8_t';
-	else if (len == 1)
-		type = 'uint8_t';
-	else if (sign && len == 2)
-		type = 'int16_t';
-	else if (len == 2)
-		type = 'uint16_t';
-	else if (sign && len == 4)
-		type = 'int32_t';
-	else if (len == 4)
-		type = 'uint32_t';
-	else if (sign && len == 8)
-		type = 'int64_t';
-	else if (len == 8)
-		type = 'uint64_t';
-
-	if (type === null)
-		throw (new Error('Malformed CTF JSON: integer has ' +
-		    'unsupported length and sign - ' + len + '/' + sign));
-
-	/*
-	 * This means that this is the same as one of our built in types. If
-	 * that's the case defining it would be an error. So instead of trying
-	 * to typedef it, we'll return here.
-	 */
-	if (name == type)
-		return;
-
-	if (name == 'char') {
-		ASSERT(type == 'int8_t');
-		return;
-	}
-
-	ctype.typedef(name, type);
-}
-
-function ctfParseFloat(entry, ctype)
-{
-	var name, len;
-
-	name = entry['name'];
-	if (!('length' in entry['float']))
-		throw (new Error('Malformed CTF JSON: float missing ' +
-		    'length value'));
-
-	len = entry['float']['length'];
-	if (len != 4 && len != 8)
-		throw (new Error('Malformed CTF JSON: float has invalid ' +
-		    'length value'));
-
-	if (len == 4) {
-		if (name == 'float')
-			return;
-		ctype.typedef(name, 'float');
-	} else if (len == 8) {
-		if (name == 'double')
-			return;
-		ctype.typedef(name, 'double');
-	}
-}
-
-function ctfParseTypedef(entry, ctype)
-{
-	var name, type, ii;
-
-	name = entry['name'];
-	if (typeof (entry['typedef']) != 'string')
-		throw (new Error('Malformed CTF JSON: typedef value in not ' +
-		    'a string'));
-
-	type = entry['typedef'];
-
-	/*
-	 * We need to ensure that we're not looking at type that's one of our
-	 * built in types. Traditionally in C a uint32_t would be a typedef to
-	 * some kind of integer. However, those size types are built ins.
-	 */
-	for (ii = 0; ii < ctf_deftypes.length; ii++) {
-		if (name == ctf_deftypes[ii])
-			return;
-	}
-
-	ctype.typedef(name, type);
-}
-
-function ctfParseStruct(entry, ctype)
-{
-	var name, type, ii, val, index, member, push;
-
-	member = [];
-	if (!Array.isArray(entry['struct']))
-		throw (new Error('Malformed CTF JSON: struct value is not ' +
-		    'an array'));
-
-	for (ii = 0; ii < entry['struct'].length; ii++) {
-		val = entry['struct'][ii];
-		if (!('name' in val))
-			throw (new Error('Malformed CTF JSON: struct member ' +
-			    'missing name'));
-
-		if (!('type' in val))
-			throw (new Error('Malformed CTF JSON: struct member ' +
-			    'missing type'));
-
-		if (typeof (val['name']) != 'string')
-			throw (new Error('Malformed CTF JSON: struct member ' +
-			    'name isn\'t a string'));
-
-		if (typeof (val['type']) != 'string')
-			throw (new Error('Malformed CTF JSON: struct member ' +
-			    'type isn\'t a string'));
-
-		/*
-		 * CTF version 2 specifies array names as <type> [<num>] where
-		 * as node-ctype does this as <type>[<num>].
-		 */
-		name = val['name'];
-		type = val['type'];
-		index = type.indexOf(' [');
-		if (index != -1) {
-			type = type.substring(0, index) +
-			    type.substring(index + 1, type.length);
-		}
-		push = {};
-		push[name] = { 'type': type };
-		member.push(push);
-	}
-
-	name = entry['name'];
-	ctype.typedef(name, member);
-}
-
-function ctfParseEntry(entry, ctype)
-{
-	var ii, found;
-
-	if (!('name' in entry))
-		throw (new Error('Malformed CTF JSON: entry missing "name" ' +
-		    'section'));
-
-	for (ii = 0; ii < ctf_entries.length; ii++) {
-		if (ctf_entries[ii] in entry)
-			found++;
-	}
-
-	if (found === 0)
-		throw (new Error('Malformed CTF JSON: found no entries'));
-
-	if (found >= 2)
-		throw (new Error('Malformed CTF JSON: found more than one ' +
-		    'entry'));
-
-	if ('integer' in entry) {
-		ctfParseInteger(entry, ctype);
-		return;
-	}
-
-	if ('float' in entry) {
-		ctfParseFloat(entry, ctype);
-		return;
-	}
-
-	if ('typedef' in entry) {
-		ctfParseTypedef(entry, ctype);
-		return;
-	}
-
-	if ('struct' in entry) {
-		ctfParseStruct(entry, ctype);
-		return;
-	}
-
-	ASSERT(false, 'shouldn\'t reach here');
-}
-
-function ctfParseJson(json, ctype)
-{
-	var version, ii;
-
-	ASSERT(json);
-	ASSERT(ctype);
-	if (!('metadata' in json))
-		throw (new Error('Invalid CTF JSON: missing metadata section'));
-
-	if (!('ctf2json_version' in json['metadata']))
-		throw (new Error('Invalid CTF JSON: missing ctf2json_version'));
-
-	version = json['metadata']['ctf2json_version'];
-	for (ii = 0; ii < ctf_versions.length; ii++) {
-		if (ctf_versions[ii] == version)
-			break;
-	}
-
-	if (ii == ctf_versions.length)
-		throw (new Error('Unsuported ctf2json_version: ' + version));
-
-	if (!('data' in json))
-		throw (new Error('Invalid CTF JSON: missing data section'));
-
-	if (!Array.isArray(json['data']))
-		throw (new Error('Malformed CTF JSON: data section is not ' +
-		    'an array'));
-
-	for (ii = 0; ii < json['data'].length; ii++)
-		ctfParseEntry(json['data'][ii], ctype);
-}
-
-exports.ctfParseJson = ctfParseJson;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js
deleted file mode 100644
index 62c5d7b2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js
+++ /dev/null
@@ -1,1485 +0,0 @@
-/*
- * rm - Feb 2011
- * ctio.js:
- *
- * A simple way to read and write simple ctypes. Of course, as you'll find the
- * code isn't as simple as it might appear. The following types are currently
- * supported in big and little endian formats:
- *
- * 	uint8_t			int8_t
- * 	uint16_t		int16_t
- * 	uint32_t		int32_t
- *	float (single precision IEEE 754)
- *	double (double precision IEEE 754)
- *
- * This is designed to work in Node and v8. It may in fact work in other
- * Javascript interpreters (that'd be pretty neat), but it hasn't been tested.
- * If you find that it does in fact work, that's pretty cool. Try and pass word
- * back to the original author.
- *
- * Note to the reader: If you're tabstop isn't set to 8, parts of this may look
- * weird.
- */
-
-/*
- * Numbers in Javascript have a secret: all numbers must be represented with an
- * IEEE-754 double. The double has a mantissa with a length of 52 bits with an
- * implicit one. Thus the range of integers that can be represented is limited
- * to the size of the mantissa, this makes reading and writing 64-bit integers
- * difficult, but far from impossible.
- *
- * Another side effect of this representation is what happens when you use the
- * bitwise operators, i.e. shift left, shift right, and, or, etc. In Javascript,
- * each operand and the result is cast to a signed 32-bit number. However, in
- * the case of >>> the values are cast to an unsigned number.
- */
-
-/*
- * A reminder on endian related issues:
- *
- * Big Endian: MSB -> First byte
- * Little Endian: MSB->Last byte
- */
-var mod_assert = require('assert');
-
-/*
- * An 8 bit unsigned integer involves doing no significant work.
- */
-function ruint8(buffer, endian, offset)
-{
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	return (buffer[offset]);
-}
-
-/*
- * For 16 bit unsigned numbers we can do all the casting that we want to do.
- */
-function rgint16(buffer, endian, offset)
-{
-	var val = 0;
-
-	if (endian == 'big') {
-		val = buffer[offset] << 8;
-		val |=  buffer[offset+1];
-	} else {
-		val = buffer[offset];
-		val |= buffer[offset+1] << 8;
-	}
-
-	return (val);
-
-}
-
-function ruint16(buffer, endian, offset)
-{
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 1 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	return (rgint16(buffer, endian, offset));
-}
-
-/*
- * Because most bitshifting is done using signed numbers, if we would go into
- * the realm where we use that 32nd bit, we'll end up going into the negative
- * range. i.e.:
- * > 200 << 24
- * -939524096
- *
- * Not the value you'd expect. To work around this, we end up having to do some
- * abuse of the JavaScript standard. in this case, we know that a >>> shift is
- * defined to cast our value to an *unsigned* 32-bit number. Because of that, we
- * use that instead to save us some additional math, though it does feel a
- * little weird and it isn't obvious as to why you woul dwant to do this at
- * first.
- */
-function rgint32(buffer, endian, offset)
-{
-	var val = 0;
-
-	if (endian == 'big') {
-		val = buffer[offset+1] << 16;
-		val |= buffer[offset+2] << 8;
-		val |= buffer[offset+3];
-		val = val + (buffer[offset] << 24 >>> 0);
-	} else {
-		val = buffer[offset+2] << 16;
-		val |= buffer[offset+1] << 8;
-		val |= buffer[offset];
-		val = val + (buffer[offset + 3] << 24 >>> 0);
-	}
-
-	return (val);
-}
-
-function ruint32(buffer, endian, offset)
-{
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 3 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	return (rgint32(buffer, endian, offset));
-}
-
-/*
- * Reads a 64-bit unsigned number. The astue observer will note that this
- * doesn't quite work. Javascript has chosen to only have numbers that can be
- * represented by a double. A double only has 52 bits of mantissa with an
- * implicit 1, thus we have up to 53 bits to represent an integer. However, 2^53
- * doesn't quite give us what we want. Isn't 53 bits enough for anyone? What
- * could you have possibly wanted to represent that was larger than that? Oh,
- * maybe a size? You mean we bypassed the 4 GB limit on file sizes, when did
- * that happen?
- *
- * To get around this egregious language issue, we're going to instead construct
- * an array of two 32 bit unsigned integers. Where arr[0] << 32 + arr[1] would
- * give the actual number. However, note that the above code probably won't
- * produce the desired results because of the way Javascript numbers are
- * doubles.
- */
-function rgint64(buffer, endian, offset)
-{
-	var val = new Array(2);
-
-	if (endian == 'big') {
-		val[0] = ruint32(buffer, endian, offset);
-		val[1] = ruint32(buffer, endian, offset+4);
-	} else {
-		val[0] = ruint32(buffer, endian, offset+4);
-		val[1] = ruint32(buffer, endian, offset);
-	}
-
-	return (val);
-}
-
-function ruint64(buffer, endian, offset)
-{
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 7 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	return (rgint64(buffer, endian, offset));
-}
-
-
-/*
- * Signed integer types, yay team! A reminder on how two's complement actually
- * works. The first bit is the signed bit, i.e. tells us whether or not the
- * number should be positive or negative. If the two's complement value is
- * positive, then we're done, as it's equivalent to the unsigned representation.
- *
- * Now if the number is positive, you're pretty much done, you can just leverage
- * the unsigned translations and return those. Unfortunately, negative numbers
- * aren't quite that straightforward.
- *
- * At first glance, one might be inclined to use the traditional formula to
- * translate binary numbers between the positive and negative values in two's
- * complement. (Though it doesn't quite work for the most negative value)
- * Mainly:
- *  - invert all the bits
- *  - add one to the result
- *
- * Of course, this doesn't quite work in Javascript. Take for example the value
- * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
- * course, Javascript will do the following:
- *
- * > ~0xff80
- * -65409
- *
- * Whoh there, Javascript, that's not quite right. But wait, according to
- * Javascript that's perfectly correct. When Javascript ends up seeing the
- * constant 0xff80, it has no notion that it is actually a signed number. It
- * assumes that we've input the unsigned value 0xff80. Thus, when it does the
- * binary negation, it casts it into a signed value, (positive 0xff80). Then
- * when you perform binary negation on that, it turns it into a negative number.
- *
- * Instead, we're going to have to use the following general formula, that works
- * in a rather Javascript friendly way. I'm glad we don't support this kind of
- * weird numbering scheme in the kernel.
- *
- * (BIT-MAX - (unsigned)val + 1) * -1
- *
- * The astute observer, may think that this doesn't make sense for 8-bit numbers
- * (really it isn't necessary for them). However, when you get 16-bit numbers,
- * you do. Let's go back to our prior example and see how this will look:
- *
- * (0xffff - 0xff80 + 1) * -1
- * (0x007f + 1) * -1
- * (0x0080) * -1
- *
- * Doing it this way ends up allowing us to treat it appropriately in
- * Javascript. Sigh, that's really quite ugly for what should just be a few bit
- * shifts, ~ and &.
- */
-
-/*
- * Endianness doesn't matter for 8-bit signed values. We could in fact optimize
- * this case because the more traditional methods work, but for consistency,
- * we'll keep doing this the same way.
- */
-function rsint8(buffer, endian, offset)
-{
-	var neg;
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	neg = buffer[offset] & 0x80;
-	if (!neg)
-		return (buffer[offset]);
-
-	return ((0xff - buffer[offset] + 1) * -1);
-}
-
-/*
- * The 16-bit version requires a bit more effort. In this case, we can leverage
- * our unsigned code to generate the value we want to return.
- */
-function rsint16(buffer, endian, offset)
-{
-	var neg, val;
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 1 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = rgint16(buffer, endian, offset);
-	neg = val & 0x8000;
-	if (!neg)
-		return (val);
-
-	return ((0xffff - val + 1) * -1);
-}
-
-/*
- * We really shouldn't leverage our 32-bit code here and instead utilize the
- * fact that we know that since these are signed numbers, we can do all the
- * shifting and binary anding to generate the 32-bit number. But, for
- * consistency we'll do the same. If we want to do otherwise, we should instead
- * make the 32 bit unsigned code do the optimization. But as long as there
- * aren't floats secretly under the hood for that, we /should/ be okay.
- */
-function rsint32(buffer, endian, offset)
-{
-	var neg, val;
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 3 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = rgint32(buffer, endian, offset);
-	neg = val & 0x80000000;
-	if (!neg)
-		return (val);
-
-	return ((0xffffffff - val + 1) * -1);
-}
-
-/*
- * The signed version of this code suffers from all of the same problems of the
- * other 64 bit version.
- */
-function rsint64(buffer, endian, offset)
-{
-	var neg, val;
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 3 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = rgint64(buffer, endian, offset);
-	neg = val[0] & 0x80000000;
-
-	if (!neg)
-		return (val);
-
-	val[0] = (0xffffffff - val[0]) * -1;
-	val[1] = (0xffffffff - val[1] + 1) * -1;
-
-	/*
-	 * If we had the key 0x8000000000000000, that would leave the lower 32
-	 * bits as 0xffffffff, however, since we're goint to add one, that would
-	 * actually leave the lower 32-bits as 0x100000000, which would break
-	 * our ability to write back a value that we received. To work around
-	 * this, if we actually get that value, we're going to bump the upper
-	 * portion by 1 and set this to zero.
-	 */
-	mod_assert.ok(val[1] <= 0x100000000);
-	if (val[1] == -0x100000000) {
-		val[1] = 0;
-		val[0]--;
-	}
-
-	return (val);
-}
-
-/*
- * We now move onto IEEE 754: The traditional form for floating point numbers
- * and what is secretly hiding at the heart of everything in this. I really hope
- * that someone is actually using this, as otherwise, this effort is probably
- * going to be more wasted.
- *
- * One might be tempted to use parseFloat here, but that wouldn't work at all
- * for several reasons. Mostly due to the way floats actually work, and
- * parseFloat only actually works in base 10. I don't see base 10 anywhere near
- * this file.
- *
- * In this case we'll implement the single and double precision versions. The
- * quadruple precision, while probably useful, wouldn't really be accepted by
- * Javascript, so let's not even waste our time.
- *
- * So let's review how this format looks like. A single precision value is 32
- * bits and has three parts:
- *   -  Sign bit
- *   -  Exponent (Using bias notation)
- *   -  Mantissa
- *
- * |s|eeeeeeee|mmmmmmmmmmmmmmmmmmmmmmmmm|
- * 31| 30-23  |  22    	-       0       |
- *
- * The exponent is stored in a biased input. The bias in this case 127.
- * Therefore, our exponent is equal to the 8-bit value - 127.
- *
- * By default, a number is normalized in IEEE, that means that the mantissa has
- * an implicit one that we don't see. So really the value stored is 1.m.
- * However, if the exponent is all zeros, then instead we have to shift
- * everything to the right one and there is no more implicit one.
- *
- * Special values:
- *  - Positive Infinity:
- *	Sign:		0
- *	Exponent: 	All 1s
- *	Mantissa:	0
- *  - Negative Infinity:
- *	Sign:		1
- *	Exponent: 	All 1s
- *	Mantissa:	0
- *  - NaN:
- *	Sign:		*
- *	Exponent: 	All 1s
- *	Mantissa:	non-zero
- *  - Zero:
- *	Sign:		*
- *	Exponent:	All 0s
- *	Mantissa:	0
- *
- * In the case of zero, the sign bit determines whether we get a positive or
- * negative zero. However, since Javascript cannot determine the difference
- * between the two: i.e. -0 == 0, we just always return 0.
- *
- */
-function rfloat(buffer, endian, offset)
-{
-	var bytes = [];
-	var sign, exponent, mantissa, val;
-	var bias = 127;
-	var maxexp = 0xff;
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 3 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	/* Normalize the bytes to be in endian order */
-	if (endian == 'big') {
-		bytes[0] = buffer[offset];
-		bytes[1] = buffer[offset+1];
-		bytes[2] = buffer[offset+2];
-		bytes[3] = buffer[offset+3];
-	} else {
-		bytes[3] = buffer[offset];
-		bytes[2] = buffer[offset+1];
-		bytes[1] = buffer[offset+2];
-		bytes[0] = buffer[offset+3];
-	}
-
-	sign = bytes[0] & 0x80;
-	exponent = (bytes[0] & 0x7f) << 1;
-	exponent |= (bytes[1] & 0x80) >>> 7;
-	mantissa = (bytes[1] & 0x7f) << 16;
-	mantissa |= bytes[2] << 8;
-	mantissa |= bytes[3];
-
-	/* Check for special cases before we do general parsing */
-	if (!sign && exponent == maxexp && mantissa === 0)
-		return (Number.POSITIVE_INFINITY);
-
-	if (sign && exponent == maxexp && mantissa === 0)
-		return (Number.NEGATIVE_INFINITY);
-
-	if (exponent == maxexp && mantissa !== 0)
-		return (Number.NaN);
-
-	/*
-	 * Javascript really doesn't have support for positive or negative zero.
-	 * So we're not going to try and give it to you. That would be just
-	 * plain weird. Besides -0 == 0.
-	 */
-	if (exponent === 0 && mantissa === 0)
-		return (0);
-
-	/*
-	 * Now we can deal with the bias and the determine whether the mantissa
-	 * has the implicit one or not.
-	 */
-	exponent -= bias;
-	if (exponent == -bias) {
-		exponent++;
-		val = 0;
-	} else {
-		val = 1;
-	}
-
-	val = (val + mantissa * Math.pow(2, -23)) * Math.pow(2, exponent);
-
-	if (sign)
-		val *= -1;
-
-	return (val);
-}
-
-/*
- * Doubles in IEEE 754 are like their brothers except for a few changes and
- * increases in size:
- *   - The exponent is now 11 bits
- *   - The mantissa is now 52 bits
- *   - The bias is now 1023
- *
- * |s|eeeeeeeeeee|mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm|
- * 63| 62 - 52   | 	51		-			0     |
- * 63| 62 - 52   |      51              -                       0     |
- *
- * While the size has increased a fair amount, we're going to end up keeping the
- * same general formula for calculating the final value. As a reminder, this
- * formula is:
- *
- * (-1)^s * (n + m) * 2^(e-b)
- *
- * Where:
- *	s	is the sign bit
- *	n	is (exponent > 0) ? 1 : 0 -- Determines whether we're normalized
- *					     or not
- *	m	is the mantissa
- *	e	is the exponent specified
- *	b	is the bias for the exponent
- *
- */
-function rdouble(buffer, endian, offset)
-{
-	var bytes = [];
-	var sign, exponent, mantissa, val, lowmant;
-	var bias = 1023;
-	var maxexp = 0x7ff;
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 7 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	/* Normalize the bytes to be in endian order */
-	if (endian == 'big') {
-		bytes[0] = buffer[offset];
-		bytes[1] = buffer[offset+1];
-		bytes[2] = buffer[offset+2];
-		bytes[3] = buffer[offset+3];
-		bytes[4] = buffer[offset+4];
-		bytes[5] = buffer[offset+5];
-		bytes[6] = buffer[offset+6];
-		bytes[7] = buffer[offset+7];
-	} else {
-		bytes[7] = buffer[offset];
-		bytes[6] = buffer[offset+1];
-		bytes[5] = buffer[offset+2];
-		bytes[4] = buffer[offset+3];
-		bytes[3] = buffer[offset+4];
-		bytes[2] = buffer[offset+5];
-		bytes[1] = buffer[offset+6];
-		bytes[0] = buffer[offset+7];
-	}
-
-	/*
-	 * We can construct the exponent and mantissa the same way as we did in
-	 * the case of a float, just increase the range of the exponent.
-	 */
-	sign = bytes[0] & 0x80;
-	exponent = (bytes[0] & 0x7f) << 4;
-	exponent |= (bytes[1] & 0xf0) >>> 4;
-
-	/*
-	 * This is going to be ugly but then again, we're dealing with IEEE 754.
-	 * This could probably be done as a node add on in a few lines of C++,
-	 * but oh we'll, we've made it this far so let's be native the rest of
-	 * the way...
-	 *
-	 * What we're going to do is break the mantissa into two parts, the
-	 * lower 24 bits and the upper 28 bits. We'll multiply the upper 28 bits
-	 * by the appropriate power and then add in the lower 24-bits. Not
-	 * really that great. It's pretty much a giant kludge to deal with
-	 * Javascript eccentricities around numbers.
-	 */
-	lowmant = bytes[7];
-	lowmant |= bytes[6] << 8;
-	lowmant |= bytes[5] << 16;
-	mantissa = bytes[4];
-	mantissa |= bytes[3] << 8;
-	mantissa |= bytes[2] << 16;
-	mantissa |= (bytes[1] & 0x0f) << 24;
-	mantissa *= Math.pow(2, 24); /* Equivalent to << 24, but JS compat */
-	mantissa += lowmant;
-
-	/* Check for special cases before we do general parsing */
-	if (!sign && exponent == maxexp && mantissa === 0)
-		return (Number.POSITIVE_INFINITY);
-
-	if (sign && exponent == maxexp && mantissa === 0)
-		return (Number.NEGATIVE_INFINITY);
-
-	if (exponent == maxexp && mantissa !== 0)
-		return (Number.NaN);
-
-	/*
-	 * Javascript really doesn't have support for positive or negative zero.
-	 * So we're not going to try and give it to you. That would be just
-	 * plain weird. Besides -0 == 0.
-	 */
-	if (exponent === 0 && mantissa === 0)
-		return (0);
-
-	/*
-	 * Now we can deal with the bias and the determine whether the mantissa
-	 * has the implicit one or not.
-	 */
-	exponent -= bias;
-	if (exponent == -bias) {
-		exponent++;
-		val = 0;
-	} else {
-		val = 1;
-	}
-
-	val = (val + mantissa * Math.pow(2, -52)) * Math.pow(2, exponent);
-
-	if (sign)
-		val *= -1;
-
-	return (val);
-}
-
-/*
- * Now that we have gone through the pain of reading the individual types, we're
- * probably going to want some way to write these back. None of this is going to
- * be good. But since we have Javascript numbers this should certainly be more
- * interesting. Though we can constrain this end a little bit more in what is
- * valid. For now, let's go back to our friends the unsigned value.
- */
-
-/*
- * Unsigned numbers seem deceptively easy. Here are the general steps and rules
- * that we are going to take:
- *   -  If the number is negative, throw an Error
- *   -  Truncate any floating point portion
- *   -  Take the modulus of the number in our base
- *   -  Write it out to the buffer in the endian format requested at the offset
- */
-
-/*
- * We have to make sure that the value is a valid integer. This means that it is
- * non-negative. It has no fractional component and that it does not exceed the
- * maximum allowed value.
- *
- *	value		The number to check for validity
- *
- *	max		The maximum value
- */
-function prepuint(value, max)
-{
-	if (typeof (value) != 'number')
-		throw (new (Error('cannot write a non-number as a number')));
-
-	if (value < 0)
-		throw (new Error('specified a negative value for writing an ' +
-		    'unsigned value'));
-
-	if (value > max)
-		throw (new Error('value is larger than maximum value for ' +
-		    'type'));
-
-	if (Math.floor(value) !== value)
-		throw (new Error('value has a fractional component'));
-
-	return (value);
-}
-
-/*
- * 8-bit version, classy. We can ignore endianness which is good.
- */
-function wuint8(value, endian, buffer, offset)
-{
-	var val;
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = prepuint(value, 0xff);
-	buffer[offset] = val;
-}
-
-/*
- * Pretty much the same as the 8-bit version, just this time we need to worry
- * about endian related issues.
- */
-function wgint16(val, endian, buffer, offset)
-{
-	if (endian == 'big') {
-		buffer[offset] = (val & 0xff00) >>> 8;
-		buffer[offset+1] = val & 0x00ff;
-	} else {
-		buffer[offset+1] = (val & 0xff00) >>> 8;
-		buffer[offset] = val & 0x00ff;
-	}
-}
-
-function wuint16(value, endian, buffer, offset)
-{
-	var val;
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 1 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = prepuint(value, 0xffff);
-	wgint16(val, endian, buffer, offset);
-}
-
-/*
- * The 32-bit version is going to have to be a little different unfortunately.
- * We can't quite bitshift to get the largest byte, because that would end up
- * getting us caught by the signed values.
- *
- * And yes, we do want to subtract out the lower part by default. This means
- * that when we do the division, it will be treated as a bit shift and we won't
- * end up generating a floating point value. If we did generate a floating point
- * value we'd have to truncate it intelligently, this saves us that problem and
- * may even be somewhat faster under the hood.
- */
-function wgint32(val, endian, buffer, offset)
-{
-	if (endian == 'big') {
-		buffer[offset] = (val - (val & 0x00ffffff)) / Math.pow(2, 24);
-		buffer[offset+1] = (val >>> 16) & 0xff;
-		buffer[offset+2] = (val >>> 8) & 0xff;
-		buffer[offset+3] = val & 0xff;
-	} else {
-		buffer[offset+3] = (val - (val & 0x00ffffff)) /
-		    Math.pow(2, 24);
-		buffer[offset+2] = (val >>> 16) & 0xff;
-		buffer[offset+1] = (val >>> 8) & 0xff;
-		buffer[offset] = val & 0xff;
-	}
-}
-
-function wuint32(value, endian, buffer, offset)
-{
-	var val;
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 3 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = prepuint(value, 0xffffffff);
-	wgint32(val, endian, buffer, offset);
-}
-
-/*
- * Unlike the other versions, we expect the value to be in the form of two
- * arrays where value[0] << 32 + value[1] would result in the value that we
- * want.
- */
-function wgint64(value, endian, buffer, offset)
-{
-	if (endian == 'big') {
-		wgint32(value[0], endian, buffer, offset);
-		wgint32(value[1], endian, buffer, offset+4);
-	} else {
-		wgint32(value[0], endian, buffer, offset+4);
-		wgint32(value[1], endian, buffer, offset);
-	}
-}
-
-function wuint64(value, endian, buffer, offset)
-{
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (!(value instanceof Array))
-		throw (new Error('value must be an array'));
-
-	if (value.length != 2)
-		throw (new Error('value must be an array of length 2'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 7 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	prepuint(value[0], 0xffffffff);
-	prepuint(value[1], 0xffffffff);
-	wgint64(value, endian, buffer, offset);
-}
-
-/*
- * We now move onto our friends in the signed number category. Unlike unsigned
- * numbers, we're going to have to worry a bit more about how we put values into
- * arrays. Since we are only worrying about signed 32-bit values, we're in
- * slightly better shape. Unfortunately, we really can't do our favorite binary
- * & in this system. It really seems to do the wrong thing. For example:
- *
- * > -32 & 0xff
- * 224
- *
- * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
- * this aren't treated as a signed number. Ultimately a bad thing.
- *
- * What we're going to want to do is basically create the unsigned equivalent of
- * our representation and pass that off to the wuint* functions. To do that
- * we're going to do the following:
- *
- *  - if the value is positive
- *	we can pass it directly off to the equivalent wuint
- *  - if the value is negative
- *	we do the following computation:
- *	mb + val + 1, where
- *	mb	is the maximum unsigned value in that byte size
- *	val	is the Javascript negative integer
- *
- *
- * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
- * you do out the computations:
- *
- * 0xffff - 128 + 1
- * 0xffff - 127
- * 0xff80
- *
- * You can then encode this value as the signed version. This is really rather
- * hacky, but it should work and get the job done which is our goal here.
- *
- * Thus the overall flow is:
- *   -  Truncate the floating point part of the number
- *   -  We don't have to take the modulus, because the unsigned versions will
- *   	take care of that for us. And we don't have to worry about that
- *   	potentially causing bad things to happen because of sign extension
- *   -  Pass it off to the appropriate unsigned version, potentially modifying
- *	the negative portions as necessary.
- */
-
-/*
- * A series of checks to make sure we actually have a signed 32-bit number
- */
-function prepsint(value, max, min)
-{
-	if (typeof (value) != 'number')
-		throw (new (Error('cannot write a non-number as a number')));
-
-	if (value > max)
-		throw (new Error('value larger than maximum allowed value'));
-
-	if (value < min)
-		throw (new Error('value smaller than minimum allowed value'));
-
-	if (Math.floor(value) !== value)
-		throw (new Error('value has a fractional component'));
-
-	return (value);
-}
-
-/*
- * The 8-bit version of the signed value. Overall, fairly straightforward.
- */
-function wsint8(value, endian, buffer, offset)
-{
-	var val;
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = prepsint(value, 0x7f, -0x80);
-	if (val >= 0)
-		wuint8(val, endian, buffer, offset);
-	else
-		wuint8(0xff + val + 1, endian, buffer, offset);
-}
-
-/*
- * The 16-bit version of the signed value. Also, fairly straightforward.
- */
-function wsint16(value, endian, buffer, offset)
-{
-	var val;
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 1 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = prepsint(value, 0x7fff, -0x8000);
-	if (val >= 0)
-		wgint16(val, endian, buffer, offset);
-	else
-		wgint16(0xffff + val + 1, endian, buffer, offset);
-
-}
-
-/*
- * We can do this relatively easily by leveraging the code used for 32-bit
- * unsigned code.
- */
-function wsint32(value, endian, buffer, offset)
-{
-	var val;
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 3 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	val = prepsint(value, 0x7fffffff, -0x80000000);
-	if (val >= 0)
-		wgint32(val, endian, buffer, offset);
-	else
-		wgint32(0xffffffff + val + 1, endian, buffer, offset);
-}
-
-/*
- * The signed 64 bit integer should by in the same format as when received.
- * Mainly it should ensure that the value is an array of two integers where
- * value[0] << 32 + value[1] is the desired number. Furthermore, the two values
- * need to be equal.
- */
-function wsint64(value, endian, buffer, offset)
-{
-	var vzpos, vopos;
-	var vals = new Array(2);
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (!(value instanceof Array))
-		throw (new Error('value must be an array'));
-
-	if (value.length != 2)
-		throw (new Error('value must be an array of length 2'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-	if (offset + 7 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	/*
-	 * We need to make sure that we have the same sign on both values. The
-	 * hokiest way to to do this is to multiply the number by +inf. If we do
-	 * this, we'll get either +/-inf depending on the sign of the value.
-	 * Once we have this, we can compare it to +inf to see if the number is
-	 * positive or not.
-	 */
-	vzpos = (value[0] * Number.POSITIVE_INFINITY) ==
-	    Number.POSITIVE_INFINITY;
-	vopos = (value[1] * Number.POSITIVE_INFINITY) ==
-	    Number.POSITIVE_INFINITY;
-
-	/*
-	 * If either of these is zero, then we don't actually need this check.
-	 */
-	if (value[0] != 0 && value[1] != 0 && vzpos != vopos)
-		throw (new Error('Both entries in the array must have ' +
-		    'the same sign'));
-
-	/*
-	 * Doing verification for a signed 64-bit integer is actually a big
-	 * trickier than it appears. We can't quite use our standard techniques
-	 * because we need to compare both sets of values. The first value is
-	 * pretty straightforward. If the first value is beond the extremes than
-	 * we error out. However, the valid range of the second value varies
-	 * based on the first one. If the first value is negative, and *not* the
-	 * largest negative value, than it can be any integer within the range [
-	 * 0, 0xffffffff ]. If it is the largest negative number, it must be
-	 * zero.
-	 *
-	 * If the first number is positive, than it doesn't matter what the
-	 * value is. We just simply have to make sure we have a valid positive
-	 * integer.
-	 */
-	if (vzpos) {
-		prepuint(value[0], 0x7fffffff);
-		prepuint(value[1], 0xffffffff);
-	} else {
-		prepsint(value[0], 0, -0x80000000);
-		prepsint(value[1], 0, -0xffffffff);
-		if (value[0] == -0x80000000 && value[1] != 0)
-			throw (new Error('value smaller than minimum ' +
-			    'allowed value'));
-	}
-
-	/* Fix negative numbers */
-	if (value[0] < 0 || value[1] < 0) {
-		vals[0] = 0xffffffff - Math.abs(value[0]);
-		vals[1] = 0x100000000 - Math.abs(value[1]);
-		if (vals[1] == 0x100000000) {
-			vals[1] = 0;
-			vals[0]++;
-		}
-	} else {
-		vals[0] = value[0];
-		vals[1] = value[1];
-	}
-	wgint64(vals, endian, buffer, offset);
-}
-
-/*
- * Now we are moving onto the weirder of these, the float and double. For this
- * we're going to just have to do something that's pretty weird. First off, we
- * have no way to get at the underlying float representation, at least not
- * easily. But that doesn't mean we can't figure it out, we just have to use our
- * heads.
- *
- * One might propose to use Number.toString(2). Of course, this is not really
- * that good, because the ECMAScript 262 v3 Standard says the following Section
- * 15.7.4.2-Number.prototype.toString (radix):
- *
- * If radix is an integer from 2 to 36, but not 10, the result is a string, the
- * choice of which is implementation-dependent.
- *
- * Well that doesn't really help us one bit now does it? We could use the
- * standard base 10 version of the string, but that's just going to create more
- * errors as we end up trying to convert it back to a binary value. So, really
- * this just means we have to be non-lazy and parse the structure intelligently.
- *
- * First off, we can do the basic checks: NaN, positive and negative infinity.
- *
- * Now that those are done we can work backwards to generate the mantissa and
- * exponent.
- *
- * The first thing we need to do is determine the sign bit, easy to do, check
- * whether the value is less than 0. And convert the number to its absolute
- * value representation. Next, we need to determine if the value is less than
- * one or greater than or equal to one and from there determine what power was
- * used to get there. What follows is now specific to floats, though the general
- * ideas behind this will hold for doubles as well, but the exact numbers
- * involved will change.
- *
- * Once we have that power we can determine the exponent and the mantissa. Call
- * the value that has the number of bits to reach the power ebits. In the
- * general case they have the following values:
- *
- *	exponent	127 + ebits
- *	mantissa	value * 2^(23 - ebits) & 0x7fffff
- *
- * In the case where the value of ebits is <= -127 we are now in the case where
- * we no longer have normalized numbers. In this case the values take on the
- * following values:
- *
- * 	exponent	0
- *	mantissa	value * 2^149 & 0x7fffff
- *
- * Once we have the values for the sign, mantissa, and exponent. We reconstruct
- * the four bytes as follows:
- *
- *	byte0		sign bit and seven most significant bits from the exp
- *			sign << 7 | (exponent & 0xfe) >>> 1
- *
- *	byte1		lsb from the exponent and 7 top bits from the mantissa
- *			(exponent & 0x01) << 7 | (mantissa & 0x7f0000) >>> 16
- *
- *	byte2		bits 8-15 (zero indexing) from mantissa
- *			mantissa & 0xff00 >> 8
- *
- *	byte3		bits 0-7 from mantissa
- *			mantissa & 0xff
- *
- * Once we have this we have to assign them into the buffer in proper endian
- * order.
- */
-
-/*
- * Compute the log base 2 of the value. Now, someone who remembers basic
- * properties of logarithms will point out that we could use the change of base
- * formula for logs, and in fact that would be astute, because that's what we'll
- * do for now. It feels cleaner, albeit it may be less efficient than just
- * iterating and dividing by 2. We may want to come back and revisit that some
- * day.
- */
-function log2(value)
-{
-	return (Math.log(value) / Math.log(2));
-}
-
-/*
- * Helper to determine the exponent of the number we're looking at.
- */
-function intexp(value)
-{
-	return (Math.floor(log2(value)));
-}
-
-/*
- * Helper to determine the exponent of the fractional part of the value.
- */
-function fracexp(value)
-{
-	return (Math.floor(log2(value)));
-}
-
-function wfloat(value, endian, buffer, offset)
-{
-	var sign, exponent, mantissa, ebits;
-	var bytes = [];
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-
-	if (offset + 3 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	if (isNaN(value)) {
-		sign = 0;
-		exponent = 0xff;
-		mantissa = 23;
-	} else if (value == Number.POSITIVE_INFINITY) {
-		sign = 0;
-		exponent = 0xff;
-		mantissa = 0;
-	} else if (value == Number.NEGATIVE_INFINITY) {
-		sign = 1;
-		exponent = 0xff;
-		mantissa = 0;
-	} else {
-		/* Well we have some work to do */
-
-		/* Thankfully the sign bit is trivial */
-		if (value < 0) {
-			sign = 1;
-			value = Math.abs(value);
-		} else {
-			sign = 0;
-		}
-
-		/* Use the correct function to determine number of bits */
-		if (value < 1)
-			ebits = fracexp(value);
-		else
-			ebits = intexp(value);
-
-		/* Time to deal with the issues surrounding normalization */
-		if (ebits <= -127) {
-			exponent = 0;
-			mantissa = (value * Math.pow(2, 149)) & 0x7fffff;
-		} else {
-			exponent = 127 + ebits;
-			mantissa = value * Math.pow(2, 23 - ebits);
-			mantissa &= 0x7fffff;
-		}
-	}
-
-	bytes[0] = sign << 7 | (exponent & 0xfe) >>> 1;
-	bytes[1] = (exponent & 0x01) << 7 | (mantissa & 0x7f0000) >>> 16;
-	bytes[2] = (mantissa & 0x00ff00) >>> 8;
-	bytes[3] = mantissa & 0x0000ff;
-
-	if (endian == 'big') {
-		buffer[offset] = bytes[0];
-		buffer[offset+1] = bytes[1];
-		buffer[offset+2] = bytes[2];
-		buffer[offset+3] = bytes[3];
-	} else {
-		buffer[offset] = bytes[3];
-		buffer[offset+1] = bytes[2];
-		buffer[offset+2] = bytes[1];
-		buffer[offset+3] = bytes[0];
-	}
-}
-
-/*
- * Now we move onto doubles. Doubles are similar to floats in pretty much all
- * ways except that the processing isn't quite as straightforward because we
- * can't always use shifting, i.e. we have > 32 bit values.
- *
- * We're going to proceed in an identical fashion to floats and utilize the same
- * helper functions. All that really is changing are the specific values that we
- * use to do the calculations. Thus, to review we have to do the following.
- *
- * First get the sign bit and convert the value to its absolute value
- * representation. Next, we determine the number of bits that we used to get to
- * the value, branching whether the value is greater than or less than 1. Once
- * we have that value which we will again call ebits, we have to do the
- * following in the general case:
- *
- *	exponent	1023 + ebits
- *	mantissa	[value * 2^(52 - ebits)] % 2^52
- *
- * In the case where the value of ebits <= -1023 we no longer use normalized
- * numbers, thus like with floats we have to do slightly different processing:
- *
- *	exponent	0
- *	mantissa	[value * 2^1074] % 2^52
- *
- * Once we have determined the sign, exponent and mantissa we can construct the
- * bytes as follows:
- *
- *	byte0		sign bit and seven most significant bits form the exp
- *			sign << 7 | (exponent & 0x7f0) >>> 4
- *
- *	byte1		Remaining 4 bits from the exponent and the four most
- *			significant bits from the mantissa 48-51
- *			(exponent & 0x00f) << 4 | mantissa >>> 48
- *
- *	byte2		Bits 40-47 from the mantissa
- *			(mantissa >>> 40) & 0xff
- *
- *	byte3		Bits 32-39 from the mantissa
- *			(mantissa >>> 32) & 0xff
- *
- *	byte4		Bits 24-31 from the mantissa
- *			(mantissa >>> 24) & 0xff
- *
- *	byte5		Bits 16-23 from the Mantissa
- *			(mantissa >>> 16) & 0xff
- *
- *	byte6		Bits 8-15 from the mantissa
- *			(mantissa >>> 8) & 0xff
- *
- *	byte7		Bits 0-7 from the mantissa
- *			mantissa & 0xff
- *
- * Now we can't quite do the right shifting that we want in bytes 1 - 3, because
- * we'll have extended too far and we'll lose those values when we try and do
- * the shift. Instead we have to use an alternate approach. To try and stay out
- * of floating point, what we'll do is say that mantissa -= bytes[4-7] and then
- * divide by 2^32. Once we've done that we can use binary arithmetic. Oof,
- * that's ugly, but it seems to avoid using floating point (just based on how v8
- * seems to be optimizing for base 2 arithmetic).
- */
-function wdouble(value, endian, buffer, offset)
-{
-	var sign, exponent, mantissa, ebits;
-	var bytes = [];
-
-	if (value === undefined)
-		throw (new Error('missing value'));
-
-	if (endian === undefined)
-		throw (new Error('missing endian'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset'));
-
-
-	if (offset + 7 >= buffer.length)
-		throw (new Error('Trying to read beyond buffer length'));
-
-	if (isNaN(value)) {
-		sign = 0;
-		exponent = 0x7ff;
-		mantissa = 23;
-	} else if (value == Number.POSITIVE_INFINITY) {
-		sign = 0;
-		exponent = 0x7ff;
-		mantissa = 0;
-	} else if (value == Number.NEGATIVE_INFINITY) {
-		sign = 1;
-		exponent = 0x7ff;
-		mantissa = 0;
-	} else {
-		/* Well we have some work to do */
-
-		/* Thankfully the sign bit is trivial */
-		if (value < 0) {
-			sign = 1;
-			value = Math.abs(value);
-		} else {
-			sign = 0;
-		}
-
-		/* Use the correct function to determine number of bits */
-		if (value < 1)
-			ebits = fracexp(value);
-		else
-			ebits = intexp(value);
-
-		/*
-		 * This is a total hack to determine a denormalized value.
-		 * Unfortunately, we sometimes do not get a proper value for
-		 * ebits, i.e. we lose the values that would get rounded off.
-		 *
-		 *
-		 * The astute observer may wonder why we would be
-		 * multiplying by two Math.pows rather than just summing
-		 * them. Well, that's to get around a small bug in the
-		 * way v8 seems to implement the function. On occasion
-		 * doing:
-		 *
-		 * foo * Math.pow(2, 1023 + 51)
-		 *
-		 * Causes us to overflow to infinity, where as doing:
-		 *
-		 * foo * Math.pow(2, 1023) * Math.pow(2, 51)
-		 *
-		 * Does not cause us to overflow. Go figure.
-		 *
-		 */
-		if (value <= 2.225073858507201e-308 || ebits <= -1023) {
-			exponent = 0;
-			mantissa = value * Math.pow(2, 1023) * Math.pow(2, 51);
-			mantissa %= Math.pow(2, 52);
-		} else {
-			/*
-			 * We might have gotten fucked by our floating point
-			 * logarithm magic. This is rather crappy, but that's
-			 * our luck. If we just had a log base 2 or access to
-			 * the stupid underlying representation this would have
-			 * been much easier and we wouldn't have such stupid
-			 * kludges or hacks.
-			 */
-			if (ebits > 1023)
-				ebits = 1023;
-			exponent = 1023 + ebits;
-			mantissa = value * Math.pow(2, -ebits);
-			mantissa *= Math.pow(2, 52);
-			mantissa %= Math.pow(2, 52);
-		}
-	}
-
-	/* Fill the bytes in backwards to deal with the size issues */
-	bytes[7] = mantissa & 0xff;
-	bytes[6] = (mantissa >>> 8) & 0xff;
-	bytes[5] = (mantissa >>> 16) & 0xff;
-	mantissa = (mantissa - (mantissa & 0xffffff)) / Math.pow(2, 24);
-	bytes[4] = mantissa & 0xff;
-	bytes[3] = (mantissa >>> 8) & 0xff;
-	bytes[2] = (mantissa >>> 16) & 0xff;
-	bytes[1] = (exponent & 0x00f) << 4 | mantissa >>> 24;
-	bytes[0] = (sign << 7) | (exponent & 0x7f0) >>> 4;
-
-	if (endian == 'big') {
-		buffer[offset] = bytes[0];
-		buffer[offset+1] = bytes[1];
-		buffer[offset+2] = bytes[2];
-		buffer[offset+3] = bytes[3];
-		buffer[offset+4] = bytes[4];
-		buffer[offset+5] = bytes[5];
-		buffer[offset+6] = bytes[6];
-		buffer[offset+7] = bytes[7];
-	} else {
-		buffer[offset+7] = bytes[0];
-		buffer[offset+6] = bytes[1];
-		buffer[offset+5] = bytes[2];
-		buffer[offset+4] = bytes[3];
-		buffer[offset+3] = bytes[4];
-		buffer[offset+2] = bytes[5];
-		buffer[offset+1] = bytes[6];
-		buffer[offset] = bytes[7];
-	}
-}
-
-/*
- * Actually export our work above. One might argue that we shouldn't expose
- * these interfaces and just force people to use the higher level abstractions
- * around this work. However, unlike say other libraries we've come across, this
- * interface has several properties: it makes sense, it's simple, and it's
- * useful.
- */
-exports.ruint8 = ruint8;
-exports.ruint16 = ruint16;
-exports.ruint32 = ruint32;
-exports.ruint64 = ruint64;
-exports.wuint8 = wuint8;
-exports.wuint16 = wuint16;
-exports.wuint32 = wuint32;
-exports.wuint64 = wuint64;
-
-exports.rsint8 = rsint8;
-exports.rsint16 = rsint16;
-exports.rsint32 = rsint32;
-exports.rsint64 = rsint64;
-exports.wsint8 = wsint8;
-exports.wsint16 = wsint16;
-exports.wsint32 = wsint32;
-exports.wsint64 = wsint64;
-
-exports.rfloat = rfloat;
-exports.rdouble = rdouble;
-exports.wfloat = wfloat;
-exports.wdouble = wdouble;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js
deleted file mode 100644
index 7d2f4a5a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * rm - Feb 2011
- * ctype.js
- *
- * This module provides a simple abstraction towards reading and writing
- * different types of binary data. It is designed to use ctio.js and provide a
- * richer and more expressive API on top of it.
- *
- * By default we support the following as built in basic types:
- *	int8_t
- *	int16_t
- *	int32_t
- *	uint8_t
- *	uint16_t
- *	uint32_t
- *	uint64_t
- *	float
- *	double
- *	char
- *	char[]
- *
- * Each type is returned as a Number, with the exception of char and char[]
- * which are returned as Node Buffers. A char is considered a uint8_t.
- *
- * Requests to read and write data are specified as an array of JSON objects.
- * This is also the same way that one declares structs. Even if just a single
- * value is requested, it must be done as a struct. The array order determines
- * the order that we try and read values. Each entry has the following format
- * with values marked with a * being optional.
- *
- * { key: { type: /type/, value*: /value/, offset*: /offset/ }
- *
- * If offset is defined, we lseek(offset, SEEK_SET) before reading the next
- * value. Value is defined when we're writing out data, otherwise it's ignored.
- *
- */
-
-var mod_ctf = require('./ctf.js');
-var mod_ctio = require('./ctio.js');
-var mod_assert = require('assert');
-
-/*
- * This is the set of basic types that we support.
- *
- *	read		The function to call to read in a value from a buffer
- *
- *	write		The function to call to write a value to a buffer
- *
- */
-var deftypes = {
-    'uint8_t':  { read: ctReadUint8, write: ctWriteUint8 },
-    'uint16_t': { read: ctReadUint16, write: ctWriteUint16 },
-    'uint32_t': { read: ctReadUint32, write: ctWriteUint32 },
-    'uint64_t': { read: ctReadUint64, write: ctWriteUint64 },
-    'int8_t': { read: ctReadSint8, write: ctWriteSint8 },
-    'int16_t': { read: ctReadSint16, write: ctWriteSint16 },
-    'int32_t': { read: ctReadSint32, write: ctWriteSint32 },
-    'int64_t': { read: ctReadSint64, write: ctWriteSint64 },
-    'float': { read: ctReadFloat, write: ctWriteFloat },
-    'double': { read: ctReadDouble, write: ctWriteDouble },
-    'char': { read: ctReadChar, write: ctWriteChar },
-    'char[]': { read: ctReadCharArray, write: ctWriteCharArray }
-};
-
-/*
- * The following are wrappers around the CType IO low level API. They encode
- * knowledge about the size and return something in the expected format.
- */
-function ctReadUint8(endian, buffer, offset)
-{
-	var val = mod_ctio.ruint8(buffer, endian, offset);
-	return ({ value: val, size: 1 });
-}
-
-function ctReadUint16(endian, buffer, offset)
-{
-	var val = mod_ctio.ruint16(buffer, endian, offset);
-	return ({ value: val, size: 2 });
-}
-
-function ctReadUint32(endian, buffer, offset)
-{
-	var val = mod_ctio.ruint32(buffer, endian, offset);
-	return ({ value: val, size: 4 });
-}
-
-function ctReadUint64(endian, buffer, offset)
-{
-	var val = mod_ctio.ruint64(buffer, endian, offset);
-	return ({ value: val, size: 8 });
-}
-
-function ctReadSint8(endian, buffer, offset)
-{
-	var val = mod_ctio.rsint8(buffer, endian, offset);
-	return ({ value: val, size: 1 });
-}
-
-function ctReadSint16(endian, buffer, offset)
-{
-	var val = mod_ctio.rsint16(buffer, endian, offset);
-	return ({ value: val, size: 2 });
-}
-
-function ctReadSint32(endian, buffer, offset)
-{
-	var val = mod_ctio.rsint32(buffer, endian, offset);
-	return ({ value: val, size: 4 });
-}
-
-function ctReadSint64(endian, buffer, offset)
-{
-	var val = mod_ctio.rsint64(buffer, endian, offset);
-	return ({ value: val, size: 8 });
-}
-
-function ctReadFloat(endian, buffer, offset)
-{
-	var val = mod_ctio.rfloat(buffer, endian, offset);
-	return ({ value: val, size: 4 });
-}
-
-function ctReadDouble(endian, buffer, offset)
-{
-	var val = mod_ctio.rdouble(buffer, endian, offset);
-	return ({ value: val, size: 8 });
-}
-
-/*
- * Reads a single character into a node buffer
- */
-function ctReadChar(endian, buffer, offset)
-{
-	var res = new Buffer(1);
-	res[0] = mod_ctio.ruint8(buffer, endian, offset);
-	return ({ value: res, size: 1 });
-}
-
-function ctReadCharArray(length, endian, buffer, offset)
-{
-	var ii;
-	var res = new Buffer(length);
-
-	for (ii = 0; ii < length; ii++)
-		res[ii] = mod_ctio.ruint8(buffer, endian, offset + ii);
-
-	return ({ value: res, size: length });
-}
-
-function ctWriteUint8(value, endian, buffer, offset)
-{
-	mod_ctio.wuint8(value, endian, buffer, offset);
-	return (1);
-}
-
-function ctWriteUint16(value, endian, buffer, offset)
-{
-	mod_ctio.wuint16(value, endian, buffer, offset);
-	return (2);
-}
-
-function ctWriteUint32(value, endian, buffer, offset)
-{
-	mod_ctio.wuint32(value, endian, buffer, offset);
-	return (4);
-}
-
-function ctWriteUint64(value, endian, buffer, offset)
-{
-	mod_ctio.wuint64(value, endian, buffer, offset);
-	return (8);
-}
-
-function ctWriteSint8(value, endian, buffer, offset)
-{
-	mod_ctio.wsint8(value, endian, buffer, offset);
-	return (1);
-}
-
-function ctWriteSint16(value, endian, buffer, offset)
-{
-	mod_ctio.wsint16(value, endian, buffer, offset);
-	return (2);
-}
-
-function ctWriteSint32(value, endian, buffer, offset)
-{
-	mod_ctio.wsint32(value, endian, buffer, offset);
-	return (4);
-}
-
-function ctWriteSint64(value, endian, buffer, offset)
-{
-	mod_ctio.wsint64(value, endian, buffer, offset);
-	return (8);
-}
-
-function ctWriteFloat(value, endian, buffer, offset)
-{
-	mod_ctio.wfloat(value, endian, buffer, offset);
-	return (4);
-}
-
-function ctWriteDouble(value, endian, buffer, offset)
-{
-	mod_ctio.wdouble(value, endian, buffer, offset);
-	return (8);
-}
-
-/*
- * Writes a single character into a node buffer
- */
-function ctWriteChar(value, endian, buffer, offset)
-{
-	if (!(value instanceof Buffer))
-		throw (new Error('Input must be a buffer'));
-
-	mod_ctio.ruint8(value[0], endian, buffer, offset);
-	return (1);
-}
-
-/*
- * We're going to write 0s into the buffer if the string is shorter than the
- * length of the array.
- */
-function ctWriteCharArray(value, length, endian, buffer, offset)
-{
-	var ii;
-
-	if (!(value instanceof Buffer))
-		throw (new Error('Input must be a buffer'));
-
-	if (value.length > length)
-		throw (new Error('value length greater than array length'));
-
-	for (ii = 0; ii < value.length && ii < length; ii++)
-		mod_ctio.wuint8(value[ii], endian, buffer, offset + ii);
-
-	for (; ii < length; ii++)
-		mod_ctio.wuint8(0, endian, offset + ii);
-
-
-	return (length);
-}
-
-/*
- * Each parser has their own set of types. We want to make sure that they each
- * get their own copy as they may need to modify it.
- */
-function ctGetBasicTypes()
-{
-	var ret = {};
-	var key;
-	for (key in deftypes)
-		ret[key] = deftypes[key];
-
-	return (ret);
-}
-
-/*
- * Given a string in the form of type[length] we want to split this into an
- * object that extracts that information. We want to note that we could possibly
- * have nested arrays so this should only check the furthest one. It may also be
- * the case that we have no [] pieces, in which case we just return the current
- * type.
- */
-function ctParseType(str)
-{
-	var begInd, endInd;
-	var type, len;
-	if (typeof (str) != 'string')
-		throw (new Error('type must be a Javascript string'));
-
-	endInd = str.lastIndexOf(']');
-	if (endInd == -1) {
-		if (str.lastIndexOf('[') != -1)
-			throw (new Error('found invalid type with \'[\' but ' +
-			    'no corresponding \']\''));
-
-		return ({ type: str });
-	}
-
-	begInd = str.lastIndexOf('[');
-	if (begInd == -1)
-		throw (new Error('found invalid type with \']\' but ' +
-		    'no corresponding \'[\''));
-
-	if (begInd >= endInd)
-		throw (new Error('malformed type, \']\' appears before \'[\''));
-
-	type = str.substring(0, begInd);
-	len = str.substring(begInd + 1, endInd);
-
-	return ({ type: type, len: len });
-}
-
-/*
- * Given a request validate that all of the fields for it are valid and make
- * sense. This includes verifying the following notions:
- *  - Each type requested is present in types
- *  - Only allow a name for a field to be specified once
- *  - If an array is specified, validate that the requested field exists and
- *    comes before it.
- *  - If fields is defined, check that each entry has the occurrence of field
- */
-function ctCheckReq(def, types, fields)
-{
-	var ii, jj;
-	var req, keys, key;
-	var found = {};
-
-	if (!(def instanceof Array))
-		throw (new Error('definition is not an array'));
-
-	if (def.length === 0)
-		throw (new Error('definition must have at least one element'));
-
-	for (ii = 0; ii < def.length; ii++) {
-		req = def[ii];
-		if (!(req instanceof Object))
-			throw (new Error('definition must be an array of' +
-			    'objects'));
-
-		keys = Object.keys(req);
-		if (keys.length != 1)
-			throw (new Error('definition entry must only have ' +
-			    'one key'));
-
-		if (keys[0] in found)
-			throw (new Error('Specified name already ' +
-			    'specified: ' + keys[0]));
-
-		if (!('type' in req[keys[0]]))
-			throw (new Error('missing required type definition'));
-
-		key = ctParseType(req[keys[0]]['type']);
-
-		/*
-		 * We may have nested arrays, we need to check the validity of
-		 * the types until the len field is undefined in key. However,
-		 * each time len is defined we need to verify it is either an
-		 * integer or corresponds to an already seen key.
-		 */
-		while (key['len'] !== undefined) {
-			if (isNaN(parseInt(key['len'], 10))) {
-				if (!(key['len'] in found))
-					throw (new Error('Given an array ' +
-					    'length without a matching type'));
-
-			}
-
-			key = ctParseType(key['type']);
-		}
-
-		/* Now we can validate if the type is valid */
-		if (!(key['type'] in types))
-			throw (new Error('type not found or typdefed: ' +
-			    key['type']));
-
-		/* Check for any required fields */
-		if (fields !== undefined) {
-			for (jj = 0; jj < fields.length; jj++) {
-				if (!(fields[jj] in req[keys[0]]))
-					throw (new Error('Missing required ' +
-					    'field: ' + fields[jj]));
-			}
-		}
-
-		found[keys[0]] = true;
-	}
-}
-
-
-/*
- * Create a new instance of the parser. Each parser has its own store of
- * typedefs and endianness. Conf is an object with the following required
- * values:
- *
- *	endian		Either 'big' or 'little' do determine the endianness we
- *			want to read from or write to.
- *
- * And the following optional values:
- *
- * 	char-type	Valid options here are uint8 and int8. If uint8 is
- * 			specified this changes the default behavior of a single
- * 			char from being a buffer of a single character to being
- * 			a uint8_t. If int8, it becomes an int8_t instead.
- */
-function CTypeParser(conf)
-{
-	if (!conf) throw (new Error('missing required argument'));
-
-	if (!('endian' in conf))
-		throw (new Error('missing required endian value'));
-
-	if (conf['endian'] != 'big' && conf['endian'] != 'little')
-		throw (new Error('Invalid endian type'));
-
-	if ('char-type' in conf && (conf['char-type'] != 'uint8' &&
-	    conf['char-type'] != 'int8'))
-		throw (new Error('invalid option for char-type: ' +
-		    conf['char-type']));
-
-	this.endian = conf['endian'];
-	this.types = ctGetBasicTypes();
-
-	/*
-	 * There may be a more graceful way to do this, but this will have to
-	 * serve.
-	 */
-	if ('char-type' in conf && conf['char-type'] == 'uint8')
-		this.types['char'] = this.types['uint8_t'];
-
-	if ('char-type' in conf && conf['char-type'] == 'int8')
-		this.types['char'] = this.types['int8_t'];
-}
-
-/*
- * Sets the current endian value for the Parser. If the value is not valid,
- * throws an Error.
- *
- *	endian		Either 'big' or 'little' do determine the endianness we
- *			want to read from or write to.
- *
- */
-CTypeParser.prototype.setEndian = function (endian)
-{
-	if (endian != 'big' && endian != 'little')
-		throw (new Error('invalid endian type, must be big or ' +
-		    'little'));
-
-	this.endian = endian;
-};
-
-/*
- * Returns the current value of the endian value for the parser.
- */
-CTypeParser.prototype.getEndian = function ()
-{
-	return (this.endian);
-};
-
-/*
- * A user has requested to add a type, let us honor their request. Yet, if their
- * request doth spurn us, send them unto the Hells which Dante describes.
- *
- * 	name		The string for the type definition we're adding
- *
- *	value		Either a string that is a type/array name or an object
- *			that describes a struct.
- */
-CTypeParser.prototype.typedef = function (name, value)
-{
-	var type;
-
-	if (name === undefined)
-		throw (new (Error('missing required typedef argument: name')));
-
-	if (value === undefined)
-		throw (new (Error('missing required typedef argument: value')));
-
-	if (typeof (name) != 'string')
-		throw (new (Error('the name of a type must be a string')));
-
-	type = ctParseType(name);
-
-	if (type['len'] !== undefined)
-		throw (new Error('Cannot have an array in the typedef name'));
-
-	if (name in this.types)
-		throw (new Error('typedef name already present: ' + name));
-
-	if (typeof (value) != 'string' && !(value instanceof Array))
-		throw (new Error('typedef value must either be a string or ' +
-		    'struct'));
-
-	if (typeof (value) == 'string') {
-		type = ctParseType(value);
-		if (type['len'] !== undefined) {
-			if (isNaN(parseInt(type['len'], 10)))
-				throw (new (Error('typedef value must use ' +
-				    'fixed size array when outside of a ' +
-				    'struct')));
-		}
-
-		this.types[name] = value;
-	} else {
-		/* We have a struct, validate it */
-		ctCheckReq(value, this.types);
-		this.types[name] = value;
-	}
-};
-
-/*
- * Include all of the typedefs, but none of the built in types. This should be
- * treated as read-only.
- */
-CTypeParser.prototype.lstypes = function ()
-{
-	var key;
-	var ret = {};
-
-	for (key in this.types) {
-		if (key in deftypes)
-			continue;
-		ret[key] = this.types[key];
-	}
-
-	return (ret);
-};
-
-/*
- * Given a type string that may have array types that aren't numbers, try and
- * fill them in from the values object. The object should be of the format where
- * indexing into it should return a number for that type.
- *
- *	str		The type string
- *
- *	values		An object that can be used to fulfill type information
- */
-function ctResolveArray(str, values)
-{
-	var ret = '';
-	var type = ctParseType(str);
-
-	while (type['len'] !== undefined) {
-		if (isNaN(parseInt(type['len'], 10))) {
-			if (typeof (values[type['len']]) != 'number')
-				throw (new Error('cannot sawp in non-number ' +
-				    'for array value'));
-			ret = '[' + values[type['len']] + ']' + ret;
-		} else {
-			ret = '[' + type['len'] + ']' + ret;
-		}
-		type = ctParseType(type['type']);
-	}
-
-	ret = type['type'] + ret;
-
-	return (ret);
-}
-
-/*
- * [private] Either the typedef resolves to another type string or to a struct.
- * If it resolves to a struct, we just pass it off to read struct. If not, we
- * can just pass it off to read entry.
- */
-CTypeParser.prototype.resolveTypedef = function (type, dispatch, buffer,
-    offset, value)
-{
-	var pt;
-
-	mod_assert.ok(type in this.types);
-	if (typeof (this.types[type]) == 'string') {
-		pt = ctParseType(this.types[type]);
-		if (dispatch == 'read')
-			return (this.readEntry(pt, buffer, offset));
-		else if (dispatch == 'write')
-			return (this.writeEntry(value, pt, buffer, offset));
-		else
-			throw (new Error('invalid dispatch type to ' +
-			    'resolveTypedef'));
-	} else {
-		if (dispatch == 'read')
-			return (this.readStruct(this.types[type], buffer,
-			    offset));
-		else if (dispatch == 'write')
-			return (this.writeStruct(value, this.types[type],
-			    buffer, offset));
-		else
-			throw (new Error('invalid dispatch type to ' +
-			    'resolveTypedef'));
-	}
-
-};
-
-/*
- * [private] Try and read in the specific entry.
- */
-CTypeParser.prototype.readEntry = function (type, buffer, offset)
-{
-	var parse, len;
-
-	/*
-	 * Because we want to special case char[]s this is unfortunately
-	 * a bit uglier than it really should be. We want to special
-	 * case char[]s so that we return a node buffer, thus they are a
-	 * first class type where as all other arrays just call into a
-	 * generic array routine which calls their data-specific routine
-	 * the specified number of times.
-	 *
-	 * The valid dispatch options we have are:
-	 *  - Array and char => char[] handler
-	 *  - Generic array handler
-	 *  - Generic typedef handler
-	 *  - Basic type handler
-	 */
-	if (type['len'] !== undefined) {
-		len = parseInt(type['len'], 10);
-		if (isNaN(len))
-			throw (new Error('somehow got a non-numeric length'));
-
-		if (type['type'] == 'char')
-			parse = this.types['char[]']['read'](len,
-			    this.endian, buffer, offset);
-		else
-			parse = this.readArray(type['type'],
-			    len, buffer, offset);
-	} else {
-		if (type['type'] in deftypes)
-			parse = this.types[type['type']]['read'](this.endian,
-			    buffer, offset);
-		else
-			parse = this.resolveTypedef(type['type'], 'read',
-			    buffer, offset);
-	}
-
-	return (parse);
-};
-
-/*
- * [private] Read an array of data
- */
-CTypeParser.prototype.readArray = function (type, length, buffer, offset)
-{
-	var ii, ent, pt;
-	var baseOffset = offset;
-	var ret = new Array(length);
-	pt = ctParseType(type);
-
-	for (ii = 0; ii < length; ii++) {
-		ent = this.readEntry(pt, buffer, offset);
-		offset += ent['size'];
-		ret[ii] = ent['value'];
-	}
-
-	return ({ value: ret, size: offset - baseOffset });
-};
-
-/*
- * [private] Read a single struct in.
- */
-CTypeParser.prototype.readStruct = function (def, buffer, offset)
-{
-	var parse, ii, type, entry, key;
-	var baseOffset = offset;
-	var ret = {};
-
-	/* Walk it and handle doing what's necessary */
-	for (ii = 0; ii < def.length; ii++) {
-		key = Object.keys(def[ii])[0];
-		entry = def[ii][key];
-
-		/* Resolve all array values */
-		type = ctParseType(ctResolveArray(entry['type'], ret));
-
-		if ('offset' in entry)
-			offset = baseOffset + entry['offset'];
-
-		parse = this.readEntry(type, buffer, offset);
-
-		offset += parse['size'];
-		ret[key] = parse['value'];
-	}
-
-	return ({ value: ret, size: (offset-baseOffset)});
-};
-
-/*
- * This is what we were born to do. We read the data from a buffer and return it
- * in an object whose keys match the values from the object.
- *
- *	def		The array definition of the data to read in
- *
- *	buffer		The buffer to read data from
- *
- *	offset		The offset to start writing to
- *
- * Returns an object where each key corresponds to an entry in def and the value
- * is the read value.
- */
-CTypeParser.prototype.readData = function (def, buffer, offset)
-{
-	/* Sanity check for arguments */
-	if (def === undefined)
-		throw (new Error('missing definition for what we should be' +
-		    'parsing'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer for what we should be ' +
-		    'parsing'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset for what we should be ' +
-		    'parsing'));
-
-	/* Sanity check the object definition */
-	ctCheckReq(def, this.types);
-
-	return (this.readStruct(def, buffer, offset)['value']);
-};
-
-/*
- * [private] Write out an array of data
- */
-CTypeParser.prototype.writeArray = function (value, type, length, buffer,
-    offset)
-{
-	var ii, pt;
-	var baseOffset = offset;
-	if (!(value instanceof Array))
-		throw (new Error('asked to write an array, but value is not ' +
-		    'an array'));
-
-	if (value.length != length)
-		throw (new Error('asked to write array of length ' + length +
-		    ' but that does not match value length: ' + value.length));
-
-	pt = ctParseType(type);
-	for (ii = 0; ii < length; ii++)
-		offset += this.writeEntry(value[ii], pt, buffer, offset);
-
-	return (offset - baseOffset);
-};
-
-/*
- * [private] Write the specific entry
- */
-CTypeParser.prototype.writeEntry = function (value, type, buffer, offset)
-{
-	var len, ret;
-
-	if (type['len'] !== undefined) {
-		len = parseInt(type['len'], 10);
-		if (isNaN(len))
-			throw (new Error('somehow got a non-numeric length'));
-
-		if (type['type'] == 'char')
-			ret = this.types['char[]']['write'](value, len,
-			    this.endian, buffer, offset);
-		else
-			ret = this.writeArray(value, type['type'],
-			    len, buffer, offset);
-	} else {
-		if (type['type'] in deftypes)
-			ret = this.types[type['type']]['write'](value,
-			    this.endian, buffer, offset);
-		else
-			ret = this.resolveTypedef(type['type'], 'write',
-			    buffer, offset, value);
-	}
-
-	return (ret);
-};
-
-/*
- * [private] Write a single struct out.
- */
-CTypeParser.prototype.writeStruct = function (value, def, buffer, offset)
-{
-	var ii, entry, type, key;
-	var baseOffset = offset;
-	var vals = {};
-
-	for (ii = 0; ii < def.length; ii++) {
-		key = Object.keys(def[ii])[0];
-		entry = def[ii][key];
-
-		type = ctParseType(ctResolveArray(entry['type'], vals));
-
-		if ('offset' in entry)
-			offset = baseOffset + entry['offset'];
-
-		offset += this.writeEntry(value[ii], type, buffer, offset);
-		/* Now that we've written it out, we can use it for arrays */
-		vals[key] = value[ii];
-	}
-
-	return (offset);
-};
-
-/*
- * Unfortunately, we're stuck with the sins of an initial poor design. Because
- * of that, we are going to have to support the old way of writing data via
- * writeData. There we insert the values that you want to write into the
- * definition. A little baroque. Internally, we use the new model. So we need to
- * just get those values out of there. But to maintain the principle of least
- * surprise, we're not going to modify the input data.
- */
-function getValues(def)
-{
-	var ii, out, key;
-	out = [];
-	for (ii = 0; ii < def.length; ii++) {
-		key = Object.keys(def[ii])[0];
-		mod_assert.ok('value' in def[ii][key]);
-		out.push(def[ii][key]['value']);
-	}
-
-	return (out);
-}
-
-/*
- * This is the second half of what we were born to do, write out the data
- * itself. Historically this function required you to put your values in the
- * definition section. This was not the smartest thing to do and a bit of an
- * oversight to be honest. As such, this function now takes a values argument.
- * If values is non-null and non-undefined, it will be used to determine the
- * values. This means that the old method is still supported, but is no longer
- * acceptable.
- *
- *	def		The array definition of the data to write out with
- *			values
- *
- *	buffer		The buffer to write to
- *
- *	offset		The offset in the buffer to write to
- *
- *	values		An array of values to write.
- */
-CTypeParser.prototype.writeData = function (def, buffer, offset, values)
-{
-	var hv;
-
-	if (def === undefined)
-		throw (new Error('missing definition for what we should be' +
-		    'parsing'));
-
-	if (buffer === undefined)
-		throw (new Error('missing buffer for what we should be ' +
-		    'parsing'));
-
-	if (offset === undefined)
-		throw (new Error('missing offset for what we should be ' +
-		    'parsing'));
-
-	hv = (values != null && values != undefined);
-	if (hv) {
-		if (!Array.isArray(values))
-			throw (new Error('missing values for writing'));
-		ctCheckReq(def, this.types);
-	} else {
-		ctCheckReq(def, this.types, [ 'value' ]);
-	}
-
-	this.writeStruct(hv ? values : getValues(def), def, buffer, offset);
-};
-
-/*
- * Functions to go to and from 64 bit numbers in a way that is compatible with
- * Javascript limitations. There are two sets. One where the user is okay with
- * an approximation and one where they are definitely not okay with an
- * approximation.
- */
-
-/*
- * Attempts to convert an array of two integers returned from rsint64 / ruint64
- * into an absolute 64 bit number. If however the value would exceed 2^52 this
- * will instead throw an error. The mantissa in a double is a 52 bit number and
- * rather than potentially give you a value that is an approximation this will
- * error. If you would rather an approximation, please see toApprox64.
- *
- *	val		An array of two 32-bit integers
- */
-function toAbs64(val)
-{
-	if (val === undefined)
-		throw (new Error('missing required arg: value'));
-
-	if (!Array.isArray(val))
-		throw (new Error('value must be an array'));
-
-	if (val.length != 2)
-		throw (new Error('value must be an array of length 2'));
-
-	/* We have 20 bits worth of precision in this range */
-	if (val[0] >= 0x100000)
-		throw (new Error('value would become approximated'));
-
-	return (val[0] * Math.pow(2, 32) + val[1]);
-}
-
-/*
- * Will return the 64 bit value as returned in an array from rsint64 / ruint64
- * to a value as close as it can. Note that Javascript stores all numbers as a
- * double and the mantissa only has 52 bits. Thus this version may approximate
- * the value.
- *
- *	val		An array of two 32-bit integers
- */
-function toApprox64(val)
-{
-	if (val === undefined)
-		throw (new Error('missing required arg: value'));
-
-	if (!Array.isArray(val))
-		throw (new Error('value must be an array'));
-
-	if (val.length != 2)
-		throw (new Error('value must be an array of length 2'));
-
-	return (Math.pow(2, 32) * val[0] + val[1]);
-}
-
-function parseCTF(json, conf)
-{
-	var ctype = new CTypeParser(conf);
-	mod_ctf.ctfParseJson(json, ctype);
-
-	return (ctype);
-}
-
-/*
- * Export the few things we actually want to. Currently this is just the CType
- * Parser and ctio.
- */
-exports.Parser = CTypeParser;
-exports.toAbs64 = toAbs64;
-exports.toApprox64 = toApprox64;
-
-exports.parseCTF = parseCTF;
-
-exports.ruint8 = mod_ctio.ruint8;
-exports.ruint16 = mod_ctio.ruint16;
-exports.ruint32 = mod_ctio.ruint32;
-exports.ruint64 = mod_ctio.ruint64;
-exports.wuint8 = mod_ctio.wuint8;
-exports.wuint16 = mod_ctio.wuint16;
-exports.wuint32 = mod_ctio.wuint32;
-exports.wuint64 = mod_ctio.wuint64;
-
-exports.rsint8 = mod_ctio.rsint8;
-exports.rsint16 = mod_ctio.rsint16;
-exports.rsint32 = mod_ctio.rsint32;
-exports.rsint64 = mod_ctio.rsint64;
-exports.wsint8 = mod_ctio.wsint8;
-exports.wsint16 = mod_ctio.wsint16;
-exports.wsint32 = mod_ctio.wsint32;
-exports.wsint64 = mod_ctio.wsint64;
-
-exports.rfloat = mod_ctio.rfloat;
-exports.rdouble = mod_ctio.rdouble;
-exports.wfloat = mod_ctio.wfloat;
-exports.wdouble = mod_ctio.wdouble;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype
deleted file mode 100644
index 3f94986a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype
+++ /dev/null
@@ -1,241 +0,0 @@
-'\" te
-.\" Copyright (c) 2011, Robert Mustacchi.  All Rights Reserved.
-.\" Copyright (c) 2011, Joyent, Inc.  All Rights Reserved.
-.\"
-.\" 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.
-.TH CTIO 3CTYPE "December 12, 2011"
-.SH NAME
-ctio, ruint8, ruint16, ruint32, ruint64, wuint8, wuint16, wuint32, wuint64,
-rsint8, rsint16, rsint32, rsint64, wsint8, wsint16, wsint32, wsint64, rfloat,
-rdouble, wfloat, wdouble \- integer and float operations
-.SH SYNOPSIS
-.LP
-.nf
-var mod_ctype = require('ctype');
-
-\fBNumber\fR \fBmod_ctype.ruint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber\fR \fBmod_ctype.ruint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber\fR \fBmod_ctype.ruint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber[2]\fR \fBmod_ctype.ruint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber\fR \fBmod_ctype.rsint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber\fR \fBmod_ctype.rsint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber\fR \fBmod_ctype.rsint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber[2]\fR \fBmod_ctype.rsint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber\fR \fBmod_ctype.rfloat\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBNumber\fR \fBmod_ctype.rdouble\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wuint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wuint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wuint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wuint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wsint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wsint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wsint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wsint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wfloat\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBmod_ctype.wdouble\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
-.fi
-
-.SH DESCRIPTION
-.sp
-.LP
-The argument \fIbuf\fR refers to a valid buffer (from calling new Buffer()). The
-argument \fIendian\fR is either the string 'big' or 'little' and controls
-whether the data in the buffer is interpreted as big or little endian. The argument
-\fIoffset\fR indicates the starting index into the buffer to read or write. All
-functions ensure that starting at \fIoffset\fR does not overflow the end of the
-buffer. The argument \fIvalue\fR is a Number that is the valid type for the
-specific function. All functions that take \fIvalue\fR as an argument, verify
-that the passed value is valid.
-
-.SS "\fBruint8()\fR, \fBruint16()\fR, \fBruint32()\fR"
-.sp
-.LP
-The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions read an 8,
-16, and 32-bit unsigned value from \fIbuf\fR and return it. The value read is
-influenced by the values of \fIoffset\fR and \fRendian\fI.
-
-
-.SS "\fBrsint8()\fR, \fBrsint16()\fR, \fBrsint32()\fR"
-.sp
-.LP
-The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions work just as
-\fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR, except they return signed
-integers.
-
-.SS "\fBruint64()\fR, \fBrsint64()\fR"
-.sp
-.LP
-The \fBruint64()\fR and \fBrsint64()\fR functions read unsigned and signed 64
-bit integers respectively from \fBbuf\fR. Due to the limitations of ECMAScript's
-\fBNumber\fR type, they cannot be stored as one value without a loss of
-precision. Instead of returning the values as a single \fBNumber\fR, the
-functions return an array of two numbers. The first entry always contains the
-upper 32-bits and the second value contains the lower 32-bits. The lossy
-transformation into a number would be \fIres[0]*Math.pow(2,32)+res[1]\fR.
-Note that, unless an entry is zero, both array entries are guaranteed to have
-the same sign.
-
-.SS "\fBwuint8()\fR, \fBwuint16()\fR, \fBwuint32()\fR"
-.sp
-.LP
-The functions \fBwuint8()\fR, \fBwuint16()\fR, and \fBwuint32()\fR modify the
-contents of \fBbuf\fR by writing an 8, 16, and 32-bit unsigned integer
-respectively to \fBbuf\fR. It is illegal to pass a number that is not an integer
-within the domain of the integer size, for example, for \fBwuint8()\fR the valid
-range is \fB[0, 255]\fR. The value will be written in either big or little
-endian format based upon the value of \fBendian\fR.
-
-
-.SS "\fBwsint8()\fR, \fBwsint16()\fR, \fBwsint32()\fR"
-.sp
-.LP
-The functions \fBwsint8()\fR, \fBwsint16()\fR, and \fBwsint32()\fR function
-identically to the functions \fBwuint8()\fR, \fBwuint16()\fR, and
-\fBwuint32()\fR except that they the valid domain for \fBvalue\fR is that of a
-signed number instead of an unsigned number. For example the \fBwsint8()\fR has
-a domain of \fB[-128, 127]\fR.
-
-.SS "\fBwuint64()\fR, \fBwsint64()\fR"
-.sp
-.LP
-The functions \fBwuint64()\fR and \fBswint64()\fR write out 64-bit unsigned and
-signed integers to \fBbuf\fR. The \fBvalue\fR argument must be in the same
-format as described in \fBruint64()\fR and \fBrsint64()\fR.
-
-.SS "\fBrfloat()\fR, \fBrdouble()\fR"
-.sp
-.LP
-The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other read
-functions, except that they read a single precision and double precision
-IEEE-754 floating point value instead.
-
-.SS "\fBwfloat()\fR, \fBwdouble()\fR"
-.sp
-.LP
-The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other write 
-functions, except that the domain for a float is that of a single precision 4
-byte value. The domain for a double is any \fBNumber\fR in ECMAScript, which is
-defined to be represented by a double.
-
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(5) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE	ATTRIBUTE VALUE
-_
-Interface Stability	Committed
-_
-MT-Level	See below.
-_
-Standard	Not standardized.
-.TE
-
-.sp
-.LP
-
-All functions are MT-safe in so far as there aren't shared memory MT concerns in
-most node programs. If one where to concoct such an environment, these functions
-wouldn't be MT-safe.
-
-.SH SEE ALSO
-.sp
-.LP
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json
deleted file mode 100644
index 9c1761ba..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "name": "ctype",
-  "version": "0.5.2",
-  "description": "read and write binary structures and data types",
-  "homepage": "https://github.com/rmustacc/node-ctype",
-  "author": {
-    "name": "Robert Mustacchi",
-    "email": "rm@fingolfin.org"
-  },
-  "engines": {
-    "node": ">= 0.4"
-  },
-  "main": "ctype.js",
-  "readme": "Node-CType is a way to read and write binary data in structured and easy to use\nformat. Its name comes from the C header file.\n\nTo get started, simply clone the repository or use npm to install it. Once it is\nthere, simply require it.\n\ngit clone git://github.com/rmustacc/node-ctype\nnpm install ctype\nvar mod_ctype = require('ctype')\n\n\nThere are two APIs that you can use, depending on what abstraction you'd like.\nThe low level API let's you read and write individual integers and floats from\nbuffers. The higher level API let's you read and write structures of these. To\nillustrate this, let's looks look at how we would read and write a binary\nencoded x,y point.\n\nIn C we would define this structure as follows:\n\ntypedef struct point {\n\tuint16_t\tp_x;\n\tuint16_t\tp_y;\n} point_t;\n\nTo read a binary encoded point from a Buffer, we first need to create a CType\nparser (where we specify the endian and other options) and add the typedef.\n\nvar parser = new mod_ctype.Parser({ endian: 'big' });\nparser.typedef('point_t', [\n\t{ x: { type: 'uint16_t' } },\n\t{ y: { type: 'uint16_t' } }\n]);\n\nFrom here, given a buffer buf and an offset into it, we can read a point.\n\nvar out = parser.readData([ { point: { type: 'point_t' } } ], buffer, 0);\nconsole.log(out);\n{ point: { x: 23, y: 42 } }\n\nAnother way to get the same information would be to use the low level methods.\nNote that these require you to manually deal with the offset. Here's how we'd\nget the same values of x and y from the buffer.\n\nvar x = mod_ctype.ruint16(buf, 'big', 0);\nvar y = mod_ctype.ruint16(buf, 'big', 2);\nconsole.log(x + ', ' + y);\n23, 42\n\nThe true power of this API comes from the ability to define and nest typedefs,\njust as you would in C. By default, the following types are defined by default.\nNote that they return a Number, unless indicated otherwise.\n\n    * int8_t\n    * int16_t\n    * int32_t\n    * int64_t (returns an array where val[0] << 32 + val[1] would be the value)\n    * uint8_t\n    * uint16_t\n    * uint32_t\n    * uint64_t (returns an array where val[0] << 32 + val[1] would be the value)\n    * float\n    * double\n    * char (either returns a buffer with that character or a uint8_t)\n    * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)\n\n\nctf2json integration:\n\nNode-CType supports consuming the output of ctf2json. Once you read in a JSON file,\nall you have to do to add all the definitions it contains is:\n\nvar data, parser;\ndata = JSON.parse(parsedJSONData);\nparser = mod_ctype.parseCTF(data, { endian: 'big' });\n\nFor more documentation, see the file README.old. Full documentation is in the\nprocess of being rewritten as a series of manual pages which will be available\nin the repository and online for viewing.\n\nTo read the ctio manual page simple run, from the root of the workspace:\n\nman -Mman -s 3ctype ctio\n",
-  "readmeFilename": "README",
-  "_id": "ctype@0.5.2",
-  "_shasum": "fe8091d468a373a0b0c9ff8bbfb3425c00973a1d",
-  "_from": "ctype@0.5.2",
-  "_resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf
deleted file mode 100755
index 845f367a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# Configuration File for JavaScript Lint 0.3.0
-# Developed by Matthias Miller (http://www.JavaScriptLint.com)
-#
-# This configuration file can be used to lint a collection of scripts, or to enable
-# or disable warnings for scripts that are linted via the command line.
-#
-
-### Warnings
-# Enable or disable warnings based on requirements.
-# Use "+WarningName" to display or "-WarningName" to suppress.
-#
-+no_return_value              # function {0} does not always return a value
-+duplicate_formal             # duplicate formal argument {0}
-+equal_as_assign              # test for equality (==) mistyped as assignment (=)?{0}
-+var_hides_arg                # variable {0} hides argument
-+redeclared_var               # redeclaration of {0} {1}
-+anon_no_return_value         # anonymous function does not always return a value
-+missing_semicolon            # missing semicolon
-+meaningless_block            # meaningless block; curly braces have no impact
-+comma_separated_stmts        # multiple statements separated by commas (use semicolons?)
-+unreachable_code             # unreachable code
-+missing_break                # missing break statement
-+missing_break_for_last_case  # missing break statement for last case in switch
-+comparison_type_conv         # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
--inc_dec_within_stmt          # increment (++) and decrement (--) operators used as part of greater statement
-+useless_void                 # use of the void type may be unnecessary (void is always undefined)
--useless_quotes			# quotation marks are unnecessary
-+multiple_plus_minus          # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
-+use_of_label                 # use of label
--block_without_braces         # block statement without curly braces
-+leading_decimal_point        # leading decimal point may indicate a number or an object member
-+trailing_decimal_point       # trailing decimal point may indicate a number or an object member
--octal_number                 # leading zeros make an octal number
-+nested_comment               # nested comment
-+misplaced_regex              # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
-+ambiguous_newline            # unexpected end of line; it is ambiguous whether these lines are part of the same statement
-+empty_statement              # empty statement or extra semicolon
--missing_option_explicit      # the "option explicit" control comment is missing
-+partial_option_explicit      # the "option explicit" control comment, if used, must be in the first script tag
-+dup_option_explicit          # duplicate "option explicit" control comment
-+useless_assign               # useless assignment
-+ambiguous_nested_stmt        # block statements containing block statements should use curly braces to resolve ambiguity
-+ambiguous_else_stmt          # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
-+missing_default_case         # missing default case in switch statement
-+duplicate_case_in_switch     # duplicate case in switch statements
-+default_not_at_end           # the default case is not at the end of the switch statement
-+legacy_cc_not_understood     # couldn't understand control comment using /*@keyword@*/ syntax
-+jsl_cc_not_understood        # couldn't understand control comment using /*jsl:keyword*/ syntax
-+useless_comparison           # useless comparison; comparing identical expressions
-+with_statement               # with statement hides undeclared variables; use temporary variable instead
-+trailing_comma_in_array      # extra comma is not recommended in array initializers
-+assign_to_function_call      # assignment to a function call
-+parseint_missing_radix       # parseInt missing radix parameter
--unreferenced_argument        # argument declared but never referenced: {name}
-
-### Output format
-# Customize the format of the error message.
-#    __FILE__ indicates current file path
-#    __FILENAME__ indicates current file name
-#    __LINE__ indicates current line
-#    __ERROR__ indicates error message
-#
-# Visual Studio syntax (default):
-+output-format __FILE__(__LINE__): __ERROR__
-# Alternative syntax:
-#+output-format __FILE__:__LINE__: __ERROR__
-
-
-### Context
-# Show the in-line position of the error.
-# Use "+context" to display or "-context" to suppress.
-#
-+context
-
-
-### Semicolons
-# By default, assignments of an anonymous function to a variable or
-# property (such as a function prototype) must be followed by a semicolon.
-#
-#+lambda_assign_requires_semicolon # deprecated setting
-
-
-### Control Comments
-# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
-# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
-# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
-# although legacy control comments are enabled by default for backward compatibility.
-#
-+legacy_control_comments
-
-
-### JScript Function Extensions
-# JScript allows member functions to be defined like this:
-#     function MyObj() { /*constructor*/ }
-#     function MyObj.prototype.go() { /*member function*/ }
-#
-# It also allows events to be attached like this:
-#     function window::onload() { /*init page*/ }
-#
-# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
-#
-#-jscript_function_extensions # deprecated setting
-
-
-### Defining identifiers
-# By default, "option explicit" is enabled on a per-file basis.
-# To enable this for all files, use "+always_use_option_explicit"
--always_use_option_explicit
-
-# Define certain identifiers of which the lint is not aware.
-# (Use this in conjunction with the "undeclared identifier" warning.)
-#
-# Common uses for webpages might be:
-#+define window
-#+define document
-+define require
-+define exports
-+define console
-+define Buffer
-+define JSON
-
-### Files
-# Specify which files to lint
-# Use "+recurse" to enable recursion (disabled by default).
-# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
-# or "+process Folder\Path\*.htm".
-#
-#+process jsl-test.js
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle
deleted file mode 100755
index 96c72b6d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle
+++ /dev/null
@@ -1,839 +0,0 @@
-#!/usr/bin/env perl
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# Copyright 2011 Joyent, Inc. All rights reserved.
-#
-# jsstyle - check for some common stylistic errors.
-#
-#	jsstyle is a sort of "lint" for Javascript coding style.  This tool is
-#	derived from the cstyle tool, used to check for the style used in the
-#	Solaris kernel, sometimes known as "Bill Joy Normal Form".
-#
-#	There's a lot this can't check for, like proper indentation of code
-#	blocks.  There's also a lot more this could check for.
-#
-#	A note to the non perl literate:
-#
-#		perl regular expressions are pretty much like egrep
-#		regular expressions, with the following special symbols
-#
-#		\s	any space character
-#		\S	any non-space character
-#		\w	any "word" character [a-zA-Z0-9_]
-#		\W	any non-word character
-#		\d	a digit [0-9]
-#		\D	a non-digit
-#		\b	word boundary (between \w and \W)
-#		\B	non-word boundary
-#
-
-require 5.0;
-use IO::File;
-use Getopt::Std;
-use strict;
-
-my $usage =
-"usage: jsstyle [-chvC] [-o constructs] file ...
-	-c	check continuation indentation inside functions
-	-h	perform heuristic checks that are sometimes wrong
-	-v	verbose
-	-C	don't check anything in header block comments
-	-o constructs
-		allow a comma-seperated list of optional constructs:
-		    doxygen	allow doxygen-style block comments (/** /*!)
-		    splint	allow splint-style lint comments (/*@ ... @*/)
-";
-
-my %opts;
-
-if (!getopts("cho:vC", \%opts)) {
-	print $usage;
-	exit 2;
-}
-
-my $check_continuation = $opts{'c'};
-my $heuristic = $opts{'h'};
-my $verbose = $opts{'v'};
-my $ignore_hdr_comment = $opts{'C'};
-
-my $doxygen_comments = 0;
-my $splint_comments = 0;
-
-if (defined($opts{'o'})) {
-	for my $x (split /,/, $opts{'o'}) {
-		if ($x eq "doxygen") {
-			$doxygen_comments = 1;
-		} elsif ($x eq "splint") {
-			$splint_comments = 1;
-		} else {
-			print "jsstyle: unrecognized construct \"$x\"\n";
-			print $usage;
-			exit 2;
-		}
-	}
-}
-
-my ($filename, $line, $prev);		# shared globals
-
-my $fmt;
-my $hdr_comment_start;
-
-if ($verbose) {
-	$fmt = "%s: %d: %s\n%s\n";
-} else {
-	$fmt = "%s: %d: %s\n";
-}
-
-if ($doxygen_comments) {
-	# doxygen comments look like "/*!" or "/**"; allow them.
-	$hdr_comment_start = qr/^\s*\/\*[\!\*]?$/;
-} else {
-	$hdr_comment_start = qr/^\s*\/\*$/;
-}
-
-# Note, following must be in single quotes so that \s and \w work right.
-my $lint_re = qr/\/\*(?:
-	jsl:\w+?|ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*|
-	CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|
-	FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*|
-	PROTOLIB[0-9]*|SCANFLIKE[0-9]*|JSSTYLED.*?
-    )\*\//x;
-
-my $splint_re = qr/\/\*@.*?@\*\//x;
-
-my $err_stat = 0;		# exit status
-
-if ($#ARGV >= 0) {
-	foreach my $arg (@ARGV) {
-		my $fh = new IO::File $arg, "r";
-		if (!defined($fh)) {
-			printf "%s: cannot open\n", $arg;
-		} else {
-			&jsstyle($arg, $fh);
-			close $fh;
-		}
-	}
-} else {
-	&jsstyle("<stdin>", *STDIN);
-}
-exit $err_stat;
-
-my $no_errs = 0;		# set for JSSTYLED-protected lines
-
-sub err($) {
-	my ($error) = @_;
-	unless ($no_errs) {
-		printf $fmt, $filename, $., $error, $line;
-		$err_stat = 1;
-	}
-}
-
-sub err_prefix($$) {
-	my ($prevline, $error) = @_;
-	my $out = $prevline."\n".$line;
-	unless ($no_errs) {
-		printf $fmt, $filename, $., $error, $out;
-		$err_stat = 1;
-	}
-}
-
-sub err_prev($) {
-	my ($error) = @_;
-	unless ($no_errs) {
-		printf $fmt, $filename, $. - 1, $error, $prev;
-		$err_stat = 1;
-	}
-}
-
-sub jsstyle($$) {
-
-my ($fn, $filehandle) = @_;
-$filename = $fn;			# share it globally
-
-my $in_cpp = 0;
-my $next_in_cpp = 0;
-
-my $in_comment = 0;
-my $in_header_comment = 0;
-my $comment_done = 0;
-my $in_function = 0;
-my $in_function_header = 0;
-my $in_declaration = 0;
-my $note_level = 0;
-my $nextok = 0;
-my $nocheck = 0;
-
-my $in_string = 0;
-
-my ($okmsg, $comment_prefix);
-
-$line = '';
-$prev = '';
-reset_indent();
-
-line: while (<$filehandle>) {
-	s/\r?\n$//;	# strip return and newline
-
-	# save the original line, then remove all text from within
-	# double or single quotes, we do not want to check such text.
-
-	$line = $_;
-
-	#
-	# C allows strings to be continued with a backslash at the end of
-	# the line.  We translate that into a quoted string on the previous
-	# line followed by an initial quote on the next line.
-	#
-	# (we assume that no-one will use backslash-continuation with character
-	# constants)
-	#
-	$_ = '"' . $_		if ($in_string && !$nocheck && !$in_comment);
-
-	#
-	# normal strings and characters
-	#
-	s/'([^\\']|\\.)*'/\'\'/g;
-	s/"([^\\"]|\\.)*"/\"\"/g;
-
-	#
-	# detect string continuation
-	#
-	if ($nocheck || $in_comment) {
-		$in_string = 0;
-	} else {
-		#
-		# Now that all full strings are replaced with "", we check
-		# for unfinished strings continuing onto the next line.
-		#
-		$in_string =
-		    (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ ||
-		    s/^("")*"([^\\"]|\\.)*\\$/""/);
-	}
-
-	#
-	# figure out if we are in a cpp directive
-	#
-	$in_cpp = $next_in_cpp || /^\s*#/;	# continued or started
-	$next_in_cpp = $in_cpp && /\\$/;	# only if continued
-
-	# strip off trailing backslashes, which appear in long macros
-	s/\s*\\$//;
-
-	# an /* END JSSTYLED */ comment ends a no-check block.
-	if ($nocheck) {
-		if (/\/\* *END *JSSTYLED *\*\//) {
-			$nocheck = 0;
-		} else {
-			reset_indent();
-			next line;
-		}
-	}
-
-	# a /*JSSTYLED*/ comment indicates that the next line is ok.
-	if ($nextok) {
-		if ($okmsg) {
-			err($okmsg);
-		}
-		$nextok = 0;
-		$okmsg = 0;
-		if (/\/\* *JSSTYLED.*\*\//) {
-			/^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
-			$okmsg = $1;
-			$nextok = 1;
-		}
-		$no_errs = 1;
-	} elsif ($no_errs) {
-		$no_errs = 0;
-	}
-
-	# check length of line.
-	# first, a quick check to see if there is any chance of being too long.
-	if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) {
-		# yes, there is a chance.
-		# replace tabs with spaces and check again.
-		my $eline = $line;
-		1 while $eline =~
-		    s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
-		if (length($eline) > 80) {
-			err("line > 80 characters");
-		}
-	}
-
-	# ignore NOTE(...) annotations (assumes NOTE is on lines by itself).
-	if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE
-		s/[^()]//g;			  # eliminate all non-parens
-		$note_level += s/\(//g - length;  # update paren nest level
-		next;
-	}
-
-	# a /* BEGIN JSSTYLED */ comment starts a no-check block.
-	if (/\/\* *BEGIN *JSSTYLED *\*\//) {
-		$nocheck = 1;
-	}
-
-	# a /*JSSTYLED*/ comment indicates that the next line is ok.
-	if (/\/\* *JSSTYLED.*\*\//) {
-		/^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
-		$okmsg = $1;
-		$nextok = 1;
-	}
-	if (/\/\/ *JSSTYLED/) {
-		/^.*\/\/ *JSSTYLED *(.*)$/;
-		$okmsg = $1;
-		$nextok = 1;
-	}
-
-	# universal checks; apply to everything
-	if (/\t +\t/) {
-		err("spaces between tabs");
-	}
-	if (/ \t+ /) {
-		err("tabs between spaces");
-	}
-	if (/\s$/) {
-		err("space or tab at end of line");
-	}
-	if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
-		err("comment preceded by non-blank");
-	}
-
-	# is this the beginning or ending of a function?
-	# (not if "struct foo\n{\n")
-	if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) {
-		$in_function = 1;
-		$in_declaration = 1;
-		$in_function_header = 0;
-		$prev = $line;
-		next line;
-	}
-	if (/^}\s*(\/\*.*\*\/\s*)*$/) {
-		if ($prev =~ /^\s*return\s*;/) {
-			err_prev("unneeded return at end of function");
-		}
-		$in_function = 0;
-		reset_indent();		# we don't check between functions
-		$prev = $line;
-		next line;
-	}
-	if (/^\w*\($/) {
-		$in_function_header = 1;
-	}
-
-	# a blank line terminates the declarations within a function.
-	# XXX - but still a problem in sub-blocks.
-	if ($in_declaration && /^$/) {
-		$in_declaration = 0;
-	}
-
-	if ($comment_done) {
-		$in_comment = 0;
-		$in_header_comment = 0;
-		$comment_done = 0;
-	}
-	# does this looks like the start of a block comment?
-	if (/$hdr_comment_start/) {
-		if (!/^\t*\/\*/) {
-			err("block comment not indented by tabs");
-		}
-		$in_comment = 1;
-		/^(\s*)\//;
-		$comment_prefix = $1;
-		if ($comment_prefix eq "") {
-			$in_header_comment = 1;
-		}
-		$prev = $line;
-		next line;
-	}
-	# are we still in the block comment?
-	if ($in_comment) {
-		if (/^$comment_prefix \*\/$/) {
-			$comment_done = 1;
-		} elsif (/\*\//) {
-			$comment_done = 1;
-			err("improper block comment close")
-			    unless ($ignore_hdr_comment && $in_header_comment);
-		} elsif (!/^$comment_prefix \*[ \t]/ &&
-		    !/^$comment_prefix \*$/) {
-			err("improper block comment")
-			    unless ($ignore_hdr_comment && $in_header_comment);
-		}
-	}
-
-	if ($in_header_comment && $ignore_hdr_comment) {
-		$prev = $line;
-		next line;
-	}
-
-	# check for errors that might occur in comments and in code.
-
-	# allow spaces to be used to draw pictures in header comments.
-	#if (/[^ ]     / && !/".*     .*"/ && !$in_header_comment) {
-	#	err("spaces instead of tabs");
-	#}
-	#if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
-	#    (!/^    \w/ || $in_function != 0)) {
-	#	err("indent by spaces instead of tabs");
-	#}
-	if (/^ {2,}/ && !/^    [^ ]/) {
-		err("indent by spaces instead of tabs");
-	}
-	if (/^\t+ [^ \t\*]/ || /^\t+  \S/ || /^\t+   \S/) {
-		err("continuation line not indented by 4 spaces");
-	}
-
-	if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) {
-		err("improper first line of block comment");
-	}
-
-	if ($in_comment) {	# still in comment, don't do further checks
-		$prev = $line;
-		next line;
-	}
-
-	if ((/[^(]\/\*\S/ || /^\/\*\S/) &&
-	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
-		err("missing blank after open comment");
-	}
-	if (/\S\*\/[^)]|\S\*\/$/ &&
-	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
-		err("missing blank before close comment");
-	}
-	if (/\/\/\S/) {		# C++ comments
-		err("missing blank after start comment");
-	}
-	# check for unterminated single line comments, but allow them when
-	# they are used to comment out the argument list of a function
-	# declaration.
-	if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) {
-		err("unterminated single line comment");
-	}
-
-	if (/^(#else|#endif|#include)(.*)$/) {
-		$prev = $line;
-		next line;
-	}
-
-	#
-	# delete any comments and check everything else.  Note that
-	# ".*?" is a non-greedy match, so that we don't get confused by
-	# multiple comments on the same line.
-	#
-	s/\/\*.*?\*\///g;
-	s/\/\/.*$//;		# C++ comments
-
-	# delete any trailing whitespace; we have already checked for that.
-	s/\s*$//;
-
-	# following checks do not apply to text in comments.
-	if (/"/) {
-		err("literal string using double-quote instead of single");
-	}
-
-	if (/[^=!<>\s][!<>=]=/ || /[^<>!=][!<>=]==?[^\s,=]/ ||
-	    (/[^->]>[^,=>\s]/ && !/[^->]>$/) ||
-	    (/[^<]<[^,=<\s]/ && !/[^<]<$/) ||
-	    /[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
-		err("missing space around relational operator");
-	}
-	if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
-	    (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
-	    (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
-		# XXX - should only check this for C++ code
-		# XXX - there are probably other forms that should be allowed
-		if (!/\soperator=/) {
-			err("missing space around assignment operator");
-		}
-	}
-	if (/[,;]\S/ && !/\bfor \(;;\)/) {
-		err("comma or semicolon followed by non-blank");
-	}
-	# allow "for" statements to have empty "while" clauses
-	if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
-		err("comma or semicolon preceded by blank");
-	}
-	if (/^\s*(&&|\|\|)/) {
-		err("improper boolean continuation");
-	}
-	if (/\S   *(&&|\|\|)/ || /(&&|\|\|)   *\S/) {
-		err("more than one space around boolean operator");
-	}
-	if (/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\(/) {
-		err("missing space between keyword and paren");
-	}
-	if (/(\b(catch|for|if|with|while|switch|return)\b.*){2,}/) {
-		# multiple "case" and "sizeof" allowed
-		err("more than one keyword on line");
-	}
-	if (/\b(delete|typeof|instanceOf|with|throw|catch|new|function|in|for|if|while|switch|return|case)\s\s+\(/ &&
-	    !/^#if\s+\(/) {
-		err("extra space between keyword and paren");
-	}
-	# try to detect "func (x)" but not "if (x)" or
-	# "#define foo (x)" or "int (*func)();"
-	if (/\w\s\(/) {
-		my $s = $_;
-		# strip off all keywords on the line
-		s/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\s\(/XXX(/g;
-		s/#elif\s\(/XXX(/g;
-		s/^#define\s+\w+\s+\(/XXX(/;
-		# do not match things like "void (*f)();"
-		# or "typedef void (func_t)();"
-		s/\w\s\(+\*/XXX(*/g;
-		s/\b(void)\s+\(+/XXX(/og;
-		if (/\w\s\(/) {
-			err("extra space between function name and left paren");
-		}
-		$_ = $s;
-	}
-
-	if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) {
-		err("unparenthesized return expression");
-	}
-	if (/\btypeof\b/ && !/\btypeof\s*\(.*\)/) {
-		err("unparenthesized typeof expression");
-	}
-	if (/\(\s/) {
-		err("whitespace after left paren");
-	}
-	# allow "for" statements to have empty "continue" clauses
-	if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
-		err("whitespace before right paren");
-	}
-	if (/^\s*\(void\)[^ ]/) {
-		err("missing space after (void) cast");
-	}
-	if (/\S{/ && !/({|\(){/) {
-		err("missing space before left brace");
-	}
-	if ($in_function && /^\s+{/ &&
-	    ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) {
-		err("left brace starting a line");
-	}
-	if (/}(else|while)/) {
-		err("missing space after right brace");
-	}
-	if (/}\s\s+(else|while)/) {
-		err("extra space after right brace");
-	}
-	if (/^\s+#/) {
-		err("preprocessor statement not in column 1");
-	}
-	if (/^#\s/) {
-		err("blank after preprocessor #");
-	}
-
-	#
-	# We completely ignore, for purposes of indentation:
-	#  * lines outside of functions
-	#  * preprocessor lines
-	#
-	if ($check_continuation && $in_function && !$in_cpp) {
-		process_indent($_);
-	}
-
-	if ($heuristic) {
-		# cannot check this everywhere due to "struct {\n...\n} foo;"
-		if ($in_function && !$in_declaration &&
-		    /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ &&
-		    !/} (else|while)/ && !/}}/) {
-			err("possible bad text following right brace");
-		}
-		# cannot check this because sub-blocks in
-		# the middle of code are ok
-		if ($in_function && /^\s+{/) {
-			err("possible left brace starting a line");
-		}
-	}
-	if (/^\s*else\W/) {
-		if ($prev =~ /^\s*}$/) {
-			err_prefix($prev,
-			    "else and right brace should be on same line");
-		}
-	}
-	$prev = $line;
-}
-
-if ($prev eq "") {
-	err("last line in file is blank");
-}
-
-}
-
-#
-# Continuation-line checking
-#
-# The rest of this file contains the code for the continuation checking
-# engine.  It's a pretty simple state machine which tracks the expression
-# depth (unmatched '('s and '['s).
-#
-# Keep in mind that the argument to process_indent() has already been heavily
-# processed; all comments have been replaced by control-A, and the contents of
-# strings and character constants have been elided.
-#
-
-my $cont_in;		# currently inside of a continuation
-my $cont_off;		# skipping an initializer or definition
-my $cont_noerr;		# suppress cascading errors
-my $cont_start;		# the line being continued
-my $cont_base;		# the base indentation
-my $cont_first;		# this is the first line of a statement
-my $cont_multiseg;	# this continuation has multiple segments
-
-my $cont_special;	# this is a C statement (if, for, etc.)
-my $cont_macro;		# this is a macro
-my $cont_case;		# this is a multi-line case
-
-my @cont_paren;		# the stack of unmatched ( and [s we've seen
-
-sub
-reset_indent()
-{
-	$cont_in = 0;
-	$cont_off = 0;
-}
-
-sub
-delabel($)
-{
-	#
-	# replace labels with tabs.  Note that there may be multiple
-	# labels on a line.
-	#
-	local $_ = $_[0];
-
-	while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) {
-		my ($pre_tabs, $label, $rest) = ($1, $2, $3);
-		$_ = $pre_tabs;
-		while ($label =~ s/^([^\t]*)(\t+)//) {
-			$_ .= "\t" x (length($2) + length($1) / 8);
-		}
-		$_ .= ("\t" x (length($label) / 8)).$rest;
-	}
-
-	return ($_);
-}
-
-sub
-process_indent($)
-{
-	require strict;
-	local $_ = $_[0];			# preserve the global $_
-
-	s///g;	# No comments
-	s/\s+$//;	# Strip trailing whitespace
-
-	return			if (/^$/);	# skip empty lines
-
-	# regexps used below; keywords taking (), macros, and continued cases
-	my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b';
-	my $macro = '[A-Z_][A-Z_0-9]*\(';
-	my $case = 'case\b[^:]*$';
-
-	# skip over enumerations, array definitions, initializers, etc.
-	if ($cont_off <= 0 && !/^\s*$special/ &&
-	    (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*)){/ ||
-	    (/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) {
-		$cont_in = 0;
-		$cont_off = tr/{/{/ - tr/}/}/;
-		return;
-	}
-	if ($cont_off) {
-		$cont_off += tr/{/{/ - tr/}/}/;
-		return;
-	}
-
-	if (!$cont_in) {
-		$cont_start = $line;
-
-		if (/^\t* /) {
-			err("non-continuation indented 4 spaces");
-			$cont_noerr = 1;		# stop reporting
-		}
-		$_ = delabel($_);	# replace labels with tabs
-
-		# check if the statement is complete
-		return		if (/^\s*\}?$/);
-		return		if (/^\s*\}?\s*else\s*\{?$/);
-		return		if (/^\s*do\s*\{?$/);
-		return		if (/{$/);
-		return		if (/}[,;]?$/);
-
-		# Allow macros on their own lines
-		return		if (/^\s*[A-Z_][A-Z_0-9]*$/);
-
-		# cases we don't deal with, generally non-kosher
-		if (/{/) {
-			err("stuff after {");
-			return;
-		}
-
-		# Get the base line, and set up the state machine
-		/^(\t*)/;
-		$cont_base = $1;
-		$cont_in = 1;
-		@cont_paren = ();
-		$cont_first = 1;
-		$cont_multiseg = 0;
-
-		# certain things need special processing
-		$cont_special = /^\s*$special/? 1 : 0;
-		$cont_macro = /^\s*$macro/? 1 : 0;
-		$cont_case = /^\s*$case/? 1 : 0;
-	} else {
-		$cont_first = 0;
-
-		# Strings may be pulled back to an earlier (half-)tabstop
-		unless ($cont_noerr || /^$cont_base    / ||
-		    (/^\t*(?:    )?(?:gettext\()?\"/ && !/^$cont_base\t/)) {
-			err_prefix($cont_start,
-			    "continuation should be indented 4 spaces");
-		}
-	}
-
-	my $rest = $_;			# keeps the remainder of the line
-
-	#
-	# The split matches 0 characters, so that each 'special' character
-	# is processed separately.  Parens and brackets are pushed and
-	# popped off the @cont_paren stack.  For normal processing, we wait
-	# until a ; or { terminates the statement.  "special" processing
-	# (if/for/while/switch) is allowed to stop when the stack empties,
-	# as is macro processing.  Case statements are terminated with a :
-	# and an empty paren stack.
-	#
-	foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) {
-		next		if (length($_) == 0);
-
-		# rest contains the remainder of the line
-		my $rxp = "[^\Q$_\E]*\Q$_\E";
-		$rest =~ s/^$rxp//;
-
-		if (/\(/ || /\[/) {
-			push @cont_paren, $_;
-		} elsif (/\)/ || /\]/) {
-			my $cur = $_;
-			tr/\)\]/\(\[/;
-
-			my $old = (pop @cont_paren);
-			if (!defined($old)) {
-				err("unexpected '$cur'");
-				$cont_in = 0;
-				last;
-			} elsif ($old ne $_) {
-				err("'$cur' mismatched with '$old'");
-				$cont_in = 0;
-				last;
-			}
-
-			#
-			# If the stack is now empty, do special processing
-			# for if/for/while/switch and macro statements.
-			#
-			next		if (@cont_paren != 0);
-			if ($cont_special) {
-				if ($rest =~ /^\s*{?$/) {
-					$cont_in = 0;
-					last;
-				}
-				if ($rest =~ /^\s*;$/) {
-					err("empty if/for/while body ".
-					    "not on its own line");
-					$cont_in = 0;
-					last;
-				}
-				if (!$cont_first && $cont_multiseg == 1) {
-					err_prefix($cont_start,
-					    "multiple statements continued ".
-					    "over multiple lines");
-					$cont_multiseg = 2;
-				} elsif ($cont_multiseg == 0) {
-					$cont_multiseg = 1;
-				}
-				# We've finished this section, start
-				# processing the next.
-				goto section_ended;
-			}
-			if ($cont_macro) {
-				if ($rest =~ /^$/) {
-					$cont_in = 0;
-					last;
-				}
-			}
-		} elsif (/\;/) {
-			if ($cont_case) {
-				err("unexpected ;");
-			} elsif (!$cont_special) {
-				err("unexpected ;")	if (@cont_paren != 0);
-				if (!$cont_first && $cont_multiseg == 1) {
-					err_prefix($cont_start,
-					    "multiple statements continued ".
-					    "over multiple lines");
-					$cont_multiseg = 2;
-				} elsif ($cont_multiseg == 0) {
-					$cont_multiseg = 1;
-				}
-				if ($rest =~ /^$/) {
-					$cont_in = 0;
-					last;
-				}
-				if ($rest =~ /^\s*special/) {
-					err("if/for/while/switch not started ".
-					    "on its own line");
-				}
-				goto section_ended;
-			}
-		} elsif (/\{/) {
-			err("{ while in parens/brackets") if (@cont_paren != 0);
-			err("stuff after {")		if ($rest =~ /[^\s}]/);
-			$cont_in = 0;
-			last;
-		} elsif (/\}/) {
-			err("} while in parens/brackets") if (@cont_paren != 0);
-			if (!$cont_special && $rest !~ /^\s*(while|else)\b/) {
-				if ($rest =~ /^$/) {
-					err("unexpected }");
-				} else {
-					err("stuff after }");
-				}
-				$cont_in = 0;
-				last;
-			}
-		} elsif (/\:/ && $cont_case && @cont_paren == 0) {
-			err("stuff after multi-line case") if ($rest !~ /$^/);
-			$cont_in = 0;
-			last;
-		}
-		next;
-section_ended:
-		# End of a statement or if/while/for loop.  Reset
-		# cont_special and cont_macro based on the rest of the
-		# line.
-		$cont_special = ($rest =~ /^\s*$special/)? 1 : 0;
-		$cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0;
-		$cont_case = 0;
-		next;
-	}
-	$cont_noerr = 0			if (!$cont_in);
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json
deleted file mode 100644
index 29d7bd89..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{ "metadata":
-	{
-		"ctf2json_version": "1.0",
-		"created_at": 1316563626,
-		"derived_from": "/lib/libc.so",
-		"ctf_version": 2,
-		"requested_types": [ "float" ]
-	},
-"data":
-	[
-		{ "name": "float", "float": { "length": 4 } }
-	]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json
deleted file mode 100644
index f9773a14..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{ "metadata":
-	{
-		"ctf2json_version": "1.0",
-		"created_at": 1316563631,
-		"derived_from": "/lib/libc.so",
-		"ctf_version": 2,
-		"requested_types": [ "int" ]
-	},
-"data":
-	[
-		{ "name": "int", "integer": { "length": 4, "signed": true } }
-	]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json
deleted file mode 100644
index e0ee5e0d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json
+++ /dev/null
@@ -1,104 +0,0 @@
-{ "metadata":
-	{
-		"ctf2json_version": "1.0",
-		"created_at": 1316563573,
-		"derived_from": "/lib/libc.so",
-		"ctf_version": 2,
-		"requested_types": [ "psinfo_t" ]
-	},
-"data":
-	[
-		{ "name": "int", "integer": { "length": 4, "signed": true } },
-		{ "name": "char", "integer": { "length": 1, "signed": true } },
-		{ "name": "unsigned short", "integer": { "length": 2, "signed": false } },
-		{ "name": "long", "integer": { "length": 4, "signed": true } },
-		{ "name": "unsigned", "integer": { "length": 4, "signed": false } },
-		{ "name": "size_t", "typedef": "unsigned" },
-		{ "name": "unsigned long", "integer": { "length": 4, "signed": false } },
-		{ "name": "time_t", "typedef": "long" },
-		{ "name": "struct timespec", "struct": [
-			{ "name": "tv_sec", "type": "time_t" },
-			{ "name": "tv_nsec", "type": "long" }
-		] },
-		{ "name": "zoneid_t", "typedef": "long" },
-		{ "name": "taskid_t", "typedef": "long" },
-		{ "name": "dev_t", "typedef": "unsigned long" },
-		{ "name": "uid_t", "typedef": "unsigned" },
-		{ "name": "gid_t", "typedef": "unsigned" },
-		{ "name": "timestruc_t", "typedef": "struct timespec" },
-		{ "name": "short", "integer": { "length": 2, "signed": true } },
-		{ "name": "projid_t", "typedef": "long" },
-		{ "name": "ushort_t", "typedef": "unsigned short" },
-		{ "name": "poolid_t", "typedef": "long" },
-		{ "name": "uintptr_t", "typedef": "unsigned" },
-		{ "name": "id_t", "typedef": "long" },
-		{ "name": "pid_t", "typedef": "long" },
-		{ "name": "processorid_t", "typedef": "int" },
-		{ "name": "psetid_t", "typedef": "int" },
-		{ "name": "struct lwpsinfo", "struct": [
-			{ "name": "pr_flag", "type": "int" },
-			{ "name": "pr_lwpid", "type": "id_t" },
-			{ "name": "pr_addr", "type": "uintptr_t" },
-			{ "name": "pr_wchan", "type": "uintptr_t" },
-			{ "name": "pr_stype", "type": "char" },
-			{ "name": "pr_state", "type": "char" },
-			{ "name": "pr_sname", "type": "char" },
-			{ "name": "pr_nice", "type": "char" },
-			{ "name": "pr_syscall", "type": "short" },
-			{ "name": "pr_oldpri", "type": "char" },
-			{ "name": "pr_cpu", "type": "char" },
-			{ "name": "pr_pri", "type": "int" },
-			{ "name": "pr_pctcpu", "type": "ushort_t" },
-			{ "name": "pr_pad", "type": "ushort_t" },
-			{ "name": "pr_start", "type": "timestruc_t" },
-			{ "name": "pr_time", "type": "timestruc_t" },
-			{ "name": "pr_clname", "type": "char [8]" },
-			{ "name": "pr_name", "type": "char [16]" },
-			{ "name": "pr_onpro", "type": "processorid_t" },
-			{ "name": "pr_bindpro", "type": "processorid_t" },
-			{ "name": "pr_bindpset", "type": "psetid_t" },
-			{ "name": "pr_lgrp", "type": "int" },
-			{ "name": "pr_filler", "type": "int [4]" }
-		] },
-		{ "name": "lwpsinfo_t", "typedef": "struct lwpsinfo" },
-		{ "name": "struct psinfo", "struct": [
-			{ "name": "pr_flag", "type": "int" },
-			{ "name": "pr_nlwp", "type": "int" },
-			{ "name": "pr_pid", "type": "pid_t" },
-			{ "name": "pr_ppid", "type": "pid_t" },
-			{ "name": "pr_pgid", "type": "pid_t" },
-			{ "name": "pr_sid", "type": "pid_t" },
-			{ "name": "pr_uid", "type": "uid_t" },
-			{ "name": "pr_euid", "type": "uid_t" },
-			{ "name": "pr_gid", "type": "gid_t" },
-			{ "name": "pr_egid", "type": "gid_t" },
-			{ "name": "pr_addr", "type": "uintptr_t" },
-			{ "name": "pr_size", "type": "size_t" },
-			{ "name": "pr_rssize", "type": "size_t" },
-			{ "name": "pr_pad1", "type": "size_t" },
-			{ "name": "pr_ttydev", "type": "dev_t" },
-			{ "name": "pr_pctcpu", "type": "ushort_t" },
-			{ "name": "pr_pctmem", "type": "ushort_t" },
-			{ "name": "pr_start", "type": "timestruc_t" },
-			{ "name": "pr_time", "type": "timestruc_t" },
-			{ "name": "pr_ctime", "type": "timestruc_t" },
-			{ "name": "pr_fname", "type": "char [16]" },
-			{ "name": "pr_psargs", "type": "char [80]" },
-			{ "name": "pr_wstat", "type": "int" },
-			{ "name": "pr_argc", "type": "int" },
-			{ "name": "pr_argv", "type": "uintptr_t" },
-			{ "name": "pr_envp", "type": "uintptr_t" },
-			{ "name": "pr_dmodel", "type": "char" },
-			{ "name": "pr_pad2", "type": "char [3]" },
-			{ "name": "pr_taskid", "type": "taskid_t" },
-			{ "name": "pr_projid", "type": "projid_t" },
-			{ "name": "pr_nzomb", "type": "int" },
-			{ "name": "pr_poolid", "type": "poolid_t" },
-			{ "name": "pr_zoneid", "type": "zoneid_t" },
-			{ "name": "pr_contract", "type": "id_t" },
-			{ "name": "pr_filler", "type": "int [1]" },
-			{ "name": "pr_lwp", "type": "lwpsinfo_t" }
-		] },
-		{ "name": "psinfo_t", "typedef": "struct psinfo" }
-	]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json
deleted file mode 100644
index e0542ff4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{ "metadata":
-	{
-		"ctf2json_version": "1.0",
-		"created_at": 1316563648,
-		"derived_from": "/lib/libc.so",
-		"ctf_version": 2,
-		"requested_types": [ "timestruc_t" ]
-	},
-"data":
-	[
-		{ "name": "long", "integer": { "length": 4, "signed": true } },
-		{ "name": "time_t", "typedef": "long" },
-		{ "name": "struct timespec", "struct": [
-			{ "name": "tv_sec", "type": "time_t" },
-			{ "name": "tv_nsec", "type": "long" }
-		] },
-		{ "name": "timestruc_t", "typedef": "struct timespec" }
-	]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js
deleted file mode 100644
index d6a52cbb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Test several conditions that should always cause us to throw.
- */
-var mod_assert = require('assert');
-var mod_ctype = require('../../ctype.js');
-
-var cases = [
-{ json: { }, msg: 'bad JSON - no metadata or data' },
-{ json: { metadata: {} }, msg: 'bad JSON - bad metadata section' },
-{ json: { metadata: { 'JSON version': [] } },
-    msg: 'bad JSON - bad JSON version' },
-{ json: { metadata: { 'JSON version': 2 } },
-    msg: 'bad JSON - bad JSON version' },
-{ json: { metadata: { 'JSON version': '100.20' } },
-    msg: 'bad JSON - bad JSON version' },
-{ json: { metadata: { 'JSON version': '1.0' } },
-    msg: 'missing data section' },
-{ json: { metadata: { 'JSON version': '1.0' }, data: 1 },
-    msg: 'invalid data section' },
-{ json: { metadata: { 'JSON version': '1.0' }, data: 1.1 },
-    msg: 'invalid data section' },
-{ json: { metadata: { 'JSON version': '1.0' }, data: '1.1' },
-    msg: 'invalid data section' },
-{ json: { metadata: { 'JSON version': '1.0' }, data: {} },
-    msg: 'invalid data section' }
-];
-
-function test()
-{
-	var ii;
-
-	for (ii = 0; ii < cases.length; ii++) {
-		mod_assert.throws(function () {
-		    mod_ctype.parseCTF(cases[ii].json);
-		}, Error, cases[ii].msg);
-	}
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js
deleted file mode 100644
index f2144994..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var mod_fs = require('fs');
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var data, parser;
-
-	data = JSON.parse(mod_fs.readFileSync('./float.json').toString());
-	parser = mod_ctype.parseCTF(data, { endian: 'big' });
-	mod_assert.deepEqual(parser.lstypes(), {});
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js
deleted file mode 100644
index 0ec0f769..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var mod_fs = require('fs');
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var data, parser;
-
-	data = JSON.parse(mod_fs.readFileSync('./int.json').toString());
-	parser = mod_ctype.parseCTF(data, { endian: 'big' });
-	mod_assert.deepEqual(parser.lstypes(), { 'int': 'int32_t' });
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js
deleted file mode 100644
index ca1a544c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js
+++ /dev/null
@@ -1,17 +0,0 @@
-var mod_fs = require('fs');
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-/*
- * This is too unwieldly to actually write out. Just make sure we can parse it
- * without errrors.
- */
-function test()
-{
-	var data;
-
-	data = JSON.parse(mod_fs.readFileSync('./psinfo.json').toString());
-	mod_ctype.parseCTF(data, { endian: 'big' });
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js
deleted file mode 100644
index c62f41f9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var mod_fs = require('fs');
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var data, parser;
-
-	data = JSON.parse(mod_fs.readFileSync('./struct.json').toString());
-	parser = mod_ctype.parseCTF(data, { endian: 'big' });
-	mod_assert.deepEqual(parser.lstypes(), { 'long': 'int32_t',
-	    'time_t': 'long',
-	    'timestruc_t': 'struct timespec',
-	    'struct timespec': [ { 'tv_sec': { 'type': 'time_t' } },
-	        { 'tv_nsec': { 'type': 'long' } } ] });
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js
deleted file mode 100644
index 9006cd1b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js
+++ /dev/null
@@ -1,15 +0,0 @@
-var mod_fs = require('fs');
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var data, parser;
-
-	data = JSON.parse(mod_fs.readFileSync('./typedef.json').toString());
-	parser = mod_ctype.parseCTF(data, { endian: 'big' });
-	mod_assert.deepEqual(parser.lstypes(), { 'bar_t': 'int',
-	    'int': 'int32_t' });
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json
deleted file mode 100644
index 35ddb50d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{ "metadata":
-	{
-		"ctf2json_version": "1.0",
-		"created_at": 1316302348,
-		"derived_from": "/lib/libc.so",
-		"ctf_version": 2,
-		"requested_types": [ "bar_t" ]
-	},
-"data":
-	[
-		{ "name": "int", "integer": { "length": 4, "signed": true } },
-		{ "name": "bar_t", "typedef": "int" }
-	]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js
deleted file mode 100644
index 2c9504a8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * Battery of tests to break our floating point implementation. Oh ho ho.
- *
- * There are a few useful ways to generate the expected output. The first is
- * just write a C program and write raw bytes out and inspect with xxd. Remember
- * to consider whether or not you're on a big endian or little endian machine.
- * Another useful site I found to help with some of this was:
- *
- * http://babbage.cs.qc.edu/IEEE-754/
- */
-
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-function testfloat()
-{
-	var buffer = new Buffer(4);
-	/* Start off with some of the easy ones: +zero */
-	buffer[0] = 0;
-	buffer[1] = 0;
-	buffer[2] = 0;
-	buffer[3] = 0;
-
-	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'big', 0));
-	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'little', 0));
-
-	/* Test -0 */
-	buffer[0] = 0x80;
-	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'big', 0));
-	buffer[3] = buffer[0];
-	buffer[0] = 0;
-	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'little', 0));
-
-	/* Catch +infin */
-	buffer[0] = 0x7f;
-	buffer[1] = 0x80;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	ASSERT.equal(Number.POSITIVE_INFINITY,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-	buffer[3] = 0x7f;
-	buffer[2] = 0x80;
-	buffer[1] = 0x00;
-	buffer[0] = 0x00;
-	ASSERT.equal(Number.POSITIVE_INFINITY,
-	    mod_ctype.rfloat(buffer, 'litle', 0));
-
-	/* Catch -infin */
-	buffer[0] = 0xff;
-	buffer[1] = 0x80;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	ASSERT.equal(Number.NEGATIVE_INFINITY,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-	buffer[3] = 0xff;
-	buffer[2] = 0x80;
-	buffer[1] = 0x00;
-	buffer[0] = 0x00;
-	ASSERT.equal(Number.NEGATIVE_INFINITY,
-	    mod_ctype.rfloat(buffer, 'litle', 0));
-
-	/* Catch NaN */
-
-	buffer[0] = 0x7f;
-	buffer[1] = 0x80;
-	buffer[2] = 0x00;
-	buffer[3] = 0x23;
-	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'big', 0)));
-	buffer[3] = 0x7f;
-	buffer[2] = 0x80;
-	buffer[1] = 0x00;
-	buffer[0] = 0x23;
-	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'little', 0)));
-
-	/* Catch -infin */
-	buffer[0] = 0xff;
-	buffer[1] = 0x80;
-	buffer[2] = 0x00;
-	buffer[3] = 0x23;
-	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'big', 0)));
-	buffer[3] = 0xff;
-	buffer[2] = 0x80;
-	buffer[1] = 0x00;
-	buffer[0] = 0x23;
-	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'little', 0)));
-
-	/* On to some basic tests */
-	/* 1.125 */
-	buffer[0] = 0x3f;
-	buffer[1] = 0x90;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	ASSERT.equal(1.125, mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x3f;
-	buffer[2] = 0x90;
-	buffer[1] = 0x00;
-	buffer[0] = 0x00;
-	ASSERT.equal(1.125, mod_ctype.rfloat(buffer, 'little', 0));
-
-	/* ff34a2b0 -2.4010576103645774e+38 */
-	buffer[0] = 0xff;
-	buffer[1] = 0x34;
-	buffer[2] = 0xa2;
-	buffer[3] = 0xb0;
-	ASSERT.equal(-2.4010576103645774e+38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0xff;
-	buffer[2] = 0x34;
-	buffer[1] = 0xa2;
-	buffer[0] = 0xb0;
-	ASSERT.equal(-2.4010576103645774e+38,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	/* Denormalized tests */
-
-	/* 0003f89a +/- 3.6468792534053364e-40 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x03;
-	buffer[2] = 0xf8;
-	buffer[3] = 0x9a;
-	ASSERT.equal(3.6468792534053364e-40,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x00;
-	buffer[2] = 0x03;
-	buffer[1] = 0xf8;
-	buffer[0] = 0x9a;
-	ASSERT.equal(3.6468792534053364e-40,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x03;
-	buffer[2] = 0xf8;
-	buffer[3] = 0x9a;
-	ASSERT.equal(-3.6468792534053364e-40,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x80;
-	buffer[2] = 0x03;
-	buffer[1] = 0xf8;
-	buffer[0] = 0x9a;
-	ASSERT.equal(-3.6468792534053364e-40,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-
-	/* Maximum and minimum normalized and denormalized values */
-
-	/* Largest normalized number +/- 3.4028234663852886e+38 */
-
-	buffer[0] = 0x7f;
-	buffer[1] = 0x7f;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	ASSERT.equal(3.4028234663852886e+38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x7f;
-	buffer[2] = 0x7f;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(3.4028234663852886e+38,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	buffer[0] = 0xff;
-	buffer[1] = 0x7f;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	ASSERT.equal(-3.4028234663852886e+38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0xff;
-	buffer[2] = 0x7f;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(-3.4028234663852886e+38,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	/* Smallest normalied number +/- 1.1754943508222875e-38 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x80;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	ASSERT.equal(1.1754943508222875e-38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x00;
-	buffer[2] = 0x80;
-	buffer[1] = 0x00;
-	buffer[0] = 0x00;
-	ASSERT.equal(1.1754943508222875e-38,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x80;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	ASSERT.equal(-1.1754943508222875e-38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x80;
-	buffer[2] = 0x80;
-	buffer[1] = 0x00;
-	buffer[0] = 0x00;
-	ASSERT.equal(-1.1754943508222875e-38,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-
-	/* Smallest denormalized number 1.401298464324817e-45 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x00;
-	buffer[2] = 0x00;
-	buffer[3] = 0x01;
-	ASSERT.equal(1.401298464324817e-45,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x00;
-	buffer[2] = 0x00;
-	buffer[1] = 0x00;
-	buffer[0] = 0x01;
-	ASSERT.equal(1.401298464324817e-45,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x00;
-	buffer[2] = 0x00;
-	buffer[3] = 0x01;
-	ASSERT.equal(-1.401298464324817e-45,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x80;
-	buffer[2] = 0x00;
-	buffer[1] = 0x00;
-	buffer[0] = 0x01;
-	ASSERT.equal(-1.401298464324817e-45,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	/* Largest denormalized value +/- 1.1754942106924411e-38 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x7f;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	ASSERT.equal(1.1754942106924411e-38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x00;
-	buffer[2] = 0x7f;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(1.1754942106924411e-38,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x7f;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	ASSERT.equal(-1.1754942106924411e-38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-
-	buffer[3] = 0x80;
-	buffer[2] = 0x7f;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(-1.1754942106924411e-38,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-
-	/* Do some quick offset testing */
-	buffer = new Buffer(6);
-	buffer[0] = 0x7f;
-	buffer[1] = 0x4e;
-	buffer[2] = 0x8a;
-	buffer[3] = 0x79;
-	buffer[4] = 0xcd;
-	buffer[5] = 0x3f;
-
-	ASSERT.equal(2.745399582697325e+38,
-	    mod_ctype.rfloat(buffer, 'big', 0));
-	ASSERT.equal(1161619072,
-	    mod_ctype.rfloat(buffer, 'big', 1));
-	ASSERT.equal(-1.2027516403607578e-32,
-	    mod_ctype.rfloat(buffer, 'big', 2));
-
-	ASSERT.equal(8.97661320504413e+34,
-	    mod_ctype.rfloat(buffer, 'little', 0));
-	ASSERT.equal(-261661920,
-	    mod_ctype.rfloat(buffer, 'little', 1));
-	ASSERT.equal(1.605271577835083,
-	    mod_ctype.rfloat(buffer, 'little', 2));
-
-}
-
-function testdouble()
-{
-	var buffer = new Buffer(10);
-
-	/* Check 0 */
-	buffer[0] = 0;
-	buffer[1] = 0;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 0;
-	ASSERT.equal(0,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-	ASSERT.equal(0,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 0;
-	ASSERT.equal(0,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-	buffer[7] = 0x80;
-	buffer[6] = 0;
-	buffer[5] = 0;
-	buffer[4] = 0;
-	buffer[3] = 0;
-	buffer[2] = 0;
-	buffer[1] = 0;
-	buffer[0] = 0;
-	ASSERT.equal(0,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Check NaN */
-	buffer[0] = 0x7f;
-	buffer[1] = 0xf0;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 23;
-	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'big', 0)));
-
-	buffer[7] = 0x7f;
-	buffer[6] = 0xf0;
-	buffer[5] = 0;
-	buffer[4] = 0;
-	buffer[3] = 0;
-	buffer[2] = 0;
-	buffer[1] = 0;
-	buffer[0] = 23;
-	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'little', 0)));
-
-	buffer[0] = 0xff;
-	buffer[1] = 0xf0;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 23;
-	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'big', 0)));
-
-	buffer[7] = 0xff;
-	buffer[6] = 0xf0;
-	buffer[5] = 0;
-	buffer[4] = 0;
-	buffer[3] = 0;
-	buffer[2] = 0;
-	buffer[1] = 0;
-	buffer[0] = 23;
-	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'little', 0)));
-
-	/* pos inf */
-	buffer[0] = 0x7f;
-	buffer[1] = 0xf0;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 0;
-	ASSERT.equal(Number.POSITIVE_INFINITY,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x7f;
-	buffer[6] = 0xf0;
-	buffer[5] = 0;
-	buffer[4] = 0;
-	buffer[3] = 0;
-	buffer[2] = 0;
-	buffer[1] = 0;
-	buffer[0] = 0;
-	ASSERT.equal(Number.POSITIVE_INFINITY,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* neg inf */
-	buffer[0] = 0xff;
-	buffer[1] = 0xf0;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 0;
-	ASSERT.equal(Number.NEGATIVE_INFINITY,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0xff;
-	buffer[6] = 0xf0;
-	buffer[5] = 0;
-	buffer[4] = 0;
-	buffer[3] = 0;
-	buffer[2] = 0;
-	buffer[1] = 0;
-	buffer[0] = 0;
-	ASSERT.equal(Number.NEGATIVE_INFINITY,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Simple normalized values */
-
-	/* +/- 1.125 */
-	buffer[0] = 0x3f;
-	buffer[1] = 0xf2;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 0;
-	ASSERT.equal(1.125,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x3f;
-	buffer[6] = 0xf2;
-	buffer[5] = 0;
-	buffer[4] = 0;
-	buffer[3] = 0;
-	buffer[2] = 0;
-	buffer[1] = 0;
-	buffer[0] = 0;
-	ASSERT.equal(1.125,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0xbf;
-	buffer[1] = 0xf2;
-	buffer[2] = 0;
-	buffer[3] = 0;
-	buffer[4] = 0;
-	buffer[5] = 0;
-	buffer[6] = 0;
-	buffer[7] = 0;
-	ASSERT.equal(-1.125,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0xbf;
-	buffer[6] = 0xf2;
-	buffer[5] = 0;
-	buffer[4] = 0;
-	buffer[3] = 0;
-	buffer[2] = 0;
-	buffer[1] = 0;
-	buffer[0] = 0;
-	ASSERT.equal(-1.125,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* +/- 1.4397318913736026e+283 */
-	buffer[0] = 0x7a;
-	buffer[1] = 0xb8;
-	buffer[2] = 0xc9;
-	buffer[3] = 0x34;
-	buffer[4] = 0x72;
-	buffer[5] = 0x16;
-	buffer[6] = 0xf9;
-	buffer[7] = 0x0e;
-	ASSERT.equal(1.4397318913736026e+283,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x7a;
-	buffer[6] = 0xb8;
-	buffer[5] = 0xc9;
-	buffer[4] = 0x34;
-	buffer[3] = 0x72;
-	buffer[2] = 0x16;
-	buffer[1] = 0xf9;
-	buffer[0] = 0x0e;
-	ASSERT.equal(1.4397318913736026e+283,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0xfa;
-	buffer[1] = 0xb8;
-	buffer[2] = 0xc9;
-	buffer[3] = 0x34;
-	buffer[4] = 0x72;
-	buffer[5] = 0x16;
-	buffer[6] = 0xf9;
-	buffer[7] = 0x0e;
-	ASSERT.equal(-1.4397318913736026e+283,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0xfa;
-	buffer[6] = 0xb8;
-	buffer[5] = 0xc9;
-	buffer[4] = 0x34;
-	buffer[3] = 0x72;
-	buffer[2] = 0x16;
-	buffer[1] = 0xf9;
-	buffer[0] = 0x0e;
-	ASSERT.equal(-1.4397318913736026e+283,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Denormalized values */
-	/* +/- 8.82521232268344e-309 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x06;
-	buffer[2] = 0x58;
-	buffer[3] = 0x94;
-	buffer[4] = 0x13;
-	buffer[5] = 0x27;
-	buffer[6] = 0x8a;
-	buffer[7] = 0xcd;
-	ASSERT.equal(8.82521232268344e-309,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x00;
-	buffer[6] = 0x06;
-	buffer[5] = 0x58;
-	buffer[4] = 0x94;
-	buffer[3] = 0x13;
-	buffer[2] = 0x27;
-	buffer[1] = 0x8a;
-	buffer[0] = 0xcd;
-	ASSERT.equal(8.82521232268344e-309,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x06;
-	buffer[2] = 0x58;
-	buffer[3] = 0x94;
-	buffer[4] = 0x13;
-	buffer[5] = 0x27;
-	buffer[6] = 0x8a;
-	buffer[7] = 0xcd;
-	ASSERT.equal(-8.82521232268344e-309,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x80;
-	buffer[6] = 0x06;
-	buffer[5] = 0x58;
-	buffer[4] = 0x94;
-	buffer[3] = 0x13;
-	buffer[2] = 0x27;
-	buffer[1] = 0x8a;
-	buffer[0] = 0xcd;
-	ASSERT.equal(-8.82521232268344e-309,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Edge cases, maximum and minimum values */
-
-	/* Smallest denormalized value 5e-324 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x00;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	buffer[4] = 0x00;
-	buffer[5] = 0x00;
-	buffer[6] = 0x00;
-	buffer[7] = 0x01;
-	ASSERT.equal(5e-324,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x00;
-	buffer[6] = 0x00;
-	buffer[5] = 0x00;
-	buffer[4] = 0x00;
-	buffer[3] = 0x00;
-	buffer[2] = 0x00;
-	buffer[1] = 0x00;
-	buffer[0] = 0x01;
-	ASSERT.equal(5e-324,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x00;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	buffer[4] = 0x00;
-	buffer[5] = 0x00;
-	buffer[6] = 0x00;
-	buffer[7] = 0x01;
-	ASSERT.equal(-5e-324,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x80;
-	buffer[6] = 0x00;
-	buffer[5] = 0x00;
-	buffer[4] = 0x00;
-	buffer[3] = 0x00;
-	buffer[2] = 0x00;
-	buffer[1] = 0x00;
-	buffer[0] = 0x01;
-	ASSERT.equal(-5e-324,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Largest denormalized value 2.225073858507201e-308 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x0f;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	buffer[4] = 0xff;
-	buffer[5] = 0xff;
-	buffer[6] = 0xff;
-	buffer[7] = 0xff;
-	ASSERT.equal(2.225073858507201e-308,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x00;
-	buffer[6] = 0x0f;
-	buffer[5] = 0xff;
-	buffer[4] = 0xff;
-	buffer[3] = 0xff;
-	buffer[2] = 0xff;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(2.225073858507201e-308,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x0f;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	buffer[4] = 0xff;
-	buffer[5] = 0xff;
-	buffer[6] = 0xff;
-	buffer[7] = 0xff;
-	ASSERT.equal(-2.225073858507201e-308,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x80;
-	buffer[6] = 0x0f;
-	buffer[5] = 0xff;
-	buffer[4] = 0xff;
-	buffer[3] = 0xff;
-	buffer[2] = 0xff;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(-2.225073858507201e-308,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Smallest normalized value 2.2250738585072014e-308 */
-	buffer[0] = 0x00;
-	buffer[1] = 0x10;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	buffer[4] = 0x00;
-	buffer[5] = 0x00;
-	buffer[6] = 0x00;
-	buffer[7] = 0x00;
-	ASSERT.equal(2.2250738585072014e-308,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x00;
-	buffer[6] = 0x10;
-	buffer[5] = 0x00;
-	buffer[4] = 0x00;
-	buffer[3] = 0x00;
-	buffer[2] = 0x00;
-	buffer[1] = 0x00;
-	buffer[0] = 0x00;
-	ASSERT.equal(2.2250738585072014e-308,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0x80;
-	buffer[1] = 0x10;
-	buffer[2] = 0x00;
-	buffer[3] = 0x00;
-	buffer[4] = 0x00;
-	buffer[5] = 0x00;
-	buffer[6] = 0x00;
-	buffer[7] = 0x00;
-	ASSERT.equal(-2.2250738585072014e-308,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x80;
-	buffer[6] = 0x10;
-	buffer[5] = 0x00;
-	buffer[4] = 0x00;
-	buffer[3] = 0x00;
-	buffer[2] = 0x00;
-	buffer[1] = 0x00;
-	buffer[0] = 0x00;
-	ASSERT.equal(-2.2250738585072014e-308,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Largest normalized value 1.7976931348623157e+308 */
-	buffer[0] = 0x7f;
-	buffer[1] = 0xef;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	buffer[4] = 0xff;
-	buffer[5] = 0xff;
-	buffer[6] = 0xff;
-	buffer[7] = 0xff;
-	ASSERT.equal(1.7976931348623157e+308,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0x7f;
-	buffer[6] = 0xef;
-	buffer[5] = 0xff;
-	buffer[4] = 0xff;
-	buffer[3] = 0xff;
-	buffer[2] = 0xff;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(1.7976931348623157e+308,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	buffer[0] = 0xff;
-	buffer[1] = 0xef;
-	buffer[2] = 0xff;
-	buffer[3] = 0xff;
-	buffer[4] = 0xff;
-	buffer[5] = 0xff;
-	buffer[6] = 0xff;
-	buffer[7] = 0xff;
-	ASSERT.equal(-1.7976931348623157e+308,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-
-	buffer[7] = 0xff;
-	buffer[6] = 0xef;
-	buffer[5] = 0xff;
-	buffer[4] = 0xff;
-	buffer[3] = 0xff;
-	buffer[2] = 0xff;
-	buffer[1] = 0xff;
-	buffer[0] = 0xff;
-	ASSERT.equal(-1.7976931348623157e+308,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-
-	/* Try offsets */
-	buffer[0] = 0xde;
-	buffer[1] = 0xad;
-	buffer[2] = 0xbe;
-	buffer[3] = 0xef;
-	buffer[4] = 0xba;
-	buffer[5] = 0xdd;
-	buffer[6] = 0xca;
-	buffer[7] = 0xfe;
-	buffer[8] = 0x16;
-	buffer[9] = 0x79;
-
-	ASSERT.equal(-1.1885958404126936e+148,
-	    mod_ctype.rdouble(buffer, 'big', 0));
-	ASSERT.equal(-2.4299184080448593e-88,
-	    mod_ctype.rdouble(buffer, 'big', 1));
-	ASSERT.equal(-0.000015130017658081283,
-	    mod_ctype.rdouble(buffer, 'big', 2));
-
-	ASSERT.equal(-5.757458694845505e+302,
-	    mod_ctype.rdouble(buffer, 'little', 0));
-	ASSERT.equal(6.436459604192476e-198,
-	    mod_ctype.rdouble(buffer, 'little', 1));
-	ASSERT.equal(1.9903745632417286e+275,
-	    mod_ctype.rdouble(buffer, 'little', 2));
-}
-
-testfloat();
-testdouble();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js
deleted file mode 100644
index b5fd95cd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Another place to find bugs that may yet plague us. This time with writing out
- * floats to arrays. We are lazy and did basically just take the opposite of our
- * test code to read in values.
- */
-
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-
-/*
- *	A useful thing to keep around for debugging
- *	console.log('buffer[0]: ' + buffer[0].toString(16));
- *	console.log('buffer[1]: ' + buffer[1].toString(16));
- *	console.log('buffer[2]: ' + buffer[2].toString(16));
- *	console.log('buffer[3]: ' + buffer[3].toString(16));
- *	console.log('buffer[4]: ' + buffer[4].toString(16));
- *	console.log('buffer[5]: ' + buffer[5].toString(16));
- * 	console.log('buffer[6]: ' + buffer[6].toString(16));
- *	console.log('buffer[7]: ' + buffer[7].toString(16));
- */
-
-function testfloat()
-{
-	var buffer = new Buffer(4);
-	mod_ctype.wfloat(0, 'big', buffer, 0);
-	/* Start off with some of the easy ones: +zero */
-	ASSERT.equal(0, buffer[0]);
-	ASSERT.equal(0, buffer[1]);
-	ASSERT.equal(0, buffer[2]);
-	ASSERT.equal(0, buffer[3]);
-	mod_ctype.wfloat(0, 'little', buffer, 0);
-	ASSERT.equal(0, buffer[0]);
-	ASSERT.equal(0, buffer[1]);
-	ASSERT.equal(0, buffer[2]);
-	ASSERT.equal(0, buffer[3]);
-
-	/* Catch +infin */
-	mod_ctype.wfloat(Number.POSITIVE_INFINITY, 'big', buffer, 0);
-	ASSERT.equal(0x7f, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	mod_ctype.wfloat(Number.POSITIVE_INFINITY, 'little', buffer, 0);
-	ASSERT.equal(0x7f, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	/* Catch -infin */
-	mod_ctype.wfloat(Number.NEGATIVE_INFINITY, 'big', buffer, 0);
-	ASSERT.equal(0xff, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	mod_ctype.wfloat(Number.NEGATIVE_INFINITY, 'little', buffer, 0);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	/* Catch NaN */
-
-	/*
-	 * NaN Is a litle weird in its requirements, so we're going to encode a
-	 * bit of how we actually implement it into this test. Probably not the
-	 * best, since technically the sign is a don't care and the mantissa
-	 * needs to just be non-zero.
-	 */
-	mod_ctype.wfloat(NaN, 'big', buffer, 0);
-	ASSERT.equal(0x7f, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x17, buffer[3]);
-	mod_ctype.wfloat(NaN, 'little', buffer, 0);
-	ASSERT.equal(0x7f, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x17, buffer[0]);
-
-	/* On to some basic tests */
-	/* 1.125 */
-	mod_ctype.wfloat(1.125, 'big', buffer, 0);
-	ASSERT.equal(0x3f, buffer[0]);
-	ASSERT.equal(0x90, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	mod_ctype.wfloat(1.125, 'little', buffer, 0);
-	ASSERT.equal(0x3f, buffer[3]);
-	ASSERT.equal(0x90, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	mod_ctype.wfloat(1.0000001192092896, 'big', buffer, 0);
-	ASSERT.equal(0x3f, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x01, buffer[3]);
-	mod_ctype.wfloat(1.0000001192092896, 'little', buffer, 0);
-	ASSERT.equal(0x3f, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x01, buffer[0]);
-
-	mod_ctype.wfloat(1.0000001192092896, 'big', buffer, 0);
-	ASSERT.equal(0x3f, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x01, buffer[3]);
-	mod_ctype.wfloat(1.0000001192092896, 'little', buffer, 0);
-	ASSERT.equal(0x3f, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x01, buffer[0]);
-
-	mod_ctype.wfloat(2.3283067140944524e-10, 'big', buffer, 0);
-	ASSERT.equal(0x2f, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x01, buffer[3]);
-	mod_ctype.wfloat(2.3283067140944524e-10, 'little', buffer, 0);
-	ASSERT.equal(0x2f, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x01, buffer[0]);
-
-	/* ff34a2b0 -2.4010576103645774e+38 */
-	mod_ctype.wfloat(-2.4010576103645774e+38,
-	    'big', buffer, 0);
-	ASSERT.equal(0xff, buffer[0]);
-	ASSERT.equal(0x34, buffer[1]);
-	ASSERT.equal(0xa2, buffer[2]);
-	ASSERT.equal(0xb0, buffer[3]);
-	mod_ctype.wfloat(-2.4010576103645774e+38,
-	    'little', buffer, 0);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0x34, buffer[2]);
-	ASSERT.equal(0xa2, buffer[1]);
-	ASSERT.equal(0xb0, buffer[0]);
-
-	/* Denormalized tests */
-
-	/* 0003f89a +/- 3.6468792534053364e-40 */
-	mod_ctype.wfloat(3.6468792534053364e-40,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x03, buffer[1]);
-	ASSERT.equal(0xf8, buffer[2]);
-	ASSERT.equal(0x9a, buffer[3]);
-	mod_ctype.wfloat(3.6468792534053364e-40,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x03, buffer[2]);
-	ASSERT.equal(0xf8, buffer[1]);
-	ASSERT.equal(0x9a, buffer[0]);
-
-	mod_ctype.wfloat(-3.6468792534053364e-40,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x03, buffer[1]);
-	ASSERT.equal(0xf8, buffer[2]);
-	ASSERT.equal(0x9a, buffer[3]);
-	mod_ctype.wfloat(-3.6468792534053364e-40,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[3]);
-	ASSERT.equal(0x03, buffer[2]);
-	ASSERT.equal(0xf8, buffer[1]);
-	ASSERT.equal(0x9a, buffer[0]);
-
-	/* Maximum and minimum normalized and denormalized values */
-
-	/* Largest normalized number +/- 3.4028234663852886e+38 */
-
-	mod_ctype.wfloat(3.4028234663852886e+38,
-	    'big', buffer, 0);
-	ASSERT.equal(0x7f, buffer[0]);
-	ASSERT.equal(0x7f, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	mod_ctype.wfloat(3.4028234663852886e+38,
-	    'little', buffer, 0);
-	ASSERT.equal(0x7f, buffer[3]);
-	ASSERT.equal(0x7f, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-	mod_ctype.wfloat(-3.4028234663852886e+38,
-	    'big', buffer, 0);
-	ASSERT.equal(0xff, buffer[0]);
-	ASSERT.equal(0x7f, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	mod_ctype.wfloat(-3.4028234663852886e+38,
-	    'little', buffer, 0);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0x7f, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-	/* Smallest normalied number +/- 1.1754943508222875e-38 */
-
-	mod_ctype.wfloat(1.1754943508222875e-38,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	mod_ctype.wfloat(1.1754943508222875e-38,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	mod_ctype.wfloat(-1.1754943508222875e-38,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x80, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	mod_ctype.wfloat(-1.1754943508222875e-38,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[3]);
-	ASSERT.equal(0x80, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	/* Smallest denormalized number 1.401298464324817e-45 */
-	mod_ctype.wfloat(1.401298464324817e-45,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x01, buffer[3]);
-	mod_ctype.wfloat(1.401298464324817e-45,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x01, buffer[0]);
-
-	mod_ctype.wfloat(-1.401298464324817e-45,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x01, buffer[3]);
-	mod_ctype.wfloat(-1.401298464324817e-45,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x01, buffer[0]);
-
-	/* Largest denormalized value +/- 1.1754942106924411e-38 */
-
-	mod_ctype.wfloat(1.1754942106924411e-38,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x7f, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	mod_ctype.wfloat(1.1754942106924411e-38,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x7f, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-	mod_ctype.wfloat(-1.1754942106924411e-38,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x7f, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	mod_ctype.wfloat(-1.1754942106924411e-38,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[3]);
-	ASSERT.equal(0x7f, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-	/* Do some quick offset testing */
-	buffer = new Buffer(6);
-	mod_ctype.wfloat(-1.2027516403607578e-32,
-	    'big', buffer, 2);
-	ASSERT.equal(0x8a, buffer[2]);
-	ASSERT.equal(0x79, buffer[3]);
-	ASSERT.equal(0xcd, buffer[4]);
-	ASSERT.equal(0x3f, buffer[5]);
-
-	mod_ctype.wfloat(-1.2027516403607578e-32,
-	    'little', buffer, 2);
-	ASSERT.equal(0x8a, buffer[5]);
-	ASSERT.equal(0x79, buffer[4]);
-	ASSERT.equal(0xcd, buffer[3]);
-	ASSERT.equal(0x3f, buffer[2]);
-
-}
-
-function testdouble()
-{
-	var buffer = new Buffer(10);
-
-	/* Check 0 */
-	mod_ctype.wdouble(0, 'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-	mod_ctype.wdouble(0, 'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[7]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	/* Check NaN */
-	/* Similar to floats we are only generating a subset of values */
-	mod_ctype.wdouble(NaN, 'big', buffer, 0);
-	ASSERT.equal(0x7f, buffer[0]);
-	ASSERT.equal(0xf0, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x17, buffer[7]);
-	mod_ctype.wdouble(NaN, 'little', buffer, 0);
-	ASSERT.equal(0x7f, buffer[7]);
-	ASSERT.equal(0xf0, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x17, buffer[0]);
-
-	/* pos inf */
-	mod_ctype.wdouble(Number.POSITIVE_INFINITY,
-	    'big', buffer, 0);
-	ASSERT.equal(0x7f, buffer[0]);
-	ASSERT.equal(0xf0, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-	mod_ctype.wdouble(Number.POSITIVE_INFINITY,
-	    'little', buffer, 0);
-	ASSERT.equal(0x7f, buffer[7]);
-	ASSERT.equal(0xf0, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	/* neg inf */
-	mod_ctype.wdouble(Number.NEGATIVE_INFINITY,
-	    'big', buffer, 0);
-	ASSERT.equal(0xff, buffer[0]);
-	ASSERT.equal(0xf0, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-	mod_ctype.wdouble(Number.NEGATIVE_INFINITY,
-	    'little', buffer, 0);
-	ASSERT.equal(0xff, buffer[7]);
-	ASSERT.equal(0xf0, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	/* Simple normalized values */
-
-	/* +/- 1.125 */
-	mod_ctype.wdouble(1.125,
-	    'big', buffer, 0);
-	ASSERT.equal(0x3f, buffer[0]);
-	ASSERT.equal(0xf2, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-
-	mod_ctype.wdouble(1.125,
-	    'little', buffer, 0);
-	ASSERT.equal(0x3f, buffer[7]);
-	ASSERT.equal(0xf2, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	mod_ctype.wdouble(-1.125,
-	    'big', buffer, 0);
-	ASSERT.equal(0xbf, buffer[0]);
-	ASSERT.equal(0xf2, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-
-	mod_ctype.wdouble(-1.125,
-	    'little', buffer, 0);
-	ASSERT.equal(0xbf, buffer[7]);
-	ASSERT.equal(0xf2, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-
-	/* +/- 1.4397318913736026e+283 */
-	mod_ctype.wdouble(1.4397318913736026e+283,
-	    'big', buffer, 0);
-	ASSERT.equal(0x7a, buffer[0]);
-	ASSERT.equal(0xb8, buffer[1]);
-	ASSERT.equal(0xc9, buffer[2]);
-	ASSERT.equal(0x34, buffer[3]);
-	ASSERT.equal(0x72, buffer[4]);
-	ASSERT.equal(0x16, buffer[5]);
-	ASSERT.equal(0xf9, buffer[6]);
-	ASSERT.equal(0x0e, buffer[7]);
-
-	mod_ctype.wdouble(1.4397318913736026e+283,
-	    'little', buffer, 0);
-	ASSERT.equal(0x7a, buffer[7]);
-	ASSERT.equal(0xb8, buffer[6]);
-	ASSERT.equal(0xc9, buffer[5]);
-	ASSERT.equal(0x34, buffer[4]);
-	ASSERT.equal(0x72, buffer[3]);
-	ASSERT.equal(0x16, buffer[2]);
-	ASSERT.equal(0xf9, buffer[1]);
-	ASSERT.equal(0x0e, buffer[0]);
-
-	mod_ctype.wdouble(-1.4397318913736026e+283,
-	    'big', buffer, 0);
-	ASSERT.equal(0xfa, buffer[0]);
-	ASSERT.equal(0xb8, buffer[1]);
-	ASSERT.equal(0xc9, buffer[2]);
-	ASSERT.equal(0x34, buffer[3]);
-	ASSERT.equal(0x72, buffer[4]);
-	ASSERT.equal(0x16, buffer[5]);
-	ASSERT.equal(0xf9, buffer[6]);
-	ASSERT.equal(0x0e, buffer[7]);
-
-	mod_ctype.wdouble(-1.4397318913736026e+283,
-	    'little', buffer, 0);
-	ASSERT.equal(0xfa, buffer[7]);
-	ASSERT.equal(0xb8, buffer[6]);
-	ASSERT.equal(0xc9, buffer[5]);
-	ASSERT.equal(0x34, buffer[4]);
-	ASSERT.equal(0x72, buffer[3]);
-	ASSERT.equal(0x16, buffer[2]);
-	ASSERT.equal(0xf9, buffer[1]);
-	ASSERT.equal(0x0e, buffer[0]);
-
-	/* Denormalized values */
-	/* +/- 8.82521232268344e-309 */
-	mod_ctype.wdouble(8.82521232268344e-309,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x06, buffer[1]);
-	ASSERT.equal(0x58, buffer[2]);
-	ASSERT.equal(0x94, buffer[3]);
-	ASSERT.equal(0x13, buffer[4]);
-	ASSERT.equal(0x27, buffer[5]);
-	ASSERT.equal(0x8a, buffer[6]);
-	ASSERT.equal(0xcd, buffer[7]);
-
-	mod_ctype.wdouble(8.82521232268344e-309,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[7]);
-	ASSERT.equal(0x06, buffer[6]);
-	ASSERT.equal(0x58, buffer[5]);
-	ASSERT.equal(0x94, buffer[4]);
-	ASSERT.equal(0x13, buffer[3]);
-	ASSERT.equal(0x27, buffer[2]);
-	ASSERT.equal(0x8a, buffer[1]);
-	ASSERT.equal(0xcd, buffer[0]);
-
-	mod_ctype.wdouble(-8.82521232268344e-309,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x06, buffer[1]);
-	ASSERT.equal(0x58, buffer[2]);
-	ASSERT.equal(0x94, buffer[3]);
-	ASSERT.equal(0x13, buffer[4]);
-	ASSERT.equal(0x27, buffer[5]);
-	ASSERT.equal(0x8a, buffer[6]);
-	ASSERT.equal(0xcd, buffer[7]);
-
-	mod_ctype.wdouble(-8.82521232268344e-309,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[7]);
-	ASSERT.equal(0x06, buffer[6]);
-	ASSERT.equal(0x58, buffer[5]);
-	ASSERT.equal(0x94, buffer[4]);
-	ASSERT.equal(0x13, buffer[3]);
-	ASSERT.equal(0x27, buffer[2]);
-	ASSERT.equal(0x8a, buffer[1]);
-	ASSERT.equal(0xcd, buffer[0]);
-
-
-	/* Edge cases, maximum and minimum values */
-
-	/* Smallest denormalized value 5e-324 */
-	mod_ctype.wdouble(5e-324,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x01, buffer[7]);
-
-	mod_ctype.wdouble(5e-324,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[7]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x01, buffer[0]);
-
-	mod_ctype.wdouble(-5e-324,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x01, buffer[7]);
-
-	mod_ctype.wdouble(-5e-324,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[7]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x01, buffer[0]);
-
-
-
-	/* Largest denormalized value 2.225073858507201e-308 */
-	mod_ctype.wdouble(2.225073858507201e-308,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x0f, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[6]);
-	ASSERT.equal(0xff, buffer[7]);
-
-	mod_ctype.wdouble(2.225073858507201e-308,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[7]);
-	ASSERT.equal(0x0f, buffer[6]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-	mod_ctype.wdouble(-2.225073858507201e-308,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x0f, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[6]);
-	ASSERT.equal(0xff, buffer[7]);
-
-	mod_ctype.wdouble(-2.225073858507201e-308,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[7]);
-	ASSERT.equal(0x0f, buffer[6]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-
-	/* Smallest normalized value 2.2250738585072014e-308 */
-	mod_ctype.wdouble(2.2250738585072014e-308,
-	    'big', buffer, 0);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x10, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-
-	mod_ctype.wdouble(2.2250738585072014e-308,
-	    'little', buffer, 0);
-	ASSERT.equal(0x00, buffer[7]);
-	ASSERT.equal(0x10, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-	mod_ctype.wdouble(-2.2250738585072014e-308,
-	    'big', buffer, 0);
-	ASSERT.equal(0x80, buffer[0]);
-	ASSERT.equal(0x10, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-
-	mod_ctype.wdouble(-2.2250738585072014e-308,
-	    'little', buffer, 0);
-	ASSERT.equal(0x80, buffer[7]);
-	ASSERT.equal(0x10, buffer[6]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[4]);
-	ASSERT.equal(0x00, buffer[3]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[0]);
-
-
-	/* Largest normalized value 1.7976931348623157e+308 */
-	mod_ctype.wdouble(1.7976931348623157e+308,
-	    'big', buffer, 0);
-	ASSERT.equal(0x7f, buffer[0]);
-	ASSERT.equal(0xef, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[6]);
-	ASSERT.equal(0xff, buffer[7]);
-
-	mod_ctype.wdouble(1.7976931348623157e+308,
-	    'little', buffer, 0);
-	ASSERT.equal(0x7f, buffer[7]);
-	ASSERT.equal(0xef, buffer[6]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-	mod_ctype.wdouble(-1.7976931348623157e+308,
-	    'big', buffer, 0);
-	ASSERT.equal(0xff, buffer[0]);
-	ASSERT.equal(0xef, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[6]);
-	ASSERT.equal(0xff, buffer[7]);
-
-	mod_ctype.wdouble(-1.7976931348623157e+308,
-	    'little', buffer, 0);
-	ASSERT.equal(0xff, buffer[7]);
-	ASSERT.equal(0xef, buffer[6]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[4]);
-	ASSERT.equal(0xff, buffer[3]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[0]);
-
-
-	/* Try offsets */
-	buffer[0] = 0xde;
-	buffer[1] = 0xad;
-	buffer[2] = 0xbe;
-	buffer[3] = 0xef;
-	buffer[4] = 0xba;
-	buffer[5] = 0xdd;
-	buffer[6] = 0xca;
-	buffer[7] = 0xfe;
-	buffer[8] = 0x16;
-	buffer[9] = 0x79;
-
-	mod_ctype.wdouble(-0.000015130017658081283,
-	    'big', buffer, 2);
-	ASSERT.equal(0xbe, buffer[2]);
-	ASSERT.equal(0xef, buffer[3]);
-	ASSERT.equal(0xba, buffer[4]);
-	ASSERT.equal(0xdd, buffer[5]);
-	ASSERT.equal(0xca, buffer[6]);
-	ASSERT.equal(0xfe, buffer[7]);
-	ASSERT.equal(0x16, buffer[8]);
-	ASSERT.equal(0x79, buffer[9]);
-
-	mod_ctype.wdouble(-0.000015130017658081283,
-	    'little', buffer, 2);
-	ASSERT.equal(0xbe, buffer[9]);
-	ASSERT.equal(0xef, buffer[8]);
-	ASSERT.equal(0xba, buffer[7]);
-	ASSERT.equal(0xdd, buffer[6]);
-	ASSERT.equal(0xca, buffer[5]);
-	ASSERT.equal(0xfe, buffer[4]);
-	ASSERT.equal(0x16, buffer[3]);
-	ASSERT.equal(0x79, buffer[2]);
-}
-
-testfloat();
-testdouble();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js
deleted file mode 100644
index 1ffdac09..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * Test our ability to read and write signed 64-bit integers.
- */
-
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-function testRead()
-{
-	var res, data;
-	data = new Buffer(10);
-
-	data[0] = 0x32;
-	data[1] = 0x65;
-	data[2] = 0x42;
-	data[3] = 0x56;
-	data[4] = 0x23;
-	data[5] = 0xff;
-	data[6] = 0xff;
-	data[7] = 0xff;
-	data[8] = 0x89;
-	data[9] = 0x11;
-	res = mod_ctype.rsint64(data, 'big', 0);
-	ASSERT.equal(0x32654256, res[0]);
-	ASSERT.equal(0x23ffffff, res[1]);
-	res = mod_ctype.rsint64(data, 'big', 1);
-	ASSERT.equal(0x65425623, res[0]);
-	ASSERT.equal(0xffffff89, res[1]);
-	res = mod_ctype.rsint64(data, 'big', 2);
-	ASSERT.equal(0x425623ff, res[0]);
-	ASSERT.equal(0xffff8911, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 0);
-	ASSERT.equal(-0x000000dc, res[0]);
-	ASSERT.equal(-0xa9bd9ace, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 1);
-	ASSERT.equal(-0x76000000, res[0]);
-	ASSERT.equal(-0xdca9bd9b, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 2);
-	ASSERT.equal(0x1189ffff, res[0]);
-	ASSERT.equal(0xff235642, res[1]);
-
-	data.fill(0x00);
-	res = mod_ctype.rsint64(data, 'big', 0);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(0x00000000, res[1]);
-	res = mod_ctype.rsint64(data, 'big', 1);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(0x00000000, res[1]);
-	res = mod_ctype.rsint64(data, 'big', 2);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(0x00000000, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 0);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(0x00000000, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 1);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(0x00000000, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 2);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(0x00000000, res[1]);
-
-	data.fill(0xff);
-	res = mod_ctype.rsint64(data, 'big', 0);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(-1, res[1]);
-	res = mod_ctype.rsint64(data, 'big', 1);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(-1, res[1]);
-	res = mod_ctype.rsint64(data, 'big', 2);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(-1, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 0);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(-1, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 1);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(-1, res[1]);
-	res = mod_ctype.rsint64(data, 'little', 2);
-	ASSERT.equal(0x00000000, res[0]);
-	ASSERT.equal(-1, res[1]);
-
-	data[0] = 0x80;
-	data[1] = 0x00;
-	data[2] = 0x00;
-	data[3] = 0x00;
-	data[4] = 0x00;
-	data[5] = 0x00;
-	data[6] = 0x00;
-	data[7] = 0x00;
-	res = mod_ctype.rsint64(data, 'big', 0);
-	ASSERT.equal(-0x80000000, res[0]);
-	ASSERT.equal(0, res[1]);
-
-
-	data[7] = 0x80;
-	data[6] = 0x00;
-	data[5] = 0x00;
-	data[4] = 0x00;
-	data[3] = 0x00;
-	data[2] = 0x00;
-	data[1] = 0x00;
-	data[0] = 0x00;
-	res = mod_ctype.rsint64(data, 'little', 0);
-	ASSERT.equal(-0x80000000, res[0]);
-	ASSERT.equal(0, res[1]);
-
-	data[0] = 0x80;
-	data[1] = 0x00;
-	data[2] = 0x00;
-	data[3] = 0x00;
-	data[4] = 0x00;
-	data[5] = 0x00;
-	data[6] = 0x00;
-	data[7] = 0x01;
-	res = mod_ctype.rsint64(data, 'big', 0);
-	ASSERT.equal(-0x7fffffff, res[0]);
-	ASSERT.equal(-0xffffffff, res[1]);
-
-
-}
-
-function testWriteZero()
-{
-	var data, buf;
-	buf = new Buffer(10);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wsint64(data, 'big', buf, 0);
-	ASSERT.equal(0, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wsint64(data, 'big', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wsint64(data, 'big', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0, buf[9]);
-
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wsint64(data, 'little', buf, 0);
-	ASSERT.equal(0, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wsint64(data, 'little', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wsint64(data, 'little', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0, buf[9]);
-}
-
-/*
- * Also include tests that are going to force us to go into a negative value and
- * insure that it's written correctly.
- */
-function testWrite()
-{
-	var data, buf;
-
-	buf = new Buffer(10);
-	data = [ 0x234456, 0x87 ];
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 0);
-	ASSERT.equal(0x00, buf[0]);
-	ASSERT.equal(0x23, buf[1]);
-	ASSERT.equal(0x44, buf[2]);
-	ASSERT.equal(0x56, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x87, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x23, buf[2]);
-	ASSERT.equal(0x44, buf[3]);
-	ASSERT.equal(0x56, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x87, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x23, buf[3]);
-	ASSERT.equal(0x44, buf[4]);
-	ASSERT.equal(0x56, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x00, buf[8]);
-	ASSERT.equal(0x87, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 0);
-	ASSERT.equal(0x87, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x56, buf[4]);
-	ASSERT.equal(0x44, buf[5]);
-	ASSERT.equal(0x23, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x87, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x56, buf[5]);
-	ASSERT.equal(0x44, buf[6]);
-	ASSERT.equal(0x23, buf[7]);
-	ASSERT.equal(0x00, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0x87, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x56, buf[6]);
-	ASSERT.equal(0x44, buf[7]);
-	ASSERT.equal(0x23, buf[8]);
-	ASSERT.equal(0x00, buf[9]);
-
-	data = [0x3421, 0x34abcdba];
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 0);
-	ASSERT.equal(0x00, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x34, buf[2]);
-	ASSERT.equal(0x21, buf[3]);
-	ASSERT.equal(0x34, buf[4]);
-	ASSERT.equal(0xab, buf[5]);
-	ASSERT.equal(0xcd, buf[6]);
-	ASSERT.equal(0xba, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x34, buf[3]);
-	ASSERT.equal(0x21, buf[4]);
-	ASSERT.equal(0x34, buf[5]);
-	ASSERT.equal(0xab, buf[6]);
-	ASSERT.equal(0xcd, buf[7]);
-	ASSERT.equal(0xba, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x34, buf[4]);
-	ASSERT.equal(0x21, buf[5]);
-	ASSERT.equal(0x34, buf[6]);
-	ASSERT.equal(0xab, buf[7]);
-	ASSERT.equal(0xcd, buf[8]);
-	ASSERT.equal(0xba, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 0);
-	ASSERT.equal(0xba, buf[0]);
-	ASSERT.equal(0xcd, buf[1]);
-	ASSERT.equal(0xab, buf[2]);
-	ASSERT.equal(0x34, buf[3]);
-	ASSERT.equal(0x21, buf[4]);
-	ASSERT.equal(0x34, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0xba, buf[1]);
-	ASSERT.equal(0xcd, buf[2]);
-	ASSERT.equal(0xab, buf[3]);
-	ASSERT.equal(0x34, buf[4]);
-	ASSERT.equal(0x21, buf[5]);
-	ASSERT.equal(0x34, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x00, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0xba, buf[2]);
-	ASSERT.equal(0xcd, buf[3]);
-	ASSERT.equal(0xab, buf[4]);
-	ASSERT.equal(0x34, buf[5]);
-	ASSERT.equal(0x21, buf[6]);
-	ASSERT.equal(0x34, buf[7]);
-	ASSERT.equal(0x00, buf[8]);
-	ASSERT.equal(0x00, buf[9]);
-
-
-	data = [ -0x80000000, 0 ];
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 0);
-	ASSERT.equal(0x80, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 0);
-	ASSERT.equal(0x00, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x80, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	data = [ -0x7fffffff, -0xffffffff ];
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 0);
-	ASSERT.equal(0x80, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x01, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 0);
-	ASSERT.equal(0x01, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x80, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	data = [ 0x0, -0x1];
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'big', buf, 0);
-	ASSERT.equal(0xff, buf[0]);
-	ASSERT.equal(0xff, buf[1]);
-	ASSERT.equal(0xff, buf[2]);
-	ASSERT.equal(0xff, buf[3]);
-	ASSERT.equal(0xff, buf[4]);
-	ASSERT.equal(0xff, buf[5]);
-	ASSERT.equal(0xff, buf[6]);
-	ASSERT.equal(0xff, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wsint64(data, 'little', buf, 0);
-	ASSERT.equal(0xff, buf[0]);
-	ASSERT.equal(0xff, buf[1]);
-	ASSERT.equal(0xff, buf[2]);
-	ASSERT.equal(0xff, buf[3]);
-	ASSERT.equal(0xff, buf[4]);
-	ASSERT.equal(0xff, buf[5]);
-	ASSERT.equal(0xff, buf[6]);
-	ASSERT.equal(0xff, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-}
-
-/*
- * Make sure we catch invalid writes.
- */
-function testWriteInvalid()
-{
-	var data, buf;
-
-	/* Buffer too small */
-	buf = new Buffer(4);
-	data = [ 0, 0];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 0);
-	}, Error, 'buffer too small');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 0);
-	}, Error, 'buffer too small');
-
-	/* Beyond the end of the buffer */
-	buf = new Buffer(12);
-	data = [ 0, 0];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 11);
-	}, Error, 'write beyond end of buffer');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 11);
-	}, Error, 'write beyond end of buffer');
-
-	/* Write fractional values */
-	buf = new Buffer(12);
-	data = [ 3.33, 0 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ 0, 3.3 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ -3.33, 0 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ 0, -3.3 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ 3.33, 2.42 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ 3.33, -2.42 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ -3.33, -2.42 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ -3.33, 2.42 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	/* Signs don't match */
-	buf = new Buffer(12);
-	data = [ 0x800000, -0x32 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ -0x800000, 0x32 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	/* Write values that are too large */
-	buf = new Buffer(12);
-	data = [ 0x80000000, 0 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ 0x7fffffff, 0x100000000 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ 0x00, 0x800000000 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ 0xffffffffff, 0xffffff238 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ 0x23, 0xffffff238 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ -0x80000000, -0xfff238 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ -0x80000004, -0xfff238 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wsint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-}
-
-
-testRead();
-testWrite();
-testWriteZero();
-testWriteInvalid();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js
deleted file mode 100644
index 5236d268..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Tests to verify we're reading in signed integers correctly
- */
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-/*
- * Test 8 bit signed integers
- */
-function test8()
-{
-	var data = new Buffer(4);
-
-	data[0] = 0x23;
-	ASSERT.equal(0x23, mod_ctype.rsint8(data, 'big', 0));
-	ASSERT.equal(0x23, mod_ctype.rsint8(data, 'little', 0));
-
-	data[0] = 0xff;
-	ASSERT.equal(-1, mod_ctype.rsint8(data, 'big', 0));
-	ASSERT.equal(-1, mod_ctype.rsint8(data, 'little', 0));
-
-	data[0] = 0x87;
-	data[1] = 0xab;
-	data[2] = 0x7c;
-	data[3] = 0xef;
-	ASSERT.equal(-121, mod_ctype.rsint8(data, 'big', 0));
-	ASSERT.equal(-85, mod_ctype.rsint8(data, 'big', 1));
-	ASSERT.equal(124, mod_ctype.rsint8(data, 'big', 2));
-	ASSERT.equal(-17, mod_ctype.rsint8(data, 'big', 3));
-	ASSERT.equal(-121, mod_ctype.rsint8(data, 'little', 0));
-	ASSERT.equal(-85, mod_ctype.rsint8(data, 'little', 1));
-	ASSERT.equal(124, mod_ctype.rsint8(data, 'little', 2));
-	ASSERT.equal(-17, mod_ctype.rsint8(data, 'little', 3));
-}
-
-function test16()
-{
-	var buffer = new Buffer(6);
-	buffer[0] = 0x16;
-	buffer[1] = 0x79;
-	ASSERT.equal(0x1679, mod_ctype.rsint16(buffer, 'big', 0));
-	ASSERT.equal(0x7916, mod_ctype.rsint16(buffer, 'little', 0));
-
-	buffer[0] = 0xff;
-	buffer[1] = 0x80;
-	ASSERT.equal(-128, mod_ctype.rsint16(buffer, 'big', 0));
-	ASSERT.equal(-32513, mod_ctype.rsint16(buffer, 'little', 0));
-
-	/* test offset with weenix */
-	buffer[0] = 0x77;
-	buffer[1] = 0x65;
-	buffer[2] = 0x65;
-	buffer[3] = 0x6e;
-	buffer[4] = 0x69;
-	buffer[5] = 0x78;
-	ASSERT.equal(0x7765, mod_ctype.rsint16(buffer, 'big', 0));
-	ASSERT.equal(0x6565, mod_ctype.rsint16(buffer, 'big', 1));
-	ASSERT.equal(0x656e, mod_ctype.rsint16(buffer, 'big', 2));
-	ASSERT.equal(0x6e69, mod_ctype.rsint16(buffer, 'big', 3));
-	ASSERT.equal(0x6978, mod_ctype.rsint16(buffer, 'big', 4));
-	ASSERT.equal(0x6577, mod_ctype.rsint16(buffer, 'little', 0));
-	ASSERT.equal(0x6565, mod_ctype.rsint16(buffer, 'little', 1));
-	ASSERT.equal(0x6e65, mod_ctype.rsint16(buffer, 'little', 2));
-	ASSERT.equal(0x696e, mod_ctype.rsint16(buffer, 'little', 3));
-	ASSERT.equal(0x7869, mod_ctype.rsint16(buffer, 'little', 4));
-}
-
-function test32()
-{
-	var buffer = new Buffer(6);
-	buffer[0] = 0x43;
-	buffer[1] = 0x53;
-	buffer[2] = 0x16;
-	buffer[3] = 0x79;
-	ASSERT.equal(0x43531679, mod_ctype.rsint32(buffer, 'big', 0));
-	ASSERT.equal(0x79165343, mod_ctype.rsint32(buffer, 'little', 0));
-
-	buffer[0] = 0xff;
-	buffer[1] = 0xfe;
-	buffer[2] = 0xef;
-	buffer[3] = 0xfa;
-	ASSERT.equal(-69638, mod_ctype.rsint32(buffer, 'big', 0));
-	ASSERT.equal(-84934913, mod_ctype.rsint32(buffer, 'little', 0));
-
-	buffer[0] = 0x42;
-	buffer[1] = 0xc3;
-	buffer[2] = 0x95;
-	buffer[3] = 0xa9;
-	buffer[4] = 0x36;
-	buffer[5] = 0x17;
-	ASSERT.equal(0x42c395a9, mod_ctype.rsint32(buffer, 'big', 0));
-	ASSERT.equal(-1013601994, mod_ctype.rsint32(buffer, 'big', 1));
-	ASSERT.equal(-1784072681, mod_ctype.rsint32(buffer, 'big', 2));
-	ASSERT.equal(-1449802942, mod_ctype.rsint32(buffer, 'little', 0));
-	ASSERT.equal(917083587, mod_ctype.rsint32(buffer, 'little', 1));
-	ASSERT.equal(389458325, mod_ctype.rsint32(buffer, 'little', 2));
-}
-
-test8();
-test16();
-test32();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js
deleted file mode 100644
index 5488177b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Test to make sure that we properly are erroring whenever we try to write
- * beyond the size of the integer.
- */
-
-var mod_ctio = require('../../../ctio.js');
-var mod_assert = require('assert');
-var tb = new Buffer(16); /* Largest buffer we'll need */
-
-var cases = [
-	{ func:
-	function () {
-		mod_ctio.wsint8(0x80, 'big', tb, 0);
-	}, test: '+int8_t' },
-	{ func:
-	function () {
-		mod_ctio.wsint8(-0x81, 'big', tb, 0);
-	}, test: '-int8_t' },
-
-	{ func:
-	function () {
-		mod_ctio.wsint16(0x8000, 'big', tb, 0);
-	}, test: '+int16_t' },
-	{ func:
-	function () {
-		mod_ctio.wsint16(-0x8001, 'big', tb, 0);
-	}, test: '-int16_t' },
-	{ func:
-	function () {
-		mod_ctio.wsint32(0x80000000, 'big', tb, 0);
-	}, test: '+int32_t' },
-	{ func:
-	function () {
-		mod_ctio.wsint32(-0x80000001, 'big', tb, 0);
-	}, test: '-int32_t' },
-	{ func:
-	function () {
-		mod_ctio.wsint64([ 0x80000000, 0 ], 'big', tb, 0);
-	}, test: '+int64_t' },
-	{ func:
-	function () {
-		mod_ctio.wsint64([ -0x80000000, -1 ], 'big', tb, 0);
-	}, test: '-int64_t' }
-];
-
-function test()
-{
-	var ii;
-	for (ii = 0; ii < cases.length; ii++)
-		mod_assert.throws(cases[ii]['func'], Error, cases[ii]['test']);
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js
deleted file mode 100644
index 98b6a32a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Tests to verify we're writing signed integers correctly
- */
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-function test8()
-{
-	var buffer = new Buffer(4);
-	mod_ctype.wsint8(0x23, 'big', buffer, 0);
-	mod_ctype.wsint8(0x23, 'little', buffer, 1);
-	mod_ctype.wsint8(-5, 'big', buffer, 2);
-	mod_ctype.wsint8(-5, 'little', buffer, 3);
-
-	ASSERT.equal(0x23, buffer[0]);
-	ASSERT.equal(0x23, buffer[1]);
-	ASSERT.equal(0xfb, buffer[2]);
-	ASSERT.equal(0xfb, buffer[3]);
-
-	/* Make sure we handle truncation correctly */
-	ASSERT.throws(function () {
-	     mod_ctype.wsint8(0xabc, 'big', buffer, 0);
-	});
-	ASSERT.throws(function () {
-	     mod_ctype.wsint8(0xabc, 'little', buffer, 0);
-	});
-}
-
-function test16()
-{
-	var buffer = new Buffer(6);
-	mod_ctype.wsint16(0x0023, 'big', buffer, 0);
-	mod_ctype.wsint16(0x0023, 'little', buffer, 2);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x23, buffer[1]);
-	ASSERT.equal(0x23, buffer[2]);
-	ASSERT.equal(0x00, buffer[3]);
-	mod_ctype.wsint16(-5, 'big', buffer, 0);
-	mod_ctype.wsint16(-5, 'little', buffer, 2);
-	ASSERT.equal(0xff, buffer[0]);
-	ASSERT.equal(0xfb, buffer[1]);
-	ASSERT.equal(0xfb, buffer[2]);
-	ASSERT.equal(0xff, buffer[3]);
-
-	mod_ctype.wsint16(-1679, 'big', buffer, 1);
-	mod_ctype.wsint16(-1679, 'little', buffer, 3);
-	ASSERT.equal(0xf9, buffer[1]);
-	ASSERT.equal(0x71, buffer[2]);
-	ASSERT.equal(0x71, buffer[3]);
-	ASSERT.equal(0xf9, buffer[4]);
-}
-
-function test32()
-{
-	var buffer = new Buffer(8);
-	mod_ctype.wsint32(0x23, 'big', buffer, 0);
-	mod_ctype.wsint32(0x23, 'little', buffer, 4);
-	ASSERT.equal(0x00, buffer[0]);
-	ASSERT.equal(0x00, buffer[1]);
-	ASSERT.equal(0x00, buffer[2]);
-	ASSERT.equal(0x23, buffer[3]);
-	ASSERT.equal(0x23, buffer[4]);
-	ASSERT.equal(0x00, buffer[5]);
-	ASSERT.equal(0x00, buffer[6]);
-	ASSERT.equal(0x00, buffer[7]);
-
-	mod_ctype.wsint32(-5, 'big', buffer, 0);
-	mod_ctype.wsint32(-5, 'little', buffer, 4);
-	ASSERT.equal(0xff, buffer[0]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xff, buffer[2]);
-	ASSERT.equal(0xfb, buffer[3]);
-	ASSERT.equal(0xfb, buffer[4]);
-	ASSERT.equal(0xff, buffer[5]);
-	ASSERT.equal(0xff, buffer[6]);
-	ASSERT.equal(0xff, buffer[7]);
-
-	mod_ctype.wsint32(-805306713, 'big', buffer, 0);
-	mod_ctype.wsint32(-805306713, 'litle', buffer, 4);
-	ASSERT.equal(0xcf, buffer[0]);
-	ASSERT.equal(0xff, buffer[1]);
-	ASSERT.equal(0xfe, buffer[2]);
-	ASSERT.equal(0xa7, buffer[3]);
-	ASSERT.equal(0xa7, buffer[4]);
-	ASSERT.equal(0xfe, buffer[5]);
-	ASSERT.equal(0xff, buffer[6]);
-	ASSERT.equal(0xcf, buffer[7]);
-}
-
-test8();
-test16();
-test32();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js
deleted file mode 100644
index cf66ac7a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Test our ability to read and write unsigned 64-bit integers.
- */
-
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-function testRead()
-{
-	var res, data;
-	data = new Buffer(10);
-
-	data[0] = 0x32;
-	data[1] = 0x65;
-	data[2] = 0x42;
-	data[3] = 0x56;
-	data[4] = 0x23;
-	data[5] = 0xff;
-	data[6] = 0xff;
-	data[7] = 0xff;
-	data[8] = 0x89;
-	data[9] = 0x11;
-	res = mod_ctype.ruint64(data, 'big', 0);
-	ASSERT.equal(0x32654256, res[0]);
-	ASSERT.equal(0x23ffffff, res[1]);
-	res = mod_ctype.ruint64(data, 'big', 1);
-	ASSERT.equal(0x65425623, res[0]);
-	ASSERT.equal(0xffffff89, res[1]);
-	res = mod_ctype.ruint64(data, 'big', 2);
-	ASSERT.equal(0x425623ff, res[0]);
-	ASSERT.equal(0xffff8911, res[1]);
-	res = mod_ctype.ruint64(data, 'little', 0);
-	ASSERT.equal(0xffffff23, res[0]);
-	ASSERT.equal(0x56426532, res[1]);
-	res = mod_ctype.ruint64(data, 'little', 1);
-	ASSERT.equal(0x89ffffff, res[0]);
-	ASSERT.equal(0x23564265, res[1]);
-	res = mod_ctype.ruint64(data, 'little', 2);
-	ASSERT.equal(0x1189ffff, res[0]);
-	ASSERT.equal(0xff235642, res[1]);
-
-}
-
-function testReadOver()
-{
-	var res, data;
-	data = new Buffer(10);
-
-	data[0] = 0x80;
-	data[1] = 0xff;
-	data[2] = 0x80;
-	data[3] = 0xff;
-	data[4] = 0x80;
-	data[5] = 0xff;
-	data[6] = 0x80;
-	data[7] = 0xff;
-	data[8] = 0x80;
-	data[9] = 0xff;
-	res = mod_ctype.ruint64(data, 'big', 0);
-	ASSERT.equal(0x80ff80ff, res[0]);
-	ASSERT.equal(0x80ff80ff, res[1]);
-	res = mod_ctype.ruint64(data, 'big', 1);
-	ASSERT.equal(0xff80ff80, res[0]);
-	ASSERT.equal(0xff80ff80, res[1]);
-	res = mod_ctype.ruint64(data, 'big', 2);
-	ASSERT.equal(0x80ff80ff, res[0]);
-	ASSERT.equal(0x80ff80ff, res[1]);
-	res = mod_ctype.ruint64(data, 'little', 0);
-	ASSERT.equal(0xff80ff80, res[0]);
-	ASSERT.equal(0xff80ff80, res[1]);
-	res = mod_ctype.ruint64(data, 'little', 1);
-	ASSERT.equal(0x80ff80ff, res[0]);
-	ASSERT.equal(0x80ff80ff, res[1]);
-	res = mod_ctype.ruint64(data, 'little', 2);
-	ASSERT.equal(0xff80ff80, res[0]);
-	ASSERT.equal(0xff80ff80, res[1]);
-}
-
-function testWriteZero()
-{
-	var data, buf;
-	buf = new Buffer(10);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wuint64(data, 'big', buf, 0);
-	ASSERT.equal(0, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wuint64(data, 'big', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wuint64(data, 'big', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0, buf[9]);
-
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wuint64(data, 'little', buf, 0);
-	ASSERT.equal(0, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wuint64(data, 'little', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	data = [0, 0];
-	mod_ctype.wuint64(data, 'little', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0, buf[2]);
-	ASSERT.equal(0, buf[3]);
-	ASSERT.equal(0, buf[4]);
-	ASSERT.equal(0, buf[5]);
-	ASSERT.equal(0, buf[6]);
-	ASSERT.equal(0, buf[7]);
-	ASSERT.equal(0, buf[8]);
-	ASSERT.equal(0, buf[9]);
-}
-
-/*
- * Also include tests that are going to force us to go into a negative value and
- * insure that it's written correctly.
- */
-function testWrite()
-{
-	var data, buf;
-
-	buf = new Buffer(10);
-	data = [ 0x234456, 0x87 ];
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'big', buf, 0);
-	ASSERT.equal(0x00, buf[0]);
-	ASSERT.equal(0x23, buf[1]);
-	ASSERT.equal(0x44, buf[2]);
-	ASSERT.equal(0x56, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x87, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'big', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x23, buf[2]);
-	ASSERT.equal(0x44, buf[3]);
-	ASSERT.equal(0x56, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x87, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'big', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x23, buf[3]);
-	ASSERT.equal(0x44, buf[4]);
-	ASSERT.equal(0x56, buf[5]);
-	ASSERT.equal(0x00, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x00, buf[8]);
-	ASSERT.equal(0x87, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'little', buf, 0);
-	ASSERT.equal(0x87, buf[0]);
-	ASSERT.equal(0x00, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x56, buf[4]);
-	ASSERT.equal(0x44, buf[5]);
-	ASSERT.equal(0x23, buf[6]);
-	ASSERT.equal(0x00, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'little', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x87, buf[1]);
-	ASSERT.equal(0x00, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x56, buf[5]);
-	ASSERT.equal(0x44, buf[6]);
-	ASSERT.equal(0x23, buf[7]);
-	ASSERT.equal(0x00, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'little', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0x87, buf[2]);
-	ASSERT.equal(0x00, buf[3]);
-	ASSERT.equal(0x00, buf[4]);
-	ASSERT.equal(0x00, buf[5]);
-	ASSERT.equal(0x56, buf[6]);
-	ASSERT.equal(0x44, buf[7]);
-	ASSERT.equal(0x23, buf[8]);
-	ASSERT.equal(0x00, buf[9]);
-
-	data = [0xffff3421, 0x34abcdba];
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'big', buf, 0);
-	ASSERT.equal(0xff, buf[0]);
-	ASSERT.equal(0xff, buf[1]);
-	ASSERT.equal(0x34, buf[2]);
-	ASSERT.equal(0x21, buf[3]);
-	ASSERT.equal(0x34, buf[4]);
-	ASSERT.equal(0xab, buf[5]);
-	ASSERT.equal(0xcd, buf[6]);
-	ASSERT.equal(0xba, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'big', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0xff, buf[1]);
-	ASSERT.equal(0xff, buf[2]);
-	ASSERT.equal(0x34, buf[3]);
-	ASSERT.equal(0x21, buf[4]);
-	ASSERT.equal(0x34, buf[5]);
-	ASSERT.equal(0xab, buf[6]);
-	ASSERT.equal(0xcd, buf[7]);
-	ASSERT.equal(0xba, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'big', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0xff, buf[2]);
-	ASSERT.equal(0xff, buf[3]);
-	ASSERT.equal(0x34, buf[4]);
-	ASSERT.equal(0x21, buf[5]);
-	ASSERT.equal(0x34, buf[6]);
-	ASSERT.equal(0xab, buf[7]);
-	ASSERT.equal(0xcd, buf[8]);
-	ASSERT.equal(0xba, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'little', buf, 0);
-	ASSERT.equal(0xba, buf[0]);
-	ASSERT.equal(0xcd, buf[1]);
-	ASSERT.equal(0xab, buf[2]);
-	ASSERT.equal(0x34, buf[3]);
-	ASSERT.equal(0x21, buf[4]);
-	ASSERT.equal(0x34, buf[5]);
-	ASSERT.equal(0xff, buf[6]);
-	ASSERT.equal(0xff, buf[7]);
-	ASSERT.equal(0x66, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'little', buf, 1);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0xba, buf[1]);
-	ASSERT.equal(0xcd, buf[2]);
-	ASSERT.equal(0xab, buf[3]);
-	ASSERT.equal(0x34, buf[4]);
-	ASSERT.equal(0x21, buf[5]);
-	ASSERT.equal(0x34, buf[6]);
-	ASSERT.equal(0xff, buf[7]);
-	ASSERT.equal(0xff, buf[8]);
-	ASSERT.equal(0x66, buf[9]);
-
-	buf.fill(0x66);
-	mod_ctype.wuint64(data, 'little', buf, 2);
-	ASSERT.equal(0x66, buf[0]);
-	ASSERT.equal(0x66, buf[1]);
-	ASSERT.equal(0xba, buf[2]);
-	ASSERT.equal(0xcd, buf[3]);
-	ASSERT.equal(0xab, buf[4]);
-	ASSERT.equal(0x34, buf[5]);
-	ASSERT.equal(0x21, buf[6]);
-	ASSERT.equal(0x34, buf[7]);
-	ASSERT.equal(0xff, buf[8]);
-	ASSERT.equal(0xff, buf[9]);
-}
-
-/*
- * Make sure we catch invalid writes.
- */
-function testWriteInvalid()
-{
-	var data, buf;
-
-	/* Buffer too small */
-	buf = new Buffer(4);
-	data = [ 0, 0];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 0);
-	}, Error, 'buffer too small');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 0);
-	}, Error, 'buffer too small');
-
-	/* Beyond the end of the buffer */
-	buf = new Buffer(12);
-	data = [ 0, 0];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 11);
-	}, Error, 'write beyond end of buffer');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 11);
-	}, Error, 'write beyond end of buffer');
-
-	/* Write negative values */
-	buf = new Buffer(12);
-	data = [ -3, 0 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write negative number');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write negative number');
-
-	data = [ 0, -3 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write negative number');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write negative number');
-
-	data = [ -3, -3 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write negative number');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write negative number');
-
-
-	/* Write fractional values */
-	buf = new Buffer(12);
-	data = [ 3.33, 0 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ 0, 3.3 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	data = [ 3.33, 2.42 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write fractions');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write fractions');
-
-	/* Write values that are too large */
-	buf = new Buffer(12);
-	data = [ 0xffffffffff, 23 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ 0xffffffffff, 0xffffff238 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-
-	data = [ 0x23, 0xffffff238 ];
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'big', buf, 1);
-	}, Error, 'write too large');
-	ASSERT.throws(function () {
-	    mod_ctype.wuint64(data, 'little', buf, 1);
-	}, Error, 'write too large');
-}
-
-
-testRead();
-testReadOver();
-testWriteZero();
-testWrite();
-testWriteInvalid();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js
deleted file mode 100644
index 87ae59b7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * A battery of tests for sucessful round-trip between writes and reads
- */
-
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-
-/*
- * What the heck, let's just test every value for 8-bits.
- */
-
-function test8() {
-	var data = new Buffer(1);
-	var i;
-	for (i = 0; i < 256; i++) {
-		mod_ctype.wuint8(i, 'big', data, 0);
-		ASSERT.equal(i, mod_ctype.ruint8(data, 'big', 0));
-		mod_ctype.wuint8(i, 'little', data, 0);
-		ASSERT.equal(i, mod_ctype.ruint8(data, 'little', 0));
-	}
-	ASSERT.ok(true);
-}
-
-/*
- * Test a random sample of 256 values in the 16-bit unsigned range
- */
-
-function test16() {
-	var data = new Buffer(2);
-	var i = 0;
-	for (i = 0; i < 256; i++) {
-		var value = Math.round(Math.random() * Math.pow(2, 16));
-		mod_ctype.wuint16(value, 'big', data, 0);
-		ASSERT.equal(value, mod_ctype.ruint16(data, 'big', 0));
-		mod_ctype.wuint16(value, 'little', data, 0);
-		ASSERT.equal(value, mod_ctype.ruint16(data, 'little', 0));
-	}
-}
-
-/*
- * Test a random sample of 256 values in the 32-bit unsigned range
- */
-
-function test32() {
-	var data = new Buffer(4);
-	var i = 0;
-	for (i = 0; i < 256; i++) {
-		var value = Math.round(Math.random() * Math.pow(2, 32));
-		mod_ctype.wuint32(value, 'big', data, 0);
-		ASSERT.equal(value, mod_ctype.ruint32(data, 'big', 0));
-		mod_ctype.wuint32(value, 'little', data, 0);
-		ASSERT.equal(value, mod_ctype.ruint32(data, 'little', 0));
-	}
-}
-
-/*
- * Test a random sample of 256 values in the 64-bit unsigned range
- */
-
-function test64() {
-	var data = new Buffer(8);
-	var i = 0;
-	for (i = 0; i < 256; i++) {
-		var low = Math.round(Math.random() * Math.pow(2, 32));
-		var high = Math.round(Math.random() * Math.pow(2, 32));
-		mod_ctype.wuint64([high, low], 'big', data, 0);
-		var result = mod_ctype.ruint64(data, 'big', 0);
-		ASSERT.equal(high, result[0]);
-		ASSERT.equal(low, result[1]);
-		mod_ctype.wuint64([high, low], 'little', data, 0);
-		result = mod_ctype.ruint64(data, 'little', 0);
-		ASSERT.equal(high, result[0]);
-		ASSERT.equal(low, result[1]);
-	}
-}
-
-exports.test8 = test8;
-exports.test16 = test16;
-exports.test32 = test32;
-exports.test64 = test64;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js
deleted file mode 100644
index b67c077f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * A battery of tests to help us read a series of uints
- */
-
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-/*
- * We need to check the following things:
- *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
- *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-function test8()
-{
-	var data = new Buffer(4);
-	data[0] = 23;
-	data[1] = 23;
-	data[2] = 23;
-	data[3] = 23;
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 0));
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 0));
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 1));
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 1));
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 2));
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 2));
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 3));
-	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 3));
-	data[0] = 255; /* If it became a signed int, would be -1 */
-	ASSERT.equal(255, mod_ctype.ruint8(data, 'big', 0));
-	ASSERT.equal(255, mod_ctype.ruint8(data, 'little', 0));
-}
-
-/*
- * Test 16 bit unsigned integers. We need to verify the same set as 8 bit, only
- * now some of the issues actually matter:
- *  - We are correctly resolving big endian
- *  - Correctly resolving little endian
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-function test16()
-{
-	var data = new Buffer(4);
-	/* Test signed values first */
-	data[0] = 0;
-	data[1] = 0x23;
-	data[2] = 0x42;
-	data[3] = 0x3f;
-
-	ASSERT.equal(0x23, mod_ctype.ruint16(data, 'big', 0));
-	ASSERT.equal(0x2342, mod_ctype.ruint16(data, 'big', 1));
-	ASSERT.equal(0x423f, mod_ctype.ruint16(data, 'big', 2));
-
-	ASSERT.equal(0x2300, mod_ctype.ruint16(data, 'little', 0));
-	ASSERT.equal(0x4223, mod_ctype.ruint16(data, 'little', 1));
-	ASSERT.equal(0x3f42, mod_ctype.ruint16(data, 'little', 2));
-
-	data[0] = 0xfe;
-	data[1] = 0xfe;
-
-	ASSERT.equal(0xfefe, mod_ctype.ruint16(data, 'big', 0));
-	ASSERT.equal(0xfefe, mod_ctype.ruint16(data, 'little', 0));
-}
-
-/*
- * Test 32 bit unsigned integers. We need to verify the same set as 8 bit, only
- * now some of the issues actually matter:
- *  - We are correctly resolving big endian
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-function test32()
-{
-	var data = new Buffer(8);
-	data[0] = 0x32;
-	data[1] = 0x65;
-	data[2] = 0x42;
-	data[3] = 0x56;
-	data[4] = 0x23;
-	data[5] = 0xff;
-
-	ASSERT.equal(0x32654256, mod_ctype.ruint32(data, 'big', 0));
-	ASSERT.equal(0x65425623, mod_ctype.ruint32(data, 'big', 1));
-	ASSERT.equal(0x425623ff, mod_ctype.ruint32(data, 'big', 2));
-
-	ASSERT.equal(0x56426532, mod_ctype.ruint32(data, 'little', 0));
-	ASSERT.equal(0x23564265, mod_ctype.ruint32(data, 'little', 1));
-	ASSERT.equal(0xff235642, mod_ctype.ruint32(data, 'little', 2));
-}
-
-test8();
-test16();
-test32();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js
deleted file mode 100644
index d6c4230f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * A battery of tests to help us read a series of uints
- */
-
-var mod_ctype = require('../../../ctio.js');
-var ASSERT = require('assert');
-
-/*
- * We need to check the following things:
- *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
- *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
- *  - Correctly using the offsets
- *  - Correctly interpreting values that are beyond the signed range as unsigned
- */
-function test8()
-{
-	var data = new Buffer(4);
-	mod_ctype.wuint8(23, 'big', data, 0);
-	mod_ctype.wuint8(23, 'big', data, 1);
-	mod_ctype.wuint8(23, 'big', data, 2);
-	mod_ctype.wuint8(23, 'big', data, 3);
-	ASSERT.equal(23, data[0]);
-	ASSERT.equal(23, data[1]);
-	ASSERT.equal(23, data[2]);
-	ASSERT.equal(23, data[3]);
-	mod_ctype.wuint8(23, 'little', data, 0);
-	mod_ctype.wuint8(23, 'little', data, 1);
-	mod_ctype.wuint8(23, 'little', data, 2);
-	mod_ctype.wuint8(23, 'little', data, 3);
-	ASSERT.equal(23, data[0]);
-	ASSERT.equal(23, data[1]);
-	ASSERT.equal(23, data[2]);
-	ASSERT.equal(23, data[3]);
-	mod_ctype.wuint8(255, 'big', data, 0);
-	ASSERT.equal(255, data[0]);
-	mod_ctype.wuint8(255, 'little', data, 0);
-	ASSERT.equal(255, data[0]);
-}
-
-function test16()
-{
-	var value = 0x2343;
-	var data = new Buffer(4);
-	mod_ctype.wuint16(value, 'big', data, 0);
-	ASSERT.equal(0x23, data[0]);
-	ASSERT.equal(0x43, data[1]);
-	mod_ctype.wuint16(value, 'big', data, 1);
-	ASSERT.equal(0x23, data[1]);
-	ASSERT.equal(0x43, data[2]);
-	mod_ctype.wuint16(value, 'big', data, 2);
-	ASSERT.equal(0x23, data[2]);
-	ASSERT.equal(0x43, data[3]);
-
-	mod_ctype.wuint16(value, 'little', data, 0);
-	ASSERT.equal(0x23, data[1]);
-	ASSERT.equal(0x43, data[0]);
-
-	mod_ctype.wuint16(value, 'little', data, 1);
-	ASSERT.equal(0x23, data[2]);
-	ASSERT.equal(0x43, data[1]);
-
-	mod_ctype.wuint16(value, 'little', data, 2);
-	ASSERT.equal(0x23, data[3]);
-	ASSERT.equal(0x43, data[2]);
-
-	value = 0xff80;
-	mod_ctype.wuint16(value, 'little', data, 0);
-	ASSERT.equal(0xff, data[1]);
-	ASSERT.equal(0x80, data[0]);
-
-	mod_ctype.wuint16(value, 'big', data, 0);
-	ASSERT.equal(0xff, data[0]);
-	ASSERT.equal(0x80, data[1]);
-}
-
-function test32()
-{
-	var data = new Buffer(6);
-	var value = 0xe7f90a6d;
-
-	mod_ctype.wuint32(value, 'big', data, 0);
-	ASSERT.equal(0xe7, data[0]);
-	ASSERT.equal(0xf9, data[1]);
-	ASSERT.equal(0x0a, data[2]);
-	ASSERT.equal(0x6d, data[3]);
-
-	mod_ctype.wuint32(value, 'big', data, 1);
-	ASSERT.equal(0xe7, data[1]);
-	ASSERT.equal(0xf9, data[2]);
-	ASSERT.equal(0x0a, data[3]);
-	ASSERT.equal(0x6d, data[4]);
-
-	mod_ctype.wuint32(value, 'big', data, 2);
-	ASSERT.equal(0xe7, data[2]);
-	ASSERT.equal(0xf9, data[3]);
-	ASSERT.equal(0x0a, data[4]);
-	ASSERT.equal(0x6d, data[5]);
-
-	mod_ctype.wuint32(value, 'little', data, 0);
-	ASSERT.equal(0xe7, data[3]);
-	ASSERT.equal(0xf9, data[2]);
-	ASSERT.equal(0x0a, data[1]);
-	ASSERT.equal(0x6d, data[0]);
-
-	mod_ctype.wuint32(value, 'little', data, 1);
-	ASSERT.equal(0xe7, data[4]);
-	ASSERT.equal(0xf9, data[3]);
-	ASSERT.equal(0x0a, data[2]);
-	ASSERT.equal(0x6d, data[1]);
-
-	mod_ctype.wuint32(value, 'little', data, 2);
-	ASSERT.equal(0xe7, data[5]);
-	ASSERT.equal(0xf9, data[4]);
-	ASSERT.equal(0x0a, data[3]);
-	ASSERT.equal(0x6d, data[2]);
-}
-
-function test64()
-{
-	var data = new Buffer(10);
-	var value = 0x0007cda8e7f90a6d;
-	var high = Math.floor(value / Math.pow(2, 32));
-	var low = value - (high * Math.pow(2, 32));
-	ASSERT.equal(0x0007cda8, high);
-	ASSERT.equal(0xe7f90a6d, low);
-
-	mod_ctype.wuint64([high, low], 'big', data, 0);
-	ASSERT.equal(0x00, data[0]);
-	ASSERT.equal(0x07, data[1]);
-	ASSERT.equal(0xcd, data[2]);
-	ASSERT.equal(0xa8, data[3]);
-	ASSERT.equal(0xe7, data[4]);
-	ASSERT.equal(0xf9, data[5]);
-	ASSERT.equal(0x0a, data[6]);
-	ASSERT.equal(0x6d, data[7]);
-
-	mod_ctype.wuint64([high, low], 'little', data, 0);
-	ASSERT.equal(0x6d, data[0]);
-	ASSERT.equal(0x0a, data[1]);
-	ASSERT.equal(0xf9, data[2]);
-	ASSERT.equal(0xe7, data[3]);
-	ASSERT.equal(0xa8, data[4]);
-	ASSERT.equal(0xcd, data[5]);
-	ASSERT.equal(0x07, data[6]);
-	ASSERT.equal(0x00, data[7]);
-}
-
-test8();
-test16();
-test32();
-test64();
-
-exports.test8 = test8;
-exports.test16 = test16;
-exports.test32 = test32;
-exports.test64 = test64;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js
deleted file mode 100644
index e9895152..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Simple does to see if it works at all
- */
-var mod_ctype = require('../../ctype');
-var ASSERT = require('assert');
-var mod_sys = require('sys');
-
-function test()
-{
-	var ii, p, result, buffer;
-
-	p = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer(4);
-	buffer[0] = 23;
-	buffer[3] = 42;
-	result = p.readData([ { x: { type: 'uint8_t' }},
-	    { y: { type: 'uint8_t', offset: 3 }}
-	], buffer, 0);
-	ASSERT.equal(23, result['x']);
-	ASSERT.equal(42, result['y']);
-
-	buffer = new Buffer(23);
-	for (ii = 0; ii < 23; ii++)
-		buffer[ii] = 0;
-
-	buffer.write('Hello, world!');
-	result = p.readData([ { x: { type: 'char[20]' }} ], buffer, 0);
-
-	/*
-	 * This is currently broken behvaior, need to redesign check
-	 * ASSERT.equal('Hello, world!', result['x'].toString('utf-8', 0,
-	 *  result['x'].length));
-	 */
-
-	buffer = new Buffer(4);
-	buffer[0] = 0x03;
-	buffer[1] = 0x24;
-	buffer[2] = 0x25;
-	buffer[3] = 0x26;
-	result = p.readData([ { y: { type: 'uint8_t' }},
-	    { x: { type: 'uint8_t[y]' }}], buffer, 0);
-	console.log(mod_sys.inspect(result, true));
-
-	p.typedef('ssize_t', 'int32_t');
-	ASSERT.deepEqual({ 'ssize_t': 'int32_t' }, p.lstypes());
-	result = p.readData([ { x: { type: 'ssize_t' } } ], buffer, 0);
-	ASSERT.equal(0x26252403, result['x']);
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js
deleted file mode 100644
index 89d446f2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Simple does it fucking work at all test
- */
-
-var mod_ctype = require('../../ctype');
-var ASSERT = require('assert');
-var mod_sys = require('sys');
-
-function test()
-{
-	var ii, p, buffer, buf2;
-
-	p = new mod_ctype.Parser({ endian: 'big' });
-	buffer = new Buffer(4);
-	p.writeData([ { x: { type: 'uint8_t', value: 23 }},
-	    { y: { type: 'uint8_t', offset: 3, value: 42 }}
-	], buffer, 0);
-	ASSERT.equal(23, buffer[0]);
-	ASSERT.equal(42, buffer[3]);
-
-	buffer = new Buffer(20);
-	for (ii = 0; ii < 20; ii++)
-		buffer[ii] = 0;
-
-	buffer.write('Hello, world!');
-	buf2 = new Buffer(22);
-	p.writeData([ { x: { type: 'char[20]', value: buffer }} ], buf2, 0);
-	for (ii = 0; ii < 20; ii++)
-		ASSERT.equal(buffer[ii], buf2[ii]);
-	/*
-	 * This is currently broken behvaior, need to redesign check
-	 * ASSERT.equal('Hello, world!', result['x'].toString('utf-8', 0,
-	 *   result['x'].length));
-	 */
-
-	buffer = new Buffer(4);
-	p.writeData([ { y: { type: 'uint8_t', value: 3 }},
-	    { x: { type: 'uint8_t[y]', value: [ 0x24, 0x25, 0x26] }}],
-	    buffer, 0);
-	console.log(mod_sys.inspect(buffer));
-
-	p.typedef('ssize_t', 'int32_t');
-	ASSERT.deepEqual({ 'ssize_t': 'int32_t' }, p.lstypes());
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js
deleted file mode 100644
index 14d9529c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Test the different forms of reading characters:
- *
- *  - the default, a single element buffer
- *  - uint8, values are uint8_ts
- *  - int8, values are int8_ts
- */
-var mod_ctype = require('../../ctype');
-var mod_assert = require('assert');
-
-function test()
-{
-	var p, buf, res;
-
-	buf = new Buffer(1);
-	buf[0] = 255;
-
-	p = new mod_ctype.Parser({ endian: 'little'});
-	res = p.readData([ { c: { type: 'char' }} ], buf, 0);
-	res = res['c'];
-	mod_assert.ok(res instanceof Buffer);
-	mod_assert.equal(255, res[0]);
-
-	p = new mod_ctype.Parser({ endian: 'little',
-	    'char-type': 'int8' });
-	res = p.readData([ { c: { type: 'char' }} ], buf, 0);
-	res = res['c'];
-	mod_assert.ok(typeof (res) == 'number', 'got typeof (res): ' +
-	    typeof (res));
-	mod_assert.equal(-1, res);
-
-	p = new mod_ctype.Parser({ endian: 'little',
-	    'char-type': 'uint8' });
-	res = p.readData([ { c: { type: 'char' }} ], buf, 0);
-	res = res['c'];
-	mod_assert.ok(typeof (res) == 'number', 'got typeof (res): ' +
-	    typeof (res));
-	mod_assert.equal(255, res);
-
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js
deleted file mode 100644
index 11fc2d2c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Simple test to make sure that the endian setting works.
- */
-
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var parser, buf;
-
-	parser = new mod_ctype.Parser({
-	    endian: 'little'
-	});
-
-	buf = new Buffer(2);
-	parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]);
-	mod_assert.equal(buf[0], 0x34);
-	mod_assert.equal(buf[1], 0x12);
-	parser.setEndian('big');
-
-	parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]);
-	mod_assert.equal(buf[0], 0x12);
-	mod_assert.equal(buf[1], 0x34);
-
-	parser.setEndian('little');
-	parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]);
-	mod_assert.equal(buf[0], 0x34);
-	mod_assert.equal(buf[1], 0x12);
-}
-
-function fail()
-{
-	var parser;
-
-	parser = new mod_ctype.Parser({
-	    endian: 'little'
-	});
-	mod_assert.throws(function () {
-		parser.setEndian('littlebigwrong');
-	});
-}
-
-test();
-fail();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js
deleted file mode 100644
index 9491cf6e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * A long overdue test to go through and verify that we can read and write
- * structures as well as nested structures.
- */
-
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var parser, buf, data;
-	parser = new mod_ctype.Parser({
-	    endian: 'little'
-	});
-	parser.typedef('point_t', [
-	    { x: { type: 'uint8_t' } },
-	    { y: { type: 'uint8_t' } }
-	]);
-	buf = new Buffer(2);
-	data = [
-	    { point: { type: 'point_t', value: [ 23, 42 ] } }
-	];
-	parser.writeData(data, buf, 0);
-	mod_assert.ok(buf[0] == 23);
-	mod_assert.ok(buf[1] == 42);
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js
deleted file mode 100644
index 6c490a2e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Testing to ensure we're reading the expected number bytes
- */
-var mod_ctype = require('../../ctype');
-var ASSERT = require('assert');
-
-function testUint8()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('80', 'hex');
-	result = parser.readStruct([ { item: { type: 'uint8_t' } } ], buffer,
-	    0);
-	ASSERT.equal(result['size'], 1);
-}
-
-function testSint8()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('80', 'hex');
-	result = parser.readStruct([ { item: { type: 'int8_t' } } ], buffer, 0);
-	ASSERT.equal(result['size'], 1);
-}
-
-function testUint16()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('8000', 'hex');
-	result = parser.readStruct([ { item: { type: 'uint16_t' } } ], buffer,
-	    0);
-	ASSERT.equal(result['size'], 2);
-}
-
-function testSint16()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('8000', 'hex');
-	result = parser.readStruct([ { item: { type: 'int16_t' } } ], buffer,
-	    0);
-	ASSERT.equal(result['size'], 2);
-}
-
-function testUint32()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('80000000', 'hex');
-	result = parser.readStruct([ { item: { type: 'uint32_t' } } ], buffer,
-	    0);
-	ASSERT.equal(result['size'], 4);
-}
-
-function testSint32()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('80000000', 'hex');
-	result = parser.readStruct([ { item: { type: 'int32_t' } } ], buffer,
-	    0);
-	ASSERT.equal(result['size'], 4);
-}
-
-function testUint64()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('8000000000000000', 'hex');
-	result = parser.readStruct([ { item: { type: 'uint64_t' } } ], buffer,
-	    0);
-	ASSERT.equal(result['size'], 8);
-}
-
-function testSint64()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('8000000000000000', 'hex');
-	result = parser.readStruct([ { item: { type: 'int64_t' } } ], buffer,
-	    0);
-	ASSERT.equal(result['size'], 8);
-}
-
-function testFloat()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('ABAAAA3E', 'hex');
-	result = parser.readStruct([ { item: { type: 'float' } } ], buffer, 0);
-	ASSERT.equal(result['size'], 4);
-}
-
-function testDouble()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('000000000000F03F', 'hex');
-	result = parser.readStruct([ { item: { type: 'double' } } ], buffer, 0);
-	ASSERT.equal(result['size'], 8);
-}
-
-function testChar()
-{
-	var parser, result, buffer;
-	parser = new mod_ctype.Parser({ endian: 'little' });
-	buffer = new Buffer('t');
-	result = parser.readStruct([ { item: { type: 'char' } } ], buffer, 0);
-	ASSERT.equal(result['size'], 1);
-}
-
-function test()
-{
-	testSint8();
-	testUint8();
-	testSint16();
-	testUint16();
-	testSint32();
-	testUint32();
-	testSint64();
-	testUint64();
-	testFloat();
-	testDouble();
-	testChar();
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js
deleted file mode 100644
index 09c1a5ba..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * A long overdue test to go through and verify that we can read and write
- * structures as well as nested structures.
- */
-
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var parser, buf, data;
-	parser = new mod_ctype.Parser({
-	    endian: 'little'
-	});
-	parser.typedef('point_t', [
-	    { x: { type: 'uint8_t' } },
-	    { y: { type: 'uint8_t' } }
-	]);
-	buf = new Buffer(2);
-	data = [
-	    { point: { type: 'point_t' } }
-	];
-	parser.writeData(data, buf, 0, [ [ 23, 42 ] ]);
-	mod_assert.ok(buf[0] == 23);
-	mod_assert.ok(buf[1] == 42);
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js
deleted file mode 100644
index 48556667..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Test to verify that the offset is incremented when structures are written to.
- * Hopefully we will not regress issue #41
- */
-
-var mod_ctype = require('../../ctype.js');
-var mod_assert = require('assert');
-
-function test()
-{
-	var parser, buf, data;
-	parser = new mod_ctype.Parser({
-	    endian: 'little'
-	});
-	parser.typedef('point_t', [
-	    { x: { type: 'uint8_t' } },
-	    { y: { type: 'uint8_t' } }
-	]);
-	buf = new Buffer(4);
-	data = [
-	    { point1: { type: 'point_t' } },
-	    { point2: { type: 'point_t' } }
-	];
-	parser.writeData(data, buf, 0, [ [ 23, 42 ], [ 91, 18 ] ]);
-	mod_assert.ok(buf[0] == 23);
-	mod_assert.ok(buf[1] == 42);
-	mod_assert.ok(buf[2] == 91);
-	mod_assert.ok(buf[3] == 18);
-}
-
-test();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/package.json
deleted file mode 100644
index 4e61e623..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/http-signature/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "author": {
-    "name": "Joyent, Inc"
-  },
-  "name": "http-signature",
-  "description": "Reference implementation of Joyent's HTTP Signature Scheme",
-  "version": "0.10.0",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/joyent/node-http-signature.git"
-  },
-  "engines": {
-    "node": ">=0.8"
-  },
-  "main": "lib/index.js",
-  "scripts": {
-    "test": "tap tst/*.js"
-  },
-  "dependencies": {
-    "assert-plus": "0.1.2",
-    "asn1": "0.1.11",
-    "ctype": "0.5.2"
-  },
-  "devDependencies": {
-    "node-uuid": "1.4.0",
-    "tap": "0.4.2"
-  },
-  "readme": "# node-http-signature\n\nnode-http-signature is a node.js library that has client and server components\nfor Joyent's [HTTP Signature Scheme](http_signing.md).\n\n## Usage\n\nNote the example below signs a request with the same key/cert used to start an\nHTTP server. This is almost certainly not what you actaully want, but is just\nused to illustrate the API calls; you will need to provide your own key\nmanagement in addition to this library.\n\n### Client\n\n    var fs = require('fs');\n    var https = require('https');\n    var httpSignature = require('http-signature');\n\n    var key = fs.readFileSync('./key.pem', 'ascii');\n\n    var options = {\n      host: 'localhost',\n      port: 8443,\n      path: '/',\n      method: 'GET',\n      headers: {}\n    };\n\n    // Adds a 'Date' header in, signs it, and adds the\n    // 'Authorization' header in.\n    var req = https.request(options, function(res) {\n      console.log(res.statusCode);\n    });\n\n\n    httpSignature.sign(req, {\n      key: key,\n      keyId: './cert.pem'\n    });\n\n    req.end();\n\n### Server\n\n    var fs = require('fs');\n    var https = require('https');\n    var httpSignature = require('http-signature');\n\n    var options = {\n      key: fs.readFileSync('./key.pem'),\n      cert: fs.readFileSync('./cert.pem')\n    };\n\n    https.createServer(options, function (req, res) {\n      var rc = 200;\n      var parsed = httpSignature.parseRequest(req);\n      var pub = fs.readFileSync(parsed.keyId, 'ascii');\n      if (!httpSignature.verifySignature(parsed, pub))\n        rc = 401;\n\n      res.writeHead(rc);\n      res.end();\n    }).listen(8443);\n\n## Installation\n\n    npm install http-signature\n\n## License\n\nMIT.\n\n## Bugs\n\nSee <https://github.com/joyent/node-http-signature/issues>.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/joyent/node-http-signature/issues"
-  },
-  "homepage": "https://github.com/joyent/node-http-signature",
-  "_id": "http-signature@0.10.0",
-  "_shasum": "1494e4f5000a83c0f11bcc12d6007c530cb99582",
-  "_from": "http-signature@~0.10.0",
-  "_resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/README.md
deleted file mode 100644
index 5d764f3a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# json-stringify-safe
-
-Like JSON.stringify, but doesn't throw on circular references.
-
-## Usage
-
-Takes the same arguments as `JSON.stringify`.
-
-```javascript
-var stringify = require('json-stringify-safe');
-var circularObj = {};
-circularObj.circularRef = circularObj;
-circularObj.list = [ circularObj, circularObj ];
-console.log(stringify(circularObj, null, 2));
-```
-
-Output:
-
-```json
-{
-  "circularRef": "[Circular]",
-  "list": [
-    "[Circular]",
-    "[Circular]"
-  ]
-}
-```
-
-## Details
-
-```
-stringify(obj, serializer, indent, decycler)
-```
-
-The first three arguments are the same as to JSON.stringify.  The last
-is an argument that's only used when the object has been seen already.
-
-The default `decycler` function returns the string `'[Circular]'`.
-If, for example, you pass in `function(k,v){}` (return nothing) then it
-will prune cycles.  If you pass in `function(k,v){ return {foo: 'bar'}}`,
-then cyclical objects will always be represented as `{"foo":"bar"}` in
-the result.
-
-```
-stringify.getSerialize(serializer, decycler)
-```
-
-Returns a serializer that can be used elsewhere.  This is the actual
-function that's passed to JSON.stringify.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/package.json
deleted file mode 100644
index db2c9aa2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "json-stringify-safe",
-  "version": "5.0.0",
-  "description": "Like JSON.stringify, but doesn't blow up on circular refs",
-  "main": "stringify.js",
-  "scripts": {
-    "test": "node test.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/json-stringify-safe"
-  },
-  "keywords": [
-    "json",
-    "stringify",
-    "circular",
-    "safe"
-  ],
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me"
-  },
-  "license": "BSD",
-  "readmeFilename": "README.md",
-  "readme": "# json-stringify-safe\n\nLike JSON.stringify, but doesn't throw on circular references.\n\n## Usage\n\nTakes the same arguments as `JSON.stringify`.\n\n```javascript\nvar stringify = require('json-stringify-safe');\nvar circularObj = {};\ncircularObj.circularRef = circularObj;\ncircularObj.list = [ circularObj, circularObj ];\nconsole.log(stringify(circularObj, null, 2));\n```\n\nOutput:\n\n```json\n{\n  \"circularRef\": \"[Circular]\",\n  \"list\": [\n    \"[Circular]\",\n    \"[Circular]\"\n  ]\n}\n```\n\n## Details\n\n```\nstringify(obj, serializer, indent, decycler)\n```\n\nThe first three arguments are the same as to JSON.stringify.  The last\nis an argument that's only used when the object has been seen already.\n\nThe default `decycler` function returns the string `'[Circular]'`.\nIf, for example, you pass in `function(k,v){}` (return nothing) then it\nwill prune cycles.  If you pass in `function(k,v){ return {foo: 'bar'}}`,\nthen cyclical objects will always be represented as `{\"foo\":\"bar\"}` in\nthe result.\n\n```\nstringify.getSerialize(serializer, decycler)\n```\n\nReturns a serializer that can be used elsewhere.  This is the actual\nfunction that's passed to JSON.stringify.\n",
-  "bugs": {
-    "url": "https://github.com/isaacs/json-stringify-safe/issues"
-  },
-  "homepage": "https://github.com/isaacs/json-stringify-safe",
-  "_id": "json-stringify-safe@5.0.0",
-  "_shasum": "4c1f228b5050837eba9d21f50c2e6e320624566e",
-  "_from": "json-stringify-safe@~5.0.0",
-  "_resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/stringify.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/stringify.js
deleted file mode 100644
index 853ef9b2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/stringify.js
+++ /dev/null
@@ -1,39 +0,0 @@
-module.exports = stringify;
-
-function getSerialize (fn, decycle) {
-  var seen = [], keys = [];
-  decycle = decycle || function(key, value) {
-    return '[Circular ' + getPath(value, seen, keys) + ']'
-  };
-  return function(key, value) {
-    var ret = value;
-    if (typeof value === 'object' && value) {
-      if (seen.indexOf(value) !== -1)
-        ret = decycle(key, value);
-      else {
-        seen.push(value);
-        keys.push(key);
-      }
-    }
-    if (fn) ret = fn(key, ret);
-    return ret;
-  }
-}
-
-function getPath (value, seen, keys) {
-  var index = seen.indexOf(value);
-  var path = [ keys[index] ];
-  for (index--; index >= 0; index--) {
-    if (seen[index][ path[0] ] === value) {
-      value = seen[index];
-      path.unshift(keys[index]);
-    }
-  }
-  return '~' + path.join('.');
-}
-
-function stringify(obj, fn, spaces, decycle) {
-  return JSON.stringify(obj, getSerialize(fn, decycle), spaces);
-}
-
-stringify.getSerialize = getSerialize;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/test.js
deleted file mode 100644
index 991e9197..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/json-stringify-safe/test.js
+++ /dev/null
@@ -1,128 +0,0 @@
-var stringify = require('./stringify.js');
-
-var circularObj = { a: 'b' };
-circularObj.circularRef = circularObj;
-circularObj.list = [ circularObj, circularObj ];
-
-//////////
-// default
-var testObj = {
-  "a": "b",
-  "circularRef": "[Circular ~]",
-  "list": [
-    "[Circular ~]",
-    "[Circular ~]"
-  ]
-};
-
-var assert = require('assert');
-assert.equal(JSON.stringify(testObj, null, 2),
-             stringify(circularObj, null, 2));
-
-assert.equal(JSON.stringify(testObj, null, 2),
-            JSON.stringify(circularObj, stringify.getSerialize(), 2));
-
-
-////////
-// prune
-testObj = {
-  "a": "b",
-  "list": [
-    null,
-    null
-  ]
-};
-
-function prune(k, v) {}
-
-assert.equal(JSON.stringify(testObj, null, 2),
-             stringify(circularObj, null, 2, prune));
-
-///////////
-// re-cycle
-// (throws)
-function recycle(k, v) {
-  return v;
-}
-
-assert.throws(function() {
-  stringify(circularObj, null, 2, recycle);
-});
-
-////////
-// fancy
-testObj = {
-  "a": "b",
-  "circularRef": "circularRef{a:string,circularRef:Object,list:Array}",
-  "list": [
-    "0{a:string,circularRef:Object,list:Array}",
-    "1{a:string,circularRef:Object,list:Array}"
-  ]
-};
-
-function signer(key, value) {
-  var ret = key + '{';
-  var f = false;
-  for (var i in value) {
-    if (f)
-      ret += ',';
-    f = true;
-    ret += i + ':';
-    var v = value[i];
-    switch (typeof v) {
-      case 'object':
-        if (!v)
-          ret += 'null';
-        else if (Array.isArray(v))
-          ret += 'Array'
-        else
-          ret += v.constructor && v.constructor.name || 'Object';
-        break;
-      default:
-        ret += typeof v;
-        break;
-    }
-  }
-  ret += '}';
-  return ret;
-}
-
-assert.equal(JSON.stringify(testObj, null, 2),
-             stringify(circularObj, null, 2, signer));
-
-
-///////
-//multi
-var a = { x: 1 };
-a.a = a;
-var b = { x: 2 };
-b.a = a;
-
-var c = { a: a, b: b };
-var d = { list: [ a, b, c ] };
-d.d = d;
-
-var multi = {
-  "list": [
-    {
-      "x": 1,
-      "a": "[Circular ~.list.0]"
-    },
-    {
-      "x": 2,
-      "a": "[Circular ~.list.0]"
-    },
-    {
-      "a": "[Circular ~.list.0]",
-      "b": "[Circular ~.list.1]"
-    }
-  ],
-  "d": "[Circular ~]"
-};
-
-assert.equal(JSON.stringify(multi, null, 2),
-             stringify(d, null, 2));
-
-////////
-// pass!
-console.log('ok');
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/LICENSE
deleted file mode 100644
index 451fc455..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/README.md
deleted file mode 100644
index 6ca19bd1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# mime
-
-Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.
-
-## Install
-
-Install with [npm](http://github.com/isaacs/npm):
-
-    npm install mime
-
-## API - Queries
-
-### mime.lookup(path)
-Get the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.
-
-    var mime = require('mime');
-
-    mime.lookup('/path/to/file.txt');         // => 'text/plain'
-    mime.lookup('file.txt');                  // => 'text/plain'
-    mime.lookup('.TXT');                      // => 'text/plain'
-    mime.lookup('htm');                       // => 'text/html'
-
-### mime.default_type
-Sets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)
-
-### mime.extension(type)
-Get the default extension for `type`
-
-    mime.extension('text/html');                 // => 'html'
-    mime.extension('application/octet-stream');  // => 'bin'
-
-### mime.charsets.lookup()
-
-Map mime-type to charset
-
-    mime.charsets.lookup('text/plain');        // => 'UTF-8'
-
-(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)
-
-## API - Defining Custom Types
-
-The following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).
-
-### mime.define()
-
-Add custom mime/extension mappings
-
-    mime.define({
-        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
-        'application/x-my-type': ['x-mt', 'x-mtt'],
-        // etc ...
-    });
-
-    mime.lookup('x-sft');                 // => 'text/x-some-format'
-
-The first entry in the extensions array is returned by `mime.extension()`. E.g.
-
-    mime.extension('text/x-some-format'); // => 'x-sf'
-
-### mime.load(filepath)
-
-Load mappings from an Apache ".types" format file
-
-    mime.load('./my_project.types');
-
-The .types file format is simple -  See the `types` dir for examples.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/mime.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/mime.js
deleted file mode 100644
index 48be0c5e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/mime.js
+++ /dev/null
@@ -1,114 +0,0 @@
-var path = require('path');
-var fs = require('fs');
-
-function Mime() {
-  // Map of extension -> mime type
-  this.types = Object.create(null);
-
-  // Map of mime type -> extension
-  this.extensions = Object.create(null);
-}
-
-/**
- * Define mimetype -> extension mappings.  Each key is a mime-type that maps
- * to an array of extensions associated with the type.  The first extension is
- * used as the default extension for the type.
- *
- * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
- *
- * @param map (Object) type definitions
- */
-Mime.prototype.define = function (map) {
-  for (var type in map) {
-    var exts = map[type];
-
-    for (var i = 0; i < exts.length; i++) {
-      if (process.env.DEBUG_MIME && this.types[exts]) {
-        console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
-          this.types[exts] + ' to ' + type);
-      }
-
-      this.types[exts[i]] = type;
-    }
-
-    // Default extension is the first one we encounter
-    if (!this.extensions[type]) {
-      this.extensions[type] = exts[0];
-    }
-  }
-};
-
-/**
- * Load an Apache2-style ".types" file
- *
- * This may be called multiple times (it's expected).  Where files declare
- * overlapping types/extensions, the last file wins.
- *
- * @param file (String) path of file to load.
- */
-Mime.prototype.load = function(file) {
-
-  this._loading = file;
-  // Read file and split into lines
-  var map = {},
-      content = fs.readFileSync(file, 'ascii'),
-      lines = content.split(/[\r\n]+/);
-
-  lines.forEach(function(line) {
-    // Clean up whitespace/comments, and split into fields
-    var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
-    map[fields.shift()] = fields;
-  });
-
-  this.define(map);
-
-  this._loading = null;
-};
-
-/**
- * Lookup a mime type based on extension
- */
-Mime.prototype.lookup = function(path, fallback) {
-  var ext = path.replace(/.*[\.\/\\]/, '').toLowerCase();
-
-  return this.types[ext] || fallback || this.default_type;
-};
-
-/**
- * Return file extension associated with a mime type
- */
-Mime.prototype.extension = function(mimeType) {
-  var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase();
-  return this.extensions[type];
-};
-
-// Default instance
-var mime = new Mime();
-
-// Load local copy of
-// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
-mime.load(path.join(__dirname, 'types/mime.types'));
-
-// Load additional types from node.js community
-mime.load(path.join(__dirname, 'types/node.types'));
-
-// Default type
-mime.default_type = mime.lookup('bin');
-
-//
-// Additional API specific to the default instance
-//
-
-mime.Mime = Mime;
-
-/**
- * Lookup a charset based on mime type.
- */
-mime.charsets = {
-  lookup: function(mimeType, fallback) {
-    // Assume text types are utf8
-    return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
-  }
-};
-
-module.exports = mime;
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/package.json
deleted file mode 100644
index e4e874d3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "author": {
-    "name": "Robert Kieffer",
-    "email": "robert@broofa.com",
-    "url": "http://github.com/broofa"
-  },
-  "contributors": [
-    {
-      "name": "Benjamin Thomas",
-      "email": "benjamin@benjaminthomas.org",
-      "url": "http://github.com/bentomas"
-    }
-  ],
-  "dependencies": {},
-  "description": "A comprehensive library for mime-type mapping",
-  "devDependencies": {},
-  "keywords": [
-    "util",
-    "mime"
-  ],
-  "main": "mime.js",
-  "name": "mime",
-  "repository": {
-    "url": "https://github.com/broofa/node-mime",
-    "type": "git"
-  },
-  "version": "1.2.11",
-  "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n    npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.\n\n    var mime = require('mime');\n\n    mime.lookup('/path/to/file.txt');         // => 'text/plain'\n    mime.lookup('file.txt');                  // => 'text/plain'\n    mime.lookup('.TXT');                      // => 'text/plain'\n    mime.lookup('htm');                       // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n    mime.extension('text/html');                 // => 'html'\n    mime.extension('application/octet-stream');  // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n    mime.charsets.lookup('text/plain');        // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n    mime.define({\n        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n        'application/x-my-type': ['x-mt', 'x-mtt'],\n        // etc ...\n    });\n\n    mime.lookup('x-sft');                 // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n    mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n    mime.load('./my_project.types');\n\nThe .types file format is simple -  See the `types` dir for examples.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/broofa/node-mime/issues"
-  },
-  "homepage": "https://github.com/broofa/node-mime",
-  "_id": "mime@1.2.11",
-  "_shasum": "58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10",
-  "_from": "mime@~1.2.9",
-  "_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/test.js
deleted file mode 100644
index 2cda1c7a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/test.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Usage: node test.js
- */
-
-var mime = require('./mime');
-var assert = require('assert');
-var path = require('path');
-
-function eq(a, b) {
-  console.log('Test: ' + a + ' === ' + b);
-  assert.strictEqual.apply(null, arguments);
-}
-
-console.log(Object.keys(mime.extensions).length + ' types');
-console.log(Object.keys(mime.types).length + ' extensions\n');
-
-//
-// Test mime lookups
-//
-
-eq('text/plain', mime.lookup('text.txt'));     // normal file
-eq('text/plain', mime.lookup('TEXT.TXT'));     // uppercase
-eq('text/plain', mime.lookup('dir/text.txt')); // dir + file
-eq('text/plain', mime.lookup('.text.txt'));    // hidden file
-eq('text/plain', mime.lookup('.txt'));         // nameless
-eq('text/plain', mime.lookup('txt'));          // extension-only
-eq('text/plain', mime.lookup('/txt'));         // extension-less ()
-eq('text/plain', mime.lookup('\\txt'));        // Windows, extension-less
-eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized
-eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default
-
-//
-// Test extensions
-//
-
-eq('txt', mime.extension(mime.types.text));
-eq('html', mime.extension(mime.types.htm));
-eq('bin', mime.extension('application/octet-stream'));
-eq('bin', mime.extension('application/octet-stream '));
-eq('html', mime.extension(' text/html; charset=UTF-8'));
-eq('html', mime.extension('text/html; charset=UTF-8 '));
-eq('html', mime.extension('text/html; charset=UTF-8'));
-eq('html', mime.extension('text/html ; charset=UTF-8'));
-eq('html', mime.extension('text/html;charset=UTF-8'));
-eq('html', mime.extension('text/Html;charset=UTF-8'));
-eq(undefined, mime.extension('unrecognized'));
-
-//
-// Test node.types lookups
-//
-
-eq('application/font-woff', mime.lookup('file.woff'));
-eq('application/octet-stream', mime.lookup('file.buffer'));
-eq('audio/mp4', mime.lookup('file.m4a'));
-eq('font/opentype', mime.lookup('file.otf'));
-
-//
-// Test charsets
-//
-
-eq('UTF-8', mime.charsets.lookup('text/plain'));
-eq(undefined, mime.charsets.lookup(mime.types.js));
-eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
-
-//
-// Test for overlaps between mime.types and node.types
-//
-
-var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime();
-apacheTypes.load(path.join(__dirname, 'types/mime.types'));
-nodeTypes.load(path.join(__dirname, 'types/node.types'));
-
-var keys = [].concat(Object.keys(apacheTypes.types))
-             .concat(Object.keys(nodeTypes.types));
-keys.sort();
-for (var i = 1; i < keys.length; i++) {
-  if (keys[i] == keys[i-1]) {
-    console.warn('Warning: ' +
-      'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] +
-      ', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]);
-  }
-}
-
-console.log('\nOK');
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/mime.types b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/mime.types
deleted file mode 100644
index da8cd691..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/mime.types
+++ /dev/null
@@ -1,1588 +0,0 @@
-# This file maps Internet media types to unique file extension(s).
-# Although created for httpd, this file is used by many software systems
-# and has been placed in the public domain for unlimited redisribution.
-#
-# The table below contains both registered and (common) unregistered types.
-# A type that has no unique extension can be ignored -- they are listed
-# here to guide configurations toward known types and to make it easier to
-# identify "new" types.  File extensions are also commonly used to indicate
-# content languages and encodings, so choose them carefully.
-#
-# Internet media types should be registered as described in RFC 4288.
-# The registry is at <http://www.iana.org/assignments/media-types/>.
-#
-# MIME type (lowercased)			Extensions
-# ============================================	==========
-# application/1d-interleaved-parityfec
-# application/3gpp-ims+xml
-# application/activemessage
-application/andrew-inset			ez
-# application/applefile
-application/applixware				aw
-application/atom+xml				atom
-application/atomcat+xml				atomcat
-# application/atomicmail
-application/atomsvc+xml				atomsvc
-# application/auth-policy+xml
-# application/batch-smtp
-# application/beep+xml
-# application/calendar+xml
-# application/cals-1840
-# application/ccmp+xml
-application/ccxml+xml				ccxml
-application/cdmi-capability			cdmia
-application/cdmi-container			cdmic
-application/cdmi-domain				cdmid
-application/cdmi-object				cdmio
-application/cdmi-queue				cdmiq
-# application/cea-2018+xml
-# application/cellml+xml
-# application/cfw
-# application/cnrp+xml
-# application/commonground
-# application/conference-info+xml
-# application/cpl+xml
-# application/csta+xml
-# application/cstadata+xml
-application/cu-seeme				cu
-# application/cybercash
-application/davmount+xml			davmount
-# application/dca-rft
-# application/dec-dx
-# application/dialog-info+xml
-# application/dicom
-# application/dns
-application/docbook+xml				dbk
-# application/dskpp+xml
-application/dssc+der				dssc
-application/dssc+xml				xdssc
-# application/dvcs
-application/ecmascript				ecma
-# application/edi-consent
-# application/edi-x12
-# application/edifact
-application/emma+xml				emma
-# application/epp+xml
-application/epub+zip				epub
-# application/eshop
-# application/example
-application/exi					exi
-# application/fastinfoset
-# application/fastsoap
-# application/fits
-application/font-tdpfr				pfr
-# application/framework-attributes+xml
-application/gml+xml				gml
-application/gpx+xml				gpx
-application/gxf					gxf
-# application/h224
-# application/held+xml
-# application/http
-application/hyperstudio				stk
-# application/ibe-key-request+xml
-# application/ibe-pkg-reply+xml
-# application/ibe-pp-data
-# application/iges
-# application/im-iscomposing+xml
-# application/index
-# application/index.cmd
-# application/index.obj
-# application/index.response
-# application/index.vnd
-application/inkml+xml				ink inkml
-# application/iotp
-application/ipfix				ipfix
-# application/ipp
-# application/isup
-application/java-archive			jar
-application/java-serialized-object		ser
-application/java-vm				class
-application/javascript				js
-application/json				json
-application/jsonml+json				jsonml
-# application/kpml-request+xml
-# application/kpml-response+xml
-application/lost+xml				lostxml
-application/mac-binhex40			hqx
-application/mac-compactpro			cpt
-# application/macwriteii
-application/mads+xml				mads
-application/marc				mrc
-application/marcxml+xml				mrcx
-application/mathematica				ma nb mb
-# application/mathml-content+xml
-# application/mathml-presentation+xml
-application/mathml+xml				mathml
-# application/mbms-associated-procedure-description+xml
-# application/mbms-deregister+xml
-# application/mbms-envelope+xml
-# application/mbms-msk+xml
-# application/mbms-msk-response+xml
-# application/mbms-protection-description+xml
-# application/mbms-reception-report+xml
-# application/mbms-register+xml
-# application/mbms-register-response+xml
-# application/mbms-user-service-description+xml
-application/mbox				mbox
-# application/media_control+xml
-application/mediaservercontrol+xml		mscml
-application/metalink+xml			metalink
-application/metalink4+xml			meta4
-application/mets+xml				mets
-# application/mikey
-application/mods+xml				mods
-# application/moss-keys
-# application/moss-signature
-# application/mosskey-data
-# application/mosskey-request
-application/mp21				m21 mp21
-application/mp4					mp4s
-# application/mpeg4-generic
-# application/mpeg4-iod
-# application/mpeg4-iod-xmt
-# application/msc-ivr+xml
-# application/msc-mixer+xml
-application/msword				doc dot
-application/mxf					mxf
-# application/nasdata
-# application/news-checkgroups
-# application/news-groupinfo
-# application/news-transmission
-# application/nss
-# application/ocsp-request
-# application/ocsp-response
-application/octet-stream	bin dms lrf mar so dist distz pkg bpk dump elc deploy
-application/oda					oda
-application/oebps-package+xml			opf
-application/ogg					ogx
-application/omdoc+xml				omdoc
-application/onenote				onetoc onetoc2 onetmp onepkg
-application/oxps				oxps
-# application/parityfec
-application/patch-ops-error+xml			xer
-application/pdf					pdf
-application/pgp-encrypted			pgp
-# application/pgp-keys
-application/pgp-signature			asc sig
-application/pics-rules				prf
-# application/pidf+xml
-# application/pidf-diff+xml
-application/pkcs10				p10
-application/pkcs7-mime				p7m p7c
-application/pkcs7-signature			p7s
-application/pkcs8				p8
-application/pkix-attr-cert			ac
-application/pkix-cert				cer
-application/pkix-crl				crl
-application/pkix-pkipath			pkipath
-application/pkixcmp				pki
-application/pls+xml				pls
-# application/poc-settings+xml
-application/postscript				ai eps ps
-# application/prs.alvestrand.titrax-sheet
-application/prs.cww				cww
-# application/prs.nprend
-# application/prs.plucker
-# application/prs.rdf-xml-crypt
-# application/prs.xsf+xml
-application/pskc+xml				pskcxml
-# application/qsig
-application/rdf+xml				rdf
-application/reginfo+xml				rif
-application/relax-ng-compact-syntax		rnc
-# application/remote-printing
-application/resource-lists+xml			rl
-application/resource-lists-diff+xml		rld
-# application/riscos
-# application/rlmi+xml
-application/rls-services+xml			rs
-application/rpki-ghostbusters			gbr
-application/rpki-manifest			mft
-application/rpki-roa				roa
-# application/rpki-updown
-application/rsd+xml				rsd
-application/rss+xml				rss
-application/rtf					rtf
-# application/rtx
-# application/samlassertion+xml
-# application/samlmetadata+xml
-application/sbml+xml				sbml
-application/scvp-cv-request			scq
-application/scvp-cv-response			scs
-application/scvp-vp-request			spq
-application/scvp-vp-response			spp
-application/sdp					sdp
-# application/set-payment
-application/set-payment-initiation		setpay
-# application/set-registration
-application/set-registration-initiation		setreg
-# application/sgml
-# application/sgml-open-catalog
-application/shf+xml				shf
-# application/sieve
-# application/simple-filter+xml
-# application/simple-message-summary
-# application/simplesymbolcontainer
-# application/slate
-# application/smil
-application/smil+xml				smi smil
-# application/soap+fastinfoset
-# application/soap+xml
-application/sparql-query			rq
-application/sparql-results+xml			srx
-# application/spirits-event+xml
-application/srgs				gram
-application/srgs+xml				grxml
-application/sru+xml				sru
-application/ssdl+xml				ssdl
-application/ssml+xml				ssml
-# application/tamp-apex-update
-# application/tamp-apex-update-confirm
-# application/tamp-community-update
-# application/tamp-community-update-confirm
-# application/tamp-error
-# application/tamp-sequence-adjust
-# application/tamp-sequence-adjust-confirm
-# application/tamp-status-query
-# application/tamp-status-response
-# application/tamp-update
-# application/tamp-update-confirm
-application/tei+xml				tei teicorpus
-application/thraud+xml				tfi
-# application/timestamp-query
-# application/timestamp-reply
-application/timestamped-data			tsd
-# application/tve-trigger
-# application/ulpfec
-# application/vcard+xml
-# application/vemmi
-# application/vividence.scriptfile
-# application/vnd.3gpp.bsf+xml
-application/vnd.3gpp.pic-bw-large		plb
-application/vnd.3gpp.pic-bw-small		psb
-application/vnd.3gpp.pic-bw-var			pvb
-# application/vnd.3gpp.sms
-# application/vnd.3gpp2.bcmcsinfo+xml
-# application/vnd.3gpp2.sms
-application/vnd.3gpp2.tcap			tcap
-application/vnd.3m.post-it-notes		pwn
-application/vnd.accpac.simply.aso		aso
-application/vnd.accpac.simply.imp		imp
-application/vnd.acucobol			acu
-application/vnd.acucorp				atc acutc
-application/vnd.adobe.air-application-installer-package+zip	air
-application/vnd.adobe.formscentral.fcdt		fcdt
-application/vnd.adobe.fxp			fxp fxpl
-# application/vnd.adobe.partial-upload
-application/vnd.adobe.xdp+xml			xdp
-application/vnd.adobe.xfdf			xfdf
-# application/vnd.aether.imp
-# application/vnd.ah-barcode
-application/vnd.ahead.space			ahead
-application/vnd.airzip.filesecure.azf		azf
-application/vnd.airzip.filesecure.azs		azs
-application/vnd.amazon.ebook			azw
-application/vnd.americandynamics.acc		acc
-application/vnd.amiga.ami			ami
-# application/vnd.amundsen.maze+xml
-application/vnd.android.package-archive		apk
-application/vnd.anser-web-certificate-issue-initiation	cii
-application/vnd.anser-web-funds-transfer-initiation	fti
-application/vnd.antix.game-component		atx
-application/vnd.apple.installer+xml		mpkg
-application/vnd.apple.mpegurl			m3u8
-# application/vnd.arastra.swi
-application/vnd.aristanetworks.swi		swi
-application/vnd.astraea-software.iota		iota
-application/vnd.audiograph			aep
-# application/vnd.autopackage
-# application/vnd.avistar+xml
-application/vnd.blueice.multipass		mpm
-# application/vnd.bluetooth.ep.oob
-application/vnd.bmi				bmi
-application/vnd.businessobjects			rep
-# application/vnd.cab-jscript
-# application/vnd.canon-cpdl
-# application/vnd.canon-lips
-# application/vnd.cendio.thinlinc.clientconf
-application/vnd.chemdraw+xml			cdxml
-application/vnd.chipnuts.karaoke-mmd		mmd
-application/vnd.cinderella			cdy
-# application/vnd.cirpack.isdn-ext
-application/vnd.claymore			cla
-application/vnd.cloanto.rp9			rp9
-application/vnd.clonk.c4group			c4g c4d c4f c4p c4u
-application/vnd.cluetrust.cartomobile-config		c11amc
-application/vnd.cluetrust.cartomobile-config-pkg	c11amz
-# application/vnd.collection+json
-# application/vnd.commerce-battelle
-application/vnd.commonspace			csp
-application/vnd.contact.cmsg			cdbcmsg
-application/vnd.cosmocaller			cmc
-application/vnd.crick.clicker			clkx
-application/vnd.crick.clicker.keyboard		clkk
-application/vnd.crick.clicker.palette		clkp
-application/vnd.crick.clicker.template		clkt
-application/vnd.crick.clicker.wordbank		clkw
-application/vnd.criticaltools.wbs+xml		wbs
-application/vnd.ctc-posml			pml
-# application/vnd.ctct.ws+xml
-# application/vnd.cups-pdf
-# application/vnd.cups-postscript
-application/vnd.cups-ppd			ppd
-# application/vnd.cups-raster
-# application/vnd.cups-raw
-# application/vnd.curl
-application/vnd.curl.car			car
-application/vnd.curl.pcurl			pcurl
-# application/vnd.cybank
-application/vnd.dart				dart
-application/vnd.data-vision.rdz			rdz
-application/vnd.dece.data			uvf uvvf uvd uvvd
-application/vnd.dece.ttml+xml			uvt uvvt
-application/vnd.dece.unspecified		uvx uvvx
-application/vnd.dece.zip			uvz uvvz
-application/vnd.denovo.fcselayout-link		fe_launch
-# application/vnd.dir-bi.plate-dl-nosuffix
-application/vnd.dna				dna
-application/vnd.dolby.mlp			mlp
-# application/vnd.dolby.mobile.1
-# application/vnd.dolby.mobile.2
-application/vnd.dpgraph				dpg
-application/vnd.dreamfactory			dfac
-application/vnd.ds-keypoint			kpxx
-application/vnd.dvb.ait				ait
-# application/vnd.dvb.dvbj
-# application/vnd.dvb.esgcontainer
-# application/vnd.dvb.ipdcdftnotifaccess
-# application/vnd.dvb.ipdcesgaccess
-# application/vnd.dvb.ipdcesgaccess2
-# application/vnd.dvb.ipdcesgpdd
-# application/vnd.dvb.ipdcroaming
-# application/vnd.dvb.iptv.alfec-base
-# application/vnd.dvb.iptv.alfec-enhancement
-# application/vnd.dvb.notif-aggregate-root+xml
-# application/vnd.dvb.notif-container+xml
-# application/vnd.dvb.notif-generic+xml
-# application/vnd.dvb.notif-ia-msglist+xml
-# application/vnd.dvb.notif-ia-registration-request+xml
-# application/vnd.dvb.notif-ia-registration-response+xml
-# application/vnd.dvb.notif-init+xml
-# application/vnd.dvb.pfr
-application/vnd.dvb.service			svc
-# application/vnd.dxr
-application/vnd.dynageo				geo
-# application/vnd.easykaraoke.cdgdownload
-# application/vnd.ecdis-update
-application/vnd.ecowin.chart			mag
-# application/vnd.ecowin.filerequest
-# application/vnd.ecowin.fileupdate
-# application/vnd.ecowin.series
-# application/vnd.ecowin.seriesrequest
-# application/vnd.ecowin.seriesupdate
-# application/vnd.emclient.accessrequest+xml
-application/vnd.enliven				nml
-# application/vnd.eprints.data+xml
-application/vnd.epson.esf			esf
-application/vnd.epson.msf			msf
-application/vnd.epson.quickanime		qam
-application/vnd.epson.salt			slt
-application/vnd.epson.ssf			ssf
-# application/vnd.ericsson.quickcall
-application/vnd.eszigno3+xml			es3 et3
-# application/vnd.etsi.aoc+xml
-# application/vnd.etsi.cug+xml
-# application/vnd.etsi.iptvcommand+xml
-# application/vnd.etsi.iptvdiscovery+xml
-# application/vnd.etsi.iptvprofile+xml
-# application/vnd.etsi.iptvsad-bc+xml
-# application/vnd.etsi.iptvsad-cod+xml
-# application/vnd.etsi.iptvsad-npvr+xml
-# application/vnd.etsi.iptvservice+xml
-# application/vnd.etsi.iptvsync+xml
-# application/vnd.etsi.iptvueprofile+xml
-# application/vnd.etsi.mcid+xml
-# application/vnd.etsi.overload-control-policy-dataset+xml
-# application/vnd.etsi.sci+xml
-# application/vnd.etsi.simservs+xml
-# application/vnd.etsi.tsl+xml
-# application/vnd.etsi.tsl.der
-# application/vnd.eudora.data
-application/vnd.ezpix-album			ez2
-application/vnd.ezpix-package			ez3
-# application/vnd.f-secure.mobile
-application/vnd.fdf				fdf
-application/vnd.fdsn.mseed			mseed
-application/vnd.fdsn.seed			seed dataless
-# application/vnd.ffsns
-# application/vnd.fints
-application/vnd.flographit			gph
-application/vnd.fluxtime.clip			ftc
-# application/vnd.font-fontforge-sfd
-application/vnd.framemaker			fm frame maker book
-application/vnd.frogans.fnc			fnc
-application/vnd.frogans.ltf			ltf
-application/vnd.fsc.weblaunch			fsc
-application/vnd.fujitsu.oasys			oas
-application/vnd.fujitsu.oasys2			oa2
-application/vnd.fujitsu.oasys3			oa3
-application/vnd.fujitsu.oasysgp			fg5
-application/vnd.fujitsu.oasysprs		bh2
-# application/vnd.fujixerox.art-ex
-# application/vnd.fujixerox.art4
-# application/vnd.fujixerox.hbpl
-application/vnd.fujixerox.ddd			ddd
-application/vnd.fujixerox.docuworks		xdw
-application/vnd.fujixerox.docuworks.binder	xbd
-# application/vnd.fut-misnet
-application/vnd.fuzzysheet			fzs
-application/vnd.genomatix.tuxedo		txd
-# application/vnd.geocube+xml
-application/vnd.geogebra.file			ggb
-application/vnd.geogebra.tool			ggt
-application/vnd.geometry-explorer		gex gre
-application/vnd.geonext				gxt
-application/vnd.geoplan				g2w
-application/vnd.geospace			g3w
-# application/vnd.globalplatform.card-content-mgt
-# application/vnd.globalplatform.card-content-mgt-response
-application/vnd.gmx				gmx
-application/vnd.google-earth.kml+xml		kml
-application/vnd.google-earth.kmz		kmz
-application/vnd.grafeq				gqf gqs
-# application/vnd.gridmp
-application/vnd.groove-account			gac
-application/vnd.groove-help			ghf
-application/vnd.groove-identity-message		gim
-application/vnd.groove-injector			grv
-application/vnd.groove-tool-message		gtm
-application/vnd.groove-tool-template		tpl
-application/vnd.groove-vcard			vcg
-# application/vnd.hal+json
-application/vnd.hal+xml				hal
-application/vnd.handheld-entertainment+xml	zmm
-application/vnd.hbci				hbci
-# application/vnd.hcl-bireports
-application/vnd.hhe.lesson-player		les
-application/vnd.hp-hpgl				hpgl
-application/vnd.hp-hpid				hpid
-application/vnd.hp-hps				hps
-application/vnd.hp-jlyt				jlt
-application/vnd.hp-pcl				pcl
-application/vnd.hp-pclxl			pclxl
-# application/vnd.httphone
-application/vnd.hydrostatix.sof-data		sfd-hdstx
-# application/vnd.hzn-3d-crossword
-# application/vnd.ibm.afplinedata
-# application/vnd.ibm.electronic-media
-application/vnd.ibm.minipay			mpy
-application/vnd.ibm.modcap			afp listafp list3820
-application/vnd.ibm.rights-management		irm
-application/vnd.ibm.secure-container		sc
-application/vnd.iccprofile			icc icm
-application/vnd.igloader			igl
-application/vnd.immervision-ivp			ivp
-application/vnd.immervision-ivu			ivu
-# application/vnd.informedcontrol.rms+xml
-# application/vnd.informix-visionary
-# application/vnd.infotech.project
-# application/vnd.infotech.project+xml
-# application/vnd.innopath.wamp.notification
-application/vnd.insors.igm			igm
-application/vnd.intercon.formnet		xpw xpx
-application/vnd.intergeo			i2g
-# application/vnd.intertrust.digibox
-# application/vnd.intertrust.nncp
-application/vnd.intu.qbo			qbo
-application/vnd.intu.qfx			qfx
-# application/vnd.iptc.g2.conceptitem+xml
-# application/vnd.iptc.g2.knowledgeitem+xml
-# application/vnd.iptc.g2.newsitem+xml
-# application/vnd.iptc.g2.newsmessage+xml
-# application/vnd.iptc.g2.packageitem+xml
-# application/vnd.iptc.g2.planningitem+xml
-application/vnd.ipunplugged.rcprofile		rcprofile
-application/vnd.irepository.package+xml		irp
-application/vnd.is-xpr				xpr
-application/vnd.isac.fcs			fcs
-application/vnd.jam				jam
-# application/vnd.japannet-directory-service
-# application/vnd.japannet-jpnstore-wakeup
-# application/vnd.japannet-payment-wakeup
-# application/vnd.japannet-registration
-# application/vnd.japannet-registration-wakeup
-# application/vnd.japannet-setstore-wakeup
-# application/vnd.japannet-verification
-# application/vnd.japannet-verification-wakeup
-application/vnd.jcp.javame.midlet-rms		rms
-application/vnd.jisp				jisp
-application/vnd.joost.joda-archive		joda
-application/vnd.kahootz				ktz ktr
-application/vnd.kde.karbon			karbon
-application/vnd.kde.kchart			chrt
-application/vnd.kde.kformula			kfo
-application/vnd.kde.kivio			flw
-application/vnd.kde.kontour			kon
-application/vnd.kde.kpresenter			kpr kpt
-application/vnd.kde.kspread			ksp
-application/vnd.kde.kword			kwd kwt
-application/vnd.kenameaapp			htke
-application/vnd.kidspiration			kia
-application/vnd.kinar				kne knp
-application/vnd.koan				skp skd skt skm
-application/vnd.kodak-descriptor		sse
-application/vnd.las.las+xml			lasxml
-# application/vnd.liberty-request+xml
-application/vnd.llamagraphics.life-balance.desktop	lbd
-application/vnd.llamagraphics.life-balance.exchange+xml	lbe
-application/vnd.lotus-1-2-3			123
-application/vnd.lotus-approach			apr
-application/vnd.lotus-freelance			pre
-application/vnd.lotus-notes			nsf
-application/vnd.lotus-organizer			org
-application/vnd.lotus-screencam			scm
-application/vnd.lotus-wordpro			lwp
-application/vnd.macports.portpkg		portpkg
-# application/vnd.marlin.drm.actiontoken+xml
-# application/vnd.marlin.drm.conftoken+xml
-# application/vnd.marlin.drm.license+xml
-# application/vnd.marlin.drm.mdcf
-application/vnd.mcd				mcd
-application/vnd.medcalcdata			mc1
-application/vnd.mediastation.cdkey		cdkey
-# application/vnd.meridian-slingshot
-application/vnd.mfer				mwf
-application/vnd.mfmp				mfm
-application/vnd.micrografx.flo			flo
-application/vnd.micrografx.igx			igx
-application/vnd.mif				mif
-# application/vnd.minisoft-hp3000-save
-# application/vnd.mitsubishi.misty-guard.trustweb
-application/vnd.mobius.daf			daf
-application/vnd.mobius.dis			dis
-application/vnd.mobius.mbk			mbk
-application/vnd.mobius.mqy			mqy
-application/vnd.mobius.msl			msl
-application/vnd.mobius.plc			plc
-application/vnd.mobius.txf			txf
-application/vnd.mophun.application		mpn
-application/vnd.mophun.certificate		mpc
-# application/vnd.motorola.flexsuite
-# application/vnd.motorola.flexsuite.adsi
-# application/vnd.motorola.flexsuite.fis
-# application/vnd.motorola.flexsuite.gotap
-# application/vnd.motorola.flexsuite.kmr
-# application/vnd.motorola.flexsuite.ttc
-# application/vnd.motorola.flexsuite.wem
-# application/vnd.motorola.iprm
-application/vnd.mozilla.xul+xml			xul
-application/vnd.ms-artgalry			cil
-# application/vnd.ms-asf
-application/vnd.ms-cab-compressed		cab
-# application/vnd.ms-color.iccprofile
-application/vnd.ms-excel			xls xlm xla xlc xlt xlw
-application/vnd.ms-excel.addin.macroenabled.12		xlam
-application/vnd.ms-excel.sheet.binary.macroenabled.12	xlsb
-application/vnd.ms-excel.sheet.macroenabled.12		xlsm
-application/vnd.ms-excel.template.macroenabled.12	xltm
-application/vnd.ms-fontobject			eot
-application/vnd.ms-htmlhelp			chm
-application/vnd.ms-ims				ims
-application/vnd.ms-lrm				lrm
-# application/vnd.ms-office.activex+xml
-application/vnd.ms-officetheme			thmx
-# application/vnd.ms-opentype
-# application/vnd.ms-package.obfuscated-opentype
-application/vnd.ms-pki.seccat			cat
-application/vnd.ms-pki.stl			stl
-# application/vnd.ms-playready.initiator+xml
-application/vnd.ms-powerpoint			ppt pps pot
-application/vnd.ms-powerpoint.addin.macroenabled.12		ppam
-application/vnd.ms-powerpoint.presentation.macroenabled.12	pptm
-application/vnd.ms-powerpoint.slide.macroenabled.12		sldm
-application/vnd.ms-powerpoint.slideshow.macroenabled.12		ppsm
-application/vnd.ms-powerpoint.template.macroenabled.12		potm
-# application/vnd.ms-printing.printticket+xml
-application/vnd.ms-project			mpp mpt
-# application/vnd.ms-tnef
-# application/vnd.ms-wmdrm.lic-chlg-req
-# application/vnd.ms-wmdrm.lic-resp
-# application/vnd.ms-wmdrm.meter-chlg-req
-# application/vnd.ms-wmdrm.meter-resp
-application/vnd.ms-word.document.macroenabled.12	docm
-application/vnd.ms-word.template.macroenabled.12	dotm
-application/vnd.ms-works			wps wks wcm wdb
-application/vnd.ms-wpl				wpl
-application/vnd.ms-xpsdocument			xps
-application/vnd.mseq				mseq
-# application/vnd.msign
-# application/vnd.multiad.creator
-# application/vnd.multiad.creator.cif
-# application/vnd.music-niff
-application/vnd.musician			mus
-application/vnd.muvee.style			msty
-application/vnd.mynfc				taglet
-# application/vnd.ncd.control
-# application/vnd.ncd.reference
-# application/vnd.nervana
-# application/vnd.netfpx
-application/vnd.neurolanguage.nlu		nlu
-application/vnd.nitf				ntf nitf
-application/vnd.noblenet-directory		nnd
-application/vnd.noblenet-sealer			nns
-application/vnd.noblenet-web			nnw
-# application/vnd.nokia.catalogs
-# application/vnd.nokia.conml+wbxml
-# application/vnd.nokia.conml+xml
-# application/vnd.nokia.isds-radio-presets
-# application/vnd.nokia.iptv.config+xml
-# application/vnd.nokia.landmark+wbxml
-# application/vnd.nokia.landmark+xml
-# application/vnd.nokia.landmarkcollection+xml
-# application/vnd.nokia.n-gage.ac+xml
-application/vnd.nokia.n-gage.data		ngdat
-application/vnd.nokia.n-gage.symbian.install	n-gage
-# application/vnd.nokia.ncd
-# application/vnd.nokia.pcd+wbxml
-# application/vnd.nokia.pcd+xml
-application/vnd.nokia.radio-preset		rpst
-application/vnd.nokia.radio-presets		rpss
-application/vnd.novadigm.edm			edm
-application/vnd.novadigm.edx			edx
-application/vnd.novadigm.ext			ext
-# application/vnd.ntt-local.file-transfer
-# application/vnd.ntt-local.sip-ta_remote
-# application/vnd.ntt-local.sip-ta_tcp_stream
-application/vnd.oasis.opendocument.chart		odc
-application/vnd.oasis.opendocument.chart-template	otc
-application/vnd.oasis.opendocument.database		odb
-application/vnd.oasis.opendocument.formula		odf
-application/vnd.oasis.opendocument.formula-template	odft
-application/vnd.oasis.opendocument.graphics		odg
-application/vnd.oasis.opendocument.graphics-template	otg
-application/vnd.oasis.opendocument.image		odi
-application/vnd.oasis.opendocument.image-template	oti
-application/vnd.oasis.opendocument.presentation		odp
-application/vnd.oasis.opendocument.presentation-template	otp
-application/vnd.oasis.opendocument.spreadsheet		ods
-application/vnd.oasis.opendocument.spreadsheet-template	ots
-application/vnd.oasis.opendocument.text			odt
-application/vnd.oasis.opendocument.text-master		odm
-application/vnd.oasis.opendocument.text-template	ott
-application/vnd.oasis.opendocument.text-web		oth
-# application/vnd.obn
-# application/vnd.oftn.l10n+json
-# application/vnd.oipf.contentaccessdownload+xml
-# application/vnd.oipf.contentaccessstreaming+xml
-# application/vnd.oipf.cspg-hexbinary
-# application/vnd.oipf.dae.svg+xml
-# application/vnd.oipf.dae.xhtml+xml
-# application/vnd.oipf.mippvcontrolmessage+xml
-# application/vnd.oipf.pae.gem
-# application/vnd.oipf.spdiscovery+xml
-# application/vnd.oipf.spdlist+xml
-# application/vnd.oipf.ueprofile+xml
-# application/vnd.oipf.userprofile+xml
-application/vnd.olpc-sugar			xo
-# application/vnd.oma-scws-config
-# application/vnd.oma-scws-http-request
-# application/vnd.oma-scws-http-response
-# application/vnd.oma.bcast.associated-procedure-parameter+xml
-# application/vnd.oma.bcast.drm-trigger+xml
-# application/vnd.oma.bcast.imd+xml
-# application/vnd.oma.bcast.ltkm
-# application/vnd.oma.bcast.notification+xml
-# application/vnd.oma.bcast.provisioningtrigger
-# application/vnd.oma.bcast.sgboot
-# application/vnd.oma.bcast.sgdd+xml
-# application/vnd.oma.bcast.sgdu
-# application/vnd.oma.bcast.simple-symbol-container
-# application/vnd.oma.bcast.smartcard-trigger+xml
-# application/vnd.oma.bcast.sprov+xml
-# application/vnd.oma.bcast.stkm
-# application/vnd.oma.cab-address-book+xml
-# application/vnd.oma.cab-feature-handler+xml
-# application/vnd.oma.cab-pcc+xml
-# application/vnd.oma.cab-user-prefs+xml
-# application/vnd.oma.dcd
-# application/vnd.oma.dcdc
-application/vnd.oma.dd2+xml			dd2
-# application/vnd.oma.drm.risd+xml
-# application/vnd.oma.group-usage-list+xml
-# application/vnd.oma.pal+xml
-# application/vnd.oma.poc.detailed-progress-report+xml
-# application/vnd.oma.poc.final-report+xml
-# application/vnd.oma.poc.groups+xml
-# application/vnd.oma.poc.invocation-descriptor+xml
-# application/vnd.oma.poc.optimized-progress-report+xml
-# application/vnd.oma.push
-# application/vnd.oma.scidm.messages+xml
-# application/vnd.oma.xcap-directory+xml
-# application/vnd.omads-email+xml
-# application/vnd.omads-file+xml
-# application/vnd.omads-folder+xml
-# application/vnd.omaloc-supl-init
-application/vnd.openofficeorg.extension		oxt
-# application/vnd.openxmlformats-officedocument.custom-properties+xml
-# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
-# application/vnd.openxmlformats-officedocument.drawing+xml
-# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
-# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
-# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
-# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
-# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
-# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
-# application/vnd.openxmlformats-officedocument.extended-properties+xml
-# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
-# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
-# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
-# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
-# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
-application/vnd.openxmlformats-officedocument.presentationml.presentation	pptx
-# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
-# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
-application/vnd.openxmlformats-officedocument.presentationml.slide	sldx
-# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
-# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
-# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
-application/vnd.openxmlformats-officedocument.presentationml.slideshow	ppsx
-# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
-# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
-# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
-# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
-application/vnd.openxmlformats-officedocument.presentationml.template	potx
-# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
-# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
-application/vnd.openxmlformats-officedocument.spreadsheetml.sheet	xlsx
-# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
-application/vnd.openxmlformats-officedocument.spreadsheetml.template	xltx
-# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
-# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
-# application/vnd.openxmlformats-officedocument.theme+xml
-# application/vnd.openxmlformats-officedocument.themeoverride+xml
-# application/vnd.openxmlformats-officedocument.vmldrawing
-# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
-application/vnd.openxmlformats-officedocument.wordprocessingml.document	docx
-# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
-application/vnd.openxmlformats-officedocument.wordprocessingml.template	dotx
-# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
-# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
-# application/vnd.openxmlformats-package.core-properties+xml
-# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
-# application/vnd.openxmlformats-package.relationships+xml
-# application/vnd.quobject-quoxdocument
-# application/vnd.osa.netdeploy
-application/vnd.osgeo.mapguide.package		mgp
-# application/vnd.osgi.bundle
-application/vnd.osgi.dp				dp
-application/vnd.osgi.subsystem			esa
-# application/vnd.otps.ct-kip+xml
-application/vnd.palm				pdb pqa oprc
-# application/vnd.paos.xml
-application/vnd.pawaafile			paw
-application/vnd.pg.format			str
-application/vnd.pg.osasli			ei6
-# application/vnd.piaccess.application-licence
-application/vnd.picsel				efif
-application/vnd.pmi.widget			wg
-# application/vnd.poc.group-advertisement+xml
-application/vnd.pocketlearn			plf
-application/vnd.powerbuilder6			pbd
-# application/vnd.powerbuilder6-s
-# application/vnd.powerbuilder7
-# application/vnd.powerbuilder7-s
-# application/vnd.powerbuilder75
-# application/vnd.powerbuilder75-s
-# application/vnd.preminet
-application/vnd.previewsystems.box		box
-application/vnd.proteus.magazine		mgz
-application/vnd.publishare-delta-tree		qps
-application/vnd.pvi.ptid1			ptid
-# application/vnd.pwg-multiplexed
-# application/vnd.pwg-xhtml-print+xml
-# application/vnd.qualcomm.brew-app-res
-application/vnd.quark.quarkxpress		qxd qxt qwd qwt qxl qxb
-# application/vnd.radisys.moml+xml
-# application/vnd.radisys.msml+xml
-# application/vnd.radisys.msml-audit+xml
-# application/vnd.radisys.msml-audit-conf+xml
-# application/vnd.radisys.msml-audit-conn+xml
-# application/vnd.radisys.msml-audit-dialog+xml
-# application/vnd.radisys.msml-audit-stream+xml
-# application/vnd.radisys.msml-conf+xml
-# application/vnd.radisys.msml-dialog+xml
-# application/vnd.radisys.msml-dialog-base+xml
-# application/vnd.radisys.msml-dialog-fax-detect+xml
-# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
-# application/vnd.radisys.msml-dialog-group+xml
-# application/vnd.radisys.msml-dialog-speech+xml
-# application/vnd.radisys.msml-dialog-transform+xml
-# application/vnd.rainstor.data
-# application/vnd.rapid
-application/vnd.realvnc.bed			bed
-application/vnd.recordare.musicxml		mxl
-application/vnd.recordare.musicxml+xml		musicxml
-# application/vnd.renlearn.rlprint
-application/vnd.rig.cryptonote			cryptonote
-application/vnd.rim.cod				cod
-application/vnd.rn-realmedia			rm
-application/vnd.rn-realmedia-vbr		rmvb
-application/vnd.route66.link66+xml		link66
-# application/vnd.rs-274x
-# application/vnd.ruckus.download
-# application/vnd.s3sms
-application/vnd.sailingtracker.track		st
-# application/vnd.sbm.cid
-# application/vnd.sbm.mid2
-# application/vnd.scribus
-# application/vnd.sealed.3df
-# application/vnd.sealed.csf
-# application/vnd.sealed.doc
-# application/vnd.sealed.eml
-# application/vnd.sealed.mht
-# application/vnd.sealed.net
-# application/vnd.sealed.ppt
-# application/vnd.sealed.tiff
-# application/vnd.sealed.xls
-# application/vnd.sealedmedia.softseal.html
-# application/vnd.sealedmedia.softseal.pdf
-application/vnd.seemail				see
-application/vnd.sema				sema
-application/vnd.semd				semd
-application/vnd.semf				semf
-application/vnd.shana.informed.formdata		ifm
-application/vnd.shana.informed.formtemplate	itp
-application/vnd.shana.informed.interchange	iif
-application/vnd.shana.informed.package		ipk
-application/vnd.simtech-mindmapper		twd twds
-application/vnd.smaf				mmf
-# application/vnd.smart.notebook
-application/vnd.smart.teacher			teacher
-# application/vnd.software602.filler.form+xml
-# application/vnd.software602.filler.form-xml-zip
-application/vnd.solent.sdkm+xml			sdkm sdkd
-application/vnd.spotfire.dxp			dxp
-application/vnd.spotfire.sfs			sfs
-# application/vnd.sss-cod
-# application/vnd.sss-dtf
-# application/vnd.sss-ntf
-application/vnd.stardivision.calc		sdc
-application/vnd.stardivision.draw		sda
-application/vnd.stardivision.impress		sdd
-application/vnd.stardivision.math		smf
-application/vnd.stardivision.writer		sdw vor
-application/vnd.stardivision.writer-global	sgl
-application/vnd.stepmania.package		smzip
-application/vnd.stepmania.stepchart		sm
-# application/vnd.street-stream
-application/vnd.sun.xml.calc			sxc
-application/vnd.sun.xml.calc.template		stc
-application/vnd.sun.xml.draw			sxd
-application/vnd.sun.xml.draw.template		std
-application/vnd.sun.xml.impress			sxi
-application/vnd.sun.xml.impress.template	sti
-application/vnd.sun.xml.math			sxm
-application/vnd.sun.xml.writer			sxw
-application/vnd.sun.xml.writer.global		sxg
-application/vnd.sun.xml.writer.template		stw
-# application/vnd.sun.wadl+xml
-application/vnd.sus-calendar			sus susp
-application/vnd.svd				svd
-# application/vnd.swiftview-ics
-application/vnd.symbian.install			sis sisx
-application/vnd.syncml+xml			xsm
-application/vnd.syncml.dm+wbxml			bdm
-application/vnd.syncml.dm+xml			xdm
-# application/vnd.syncml.dm.notification
-# application/vnd.syncml.ds.notification
-application/vnd.tao.intent-module-archive	tao
-application/vnd.tcpdump.pcap			pcap cap dmp
-application/vnd.tmobile-livetv			tmo
-application/vnd.trid.tpt			tpt
-application/vnd.triscape.mxs			mxs
-application/vnd.trueapp				tra
-# application/vnd.truedoc
-# application/vnd.ubisoft.webplayer
-application/vnd.ufdl				ufd ufdl
-application/vnd.uiq.theme			utz
-application/vnd.umajin				umj
-application/vnd.unity				unityweb
-application/vnd.uoml+xml			uoml
-# application/vnd.uplanet.alert
-# application/vnd.uplanet.alert-wbxml
-# application/vnd.uplanet.bearer-choice
-# application/vnd.uplanet.bearer-choice-wbxml
-# application/vnd.uplanet.cacheop
-# application/vnd.uplanet.cacheop-wbxml
-# application/vnd.uplanet.channel
-# application/vnd.uplanet.channel-wbxml
-# application/vnd.uplanet.list
-# application/vnd.uplanet.list-wbxml
-# application/vnd.uplanet.listcmd
-# application/vnd.uplanet.listcmd-wbxml
-# application/vnd.uplanet.signal
-application/vnd.vcx				vcx
-# application/vnd.vd-study
-# application/vnd.vectorworks
-# application/vnd.verimatrix.vcas
-# application/vnd.vidsoft.vidconference
-application/vnd.visio				vsd vst vss vsw
-application/vnd.visionary			vis
-# application/vnd.vividence.scriptfile
-application/vnd.vsf				vsf
-# application/vnd.wap.sic
-# application/vnd.wap.slc
-application/vnd.wap.wbxml			wbxml
-application/vnd.wap.wmlc			wmlc
-application/vnd.wap.wmlscriptc			wmlsc
-application/vnd.webturbo			wtb
-# application/vnd.wfa.wsc
-# application/vnd.wmc
-# application/vnd.wmf.bootstrap
-# application/vnd.wolfram.mathematica
-# application/vnd.wolfram.mathematica.package
-application/vnd.wolfram.player			nbp
-application/vnd.wordperfect			wpd
-application/vnd.wqd				wqd
-# application/vnd.wrq-hp3000-labelled
-application/vnd.wt.stf				stf
-# application/vnd.wv.csp+wbxml
-# application/vnd.wv.csp+xml
-# application/vnd.wv.ssp+xml
-application/vnd.xara				xar
-application/vnd.xfdl				xfdl
-# application/vnd.xfdl.webform
-# application/vnd.xmi+xml
-# application/vnd.xmpie.cpkg
-# application/vnd.xmpie.dpkg
-# application/vnd.xmpie.plan
-# application/vnd.xmpie.ppkg
-# application/vnd.xmpie.xlim
-application/vnd.yamaha.hv-dic			hvd
-application/vnd.yamaha.hv-script		hvs
-application/vnd.yamaha.hv-voice			hvp
-application/vnd.yamaha.openscoreformat			osf
-application/vnd.yamaha.openscoreformat.osfpvg+xml	osfpvg
-# application/vnd.yamaha.remote-setup
-application/vnd.yamaha.smaf-audio		saf
-application/vnd.yamaha.smaf-phrase		spf
-# application/vnd.yamaha.through-ngn
-# application/vnd.yamaha.tunnel-udpencap
-application/vnd.yellowriver-custom-menu		cmp
-application/vnd.zul				zir zirz
-application/vnd.zzazz.deck+xml			zaz
-application/voicexml+xml			vxml
-# application/vq-rtcpxr
-# application/watcherinfo+xml
-# application/whoispp-query
-# application/whoispp-response
-application/widget				wgt
-application/winhlp				hlp
-# application/wita
-# application/wordperfect5.1
-application/wsdl+xml				wsdl
-application/wspolicy+xml			wspolicy
-application/x-7z-compressed			7z
-application/x-abiword				abw
-application/x-ace-compressed			ace
-# application/x-amf
-application/x-apple-diskimage			dmg
-application/x-authorware-bin			aab x32 u32 vox
-application/x-authorware-map			aam
-application/x-authorware-seg			aas
-application/x-bcpio				bcpio
-application/x-bittorrent			torrent
-application/x-blorb				blb blorb
-application/x-bzip				bz
-application/x-bzip2				bz2 boz
-application/x-cbr				cbr cba cbt cbz cb7
-application/x-cdlink				vcd
-application/x-cfs-compressed			cfs
-application/x-chat				chat
-application/x-chess-pgn				pgn
-application/x-conference			nsc
-# application/x-compress
-application/x-cpio				cpio
-application/x-csh				csh
-application/x-debian-package			deb udeb
-application/x-dgc-compressed			dgc
-application/x-director			dir dcr dxr cst cct cxt w3d fgd swa
-application/x-doom				wad
-application/x-dtbncx+xml			ncx
-application/x-dtbook+xml			dtb
-application/x-dtbresource+xml			res
-application/x-dvi				dvi
-application/x-envoy				evy
-application/x-eva				eva
-application/x-font-bdf				bdf
-# application/x-font-dos
-# application/x-font-framemaker
-application/x-font-ghostscript			gsf
-# application/x-font-libgrx
-application/x-font-linux-psf			psf
-application/x-font-otf				otf
-application/x-font-pcf				pcf
-application/x-font-snf				snf
-# application/x-font-speedo
-# application/x-font-sunos-news
-application/x-font-ttf				ttf ttc
-application/x-font-type1			pfa pfb pfm afm
-application/font-woff				woff
-# application/x-font-vfont
-application/x-freearc				arc
-application/x-futuresplash			spl
-application/x-gca-compressed			gca
-application/x-glulx				ulx
-application/x-gnumeric				gnumeric
-application/x-gramps-xml			gramps
-application/x-gtar				gtar
-# application/x-gzip
-application/x-hdf				hdf
-application/x-install-instructions		install
-application/x-iso9660-image			iso
-application/x-java-jnlp-file			jnlp
-application/x-latex				latex
-application/x-lzh-compressed			lzh lha
-application/x-mie				mie
-application/x-mobipocket-ebook			prc mobi
-application/x-ms-application			application
-application/x-ms-shortcut			lnk
-application/x-ms-wmd				wmd
-application/x-ms-wmz				wmz
-application/x-ms-xbap				xbap
-application/x-msaccess				mdb
-application/x-msbinder				obd
-application/x-mscardfile			crd
-application/x-msclip				clp
-application/x-msdownload			exe dll com bat msi
-application/x-msmediaview			mvb m13 m14
-application/x-msmetafile			wmf wmz emf emz
-application/x-msmoney				mny
-application/x-mspublisher			pub
-application/x-msschedule			scd
-application/x-msterminal			trm
-application/x-mswrite				wri
-application/x-netcdf				nc cdf
-application/x-nzb				nzb
-application/x-pkcs12				p12 pfx
-application/x-pkcs7-certificates		p7b spc
-application/x-pkcs7-certreqresp			p7r
-application/x-rar-compressed			rar
-application/x-research-info-systems		ris
-application/x-sh				sh
-application/x-shar				shar
-application/x-shockwave-flash			swf
-application/x-silverlight-app			xap
-application/x-sql				sql
-application/x-stuffit				sit
-application/x-stuffitx				sitx
-application/x-subrip				srt
-application/x-sv4cpio				sv4cpio
-application/x-sv4crc				sv4crc
-application/x-t3vm-image			t3
-application/x-tads				gam
-application/x-tar				tar
-application/x-tcl				tcl
-application/x-tex				tex
-application/x-tex-tfm				tfm
-application/x-texinfo				texinfo texi
-application/x-tgif				obj
-application/x-ustar				ustar
-application/x-wais-source			src
-application/x-x509-ca-cert			der crt
-application/x-xfig				fig
-application/x-xliff+xml				xlf
-application/x-xpinstall				xpi
-application/x-xz				xz
-application/x-zmachine				z1 z2 z3 z4 z5 z6 z7 z8
-# application/x400-bp
-application/xaml+xml				xaml
-# application/xcap-att+xml
-# application/xcap-caps+xml
-application/xcap-diff+xml			xdf
-# application/xcap-el+xml
-# application/xcap-error+xml
-# application/xcap-ns+xml
-# application/xcon-conference-info-diff+xml
-# application/xcon-conference-info+xml
-application/xenc+xml				xenc
-application/xhtml+xml				xhtml xht
-# application/xhtml-voice+xml
-application/xml					xml xsl
-application/xml-dtd				dtd
-# application/xml-external-parsed-entity
-# application/xmpp+xml
-application/xop+xml				xop
-application/xproc+xml				xpl
-application/xslt+xml				xslt
-application/xspf+xml				xspf
-application/xv+xml				mxml xhvml xvml xvm
-application/yang				yang
-application/yin+xml				yin
-application/zip					zip
-# audio/1d-interleaved-parityfec
-# audio/32kadpcm
-# audio/3gpp
-# audio/3gpp2
-# audio/ac3
-audio/adpcm					adp
-# audio/amr
-# audio/amr-wb
-# audio/amr-wb+
-# audio/asc
-# audio/atrac-advanced-lossless
-# audio/atrac-x
-# audio/atrac3
-audio/basic					au snd
-# audio/bv16
-# audio/bv32
-# audio/clearmode
-# audio/cn
-# audio/dat12
-# audio/dls
-# audio/dsr-es201108
-# audio/dsr-es202050
-# audio/dsr-es202211
-# audio/dsr-es202212
-# audio/dv
-# audio/dvi4
-# audio/eac3
-# audio/evrc
-# audio/evrc-qcp
-# audio/evrc0
-# audio/evrc1
-# audio/evrcb
-# audio/evrcb0
-# audio/evrcb1
-# audio/evrcwb
-# audio/evrcwb0
-# audio/evrcwb1
-# audio/example
-# audio/fwdred
-# audio/g719
-# audio/g722
-# audio/g7221
-# audio/g723
-# audio/g726-16
-# audio/g726-24
-# audio/g726-32
-# audio/g726-40
-# audio/g728
-# audio/g729
-# audio/g7291
-# audio/g729d
-# audio/g729e
-# audio/gsm
-# audio/gsm-efr
-# audio/gsm-hr-08
-# audio/ilbc
-# audio/ip-mr_v2.5
-# audio/isac
-# audio/l16
-# audio/l20
-# audio/l24
-# audio/l8
-# audio/lpc
-audio/midi					mid midi kar rmi
-# audio/mobile-xmf
-audio/mp4					mp4a
-# audio/mp4a-latm
-# audio/mpa
-# audio/mpa-robust
-audio/mpeg					mpga mp2 mp2a mp3 m2a m3a
-# audio/mpeg4-generic
-# audio/musepack
-audio/ogg					oga ogg spx
-# audio/opus
-# audio/parityfec
-# audio/pcma
-# audio/pcma-wb
-# audio/pcmu-wb
-# audio/pcmu
-# audio/prs.sid
-# audio/qcelp
-# audio/red
-# audio/rtp-enc-aescm128
-# audio/rtp-midi
-# audio/rtx
-audio/s3m					s3m
-audio/silk					sil
-# audio/smv
-# audio/smv0
-# audio/smv-qcp
-# audio/sp-midi
-# audio/speex
-# audio/t140c
-# audio/t38
-# audio/telephone-event
-# audio/tone
-# audio/uemclip
-# audio/ulpfec
-# audio/vdvi
-# audio/vmr-wb
-# audio/vnd.3gpp.iufp
-# audio/vnd.4sb
-# audio/vnd.audiokoz
-# audio/vnd.celp
-# audio/vnd.cisco.nse
-# audio/vnd.cmles.radio-events
-# audio/vnd.cns.anp1
-# audio/vnd.cns.inf1
-audio/vnd.dece.audio				uva uvva
-audio/vnd.digital-winds				eol
-# audio/vnd.dlna.adts
-# audio/vnd.dolby.heaac.1
-# audio/vnd.dolby.heaac.2
-# audio/vnd.dolby.mlp
-# audio/vnd.dolby.mps
-# audio/vnd.dolby.pl2
-# audio/vnd.dolby.pl2x
-# audio/vnd.dolby.pl2z
-# audio/vnd.dolby.pulse.1
-audio/vnd.dra					dra
-audio/vnd.dts					dts
-audio/vnd.dts.hd				dtshd
-# audio/vnd.dvb.file
-# audio/vnd.everad.plj
-# audio/vnd.hns.audio
-audio/vnd.lucent.voice				lvp
-audio/vnd.ms-playready.media.pya		pya
-# audio/vnd.nokia.mobile-xmf
-# audio/vnd.nortel.vbk
-audio/vnd.nuera.ecelp4800			ecelp4800
-audio/vnd.nuera.ecelp7470			ecelp7470
-audio/vnd.nuera.ecelp9600			ecelp9600
-# audio/vnd.octel.sbc
-# audio/vnd.qcelp
-# audio/vnd.rhetorex.32kadpcm
-audio/vnd.rip					rip
-# audio/vnd.sealedmedia.softseal.mpeg
-# audio/vnd.vmx.cvsd
-# audio/vorbis
-# audio/vorbis-config
-audio/webm					weba
-audio/x-aac					aac
-audio/x-aiff					aif aiff aifc
-audio/x-caf					caf
-audio/x-flac					flac
-audio/x-matroska				mka
-audio/x-mpegurl					m3u
-audio/x-ms-wax					wax
-audio/x-ms-wma					wma
-audio/x-pn-realaudio				ram ra
-audio/x-pn-realaudio-plugin			rmp
-# audio/x-tta
-audio/x-wav					wav
-audio/xm					xm
-chemical/x-cdx					cdx
-chemical/x-cif					cif
-chemical/x-cmdf					cmdf
-chemical/x-cml					cml
-chemical/x-csml					csml
-# chemical/x-pdb
-chemical/x-xyz					xyz
-image/bmp					bmp
-image/cgm					cgm
-# image/example
-# image/fits
-image/g3fax					g3
-image/gif					gif
-image/ief					ief
-# image/jp2
-image/jpeg					jpeg jpg jpe
-# image/jpm
-# image/jpx
-image/ktx					ktx
-# image/naplps
-image/png					png
-image/prs.btif					btif
-# image/prs.pti
-image/sgi					sgi
-image/svg+xml					svg svgz
-# image/t38
-image/tiff					tiff tif
-# image/tiff-fx
-image/vnd.adobe.photoshop			psd
-# image/vnd.cns.inf2
-image/vnd.dece.graphic				uvi uvvi uvg uvvg
-image/vnd.dvb.subtitle				sub
-image/vnd.djvu					djvu djv
-image/vnd.dwg					dwg
-image/vnd.dxf					dxf
-image/vnd.fastbidsheet				fbs
-image/vnd.fpx					fpx
-image/vnd.fst					fst
-image/vnd.fujixerox.edmics-mmr			mmr
-image/vnd.fujixerox.edmics-rlc			rlc
-# image/vnd.globalgraphics.pgb
-# image/vnd.microsoft.icon
-# image/vnd.mix
-image/vnd.ms-modi				mdi
-image/vnd.ms-photo				wdp
-image/vnd.net-fpx				npx
-# image/vnd.radiance
-# image/vnd.sealed.png
-# image/vnd.sealedmedia.softseal.gif
-# image/vnd.sealedmedia.softseal.jpg
-# image/vnd.svf
-image/vnd.wap.wbmp				wbmp
-image/vnd.xiff					xif
-image/webp					webp
-image/x-3ds					3ds
-image/x-cmu-raster				ras
-image/x-cmx					cmx
-image/x-freehand				fh fhc fh4 fh5 fh7
-image/x-icon					ico
-image/x-mrsid-image				sid
-image/x-pcx					pcx
-image/x-pict					pic pct
-image/x-portable-anymap				pnm
-image/x-portable-bitmap				pbm
-image/x-portable-graymap			pgm
-image/x-portable-pixmap				ppm
-image/x-rgb					rgb
-image/x-tga					tga
-image/x-xbitmap					xbm
-image/x-xpixmap					xpm
-image/x-xwindowdump				xwd
-# message/cpim
-# message/delivery-status
-# message/disposition-notification
-# message/example
-# message/external-body
-# message/feedback-report
-# message/global
-# message/global-delivery-status
-# message/global-disposition-notification
-# message/global-headers
-# message/http
-# message/imdn+xml
-# message/news
-# message/partial
-message/rfc822					eml mime
-# message/s-http
-# message/sip
-# message/sipfrag
-# message/tracking-status
-# message/vnd.si.simp
-# model/example
-model/iges					igs iges
-model/mesh					msh mesh silo
-model/vnd.collada+xml				dae
-model/vnd.dwf					dwf
-# model/vnd.flatland.3dml
-model/vnd.gdl					gdl
-# model/vnd.gs-gdl
-# model/vnd.gs.gdl
-model/vnd.gtw					gtw
-# model/vnd.moml+xml
-model/vnd.mts					mts
-# model/vnd.parasolid.transmit.binary
-# model/vnd.parasolid.transmit.text
-model/vnd.vtu					vtu
-model/vrml					wrl vrml
-model/x3d+binary				x3db x3dbz
-model/x3d+vrml					x3dv x3dvz
-model/x3d+xml					x3d x3dz
-# multipart/alternative
-# multipart/appledouble
-# multipart/byteranges
-# multipart/digest
-# multipart/encrypted
-# multipart/example
-# multipart/form-data
-# multipart/header-set
-# multipart/mixed
-# multipart/parallel
-# multipart/related
-# multipart/report
-# multipart/signed
-# multipart/voice-message
-# text/1d-interleaved-parityfec
-text/cache-manifest				appcache
-text/calendar					ics ifb
-text/css					css
-text/csv					csv
-# text/directory
-# text/dns
-# text/ecmascript
-# text/enriched
-# text/example
-# text/fwdred
-text/html					html htm
-# text/javascript
-text/n3						n3
-# text/parityfec
-text/plain					txt text conf def list log in
-# text/prs.fallenstein.rst
-text/prs.lines.tag				dsc
-# text/vnd.radisys.msml-basic-layout
-# text/red
-# text/rfc822-headers
-text/richtext					rtx
-# text/rtf
-# text/rtp-enc-aescm128
-# text/rtx
-text/sgml					sgml sgm
-# text/t140
-text/tab-separated-values			tsv
-text/troff					t tr roff man me ms
-text/turtle					ttl
-# text/ulpfec
-text/uri-list					uri uris urls
-text/vcard					vcard
-# text/vnd.abc
-text/vnd.curl					curl
-text/vnd.curl.dcurl				dcurl
-text/vnd.curl.scurl				scurl
-text/vnd.curl.mcurl				mcurl
-# text/vnd.dmclientscript
-text/vnd.dvb.subtitle				sub
-# text/vnd.esmertec.theme-descriptor
-text/vnd.fly					fly
-text/vnd.fmi.flexstor				flx
-text/vnd.graphviz				gv
-text/vnd.in3d.3dml				3dml
-text/vnd.in3d.spot				spot
-# text/vnd.iptc.newsml
-# text/vnd.iptc.nitf
-# text/vnd.latex-z
-# text/vnd.motorola.reflex
-# text/vnd.ms-mediapackage
-# text/vnd.net2phone.commcenter.command
-# text/vnd.si.uricatalogue
-text/vnd.sun.j2me.app-descriptor		jad
-# text/vnd.trolltech.linguist
-# text/vnd.wap.si
-# text/vnd.wap.sl
-text/vnd.wap.wml				wml
-text/vnd.wap.wmlscript				wmls
-text/x-asm					s asm
-text/x-c					c cc cxx cpp h hh dic
-text/x-fortran					f for f77 f90
-text/x-java-source				java
-text/x-opml					opml
-text/x-pascal					p pas
-text/x-nfo					nfo
-text/x-setext					etx
-text/x-sfv					sfv
-text/x-uuencode					uu
-text/x-vcalendar				vcs
-text/x-vcard					vcf
-# text/xml
-# text/xml-external-parsed-entity
-# video/1d-interleaved-parityfec
-video/3gpp					3gp
-# video/3gpp-tt
-video/3gpp2					3g2
-# video/bmpeg
-# video/bt656
-# video/celb
-# video/dv
-# video/example
-video/h261					h261
-video/h263					h263
-# video/h263-1998
-# video/h263-2000
-video/h264					h264
-# video/h264-rcdo
-# video/h264-svc
-video/jpeg					jpgv
-# video/jpeg2000
-video/jpm					jpm jpgm
-video/mj2					mj2 mjp2
-# video/mp1s
-# video/mp2p
-# video/mp2t
-video/mp4					mp4 mp4v mpg4
-# video/mp4v-es
-video/mpeg					mpeg mpg mpe m1v m2v
-# video/mpeg4-generic
-# video/mpv
-# video/nv
-video/ogg					ogv
-# video/parityfec
-# video/pointer
-video/quicktime					qt mov
-# video/raw
-# video/rtp-enc-aescm128
-# video/rtx
-# video/smpte292m
-# video/ulpfec
-# video/vc1
-# video/vnd.cctv
-video/vnd.dece.hd				uvh uvvh
-video/vnd.dece.mobile				uvm uvvm
-# video/vnd.dece.mp4
-video/vnd.dece.pd				uvp uvvp
-video/vnd.dece.sd				uvs uvvs
-video/vnd.dece.video				uvv uvvv
-# video/vnd.directv.mpeg
-# video/vnd.directv.mpeg-tts
-# video/vnd.dlna.mpeg-tts
-video/vnd.dvb.file				dvb
-video/vnd.fvt					fvt
-# video/vnd.hns.video
-# video/vnd.iptvforum.1dparityfec-1010
-# video/vnd.iptvforum.1dparityfec-2005
-# video/vnd.iptvforum.2dparityfec-1010
-# video/vnd.iptvforum.2dparityfec-2005
-# video/vnd.iptvforum.ttsavc
-# video/vnd.iptvforum.ttsmpeg2
-# video/vnd.motorola.video
-# video/vnd.motorola.videop
-video/vnd.mpegurl				mxu m4u
-video/vnd.ms-playready.media.pyv		pyv
-# video/vnd.nokia.interleaved-multimedia
-# video/vnd.nokia.videovoip
-# video/vnd.objectvideo
-# video/vnd.sealed.mpeg1
-# video/vnd.sealed.mpeg4
-# video/vnd.sealed.swf
-# video/vnd.sealedmedia.softseal.mov
-video/vnd.uvvu.mp4				uvu uvvu
-video/vnd.vivo					viv
-video/webm					webm
-video/x-f4v					f4v
-video/x-fli					fli
-video/x-flv					flv
-video/x-m4v					m4v
-video/x-matroska				mkv mk3d mks
-video/x-mng					mng
-video/x-ms-asf					asf asx
-video/x-ms-vob					vob
-video/x-ms-wm					wm
-video/x-ms-wmv					wmv
-video/x-ms-wmx					wmx
-video/x-ms-wvx					wvx
-video/x-msvideo					avi
-video/x-sgi-movie				movie
-video/x-smv					smv
-x-conference/x-cooltalk				ice
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/node.types b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/node.types
deleted file mode 100644
index 55b2cf79..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/mime/types/node.types
+++ /dev/null
@@ -1,77 +0,0 @@
-# What: WebVTT
-# Why: To allow formats intended for marking up external text track resources.
-# http://dev.w3.org/html5/webvtt/
-# Added by: niftylettuce
-text/vtt  vtt
-
-# What: Google Chrome Extension
-# Why: To allow apps to (work) be served with the right content type header.
-# http://codereview.chromium.org/2830017
-# Added by: niftylettuce
-application/x-chrome-extension  crx
-
-# What: HTC support
-# Why: To properly render .htc files such as CSS3PIE
-# Added by: niftylettuce
-text/x-component  htc
-
-# What: HTML5 application cache manifes ('.manifest' extension)
-# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
-# per https://developer.mozilla.org/en/offline_resources_in_firefox
-# Added by: louisremi
-text/cache-manifest  manifest
-
-# What: node binary buffer format
-# Why: semi-standard extension w/in the node community
-# Added by: tootallnate
-application/octet-stream  buffer
-
-# What: The "protected" MP-4 formats used by iTunes.
-# Why: Required for streaming music to browsers (?)
-# Added by: broofa
-application/mp4  m4p
-audio/mp4  m4a
-
-# What: Video format, Part of RFC1890
-# Why: See https://github.com/bentomas/node-mime/pull/6
-# Added by: mjrusso
-video/MP2T  ts
-
-# What: EventSource mime type
-# Why: mime type of Server-Sent Events stream
-# http://www.w3.org/TR/eventsource/#text-event-stream
-# Added by: francois2metz
-text/event-stream  event-stream
-
-# What: Mozilla App manifest mime type
-# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
-# Added by: ednapiranha
-application/x-web-app-manifest+json   webapp
-
-# What: Lua file types
-# Why: Googling around shows de-facto consensus on these
-# Added by: creationix (Issue #45)
-text/x-lua  lua
-application/x-lua-bytecode  luac
-
-# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax
-# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown
-# Added by: avoidwork
-text/x-markdown  markdown md mkd
-
-# What: ini files
-# Why: because they're just text files
-# Added by: Matthew Kastor
-text/plain  ini
-
-# What: DASH Adaptive Streaming manifest
-# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video
-# Added by: eelcocramer
-application/dash+xml mdp
-
-# What: OpenType font files - http://www.microsoft.com/typography/otspec/
-# Why:  Browsers usually ignore the font MIME types and sniff the content,
-#       but Chrome, shows a warning if OpenType fonts aren't served with
-#       the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png.
-# Added by: alrra
-font/opentype  otf
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/.npmignore
deleted file mode 100644
index fd4f2b06..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules
-.DS_Store
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/LICENSE.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/LICENSE.md
deleted file mode 100644
index f039427f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/LICENSE.md
+++ /dev/null
@@ -1,2 +0,0 @@
-Copyright (c) 2010-2012 Robert Kieffer
-MIT License - http://opensource.org/licenses/mit-license.php
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/README.md
deleted file mode 100644
index e436a89f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/README.md
+++ /dev/null
@@ -1,207 +0,0 @@
-# node-uuid
-
-Simple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.
-
-Features:
-
-* Generate RFC4122 version 1 or version 4 UUIDs
-* Runs in node.js and all browsers.
-* Registered as a [ComponentJS](https://github.com/component/component) [component](https://github.com/component/component/wiki/Components) ('broofa/node-uuid').
-* Cryptographically strong random # generation on supporting platforms
-* 1.1K minified and gzip'ed  (Want something smaller?  Check this [crazy shit](https://gist.github.com/982883) out! )
-* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)
-
-## Getting Started
-
-Install it in your browser:
-
-```html
-<script src="uuid.js"></script>
-```
-
-Or in node.js:
-
-```
-npm install node-uuid
-```
-
-```javascript
-var uuid = require('node-uuid');
-```
-
-Then create some ids ...
-
-```javascript
-// Generate a v1 (time-based) id
-uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
-
-// Generate a v4 (random) id
-uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
-```
-
-## API
-
-### uuid.v1([`options` [, `buffer` [, `offset`]]])
-
-Generate and return a RFC4122 v1 (timestamp-based) UUID.
-
-* `options` - (Object) Optional uuid state to apply. Properties may include:
-
-  * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID.  See note 1.
-  * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence.  Default: An internally maintained clockseq is used.
-  * `msecs` - (Number | Date) Time in milliseconds since unix Epoch.  Default: The current time is used.
-  * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.
-
-* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
-* `offset` - (Number) Starting index in `buffer` at which to begin writing.
-
-Returns `buffer`, if specified, otherwise the string form of the UUID
-
-Notes:
-
-1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)
-
-Example: Generate string UUID with fully-specified options
-
-```javascript
-uuid.v1({
-  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
-  clockseq: 0x1234,
-  msecs: new Date('2011-11-01').getTime(),
-  nsecs: 5678
-});   // -> "710b962e-041c-11e1-9234-0123456789ab"
-```
-
-Example: In-place generation of two binary IDs
-
-```javascript
-// Generate two ids in an array
-var arr = new Array(32); // -> []
-uuid.v1(null, arr, 0);   // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
-uuid.v1(null, arr, 16);  // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
-
-// Optionally use uuid.unparse() to get stringify the ids
-uuid.unparse(buffer);    // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'
-uuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'
-```
-
-### uuid.v4([`options` [, `buffer` [, `offset`]]])
-
-Generate and return a RFC4122 v4 UUID.
-
-* `options` - (Object) Optional uuid state to apply. Properties may include:
-
-  * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values
-  * `rng` - (Function) Random # generator to use.  Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.
-
-* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
-* `offset` - (Number) Starting index in `buffer` at which to begin writing.
-
-Returns `buffer`, if specified, otherwise the string form of the UUID
-
-Example: Generate string UUID with fully-specified options
-
-```javascript
-uuid.v4({
-  random: [
-    0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,
-    0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36
-  ]
-});
-// -> "109156be-c4fb-41ea-b1b4-efe1671c5836"
-```
-
-Example: Generate two IDs in a single buffer
-
-```javascript
-var buffer = new Array(32); // (or 'new Buffer' in node.js)
-uuid.v4(null, buffer, 0);
-uuid.v4(null, buffer, 16);
-```
-
-### uuid.parse(id[, buffer[, offset]])
-### uuid.unparse(buffer[, offset])
-
-Parse and unparse UUIDs
-
-  * `id` - (String) UUID(-like) string
-  * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used
-  * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0
-
-Example parsing and unparsing a UUID string
-
-```javascript
-var bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> <Buffer 79 7f f0 43 11 eb 11 e1 80 d6 51 09 98 75 5d 10>
-var string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'
-```
-
-### uuid.noConflict()
-
-(Browsers only) Set `uuid` property back to it's previous value.
-
-Returns the node-uuid object.
-
-Example:
-
-```javascript
-var myUuid = uuid.noConflict();
-myUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
-```
-
-## Deprecated APIs
-
-Support for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.
-
-### uuid([format [, buffer [, offset]]])
-
-uuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).
-
-### uuid.BufferClass
-
-The class of container created when generating binary uuid data if no buffer argument is specified.  This is expected to go away, with no replacement API.
-
-## Testing
-
-In node.js
-
-```
-> cd test
-> node test.js
-```
-
-In Browser
-
-```
-open test/test.html
-```
-
-### Benchmarking
-
-Requires node.js
-
-```
-npm install uuid uuid-js
-node benchmark/benchmark.js
-```
-
-For a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)
-
-For browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).
-
-## Release notes
-
-### 1.4.0
-
-* Improved module context detection
-* Removed public RNG functions
-
-### 1.3.2
-
-* Improve tests and handling of v1() options (Issue #24)
-* Expose RNG option to allow for perf testing with different generators
-
-### 1.3.0
-
-* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!
-* Support for node.js crypto API
-* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/README.md
deleted file mode 100644
index aaeb2ea0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# node-uuid Benchmarks
-
-### Results
-
-To see the results of our benchmarks visit https://github.com/broofa/node-uuid/wiki/Benchmark
-
-### Run them yourself
-
-node-uuid comes with some benchmarks to measure performance of generating UUIDs. These can be run using node.js. node-uuid is being benchmarked against some other uuid modules, that are available through npm namely `uuid` and `uuid-js`.
-
-To prepare and run the benchmark issue;
-
-```
-npm install uuid uuid-js
-node benchmark/benchmark.js
-```
-
-You'll see an output like this one:
-
-```
-# v4
-nodeuuid.v4(): 854700 uuids/second
-nodeuuid.v4('binary'): 788643 uuids/second
-nodeuuid.v4('binary', buffer): 1336898 uuids/second
-uuid(): 479386 uuids/second
-uuid('binary'): 582072 uuids/second
-uuidjs.create(4): 312304 uuids/second
-
-# v1
-nodeuuid.v1(): 938086 uuids/second
-nodeuuid.v1('binary'): 683060 uuids/second
-nodeuuid.v1('binary', buffer): 1644736 uuids/second
-uuidjs.create(1): 190621 uuids/second
-```
-
-* The `uuid()` entries are for Nikhil Marathe's [uuid module](https://bitbucket.org/nikhilm/uuidjs) which is a wrapper around the native libuuid library.
-* The `uuidjs()` entries are for Patrick Negri's [uuid-js module](https://github.com/pnegri/uuid-js) which is a pure javascript implementation based on [UUID.js](https://github.com/LiosK/UUID.js) by LiosK.
-
-If you want to get more reliable results you can run the benchmark multiple times and write the output into a log file:
-
-```
-for i in {0..9}; do node benchmark/benchmark.js >> benchmark/bench_0.4.12.log; done;
-```
-
-If you're interested in how performance varies between different node versions, you can issue the above command multiple times.
-
-You can then use the shell script `bench.sh` provided in this directory to calculate the averages over all benchmark runs and draw a nice plot:
-
-```
-(cd benchmark/ && ./bench.sh)
-```
-
-This assumes you have [gnuplot](http://www.gnuplot.info/) and [ImageMagick](http://www.imagemagick.org/) installed. You'll find a nice `bench.png` graph in the `benchmark/` directory then.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu
deleted file mode 100644
index a342fbbe..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu
+++ /dev/null
@@ -1,174 +0,0 @@
-#!/opt/local/bin/gnuplot -persist
-#
-#    
-#    	G N U P L O T
-#    	Version 4.4 patchlevel 3
-#    	last modified March 2011
-#    	System: Darwin 10.8.0
-#    
-#    	Copyright (C) 1986-1993, 1998, 2004, 2007-2010
-#    	Thomas Williams, Colin Kelley and many others
-#    
-#    	gnuplot home:     http://www.gnuplot.info
-#    	faq, bugs, etc:   type "help seeking-assistance"
-#    	immediate help:   type "help"
-#    	plot window:      hit 'h'
-set terminal postscript eps noenhanced defaultplex \
- leveldefault color colortext \
- solid linewidth 1.2 butt noclip \
- palfuncparam 2000,0.003 \
- "Helvetica" 14 
-set output 'bench.eps'
-unset clip points
-set clip one
-unset clip two
-set bar 1.000000 front
-set border 31 front linetype -1 linewidth 1.000
-set xdata
-set ydata
-set zdata
-set x2data
-set y2data
-set timefmt x "%d/%m/%y,%H:%M"
-set timefmt y "%d/%m/%y,%H:%M"
-set timefmt z "%d/%m/%y,%H:%M"
-set timefmt x2 "%d/%m/%y,%H:%M"
-set timefmt y2 "%d/%m/%y,%H:%M"
-set timefmt cb "%d/%m/%y,%H:%M"
-set boxwidth
-set style fill  empty border
-set style rectangle back fc lt -3 fillstyle   solid 1.00 border lt -1
-set style circle radius graph 0.02, first 0, 0 
-set dummy x,y
-set format x "% g"
-set format y "% g"
-set format x2 "% g"
-set format y2 "% g"
-set format z "% g"
-set format cb "% g"
-set angles radians
-unset grid
-set key title ""
-set key outside left top horizontal Right noreverse enhanced autotitles columnhead nobox
-set key noinvert samplen 4 spacing 1 width 0 height 0 
-set key maxcolumns 2 maxrows 0
-unset label
-unset arrow
-set style increment default
-unset style line
-set style line 1  linetype 1 linewidth 2.000 pointtype 1 pointsize default pointinterval 0
-unset style arrow
-set style histogram clustered gap 2 title  offset character 0, 0, 0
-unset logscale
-set offsets graph 0.05, 0.15, 0, 0
-set pointsize 1.5
-set pointintervalbox 1
-set encoding default
-unset polar
-unset parametric
-unset decimalsign
-set view 60, 30, 1, 1
-set samples 100, 100
-set isosamples 10, 10
-set surface
-unset contour
-set clabel '%8.3g'
-set mapping cartesian
-set datafile separator whitespace
-unset hidden3d
-set cntrparam order 4
-set cntrparam linear
-set cntrparam levels auto 5
-set cntrparam points 5
-set size ratio 0 1,1
-set origin 0,0
-set style data points
-set style function lines
-set xzeroaxis linetype -2 linewidth 1.000
-set yzeroaxis linetype -2 linewidth 1.000
-set zzeroaxis linetype -2 linewidth 1.000
-set x2zeroaxis linetype -2 linewidth 1.000
-set y2zeroaxis linetype -2 linewidth 1.000
-set ticslevel 0.5
-set mxtics default
-set mytics default
-set mztics default
-set mx2tics default
-set my2tics default
-set mcbtics default
-set xtics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
-set xtics  norangelimit
-set xtics   ()
-set ytics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
-set ytics autofreq  norangelimit
-set ztics border in scale 1,0.5 nomirror norotate  offset character 0, 0, 0
-set ztics autofreq  norangelimit
-set nox2tics
-set noy2tics
-set cbtics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
-set cbtics autofreq  norangelimit
-set title "" 
-set title  offset character 0, 0, 0 font "" norotate
-set timestamp bottom 
-set timestamp "" 
-set timestamp  offset character 0, 0, 0 font "" norotate
-set rrange [ * : * ] noreverse nowriteback  # (currently [8.98847e+307:-8.98847e+307] )
-set autoscale rfixmin
-set autoscale rfixmax
-set trange [ * : * ] noreverse nowriteback  # (currently [-5.00000:5.00000] )
-set autoscale tfixmin
-set autoscale tfixmax
-set urange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
-set autoscale ufixmin
-set autoscale ufixmax
-set vrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
-set autoscale vfixmin
-set autoscale vfixmax
-set xlabel "" 
-set xlabel  offset character 0, 0, 0 font "" textcolor lt -1 norotate
-set x2label "" 
-set x2label  offset character 0, 0, 0 font "" textcolor lt -1 norotate
-set xrange [ * : * ] noreverse nowriteback  # (currently [-0.150000:3.15000] )
-set autoscale xfixmin
-set autoscale xfixmax
-set x2range [ * : * ] noreverse nowriteback  # (currently [0.00000:3.00000] )
-set autoscale x2fixmin
-set autoscale x2fixmax
-set ylabel "" 
-set ylabel  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
-set y2label "" 
-set y2label  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
-set yrange [ 0.00000 : 1.90000e+06 ] noreverse nowriteback  # (currently [:] )
-set autoscale yfixmin
-set autoscale yfixmax
-set y2range [ * : * ] noreverse nowriteback  # (currently [0.00000:1.90000e+06] )
-set autoscale y2fixmin
-set autoscale y2fixmax
-set zlabel "" 
-set zlabel  offset character 0, 0, 0 font "" textcolor lt -1 norotate
-set zrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
-set autoscale zfixmin
-set autoscale zfixmax
-set cblabel "" 
-set cblabel  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
-set cbrange [ * : * ] noreverse nowriteback  # (currently [8.98847e+307:-8.98847e+307] )
-set autoscale cbfixmin
-set autoscale cbfixmax
-set zero 1e-08
-set lmargin  -1
-set bmargin  -1
-set rmargin  -1
-set tmargin  -1
-set pm3d explicit at s
-set pm3d scansautomatic
-set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean
-set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB 
-set palette rgbformulae 7, 5, 15
-set colorbox default
-set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 front bdefault
-set loadpath 
-set fontpath 
-set fit noerrorvariables
-GNUTERM = "aqua"
-plot 'bench_results.txt' using 2:xticlabel(1) w lp lw 2, '' using 3:xticlabel(1) w lp lw 2, '' using 4:xticlabel(1) w lp lw 2, '' using 5:xticlabel(1) w lp lw 2, '' using 6:xticlabel(1) w lp lw 2, '' using 7:xticlabel(1) w lp lw 2, '' using 8:xticlabel(1) w lp lw 2, '' using 9:xticlabel(1) w lp lw 2
-#    EOF
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.sh b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.sh
deleted file mode 100755
index d870a0cb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/bench.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-
-# for a given node version run:
-# for i in {0..9}; do node benchmark.js >> bench_0.6.2.log; done;
-
-PATTERNS=('nodeuuid.v1()' "nodeuuid.v1('binary'," 'nodeuuid.v4()' "nodeuuid.v4('binary'," "uuid()" "uuid('binary')" 'uuidjs.create(1)' 'uuidjs.create(4)' '140byte')
-FILES=(node_uuid_v1_string node_uuid_v1_buf node_uuid_v4_string node_uuid_v4_buf libuuid_v4_string libuuid_v4_binary uuidjs_v1_string uuidjs_v4_string 140byte_es)
-INDICES=(2 3 2 3 2 2 2 2 2)
-VERSIONS=$( ls bench_*.log | sed -e 's/^bench_\([0-9\.]*\)\.log/\1/' | tr "\\n" " " )
-TMPJOIN="tmp_join"
-OUTPUT="bench_results.txt"
-
-for I in ${!FILES[*]}; do
-  F=${FILES[$I]}
-  P=${PATTERNS[$I]}
-  INDEX=${INDICES[$I]}
-  echo "version $F" > $F
-  for V in $VERSIONS; do
-    (VAL=$( grep "$P" bench_$V.log | LC_ALL=en_US awk '{ sum += $'$INDEX' } END { print sum/NR }' ); echo $V $VAL) >> $F
-  done
-  if [ $I == 0 ]; then
-    cat $F > $TMPJOIN
-  else
-    join $TMPJOIN $F > $OUTPUT
-    cp $OUTPUT $TMPJOIN
-  fi
-  rm $F
-done
-
-rm $TMPJOIN
-
-gnuplot bench.gnu
-convert -density 200 -resize 800x560 -flatten bench.eps bench.png
-rm bench.eps
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c
deleted file mode 100644
index dbfc75f6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-Test performance of native C UUID generation
-
-To Compile: cc -luuid benchmark-native.c -o benchmark-native
-*/
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <uuid/uuid.h>
-
-int main() {
-  uuid_t myid;
-  char buf[36+1];
-  int i;
-  struct timeval t;
-  double start, finish;
-
-  gettimeofday(&t, NULL);
-  start = t.tv_sec + t.tv_usec/1e6;
-
-  int n = 2e5;
-  for (i = 0; i < n; i++) {
-    uuid_generate(myid);
-    uuid_unparse(myid, buf);
-  }
-
-  gettimeofday(&t, NULL);
-  finish = t.tv_sec + t.tv_usec/1e6;
-  double dur = finish - start;
-
-  printf("%d uuids/sec", (int)(n/dur));
-  return 0;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js
deleted file mode 100644
index 40e6efbe..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js
+++ /dev/null
@@ -1,84 +0,0 @@
-try {
-  var nodeuuid = require('../uuid');
-} catch (e) {
-  console.error('node-uuid require failed - skipping tests');
-}
-
-try {
-  var uuid = require('uuid');
-} catch (e) {
-  console.error('uuid require failed - skipping tests');
-}
-
-try {
-  var uuidjs = require('uuid-js');
-} catch (e) {
-  console.error('uuid-js require failed - skipping tests');
-}
-
-var N = 5e5;
-
-function rate(msg, t) {
-  console.log(msg + ': ' +
-    (N / (Date.now() - t) * 1e3 | 0) +
-    ' uuids/second');
-}
-
-console.log('# v4');
-
-// node-uuid - string form
-if (nodeuuid) {
-  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4();
-  rate('nodeuuid.v4() - using node.js crypto RNG', t);
-
-  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4({rng: nodeuuid.mathRNG});
-  rate('nodeuuid.v4() - using Math.random() RNG', t);
-
-  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary');
-  rate('nodeuuid.v4(\'binary\')', t);
-
-  var buffer = new nodeuuid.BufferClass(16);
-  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary', buffer);
-  rate('nodeuuid.v4(\'binary\', buffer)', t);
-}
-
-// libuuid - string form
-if (uuid) {
-  for (var i = 0, t = Date.now(); i < N; i++) uuid();
-  rate('uuid()', t);
-
-  for (var i = 0, t = Date.now(); i < N; i++) uuid('binary');
-  rate('uuid(\'binary\')', t);
-}
-
-// uuid-js - string form
-if (uuidjs) {
-  for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(4);
-  rate('uuidjs.create(4)', t);
-}
-
-// 140byte.es
-for (var i = 0, t = Date.now(); i < N; i++) 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(s,r){r=Math.random()*16|0;return (s=='x'?r:r&0x3|0x8).toString(16)});
-rate('140byte.es_v4', t);
-
-console.log('');
-console.log('# v1');
-
-// node-uuid - v1 string form
-if (nodeuuid) {
-  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1();
-  rate('nodeuuid.v1()', t);
-
-  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary');
-  rate('nodeuuid.v1(\'binary\')', t);
-
-  var buffer = new nodeuuid.BufferClass(16);
-  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary', buffer);
-  rate('nodeuuid.v1(\'binary\', buffer)', t);
-}
-
-// uuid-js - v1 string form
-if (uuidjs) {
-  for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(1);
-  rate('uuidjs.create(1)', t);
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/component.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/component.json
deleted file mode 100644
index ace21348..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/component.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "name": "node-uuid",
-  "repo": "broofa/node-uuid",
-  "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.",
-  "version": "1.4.0",
-  "author": "Robert Kieffer <robert@broofa.com>",
-  "contributors": [
-    {"name": "Christoph Tavan <dev@tavan.de>", "github": "https://github.com/ctavan"}
-  ],
-  "keywords": ["uuid", "guid", "rfc4122"],
-  "dependencies": {},
-  "development": {},
-  "main": "uuid.js",
-  "scripts": [
-    "uuid.js"
-  ],
-  "license": "MIT"
-}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/package.json
deleted file mode 100644
index 7b709ee9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/package.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "name": "node-uuid",
-  "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.",
-  "url": "http://github.com/broofa/node-uuid",
-  "keywords": [
-    "uuid",
-    "guid",
-    "rfc4122"
-  ],
-  "author": {
-    "name": "Robert Kieffer",
-    "email": "robert@broofa.com"
-  },
-  "contributors": [
-    {
-      "name": "Christoph Tavan",
-      "email": "dev@tavan.de"
-    }
-  ],
-  "lib": ".",
-  "main": "./uuid.js",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/broofa/node-uuid.git"
-  },
-  "version": "1.4.1",
-  "readme": "# node-uuid\n\nSimple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.\n\nFeatures:\n\n* Generate RFC4122 version 1 or version 4 UUIDs\n* Runs in node.js and all browsers.\n* Registered as a [ComponentJS](https://github.com/component/component) [component](https://github.com/component/component/wiki/Components) ('broofa/node-uuid').\n* Cryptographically strong random # generation on supporting platforms\n* 1.1K minified and gzip'ed  (Want something smaller?  Check this [crazy shit](https://gist.github.com/982883) out! )\n* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)\n\n## Getting Started\n\nInstall it in your browser:\n\n```html\n<script src=\"uuid.js\"></script>\n```\n\nOr in node.js:\n\n```\nnpm install node-uuid\n```\n\n```javascript\nvar uuid = require('node-uuid');\n```\n\nThen create some ids ...\n\n```javascript\n// Generate a v1 (time-based) id\nuuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n\n// Generate a v4 (random) id\nuuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'\n```\n\n## API\n\n### uuid.v1([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v1 (timestamp-based) UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n  * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID.  See note 1.\n  * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence.  Default: An internally maintained clockseq is used.\n  * `msecs` - (Number | Date) Time in milliseconds since unix Epoch.  Default: The current time is used.\n  * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nNotes:\n\n1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v1({\n  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],\n  clockseq: 0x1234,\n  msecs: new Date('2011-11-01').getTime(),\n  nsecs: 5678\n});   // -> \"710b962e-041c-11e1-9234-0123456789ab\"\n```\n\nExample: In-place generation of two binary IDs\n\n```javascript\n// Generate two ids in an array\nvar arr = new Array(32); // -> []\nuuid.v1(null, arr, 0);   // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\nuuid.v1(null, arr, 16);  // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\n\n// Optionally use uuid.unparse() to get stringify the ids\nuuid.unparse(buffer);    // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'\nuuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'\n```\n\n### uuid.v4([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v4 UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n  * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values\n  * `rng` - (Function) Random # generator to use.  Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v4({\n  random: [\n    0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,\n    0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36\n  ]\n});\n// -> \"109156be-c4fb-41ea-b1b4-efe1671c5836\"\n```\n\nExample: Generate two IDs in a single buffer\n\n```javascript\nvar buffer = new Array(32); // (or 'new Buffer' in node.js)\nuuid.v4(null, buffer, 0);\nuuid.v4(null, buffer, 16);\n```\n\n### uuid.parse(id[, buffer[, offset]])\n### uuid.unparse(buffer[, offset])\n\nParse and unparse UUIDs\n\n  * `id` - (String) UUID(-like) string\n  * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used\n  * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0\n\nExample parsing and unparsing a UUID string\n\n```javascript\nvar bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> <Buffer 79 7f f0 43 11 eb 11 e1 80 d6 51 09 98 75 5d 10>\nvar string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'\n```\n\n### uuid.noConflict()\n\n(Browsers only) Set `uuid` property back to it's previous value.\n\nReturns the node-uuid object.\n\nExample:\n\n```javascript\nvar myUuid = uuid.noConflict();\nmyUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n```\n\n## Deprecated APIs\n\nSupport for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.\n\n### uuid([format [, buffer [, offset]]])\n\nuuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).\n\n### uuid.BufferClass\n\nThe class of container created when generating binary uuid data if no buffer argument is specified.  This is expected to go away, with no replacement API.\n\n## Testing\n\nIn node.js\n\n```\n> cd test\n> node test.js\n```\n\nIn Browser\n\n```\nopen test/test.html\n```\n\n### Benchmarking\n\nRequires node.js\n\n```\nnpm install uuid uuid-js\nnode benchmark/benchmark.js\n```\n\nFor a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)\n\nFor browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).\n\n## Release notes\n\n### 1.4.0\n\n* Improved module context detection\n* Removed public RNG functions\n\n### 1.3.2\n\n* Improve tests and handling of v1() options (Issue #24)\n* Expose RNG option to allow for perf testing with different generators\n\n### 1.3.0\n\n* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!\n* Support for node.js crypto API\n* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/broofa/node-uuid/issues"
-  },
-  "homepage": "https://github.com/broofa/node-uuid",
-  "_id": "node-uuid@1.4.1",
-  "_shasum": "39aef510e5889a3dca9c895b506c73aae1bac048",
-  "_from": "node-uuid@~1.4.0",
-  "_resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/compare_v1.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/compare_v1.js
deleted file mode 100644
index 05af8221..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/compare_v1.js
+++ /dev/null
@@ -1,63 +0,0 @@
-var assert = require('assert'),
-    nodeuuid = require('../uuid'),
-    uuidjs = require('uuid-js'),
-    libuuid = require('uuid').generate,
-    util = require('util'),
-    exec = require('child_process').exec,
-    os = require('os');
-
-// On Mac Os X / macports there's only the ossp-uuid package that provides uuid
-// On Linux there's uuid-runtime which provides uuidgen
-var uuidCmd = os.type() === 'Darwin' ? 'uuid -1' : 'uuidgen -t';
-
-function compare(ids) {
-  console.log(ids);
-  for (var i = 0; i < ids.length; i++) {
-    var id = ids[i].split('-');
-    id = [id[2], id[1], id[0]].join('');
-    ids[i] = id;
-  }
-  var sorted = ([].concat(ids)).sort();
-
-  if (sorted.toString() !== ids.toString()) {
-    console.log('Warning: sorted !== ids');
-  } else {
-    console.log('everything in order!');
-  }
-}
-
-// Test time order of v1 uuids
-var ids = [];
-while (ids.length < 10e3) ids.push(nodeuuid.v1());
-
-var max = 10;
-console.log('node-uuid:');
-ids = [];
-for (var i = 0; i < max; i++) ids.push(nodeuuid.v1());
-compare(ids);
-
-console.log('');
-console.log('uuidjs:');
-ids = [];
-for (var i = 0; i < max; i++) ids.push(uuidjs.create(1).toString());
-compare(ids);
-
-console.log('');
-console.log('libuuid:');
-ids = [];
-var count = 0;
-var last = function() {
-  compare(ids);
-}
-var cb = function(err, stdout, stderr) {
-  ids.push(stdout.substring(0, stdout.length-1));
-  count++;
-  if (count < max) {
-    return next();
-  }
-  last();
-};
-var next = function() {
-  exec(uuidCmd, cb);
-};
-next();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.html b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.html
deleted file mode 100644
index d80326ec..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
-  <head>
-    <style>
-      div {
-        font-family: monospace;
-        font-size: 8pt;
-      }
-      div.log {color: #444;}
-      div.warn {color: #550;}
-      div.error {color: #800; font-weight: bold;}
-    </style>
-    <script src="../uuid.js"></script>
-  </head>
-  <body>
-    <script src="./test.js"></script>
-  </body>
-</html>
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.js
deleted file mode 100644
index 24692256..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/test/test.js
+++ /dev/null
@@ -1,228 +0,0 @@
-if (!this.uuid) {
-  // node.js
-  uuid = require('../uuid');
-}
-
-//
-// x-platform log/assert shims
-//
-
-function _log(msg, type) {
-  type = type || 'log';
-
-  if (typeof(document) != 'undefined') {
-    document.write('<div class="' + type + '">' + msg.replace(/\n/g, '<br />') + '</div>');
-  }
-  if (typeof(console) != 'undefined') {
-    var color = {
-      log: '\033[39m',
-      warn: '\033[33m',
-      error: '\033[31m'
-    };
-    console[type](color[type] + msg + color.log);
-  }
-}
-
-function log(msg) {_log(msg, 'log');}
-function warn(msg) {_log(msg, 'warn');}
-function error(msg) {_log(msg, 'error');}
-
-function assert(res, msg) {
-  if (!res) {
-    error('FAIL: ' + msg);
-  } else {
-    log('Pass: ' + msg);
-  }
-}
-
-//
-// Unit tests
-//
-
-// Verify ordering of v1 ids created with explicit times
-var TIME = 1321644961388; // 2011-11-18 11:36:01.388-08:00
-
-function compare(name, ids) {
-  ids = ids.map(function(id) {
-    return id.split('-').reverse().join('-');
-  }).sort();
-  var sorted = ([].concat(ids)).sort();
-
-  assert(sorted.toString() == ids.toString(), name + ' have expected order');
-}
-
-// Verify ordering of v1 ids created using default behavior
-compare('uuids with current time', [
-  uuid.v1(),
-  uuid.v1(),
-  uuid.v1(),
-  uuid.v1(),
-  uuid.v1()
-]);
-
-// Verify ordering of v1 ids created with explicit times
-compare('uuids with time option', [
-  uuid.v1({msecs: TIME - 10*3600*1000}),
-  uuid.v1({msecs: TIME - 1}),
-  uuid.v1({msecs: TIME}),
-  uuid.v1({msecs: TIME + 1}),
-  uuid.v1({msecs: TIME + 28*24*3600*1000})
-]);
-
-assert(
-  uuid.v1({msecs: TIME}) != uuid.v1({msecs: TIME}),
-  'IDs created at same msec are different'
-);
-
-// Verify throw if too many ids created
-var thrown = false;
-try {
-  uuid.v1({msecs: TIME, nsecs: 10000});
-} catch (e) {
-  thrown = true;
-}
-assert(thrown, 'Exception thrown when > 10K ids created in 1 ms');
-
-// Verify clock regression bumps clockseq
-var uidt = uuid.v1({msecs: TIME});
-var uidtb = uuid.v1({msecs: TIME - 1});
-assert(
-  parseInt(uidtb.split('-')[3], 16) - parseInt(uidt.split('-')[3], 16) === 1,
-  'Clock regression by msec increments the clockseq'
-);
-
-// Verify clock regression bumps clockseq
-var uidtn = uuid.v1({msecs: TIME, nsecs: 10});
-var uidtnb = uuid.v1({msecs: TIME, nsecs: 9});
-assert(
-  parseInt(uidtnb.split('-')[3], 16) - parseInt(uidtn.split('-')[3], 16) === 1,
-  'Clock regression by nsec increments the clockseq'
-);
-
-// Verify explicit options produce expected id
-var id = uuid.v1({
-  msecs: 1321651533573,
-  nsecs: 5432,
-  clockseq: 0x385c,
-  node: [ 0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10 ]
-});
-assert(id == 'd9428888-122b-11e1-b85c-61cd3cbb3210', 'Explicit options produce expected id');
-
-// Verify adjacent ids across a msec boundary are 1 time unit apart
-var u0 = uuid.v1({msecs: TIME, nsecs: 9999});
-var u1 = uuid.v1({msecs: TIME + 1, nsecs: 0});
-
-var before = u0.split('-')[0], after = u1.split('-')[0];
-var dt = parseInt(after, 16) - parseInt(before, 16);
-assert(dt === 1, 'Ids spanning 1ms boundary are 100ns apart');
-
-//
-// Test parse/unparse
-//
-
-id = '00112233445566778899aabbccddeeff';
-assert(uuid.unparse(uuid.parse(id.substr(0,10))) ==
-  '00112233-4400-0000-0000-000000000000', 'Short parse');
-assert(uuid.unparse(uuid.parse('(this is the uuid -> ' + id + id)) ==
-  '00112233-4455-6677-8899-aabbccddeeff', 'Dirty parse');
-
-//
-// Perf tests
-//
-
-var generators = {
-  v1: uuid.v1,
-  v4: uuid.v4
-};
-
-var UUID_FORMAT = {
-  v1: /[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i,
-  v4: /[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i
-};
-
-var N = 1e4;
-
-// Get %'age an actual value differs from the ideal value
-function divergence(actual, ideal) {
-  return Math.round(100*100*(actual - ideal)/ideal)/100;
-}
-
-function rate(msg, t) {
-  log(msg + ': ' + (N / (Date.now() - t) * 1e3 | 0) + ' uuids\/second');
-}
-
-for (var version in generators) {
-  var counts = {}, max = 0;
-  var generator = generators[version];
-  var format = UUID_FORMAT[version];
-
-  log('\nSanity check ' + N + ' ' + version + ' uuids');
-  for (var i = 0, ok = 0; i < N; i++) {
-    id = generator();
-    if (!format.test(id)) {
-      throw Error(id + ' is not a valid UUID string');
-    }
-
-    if (id != uuid.unparse(uuid.parse(id))) {
-      assert(fail, id + ' is not a valid id');
-    }
-
-    // Count digits for our randomness check
-    if (version == 'v4') {
-      var digits = id.replace(/-/g, '').split('');
-      for (var j = digits.length-1; j >= 0; j--) {
-        var c = digits[j];
-        max = Math.max(max, counts[c] = (counts[c] || 0) + 1);
-      }
-    }
-  }
-
-  // Check randomness for v4 UUIDs
-  if (version == 'v4') {
-    // Limit that we get worried about randomness. (Purely empirical choice, this!)
-    var limit = 2*100*Math.sqrt(1/N);
-
-    log('\nChecking v4 randomness.  Distribution of Hex Digits (% deviation from ideal)');
-
-    for (var i = 0; i < 16; i++) {
-      var c = i.toString(16);
-      var bar = '', n = counts[c], p = Math.round(n/max*100|0);
-
-      // 1-3,5-8, and D-F: 1:16 odds over 30 digits
-      var ideal = N*30/16;
-      if (i == 4) {
-        // 4: 1:1 odds on 1 digit, plus 1:16 odds on 30 digits
-        ideal = N*(1 + 30/16);
-      } else if (i >= 8 && i <= 11) {
-        // 8-B: 1:4 odds on 1 digit, plus 1:16 odds on 30 digits
-        ideal = N*(1/4 + 30/16);
-      } else {
-        // Otherwise: 1:16 odds on 30 digits
-        ideal = N*30/16;
-      }
-      var d = divergence(n, ideal);
-
-      // Draw bar using UTF squares (just for grins)
-      var s = n/max*50 | 0;
-      while (s--) bar += '=';
-
-      assert(Math.abs(d) < limit, c + ' |' + bar + '| ' + counts[c] + ' (' + d + '% < ' + limit + '%)');
-    }
-  }
-}
-
-// Perf tests
-for (var version in generators) {
-  log('\nPerformance testing ' + version + ' UUIDs');
-  var generator = generators[version];
-  var buf = new uuid.BufferClass(16);
-
-  for (var i = 0, t = Date.now(); i < N; i++) generator();
-  rate('uuid.' + version + '()', t);
-
-  for (var i = 0, t = Date.now(); i < N; i++) generator('binary');
-  rate('uuid.' + version + '(\'binary\')', t);
-
-  for (var i = 0, t = Date.now(); i < N; i++) generator('binary', buf);
-  rate('uuid.' + version + '(\'binary\', buffer)', t);
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/uuid.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/uuid.js
deleted file mode 100644
index 2fac6dc4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/node-uuid/uuid.js
+++ /dev/null
@@ -1,245 +0,0 @@
-//     uuid.js
-//
-//     Copyright (c) 2010-2012 Robert Kieffer
-//     MIT License - http://opensource.org/licenses/mit-license.php
-
-(function() {
-  var _global = this;
-
-  // Unique ID creation requires a high quality random # generator.  We feature
-  // detect to determine the best RNG source, normalizing to a function that
-  // returns 128-bits of randomness, since that's what's usually required
-  var _rng;
-
-  // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
-  //
-  // Moderately fast, high quality
-  if (typeof(require) == 'function') {
-    try {
-      var _rb = require('crypto').randomBytes;
-      _rng = _rb && function() {return _rb(16);};
-    } catch(e) {}
-  }
-
-  if (!_rng && _global.crypto && crypto.getRandomValues) {
-    // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
-    //
-    // Moderately fast, high quality
-    var _rnds8 = new Uint8Array(16);
-    _rng = function whatwgRNG() {
-      crypto.getRandomValues(_rnds8);
-      return _rnds8;
-    };
-  }
-
-  if (!_rng) {
-    // Math.random()-based (RNG)
-    //
-    // If all else fails, use Math.random().  It's fast, but is of unspecified
-    // quality.
-    var  _rnds = new Array(16);
-    _rng = function() {
-      for (var i = 0, r; i < 16; i++) {
-        if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
-        _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
-      }
-
-      return _rnds;
-    };
-  }
-
-  // Buffer class to use
-  var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
-
-  // Maps for number <-> hex string conversion
-  var _byteToHex = [];
-  var _hexToByte = {};
-  for (var i = 0; i < 256; i++) {
-    _byteToHex[i] = (i + 0x100).toString(16).substr(1);
-    _hexToByte[_byteToHex[i]] = i;
-  }
-
-  // **`parse()` - Parse a UUID into it's component bytes**
-  function parse(s, buf, offset) {
-    var i = (buf && offset) || 0, ii = 0;
-
-    buf = buf || [];
-    s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
-      if (ii < 16) { // Don't overflow!
-        buf[i + ii++] = _hexToByte[oct];
-      }
-    });
-
-    // Zero out remaining bytes if string was short
-    while (ii < 16) {
-      buf[i + ii++] = 0;
-    }
-
-    return buf;
-  }
-
-  // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
-  function unparse(buf, offset) {
-    var i = offset || 0, bth = _byteToHex;
-    return  bth[buf[i++]] + bth[buf[i++]] +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] + '-' +
-            bth[buf[i++]] + bth[buf[i++]] +
-            bth[buf[i++]] + bth[buf[i++]] +
-            bth[buf[i++]] + bth[buf[i++]];
-  }
-
-  // **`v1()` - Generate time-based UUID**
-  //
-  // Inspired by https://github.com/LiosK/UUID.js
-  // and http://docs.python.org/library/uuid.html
-
-  // random #'s we need to init node and clockseq
-  var _seedBytes = _rng();
-
-  // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
-  var _nodeId = [
-    _seedBytes[0] | 0x01,
-    _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
-  ];
-
-  // Per 4.2.2, randomize (14 bit) clockseq
-  var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
-
-  // Previous uuid creation time
-  var _lastMSecs = 0, _lastNSecs = 0;
-
-  // See https://github.com/broofa/node-uuid for API details
-  function v1(options, buf, offset) {
-    var i = buf && offset || 0;
-    var b = buf || [];
-
-    options = options || {};
-
-    var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
-
-    // UUID timestamps are 100 nano-second units since the Gregorian epoch,
-    // (1582-10-15 00:00).  JSNumbers aren't precise enough for this, so
-    // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
-    // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
-    var msecs = options.msecs != null ? options.msecs : new Date().getTime();
-
-    // Per 4.2.1.2, use count of uuid's generated during the current clock
-    // cycle to simulate higher resolution clock
-    var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
-
-    // Time since last uuid creation (in msecs)
-    var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
-
-    // Per 4.2.1.2, Bump clockseq on clock regression
-    if (dt < 0 && options.clockseq == null) {
-      clockseq = clockseq + 1 & 0x3fff;
-    }
-
-    // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
-    // time interval
-    if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
-      nsecs = 0;
-    }
-
-    // Per 4.2.1.2 Throw error if too many uuids are requested
-    if (nsecs >= 10000) {
-      throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
-    }
-
-    _lastMSecs = msecs;
-    _lastNSecs = nsecs;
-    _clockseq = clockseq;
-
-    // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
-    msecs += 12219292800000;
-
-    // `time_low`
-    var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
-    b[i++] = tl >>> 24 & 0xff;
-    b[i++] = tl >>> 16 & 0xff;
-    b[i++] = tl >>> 8 & 0xff;
-    b[i++] = tl & 0xff;
-
-    // `time_mid`
-    var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
-    b[i++] = tmh >>> 8 & 0xff;
-    b[i++] = tmh & 0xff;
-
-    // `time_high_and_version`
-    b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
-    b[i++] = tmh >>> 16 & 0xff;
-
-    // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
-    b[i++] = clockseq >>> 8 | 0x80;
-
-    // `clock_seq_low`
-    b[i++] = clockseq & 0xff;
-
-    // `node`
-    var node = options.node || _nodeId;
-    for (var n = 0; n < 6; n++) {
-      b[i + n] = node[n];
-    }
-
-    return buf ? buf : unparse(b);
-  }
-
-  // **`v4()` - Generate random UUID**
-
-  // See https://github.com/broofa/node-uuid for API details
-  function v4(options, buf, offset) {
-    // Deprecated - 'format' argument, as supported in v1.2
-    var i = buf && offset || 0;
-
-    if (typeof(options) == 'string') {
-      buf = options == 'binary' ? new BufferClass(16) : null;
-      options = null;
-    }
-    options = options || {};
-
-    var rnds = options.random || (options.rng || _rng)();
-
-    // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
-    rnds[6] = (rnds[6] & 0x0f) | 0x40;
-    rnds[8] = (rnds[8] & 0x3f) | 0x80;
-
-    // Copy bytes to buffer, if provided
-    if (buf) {
-      for (var ii = 0; ii < 16; ii++) {
-        buf[i + ii] = rnds[ii];
-      }
-    }
-
-    return buf || unparse(rnds);
-  }
-
-  // Export public API
-  var uuid = v4;
-  uuid.v1 = v1;
-  uuid.v4 = v4;
-  uuid.parse = parse;
-  uuid.unparse = unparse;
-  uuid.BufferClass = BufferClass;
-
-  if (typeof define === 'function' && define.amd) {
-    // Publish as AMD module
-    define(function() {return uuid;});
-  } else if (typeof(module) != 'undefined' && module.exports) {
-    // Publish as node.js module
-    module.exports = uuid;
-  } else {
-    // Publish as global (in browsers)
-    var _previousRoot = _global.uuid;
-
-    // **`noConflict()` - (browser only) to reset global 'uuid' var**
-    uuid.noConflict = function() {
-      _global.uuid = _previousRoot;
-      return uuid;
-    };
-
-    _global.uuid = uuid;
-  }
-}).call(this);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/LICENSE
deleted file mode 100644
index a4a9aee0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/LICENSE
+++ /dev/null
@@ -1,55 +0,0 @@
-Apache License
-
-Version 2.0, January 2004
-
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
-
-"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of this License; and
-
-You must cause any modified files to carry prominent notices stating that You changed the files; and
-
-You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
-
-If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/README.md
deleted file mode 100644
index 34c4a85d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-oauth-sign
-==========
-
-OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. 
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/index.js
deleted file mode 100644
index e35bfa67..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-var crypto = require('crypto')
-  , qs = require('querystring')
-  ;
-
-function sha1 (key, body) {
-  return crypto.createHmac('sha1', key).update(body).digest('base64')
-}
-
-function rfc3986 (str) {
-  return encodeURIComponent(str)
-    .replace(/!/g,'%21')
-    .replace(/\*/g,'%2A')
-    .replace(/\(/g,'%28')
-    .replace(/\)/g,'%29')
-    .replace(/'/g,'%27')
-    ;
-}
-
-function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret) {
-  // adapted from https://dev.twitter.com/docs/auth/oauth and 
-  // https://dev.twitter.com/docs/auth/creating-signature
-
-  var querystring = Object.keys(params).sort().map(function(key){
-    // big WTF here with the escape + encoding but it's what twitter wants
-    return escape(rfc3986(key)) + "%3D" + escape(rfc3986(params[key]))
-  }).join('%26')
-
-  var base = [
-    httpMethod ? httpMethod.toUpperCase() : 'GET',
-    rfc3986(base_uri),
-    querystring
-  ].join('&')
-
-  var key = [
-    consumer_secret,
-    token_secret || ''
-  ].map(rfc3986).join('&')
-
-  return sha1(key, base)
-}
-
-exports.hmacsign = hmacsign
-exports.rfc3986 = rfc3986
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/package.json
deleted file mode 100644
index 95e96890..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/package.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "author": {
-    "name": "Mikeal Rogers",
-    "email": "mikeal.rogers@gmail.com",
-    "url": "http://www.futurealoof.com"
-  },
-  "name": "oauth-sign",
-  "description": "OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module.",
-  "version": "0.3.0",
-  "repository": {
-    "url": "https://github.com/mikeal/oauth-sign"
-  },
-  "main": "index.js",
-  "dependencies": {},
-  "devDependencies": {},
-  "optionalDependencies": {},
-  "engines": {
-    "node": "*"
-  },
-  "scripts": {
-    "test": "node test.js"
-  },
-  "readme": "oauth-sign\n==========\n\nOAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. \n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/mikeal/oauth-sign/issues"
-  },
-  "homepage": "https://github.com/mikeal/oauth-sign",
-  "_id": "oauth-sign@0.3.0",
-  "_shasum": "cb540f93bb2b22a7d5941691a288d60e8ea9386e",
-  "_from": "oauth-sign@~0.3.0",
-  "_resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/test.js
deleted file mode 100644
index 46955ff6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/oauth-sign/test.js
+++ /dev/null
@@ -1,49 +0,0 @@
-var hmacsign = require('./index').hmacsign
-  , assert = require('assert')
-  , qs = require('querystring')
-  ;
-
-// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth
-
-var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', 
-  { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11'
-  , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g'
-  , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk'
-  , oauth_signature_method: 'HMAC-SHA1'
-  , oauth_timestamp: '1272323042'
-  , oauth_version: '1.0'
-  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98")
-
-console.log(reqsign)
-console.log('8wUi7m5HFQy76nowoCThusfgB+Q=')
-assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=')
-
-var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token',
-  { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g'
-  , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8'
-  , oauth_signature_method: 'HMAC-SHA1'
-  , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc'
-  , oauth_timestamp: '1272323047'
-  , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY'
-  , oauth_version: '1.0'
-  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA")
-  
-console.log(accsign)
-console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=')
-assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=')
-
-var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', 
-  { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g"
-  , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y"
-  , oauth_signature_method: "HMAC-SHA1"
-  , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw"
-  , oauth_timestamp: "1272325550"
-  , oauth_version: "1.0"
-  , status: 'setting up my twitter 私のさえずりを設定する'
-  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA")
-
-console.log(upsign)
-console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=')
-assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=')
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.gitmodules b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.gitmodules
deleted file mode 100644
index 49e31dac..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.gitmodules
+++ /dev/null
@@ -1,6 +0,0 @@
-[submodule "support/expresso"]
-	path = support/expresso
-	url = git://github.com/visionmedia/expresso.git
-[submodule "support/should"]
-	path = support/should
-	url = git://github.com/visionmedia/should.js.git
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.npmignore
deleted file mode 100644
index e85ce2af..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/.npmignore
+++ /dev/null
@@ -1,7 +0,0 @@
-test
-.travis.yml
-benchmark.js
-component.json
-examples.js
-History.md
-Makefile
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/Readme.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/Readme.md
deleted file mode 100644
index 27e54a4a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/Readme.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# node-querystring
-
-  query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
-
-## Installation
-
-    $ npm install qs
-
-## Examples
-
-```js
-var qs = require('qs');
-
-qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
-// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
-
-qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
-// => user[name]=Tobi&user[email]=tobi%40learnboost.com
-```
-
-## Testing
-
-Install dev dependencies:
-
-    $ npm install -d
-
-and execute:
-
-    $ make test
-
-browser:
-
-    $ open test/browser/index.html
-
-## License 
-
-(The MIT License)
-
-Copyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
-
-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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/index.js
deleted file mode 100644
index b05938ac..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/index.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/**
- * Object#toString() ref for stringify().
- */
-
-var toString = Object.prototype.toString;
-
-/**
- * Object#hasOwnProperty ref
- */
-
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-/**
- * Array#indexOf shim.
- */
-
-var indexOf = typeof Array.prototype.indexOf === 'function'
-  ? function(arr, el) { return arr.indexOf(el); }
-  : function(arr, el) {
-      for (var i = 0; i < arr.length; i++) {
-        if (arr[i] === el) return i;
-      }
-      return -1;
-    };
-
-/**
- * Array.isArray shim.
- */
-
-var isArray = Array.isArray || function(arr) {
-  return toString.call(arr) == '[object Array]';
-};
-
-/**
- * Object.keys shim.
- */
-
-var objectKeys = Object.keys || function(obj) {
-  var ret = [];
-  for (var key in obj) {
-    if (obj.hasOwnProperty(key)) {
-      ret.push(key);
-    }
-  }
-  return ret;
-};
-
-/**
- * Array#forEach shim.
- */
-
-var forEach = typeof Array.prototype.forEach === 'function'
-  ? function(arr, fn) { return arr.forEach(fn); }
-  : function(arr, fn) {
-      for (var i = 0; i < arr.length; i++) fn(arr[i]);
-    };
-
-/**
- * Array#reduce shim.
- */
-
-var reduce = function(arr, fn, initial) {
-  if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
-  var res = initial;
-  for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
-  return res;
-};
-
-/**
- * Cache non-integer test regexp.
- */
-
-var isint = /^[0-9]+$/;
-
-function promote(parent, key) {
-  if (parent[key].length == 0) return parent[key] = {}
-  var t = {};
-  for (var i in parent[key]) {
-    if (hasOwnProperty.call(parent[key], i)) {
-      t[i] = parent[key][i];
-    }
-  }
-  parent[key] = t;
-  return t;
-}
-
-function parse(parts, parent, key, val) {
-  var part = parts.shift();
-  
-  // illegal
-  if (Object.getOwnPropertyDescriptor(Object.prototype, key)) return;
-  
-  // end
-  if (!part) {
-    if (isArray(parent[key])) {
-      parent[key].push(val);
-    } else if ('object' == typeof parent[key]) {
-      parent[key] = val;
-    } else if ('undefined' == typeof parent[key]) {
-      parent[key] = val;
-    } else {
-      parent[key] = [parent[key], val];
-    }
-    // array
-  } else {
-    var obj = parent[key] = parent[key] || [];
-    if (']' == part) {
-      if (isArray(obj)) {
-        if ('' != val) obj.push(val);
-      } else if ('object' == typeof obj) {
-        obj[objectKeys(obj).length] = val;
-      } else {
-        obj = parent[key] = [parent[key], val];
-      }
-      // prop
-    } else if (~indexOf(part, ']')) {
-      part = part.substr(0, part.length - 1);
-      if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
-      parse(parts, obj, part, val);
-      // key
-    } else {
-      if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
-      parse(parts, obj, part, val);
-    }
-  }
-}
-
-/**
- * Merge parent key/val pair.
- */
-
-function merge(parent, key, val){
-  if (~indexOf(key, ']')) {
-    var parts = key.split('[')
-      , len = parts.length
-      , last = len - 1;
-    parse(parts, parent, 'base', val);
-    // optimize
-  } else {
-    if (!isint.test(key) && isArray(parent.base)) {
-      var t = {};
-      for (var k in parent.base) t[k] = parent.base[k];
-      parent.base = t;
-    }
-    set(parent.base, key, val);
-  }
-
-  return parent;
-}
-
-/**
- * Compact sparse arrays.
- */
-
-function compact(obj) {
-  if ('object' != typeof obj) return obj;
-
-  if (isArray(obj)) {
-    var ret = [];
-
-    for (var i in obj) {
-      if (hasOwnProperty.call(obj, i)) {
-        ret.push(obj[i]);
-      }
-    }
-
-    return ret;
-  }
-
-  for (var key in obj) {
-    obj[key] = compact(obj[key]);
-  }
-
-  return obj;
-}
-
-/**
- * Parse the given obj.
- */
-
-function parseObject(obj){
-  var ret = { base: {} };
-
-  forEach(objectKeys(obj), function(name){
-    merge(ret, name, obj[name]);
-  });
-
-  return compact(ret.base);
-}
-
-/**
- * Parse the given str.
- */
-
-function parseString(str){
-  var ret = reduce(String(str).split('&'), function(ret, pair){
-    var eql = indexOf(pair, '=')
-      , brace = lastBraceInKey(pair)
-      , key = pair.substr(0, brace || eql)
-      , val = pair.substr(brace || eql, pair.length)
-      , val = val.substr(indexOf(val, '=') + 1, val.length);
-
-    // ?foo
-    if ('' == key) key = pair, val = '';
-    if ('' == key) return ret;
-
-    return merge(ret, decode(key), decode(val));
-  }, { base: {} }).base;
-
-  return compact(ret);
-}
-
-/**
- * Parse the given query `str` or `obj`, returning an object.
- *
- * @param {String} str | {Object} obj
- * @return {Object}
- * @api public
- */
-
-exports.parse = function(str){
-  if (null == str || '' == str) return {};
-  return 'object' == typeof str
-    ? parseObject(str)
-    : parseString(str);
-};
-
-/**
- * Turn the given `obj` into a query string
- *
- * @param {Object} obj
- * @return {String}
- * @api public
- */
-
-var stringify = exports.stringify = function(obj, prefix) {
-  if (isArray(obj)) {
-    return stringifyArray(obj, prefix);
-  } else if ('[object Object]' == toString.call(obj)) {
-    return stringifyObject(obj, prefix);
-  } else if ('string' == typeof obj) {
-    return stringifyString(obj, prefix);
-  } else {
-    return prefix + '=' + encodeURIComponent(String(obj));
-  }
-};
-
-/**
- * Stringify the given `str`.
- *
- * @param {String} str
- * @param {String} prefix
- * @return {String}
- * @api private
- */
-
-function stringifyString(str, prefix) {
-  if (!prefix) throw new TypeError('stringify expects an object');
-  return prefix + '=' + encodeURIComponent(str);
-}
-
-/**
- * Stringify the given `arr`.
- *
- * @param {Array} arr
- * @param {String} prefix
- * @return {String}
- * @api private
- */
-
-function stringifyArray(arr, prefix) {
-  var ret = [];
-  if (!prefix) throw new TypeError('stringify expects an object');
-  for (var i = 0; i < arr.length; i++) {
-    ret.push(stringify(arr[i], prefix + '[' + i + ']'));
-  }
-  return ret.join('&');
-}
-
-/**
- * Stringify the given `obj`.
- *
- * @param {Object} obj
- * @param {String} prefix
- * @return {String}
- * @api private
- */
-
-function stringifyObject(obj, prefix) {
-  var ret = []
-    , keys = objectKeys(obj)
-    , key;
-
-  for (var i = 0, len = keys.length; i < len; ++i) {
-    key = keys[i];
-    if ('' == key) continue;
-    if (null == obj[key]) {
-      ret.push(encodeURIComponent(key) + '=');
-    } else {
-      ret.push(stringify(obj[key], prefix
-        ? prefix + '[' + encodeURIComponent(key) + ']'
-        : encodeURIComponent(key)));
-    }
-  }
-
-  return ret.join('&');
-}
-
-/**
- * Set `obj`'s `key` to `val` respecting
- * the weird and wonderful syntax of a qs,
- * where "foo=bar&foo=baz" becomes an array.
- *
- * @param {Object} obj
- * @param {String} key
- * @param {String} val
- * @api private
- */
-
-function set(obj, key, val) {
-  var v = obj[key];
-  if (Object.getOwnPropertyDescriptor(Object.prototype, key)) return;
-  if (undefined === v) {
-    obj[key] = val;
-  } else if (isArray(v)) {
-    v.push(val);
-  } else {
-    obj[key] = [v, val];
-  }
-}
-
-/**
- * Locate last brace in `str` within the key.
- *
- * @param {String} str
- * @return {Number}
- * @api private
- */
-
-function lastBraceInKey(str) {
-  var len = str.length
-    , brace
-    , c;
-  for (var i = 0; i < len; ++i) {
-    c = str[i];
-    if (']' == c) brace = false;
-    if ('[' == c) brace = true;
-    if ('=' == c && !brace) return i;
-  }
-}
-
-/**
- * Decode `str`.
- *
- * @param {String} str
- * @return {String}
- * @api private
- */
-
-function decode(str) {
-  try {
-    return decodeURIComponent(str.replace(/\+/g, ' '));
-  } catch (err) {
-    return str;
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/package.json
deleted file mode 100644
index 0397a8f0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/qs/package.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
-  "name": "qs",
-  "description": "querystring parser",
-  "version": "0.6.6",
-  "keywords": [
-    "query string",
-    "parser",
-    "component"
-  ],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/visionmedia/node-querystring.git"
-  },
-  "devDependencies": {
-    "mocha": "*",
-    "expect.js": "*"
-  },
-  "scripts": {
-    "test": "make test"
-  },
-  "author": {
-    "name": "TJ Holowaychuk",
-    "email": "tj@vision-media.ca",
-    "url": "http://tjholowaychuk.com"
-  },
-  "main": "index",
-  "engines": {
-    "node": "*"
-  },
-  "readme": "# node-querystring\n\n  query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n    $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n    $ npm install -d\n\nand execute:\n\n    $ make test\n\nbrowser:\n\n    $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
-  "readmeFilename": "Readme.md",
-  "bugs": {
-    "url": "https://github.com/visionmedia/node-querystring/issues"
-  },
-  "homepage": "https://github.com/visionmedia/node-querystring",
-  "_id": "qs@0.6.6",
-  "_shasum": "6e015098ff51968b8a3c819001d5f2c89bc4b107",
-  "_from": "qs@~0.6.0",
-  "_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.jshintrc b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.jshintrc
deleted file mode 100644
index fb11913a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.jshintrc
+++ /dev/null
@@ -1,70 +0,0 @@
-{
-    "passfail"      : false,
-    "maxerr"        : 100,
-
-    "browser"       : false,
-    "node"          : true,
-    "rhino"         : false,
-    "couch"         : false,
-    "wsh"           : false,
-
-    "jquery"        : false,
-    "prototypejs"   : false,
-    "mootools"      : false,
-    "dojo"          : false,
-
-    "debug"         : false,
-    "devel"         : false,
-
-    "esnext"        : true,
-    "strict"        : true,
-    "globalstrict"  : true,
-
-    "asi"           : false,
-    "laxbreak"      : false,
-    "bitwise"       : true,
-    "boss"          : false,
-    "curly"         : true,
-    "eqeqeq"        : false,
-    "eqnull"        : true,
-    "evil"          : false,
-    "expr"          : false,
-    "forin"         : false,
-    "immed"         : true,
-    "lastsemic"     : true,
-    "latedef"       : false,
-    "loopfunc"      : false,
-    "noarg"         : true,
-    "regexp"        : false,
-    "regexdash"     : false,
-    "scripturl"     : false,
-    "shadow"        : false,
-    "supernew"      : false,
-    "undef"         : true,
-    "unused"         : true,
-
-    "newcap"        : true,
-    "noempty"       : true,
-    "nonew"         : true,
-    "nomen"         : false,
-    "onevar"        : false,
-    "onecase"       : true,
-    "plusplus"      : false,
-    "proto"         : false,
-    "sub"           : true,
-    "trailing"      : true,
-    "white"         : false,
-
-    "predef": [
-      "describe",
-      "it",
-      "before",
-      "beforeEach",
-      "after",
-      "afterEach",
-      "expect",
-      "setTimeout",
-      "clearTimeout"
-    ],
-    "maxlen": 0
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.npmignore
deleted file mode 100644
index 54efff98..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules/
-.*.sw[nmop]
-npm-debug.log
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.travis.yml
deleted file mode 100644
index 5d892654..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-language: node_js
-node_js:
-- "0.10"
-- "0.11"
-matrix:
-  fast_finish: true
-  allow_failures:
-    - node_js: 0.11
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/LICENSE
deleted file mode 100644
index 3fac4c85..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/LICENSE
+++ /dev/null
@@ -1,78 +0,0 @@
-Copyright GoInstant, Inc. and other contributors. All rights reserved.
-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.
-
-The following exceptions apply:
-
-===
-
-`pubSufTest()` of generate-pubsuffix.js is in the public domain.
-
-  // Any copyright is dedicated to the Public Domain.
-  // http://creativecommons.org/publicdomain/zero/1.0/
-
-===
-
-`public-suffix.txt` was obtained from
-<https://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1>
-via <http://publicsuffix.org>.
-
-That file contains the usual Mozilla triple-license, for which this project uses it
-under the terms of the MPL 1.1:
-
-    // ***** BEGIN LICENSE BLOCK *****
-    // Version: MPL 1.1/GPL 2.0/LGPL 2.1
-    // 
-    // The contents of this file are subject to the Mozilla Public License Version 
-    // 1.1 (the "License"); you may not use this file except in compliance with 
-    // the License. You may obtain a copy of the License at 
-    // http://www.mozilla.org/MPL/
-    // 
-    // Software distributed under the License is distributed on an "AS IS" basis,
-    // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-    // for the specific language governing rights and limitations under the
-    // License.
-    // 
-    // The Original Code is the Public Suffix List.
-    // 
-    // The Initial Developer of the Original Code is
-    // Jo Hermans <jo.hermans@gmail.com>.
-    // Portions created by the Initial Developer are Copyright (C) 2007
-    // the Initial Developer. All Rights Reserved.
-    // 
-    // Contributor(s):
-    //   Ruben Arakelyan <ruben@rubenarakelyan.com>
-    //   Gervase Markham <gerv@gerv.net>
-    //   Pamela Greene <pamg.bugs@gmail.com>
-    //   David Triendl <david@triendl.name>
-    //   Jothan Frakes <jothan@gmail.com>
-    //   The kind representatives of many TLD registries
-    // 
-    // Alternatively, the contents of this file may be used under the terms of
-    // either the GNU General Public License Version 2 or later (the "GPL"), or
-    // the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-    // in which case the provisions of the GPL or the LGPL are applicable instead
-    // of those above. If you wish to allow use of your version of this file only
-    // under the terms of either the GPL or the LGPL, and not to allow others to
-    // use your version of this file under the terms of the MPL, indicate your
-    // decision by deleting the provisions above and replace them with the notice
-    // and other provisions required by the GPL or the LGPL. If you do not delete
-    // the provisions above, a recipient may use your version of this file under
-    // the terms of any one of the MPL, the GPL or the LGPL.
-    // 
-    // ***** END LICENSE BLOCK *****
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/README.md
deleted file mode 100644
index 9e6caee1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/README.md
+++ /dev/null
@@ -1,412 +0,0 @@
-[RFC6265](http://tools.ietf.org/html/rfc6265) Cookies and CookieJar for Node.js
-
-![Tough Cookie](http://www.goinstant.com.s3.amazonaws.com/tough-cookie.jpg)
-
-[![Build Status](https://travis-ci.org/goinstant/node-cookie.png?branch=master)](https://travis-ci.org/goinstant/node-cookie)
-
-[![NPM Stats](https://nodei.co/npm/tough-cookie.png?downloads=true&stars=true)](https://npmjs.org/package/tough-cookie)
-![NPM Downloads](https://nodei.co/npm-dl/tough-cookie.png?months=9)
-
-# Synopsis
-
-``` javascript
-var tough = require('tough-cookie'); // note: not 'cookie', 'cookies' or 'node-cookie'
-var Cookie = tough.Cookie;
-var cookie = Cookie.parse(header);
-cookie.value = 'somethingdifferent';
-header = cookie.toString();
-
-var cookiejar = new tough.CookieJar();
-cookiejar.setCookie(cookie, 'http://currentdomain.example.com/path', cb);
-// ...
-cookiejar.getCookies('http://example.com/otherpath',function(err,cookies) {
-  res.headers['cookie'] = cookies.join('; ');
-});
-```
-
-# Installation
-
-It's _so_ easy!
-
-`npm install tough-cookie`
-
-Requires `punycode`, which should get installed automatically for you.  Note that node.js v0.6.2+ bundles punycode by default.
-
-Why the name?  NPM modules `cookie`, `cookies` and `cookiejar` were already taken.
-
-# API
-
-tough
-=====
-
-Functions on the module you get from `require('tough-cookie')`.  All can be used as pure functions and don't need to be "bound".
-
-parseDate(string[,strict])
------------------
-
-Parse a cookie date string into a `Date`.  Parses according to RFC6265 Section 5.1.1, not `Date.parse()`.  If strict is set to true then leading/trailing non-seperator characters around the time part will cause the parsing to fail (e.g. "Thu, 01 Jan 1970 00:00:010 GMT" has an extra trailing zero but Chrome, an assumedly RFC-compliant browser, treats this as valid).
-
-formatDate(date)
-----------------
-
-Format a Date into a RFC1123 string (the RFC6265-recommended format).
-
-canonicalDomain(str)
---------------------
-
-Transforms a domain-name into a canonical domain-name.  The canonical domain-name is a trimmed, lowercased, stripped-of-leading-dot and optionally punycode-encoded domain-name (Section 5.1.2 of RFC6265).  For the most part, this function is idempotent (can be run again on its output without ill effects).
-
-domainMatch(str,domStr[,canonicalize=true])
--------------------------------------------
-
-Answers "does this real domain match the domain in a cookie?".  The `str` is the "current" domain-name and the `domStr` is the "cookie" domain-name.  Matches according to RFC6265 Section 5.1.3, but it helps to think of it as a "suffix match".
-
-The `canonicalize` parameter will run the other two paramters through `canonicalDomain` or not.
-
-defaultPath(path)
------------------
-
-Given a current request/response path, gives the Path apropriate for storing in a cookie.  This is basically the "directory" of a "file" in the path, but is specified by Section 5.1.4 of the RFC.
-
-The `path` parameter MUST be _only_ the pathname part of a URI (i.e. excludes the hostname, query, fragment, etc.).  This is the `.pathname` property of node's `uri.parse()` output.
-
-pathMatch(reqPath,cookiePath)
------------------------------
-
-Answers "does the request-path path-match a given cookie-path?" as per RFC6265 Section 5.1.4.  Returns a boolean.
-
-This is essentially a prefix-match where `cookiePath` is a prefix of `reqPath`.
-
-parse(header[,strict=false])
-----------------------------
-
-alias for `Cookie.parse(header[,strict])`
-
-fromJSON(string)
-----------------
-
-alias for `Cookie.fromJSON(string)`
-
-getPublicSuffix(hostname)
--------------------------
-
-Returns the public suffix of this hostname.  The public suffix is the shortest domain-name upon which a cookie can be set.  Returns `null` if the hostname cannot have cookies set for it.
-
-For example: `www.example.com` and `www.subdomain.example.com` both have public suffix `example.com`.
-
-For further information, see http://publicsuffix.org/.  This module derives its list from that site.
-
-cookieCompare(a,b)
-------------------
-
-For use with `.sort()`, sorts a list of cookies into the recommended order given in the RFC (Section 5.4 step 2).  Longest `.path`s go first, then sorted oldest to youngest.
-
-``` javascript
-var cookies = [ /* unsorted array of Cookie objects */ ];
-cookies = cookies.sort(cookieCompare);
-```
-
-permuteDomain(domain)
----------------------
-
-Generates a list of all possible domains that `domainMatch()` the parameter.  May be handy for implementing cookie stores.
-
-
-permutePath(path)
------------------
-
-Generates a list of all possible paths that `pathMatch()` the parameter.  May be handy for implementing cookie stores.
-
-Cookie
-======
-
-Cookie.parse(header[,strict=false])
------------------------------------
-
-Parses a single Cookie or Set-Cookie HTTP header into a `Cookie` object.  Returns `undefined` if the string can't be parsed.  If in strict mode, returns `undefined` if the cookie doesn't follow the guidelines in section 4 of RFC6265.  Generally speaking, strict mode can be used to validate your own generated Set-Cookie headers, but acting as a client you want to be lenient and leave strict mode off.
-
-Here's how to process the Set-Cookie header(s) on a node HTTP/HTTPS response:
-
-``` javascript
-if (res.headers['set-cookie'] instanceof Array)
-  cookies = res.headers['set-cookie'].map(function (c) { return (Cookie.parse(c)); });
-else
-  cookies = [Cookie.parse(res.headers['set-cookie'])];
-```
-
-Cookie.fromJSON(string)
------------------------
-
-Convert a JSON string to a `Cookie` object.  Does a `JSON.parse()` and converts the `.created`, `.lastAccessed` and `.expires` properties into `Date` objects.
-
-Properties
-==========
-
-  * _key_ - string - the name or key of the cookie (default "")
-  * _value_ - string - the value of the cookie (default "")
-  * _expires_ - `Date` - if set, the `Expires=` attribute of the cookie (defaults to the string `"Infinity"`). See `setExpires()`
-  * _maxAge_ - seconds - if set, the `Max-Age=` attribute _in seconds_ of the cookie.  May also be set to strings `"Infinity"` and `"-Infinity"` for non-expiry and immediate-expiry, respectively.  See `setMaxAge()`
-  * _domain_ - string - the `Domain=` attribute of the cookie
-  * _path_ - string - the `Path=` of the cookie
-  * _secure_ - boolean - the `Secure` cookie flag
-  * _httpOnly_ - boolean - the `HttpOnly` cookie flag
-  * _extensions_ - `Array` - any unrecognized cookie attributes as strings (even if equal-signs inside)
-
-After a cookie has been passed through `CookieJar.setCookie()` it will have the following additional attributes:
-
-  * _hostOnly_ - boolean - is this a host-only cookie (i.e. no Domain field was set, but was instead implied)
-  * _pathIsDefault_ - boolean - if true, there was no Path field on the cookie and `defaultPath()` was used to derive one.
-  * _created_ - `Date` - when this cookie was added to the jar
-  * _lastAccessed_ - `Date` - last time the cookie got accessed. Will affect cookie cleaning once implemented.  Using `cookiejar.getCookies(...)` will update this attribute.
-
-Construction([{options}])
-------------
-
-Receives an options object that can contain any Cookie properties, uses the default for unspecified properties.
-
-.toString()
------------
-
-encode to a Set-Cookie header value.  The Expires cookie field is set using `formatDate()`, but is omitted entirely if `.expires` is `Infinity`.
-
-.cookieString()
----------------
-
-encode to a Cookie header value (i.e. the `.key` and `.value` properties joined with '=').
-
-.setExpires(String)
--------------------
-
-sets the expiry based on a date-string passed through `parseDate()`.  If parseDate returns `null` (i.e. can't parse this date string), `.expires` is set to `"Infinity"` (a string) is set.
-
-.setMaxAge(number)
--------------------
-
-sets the maxAge in seconds.  Coerces `-Infinity` to `"-Infinity"` and `Infinity` to `"Infinity"` so it JSON serializes correctly.
-
-.expiryTime([now=Date.now()])
------------------------------
-
-.expiryDate([now=Date.now()])
------------------------------
-
-expiryTime() Computes the absolute unix-epoch milliseconds that this cookie expires. expiryDate() works similarly, except it returns a `Date` object.  Note that in both cases the `now` parameter should be milliseconds.
-
-Max-Age takes precedence over Expires (as per the RFC). The `.created` attribute -- or, by default, the `now` paramter -- is used to offset the `.maxAge` attribute.
-
-If Expires (`.expires`) is set, that's returned.
-
-Otherwise, `expiryTime()` returns `Infinity` and `expiryDate()` returns a `Date` object for "Tue, 19 Jan 2038 03:14:07 GMT" (latest date that can be expressed by a 32-bit `time_t`; the common limit for most user-agents).
-
-.TTL([now=Date.now()])
----------
-
-compute the TTL relative to `now` (milliseconds).  The same precedence rules as for `expiryTime`/`expiryDate` apply.
-
-The "number" `Infinity` is returned for cookies without an explicit expiry and `0` is returned if the cookie is expired.  Otherwise a time-to-live in milliseconds is returned.
-
-.canonicalizedDoman()
----------------------
-
-.cdomain()
-----------
-
-return the canonicalized `.domain` field.  This is lower-cased and punycode (RFC3490) encoded if the domain has any non-ASCII characters.
-
-.validate()
------------
-
-Status: *IN PROGRESS*. Works for a few things, but is by no means comprehensive.
-
-validates cookie attributes for semantic correctness.  Useful for "lint" checking any Set-Cookie headers you generate.  For now, it returns a boolean, but eventually could return a reason string -- you can future-proof with this construct:
-
-``` javascript
-if (cookie.validate() === true) {
-  // it's tasty
-} else {
-  // yuck!
-}
-```
-
-CookieJar
-=========
-
-Construction([store = new MemoryCookieStore()][, rejectPublicSuffixes])
-------------
-
-Simply use `new CookieJar()`.  If you'd like to use a custom store, pass that to the constructor otherwise a `MemoryCookieStore` will be created and used.
-
-
-Attributes
-----------
-
-  * _rejectPublicSuffixes_ - boolean - reject cookies with domains like "com" and "co.uk" (default: `true`)
-
-Since eventually this module would like to support database/remote/etc. CookieJars, continuation passing style is used for CookieJar methods.
-
-.setCookie(cookieOrString, currentUrl, [{options},] cb(err,cookie))
--------------------------------------------------------------------
-
-Attempt to set the cookie in the cookie jar.  If the operation fails, an error will be given to the callback `cb`, otherwise the cookie is passed through.  The cookie will have updated `.created`, `.lastAccessed` and `.hostOnly` properties.
-
-The `options` object can be omitted and can have the following properties:
-
-  * _http_ - boolean - default `true` - indicates if this is an HTTP or non-HTTP API.  Affects HttpOnly cookies.
-  * _secure_ - boolean - autodetect from url - indicates if this is a "Secure" API.  If the currentUrl starts with `https:` or `wss:` then this is defaulted to `true`, otherwise `false`.
-  * _now_ - Date - default `new Date()` - what to use for the creation/access time of cookies
-  * _strict_ - boolean - default `false` - perform extra checks
-  * _ignoreError_ - boolean - default `false` - silently ignore things like parse errors and invalid domains.  CookieStore errors aren't ignored by this option.
-
-As per the RFC, the `.hostOnly` property is set if there was no "Domain=" parameter in the cookie string (or `.domain` was null on the Cookie object).  The `.domain` property is set to the fully-qualified hostname of `currentUrl` in this case.  Matching this cookie requires an exact hostname match (not a `domainMatch` as per usual).
-
-.setCookieSync(cookieOrString, currentUrl, [{options}])
--------------------------------------------------------
-
-Synchronous version of `setCookie`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).
-
-.storeCookie(cookie, [{options},] cb(err,cookie))
--------------------------------------------------
-
-__REMOVED__ removed in lieu of the CookieStore API below
-
-.getCookies(currentUrl, [{options},] cb(err,cookies))
------------------------------------------------------
-
-Retrieve the list of cookies that can be sent in a Cookie header for the current url.
-
-If an error is encountered, that's passed as `err` to the callback, otherwise an `Array` of `Cookie` objects is passed.  The array is sorted with `cookieCompare()` unless the `{sort:false}` option is given.
-
-The `options` object can be omitted and can have the following properties:
-
-  * _http_ - boolean - default `true` - indicates if this is an HTTP or non-HTTP API.  Affects HttpOnly cookies.
-  * _secure_ - boolean - autodetect from url - indicates if this is a "Secure" API.  If the currentUrl starts with `https:` or `wss:` then this is defaulted to `true`, otherwise `false`.
-  * _now_ - Date - default `new Date()` - what to use for the creation/access time of cookies
-  * _expire_ - boolean - default `true` - perform expiry-time checking of cookies and asynchronously remove expired cookies from the store.  Using `false` will return expired cookies and **not** remove them from the store (which is useful for replaying Set-Cookie headers, potentially).
-  * _allPaths_ - boolean - default `false` - if `true`, do not scope cookies by path. The default uses RFC-compliant path scoping. **Note**: may not be supported by the CookieStore `fetchCookies` function (the default MemoryCookieStore supports it).
-
-The `.lastAccessed` property of the returned cookies will have been updated.
-
-.getCookiesSync(currentUrl, [{options}])
-----------------------------------------
-
-Synchronous version of `getCookies`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).
-
-.getCookieString(...)
----------------------
-
-Accepts the same options as `.getCookies()` but passes a string suitable for a Cookie header rather than an array to the callback.  Simply maps the `Cookie` array via `.cookieString()`.
-
-.getCookieStringSync(...)
--------------------------
-
-Synchronous version of `getCookieString`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).
-
-.getSetCookieStrings(...)
--------------------------
-
-Returns an array of strings suitable for **Set-Cookie** headers. Accepts the same options as `.getCookies()`.  Simply maps the cookie array via `.toString()`.
-
-.getSetCookieStringsSync(...)
------------------------------
-
-Synchronous version of `getSetCookieStrings`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).
-
-Store
-=====
-
-Base class for CookieJar stores.
-
-# CookieStore API
-
-The storage model for each `CookieJar` instance can be replaced with a custom implementation.  The default is `MemoryCookieStore` which can be found in the `lib/memstore.js` file.  The API uses continuation-passing-style to allow for asynchronous stores.
-
-Stores should inherit from the base `Store` class, which is available as `require('tough-cookie').Store`.  Stores are asynchronous by default, but if `store.synchronous` is set, then the `*Sync` methods on the CookieJar can be used.
-
-All `domain` parameters will have been normalized before calling.
-
-The Cookie store must have all of the following methods.
-
-store.findCookie(domain, path, key, cb(err,cookie))
----------------------------------------------------
-
-Retrieve a cookie with the given domain, path and key (a.k.a. name).  The RFC maintains that exactly one of these cookies should exist in a store.  If the store is using versioning, this means that the latest/newest such cookie should be returned.
-
-Callback takes an error and the resulting `Cookie` object.  If no cookie is found then `null` MUST be passed instead (i.e. not an error).
-
-store.findCookies(domain, path, cb(err,cookies))
-------------------------------------------------
-
-Locates cookies matching the given domain and path.  This is most often called in the context of `cookiejar.getCookies()` above.
-
-If no cookies are found, the callback MUST be passed an empty array.
-
-The resulting list will be checked for applicability to the current request according to the RFC (domain-match, path-match, http-only-flag, secure-flag, expiry, etc.), so it's OK to use an optimistic search algorithm when implementing this method.  However, the search algorithm used SHOULD try to find cookies that `domainMatch()` the domain and `pathMatch()` the path in order to limit the amount of checking that needs to be done.
-
-As of version 0.9.12, the `allPaths` option to `cookiejar.getCookies()` above will cause the path here to be `null`.  If the path is `null`, path-matching MUST NOT be performed (i.e. domain-matching only).
-
-store.putCookie(cookie, cb(err))
---------------------------------
-
-Adds a new cookie to the store.  The implementation SHOULD replace any existing cookie with the same `.domain`, `.path`, and `.key` properties -- depending on the nature of the implementation, it's possible that between the call to `fetchCookie` and `putCookie` that a duplicate `putCookie` can occur.
-
-The `cookie` object MUST NOT be modified; the caller will have already updated the `.creation` and `.lastAccessed` properties.
-
-Pass an error if the cookie cannot be stored.
-
-store.updateCookie(oldCookie, newCookie, cb(err))
--------------------------------------------------
-
-Update an existing cookie.  The implementation MUST update the `.value` for a cookie with the same `domain`, `.path` and `.key`.  The implementation SHOULD check that the old value in the store is equivalent to `oldCookie` - how the conflict is resolved is up to the store.
-
-The `.lastAccessed` property will always be different between the two objects and `.created` will always be the same.  Stores MAY ignore or defer the `.lastAccessed` change at the cost of affecting how cookies are sorted (or selected for deletion).
-
-Stores may wish to optimize changing the `.value` of the cookie in the store versus storing a new cookie.  If the implementation doesn't define this method a stub that calls `putCookie(newCookie,cb)` will be added to the store object.
-
-The `newCookie` and `oldCookie` objects MUST NOT be modified.
-
-Pass an error if the newCookie cannot be stored.
-
-store.removeCookie(domain, path, key, cb(err))
-----------------------------------------------
-
-Remove a cookie from the store (see notes on `findCookie` about the uniqueness constraint).
-
-The implementation MUST NOT pass an error if the cookie doesn't exist; only pass an error due to the failure to remove an existing cookie.
-
-store.removeCookies(domain, path, cb(err))
-------------------------------------------
-
-Removes matching cookies from the store.  The `path` paramter is optional, and if missing means all paths in a domain should be removed.
-
-Pass an error ONLY if removing any existing cookies failed.
-
-# TODO
-
-  * _full_ RFC5890/RFC5891 canonicalization for domains in `cdomain()`
-    * the optional `punycode` requirement implements RFC3492, but RFC6265 requires RFC5891
-  * better tests for `validate()`?
-
-# Copyright and License
-
-(tl;dr: MIT with some MPL/1.1)
-
-Copyright 2012- GoInstant, Inc. and other contributors. All rights reserved.
-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.
-
-Portions may be licensed under different licenses (in particular public-suffix.txt is MPL/1.1); please read the LICENSE file for full details.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/generate-pubsuffix.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/generate-pubsuffix.js
deleted file mode 100644
index 74d76aa1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/generate-pubsuffix.js
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright GoInstant, Inc. and other contributors. All rights reserved.
- * 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.
- */
-'use strict';
-var fs = require('fs');
-var assert = require('assert');
-var punycode = require('punycode');
-
-fs.readFile('./public-suffix.txt', 'utf8', function(err,string) {
-  if (err) {
-    throw err;
-  }
-  var lines = string.split("\n");
-  process.nextTick(function() {
-    processList(lines);
-  });
-});
-
-var index = {};
-
-var COMMENT = new RegExp('//.+');
-function processList(lines) {
-  while (lines.length) {
-    var line = lines.shift();
-    line = line.replace(COMMENT,'').trim();
-    if (!line) {
-      continue;
-    }
-    addToIndex(index,line);
-  }
-
-  pubSufTest();
-
-  var w = fs.createWriteStream('./lib/pubsuffix.js',{
-    flags: 'w',
-    encoding: 'utf8',
-    mode: parseInt('644',8)
-  });
-  w.on('end', process.exit);
-  w.write("/****************************************************\n");
-  w.write(" * AUTOMATICALLY GENERATED by generate-pubsuffix.js *\n");
-  w.write(" *                  DO NOT EDIT!                    *\n");
-  w.write(" ****************************************************/\n\n");
-
-  w.write("module.exports.getPublicSuffix = ");
-  w.write(getPublicSuffix.toString());
-  w.write(";\n\n");
-
-  w.write("// The following generated structure is used under the MPL version 1.1\n");
-  w.write("// See public-suffix.txt for more information\n\n");
-  w.write("var index = module.exports.index = Object.freeze(\n");
-  w.write(JSON.stringify(index));
-  w.write(");\n\n");
-  w.write("// END of automatically generated file\n");
-
-  w.end();
-}
-
-function addToIndex(index,line) {
-  var prefix = '';
-  if (line.replace(/^(!|\*\.)/)) {
-    prefix = RegExp.$1;
-    line = line.slice(prefix.length);
-  }
-  line = prefix + punycode.toASCII(line);
-
-  if (line.substr(0,1) == '!') {
-    index[line.substr(1)] = false;
-  } else {
-    index[line] = true;
-  }
-}
-
-// include the licence in the function since it gets written to pubsuffix.js
-function getPublicSuffix(domain) {
-  /*
-   * Copyright GoInstant, Inc. and other contributors. All rights reserved.
-   * 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.
-   */
-  if (!domain) {
-    return null;
-  }
-  if (domain.match(/^\./)) {
-    return null;
-  }
-
-  domain = domain.toLowerCase();
-  var parts = domain.split('.').reverse();
-
-  var suffix = '';
-  var suffixLen = 0;
-  for (var i=0; i<parts.length; i++) {
-    var part = parts[i];
-    var starstr = '*'+suffix;
-    var partstr = part+suffix;
-
-    if (index[starstr]) { // star rule matches
-      suffixLen = i+1;
-      if (index[partstr] === false) { // exception rule matches (NB: false, not undefined)
-        suffixLen--;
-      }
-    } else if (index[partstr]) { // exact match, not exception
-      suffixLen = i+1;
-    }
-
-    suffix = '.'+part+suffix;
-  }
-
-  if (index['*'+suffix]) { // *.domain exists (e.g. *.kyoto.jp for domain='kyoto.jp');
-    return null;
-  }
-
-  if (suffixLen && parts.length > suffixLen) {
-    return parts.slice(0,suffixLen+1).reverse().join('.');
-  }
-
-  return null;
-}
-
-function checkPublicSuffix(give,get) {
-  var got = getPublicSuffix(give);
-  assert.equal(got, get, give+' should be '+(get==null?'NULL':get)+' but got '+got);
-}
-
-// pubSufTest() was converted to JavaScript from http://publicsuffix.org/list/test.txt
-function pubSufTest() {
-  // For this function-scope and this function-scope ONLY:
-  // Any copyright is dedicated to the Public Domain.
-  // http://creativecommons.org/publicdomain/zero/1.0/
-
-  // NULL input.
-  checkPublicSuffix(null, null);
-  // Mixed case.
-  checkPublicSuffix('COM', null);
-  checkPublicSuffix('example.COM', 'example.com');
-  checkPublicSuffix('WwW.example.COM', 'example.com');
-  // Leading dot.
-  checkPublicSuffix('.com', null);
-  checkPublicSuffix('.example', null);
-  checkPublicSuffix('.example.com', null);
-  checkPublicSuffix('.example.example', null);
-  // Unlisted TLD.
-  checkPublicSuffix('example', null);
-  checkPublicSuffix('example.example', null);
-  checkPublicSuffix('b.example.example', null);
-  checkPublicSuffix('a.b.example.example', null);
-  // Listed, but non-Internet, TLD.
-  checkPublicSuffix('local', null);
-  checkPublicSuffix('example.local', null);
-  checkPublicSuffix('b.example.local', null);
-  checkPublicSuffix('a.b.example.local', null);
-  // TLD with only 1 rule.
-  checkPublicSuffix('biz', null);
-  checkPublicSuffix('domain.biz', 'domain.biz');
-  checkPublicSuffix('b.domain.biz', 'domain.biz');
-  checkPublicSuffix('a.b.domain.biz', 'domain.biz');
-  // TLD with some 2-level rules.
-  checkPublicSuffix('com', null);
-  checkPublicSuffix('example.com', 'example.com');
-  checkPublicSuffix('b.example.com', 'example.com');
-  checkPublicSuffix('a.b.example.com', 'example.com');
-  checkPublicSuffix('uk.com', null);
-  checkPublicSuffix('example.uk.com', 'example.uk.com');
-  checkPublicSuffix('b.example.uk.com', 'example.uk.com');
-  checkPublicSuffix('a.b.example.uk.com', 'example.uk.com');
-  checkPublicSuffix('test.ac', 'test.ac');
-  // TLD with only 1 (wildcard) rule.
-  checkPublicSuffix('cy', null);
-  checkPublicSuffix('c.cy', null);
-  checkPublicSuffix('b.c.cy', 'b.c.cy');
-  checkPublicSuffix('a.b.c.cy', 'b.c.cy');
-  // More complex TLD.
-  checkPublicSuffix('jp', null);
-  checkPublicSuffix('test.jp', 'test.jp');
-  checkPublicSuffix('www.test.jp', 'test.jp');
-  checkPublicSuffix('ac.jp', null);
-  checkPublicSuffix('test.ac.jp', 'test.ac.jp');
-  checkPublicSuffix('www.test.ac.jp', 'test.ac.jp');
-  checkPublicSuffix('kyoto.jp', null);
-  checkPublicSuffix('c.kyoto.jp', null);
-  checkPublicSuffix('b.c.kyoto.jp', 'b.c.kyoto.jp');
-  checkPublicSuffix('a.b.c.kyoto.jp', 'b.c.kyoto.jp');
-  checkPublicSuffix('pref.kyoto.jp', 'pref.kyoto.jp');  // Exception rule.
-  checkPublicSuffix('www.pref.kyoto.jp', 'pref.kyoto.jp');  // Exception rule.
-  checkPublicSuffix('city.kyoto.jp', 'city.kyoto.jp');  // Exception rule.
-  checkPublicSuffix('www.city.kyoto.jp', 'city.kyoto.jp');  // Exception rule.
-  // TLD with a wildcard rule and exceptions.
-  checkPublicSuffix('om', null);
-  checkPublicSuffix('test.om', null);
-  checkPublicSuffix('b.test.om', 'b.test.om');
-  checkPublicSuffix('a.b.test.om', 'b.test.om');
-  checkPublicSuffix('songfest.om', 'songfest.om');
-  checkPublicSuffix('www.songfest.om', 'songfest.om');
-  // US K12.
-  checkPublicSuffix('us', null);
-  checkPublicSuffix('test.us', 'test.us');
-  checkPublicSuffix('www.test.us', 'test.us');
-  checkPublicSuffix('ak.us', null);
-  checkPublicSuffix('test.ak.us', 'test.ak.us');
-  checkPublicSuffix('www.test.ak.us', 'test.ak.us');
-  checkPublicSuffix('k12.ak.us', null);
-  checkPublicSuffix('test.k12.ak.us', 'test.k12.ak.us');
-  checkPublicSuffix('www.test.k12.ak.us', 'test.k12.ak.us');
-
-
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/cookie.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/cookie.js
deleted file mode 100644
index c93e927a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/cookie.js
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- * Copyright GoInstant, Inc. and other contributors. All rights reserved.
- * 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.
- */
-
-'use strict';
-var net = require('net');
-var urlParse = require('url').parse;
-var pubsuffix = require('./pubsuffix');
-var Store = require('./store').Store;
-
-var punycode;
-try {
-  punycode = require('punycode');
-} catch(e) {
-  console.warn("cookie: can't load punycode; won't use punycode for domain normalization");
-}
-
-var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
-
-// From RFC2616 S2.2:
-var TOKEN = /[\x21\x23-\x26\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;
-
-// From RFC6265 S4.1.1
-// note that it excludes \x3B ";"
-var COOKIE_OCTET  = /[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]/;
-var COOKIE_OCTETS = new RegExp('^'+COOKIE_OCTET.source+'$');
-
-// The name/key cannot be empty but the value can (S5.2):
-var COOKIE_PAIR_STRICT = new RegExp('^('+TOKEN.source+'+)=("?)('+COOKIE_OCTET.source+'*)\\2$');
-var COOKIE_PAIR = /^([^=\s]+)\s*=\s*("?)\s*(.*)\s*\2\s*$/;
-
-// RFC6265 S4.1.1 defines extension-av as 'any CHAR except CTLs or ";"'
-// Note ';' is \x3B
-var NON_CTL_SEMICOLON = /[\x20-\x3A\x3C-\x7E]+/;
-var EXTENSION_AV = NON_CTL_SEMICOLON;
-var PATH_VALUE = NON_CTL_SEMICOLON;
-
-// Used for checking whether or not there is a trailing semi-colon
-var TRAILING_SEMICOLON = /;+$/;
-
-/* RFC6265 S5.1.1.5:
- * [fail if] the day-of-month-value is less than 1 or greater than 31
- */
-var DAY_OF_MONTH = /^(0?[1-9]|[12][0-9]|3[01])$/;
-
-/* RFC6265 S5.1.1.5:
- * [fail if]
- * *  the hour-value is greater than 23,
- * *  the minute-value is greater than 59, or
- * *  the second-value is greater than 59.
- */
-var TIME = /(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])/;
-var STRICT_TIME = /^(0?[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/;
-
-var MONTH = /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)$/i;
-var MONTH_TO_NUM = {
-  jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
-  jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
-};
-var NUM_TO_MONTH = [
-  'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
-];
-var NUM_TO_DAY = [
-  'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
-];
-
-var YEAR = /^([1-9][0-9]{1,3})$/; // 2 to 4 digits
-
-var MAX_TIME = 2147483647000; // 31-bit max
-var MIN_TIME = 0; // 31-bit min
-
-
-// RFC6265 S5.1.1 date parser:
-function parseDate(str,strict) {
-  if (!str) {
-    return;
-  }
-  var found_time, found_dom, found_month, found_year;
-
-  /* RFC6265 S5.1.1:
-   * 2. Process each date-token sequentially in the order the date-tokens
-   * appear in the cookie-date
-   */
-  var tokens = str.split(DATE_DELIM);
-  if (!tokens) {
-    return;
-  }
-
-  var date = new Date();
-  date.setMilliseconds(0);
-
-  for (var i=0; i<tokens.length; i++) {
-    var token = tokens[i].trim();
-    if (!token.length) {
-      continue;
-    }
-
-    var result;
-
-    /* 2.1. If the found-time flag is not set and the token matches the time
-     * production, set the found-time flag and set the hour- value,
-     * minute-value, and second-value to the numbers denoted by the digits in
-     * the date-token, respectively.  Skip the remaining sub-steps and continue
-     * to the next date-token.
-     */
-    if (!found_time) {
-      result = (strict ? STRICT_TIME : TIME).exec(token);
-      if (result) {
-        found_time = true;
-        date.setUTCHours(result[1]);
-        date.setUTCMinutes(result[2]);
-        date.setUTCSeconds(result[3]);
-        continue;
-      }
-    }
-
-    /* 2.2. If the found-day-of-month flag is not set and the date-token matches
-     * the day-of-month production, set the found-day-of- month flag and set
-     * the day-of-month-value to the number denoted by the date-token.  Skip
-     * the remaining sub-steps and continue to the next date-token.
-     */
-    if (!found_dom) {
-      result = DAY_OF_MONTH.exec(token);
-      if (result) {
-        found_dom = true;
-        date.setUTCDate(result[1]);
-        continue;
-      }
-    }
-
-    /* 2.3. If the found-month flag is not set and the date-token matches the
-     * month production, set the found-month flag and set the month-value to
-     * the month denoted by the date-token.  Skip the remaining sub-steps and
-     * continue to the next date-token.
-     */
-    if (!found_month) {
-      result = MONTH.exec(token);
-      if (result) {
-        found_month = true;
-        date.setUTCMonth(MONTH_TO_NUM[result[1].toLowerCase()]);
-        continue;
-      }
-    }
-
-    /* 2.4. If the found-year flag is not set and the date-token matches the year
-     * production, set the found-year flag and set the year-value to the number
-     * denoted by the date-token.  Skip the remaining sub-steps and continue to
-     * the next date-token.
-     */
-    if (!found_year) {
-      result = YEAR.exec(token);
-      if (result) {
-        var year = result[0];
-        /* From S5.1.1:
-         * 3.  If the year-value is greater than or equal to 70 and less
-         * than or equal to 99, increment the year-value by 1900.
-         * 4.  If the year-value is greater than or equal to 0 and less
-         * than or equal to 69, increment the year-value by 2000.
-         */
-        if (70 <= year && year <= 99) {
-          year += 1900;
-        } else if (0 <= year && year <= 69) {
-          year += 2000;
-        }
-
-        if (year < 1601) {
-          return; // 5. ... the year-value is less than 1601
-        }
-
-        found_year = true;
-        date.setUTCFullYear(year);
-        continue;
-      }
-    }
-  }
-
-  if (!(found_time && found_dom && found_month && found_year)) {
-    return; // 5. ... at least one of the found-day-of-month, found-month, found-
-            // year, or found-time flags is not set,
-  }
-
-  return date;
-}
-
-function formatDate(date) {
-  var d = date.getUTCDate(); d = d >= 10 ? d : '0'+d;
-  var h = date.getUTCHours(); h = h >= 10 ? h : '0'+h;
-  var m = date.getUTCMinutes(); m = m >= 10 ? m : '0'+m;
-  var s = date.getUTCSeconds(); s = s >= 10 ? s : '0'+s;
-  return NUM_TO_DAY[date.getUTCDay()] + ', ' +
-    d+' '+ NUM_TO_MONTH[date.getUTCMonth()] +' '+ date.getUTCFullYear() +' '+
-    h+':'+m+':'+s+' GMT';
-}
-
-// S5.1.2 Canonicalized Host Names
-function canonicalDomain(str) {
-  if (str == null) {
-    return null;
-  }
-  str = str.trim().replace(/^\./,''); // S4.1.2.3 & S5.2.3: ignore leading .
-
-  // convert to IDN if any non-ASCII characters
-  if (punycode && /[^\u0001-\u007f]/.test(str)) {
-    str = punycode.toASCII(str);
-  }
-
-  return str.toLowerCase();
-}
-
-// S5.1.3 Domain Matching
-function domainMatch(str, domStr, canonicalize) {
-  if (str == null || domStr == null) {
-    return null;
-  }
-  if (canonicalize !== false) {
-    str = canonicalDomain(str);
-    domStr = canonicalDomain(domStr);
-  }
-
-  /*
-   * "The domain string and the string are identical. (Note that both the
-   * domain string and the string will have been canonicalized to lower case at
-   * this point)"
-   */
-  if (str == domStr) {
-    return true;
-  }
-
-  /* "All of the following [three] conditions hold:" (order adjusted from the RFC) */
-
-  /* "* The string is a host name (i.e., not an IP address)." */
-  if (net.isIP(str)) {
-    return false;
-  }
-
-  /* "* The domain string is a suffix of the string" */
-  var idx = str.indexOf(domStr);
-  if (idx <= 0) {
-    return false; // it's a non-match (-1) or prefix (0)
-  }
-
-  // e.g "a.b.c".indexOf("b.c") === 2
-  // 5 === 3+2
-  if (str.length !== domStr.length + idx) { // it's not a suffix
-    return false;
-  }
-
-  /* "* The last character of the string that is not included in the domain
-  * string is a %x2E (".") character." */
-  if (str.substr(idx-1,1) !== '.') {
-    return false;
-  }
-
-  return true;
-}
-
-
-// RFC6265 S5.1.4 Paths and Path-Match
-
-/*
- * "The user agent MUST use an algorithm equivalent to the following algorithm
- * to compute the default-path of a cookie:"
- *
- * Assumption: the path (and not query part or absolute uri) is passed in.
- */
-function defaultPath(path) {
-  // "2. If the uri-path is empty or if the first character of the uri-path is not
-  // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
-  if (!path || path.substr(0,1) !== "/") {
-    return "/";
-  }
-
-  // "3. If the uri-path contains no more than one %x2F ("/") character, output
-  // %x2F ("/") and skip the remaining step."
-  if (path === "/") {
-    return path;
-  }
-
-  var rightSlash = path.lastIndexOf("/");
-  if (rightSlash === 0) {
-    return "/";
-  }
-
-  // "4. Output the characters of the uri-path from the first character up to,
-  // but not including, the right-most %x2F ("/")."
-  return path.slice(0, rightSlash);
-}
-
-/*
- * "A request-path path-matches a given cookie-path if at least one of the
- * following conditions holds:"
- */
-function pathMatch(reqPath,cookiePath) {
-  // "o  The cookie-path and the request-path are identical."
-  if (cookiePath === reqPath) {
-    return true;
-  }
-
-  var idx = reqPath.indexOf(cookiePath);
-  if (idx === 0) {
-    // "o  The cookie-path is a prefix of the request-path, and the last
-    // character of the cookie-path is %x2F ("/")."
-    if (cookiePath.substr(-1) === "/") {
-      return true;
-    }
-
-    // " o  The cookie-path is a prefix of the request-path, and the first
-    // character of the request-path that is not included in the cookie- path
-    // is a %x2F ("/") character."
-    if (reqPath.substr(cookiePath.length,1) === "/") {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-function parse(str, strict) {
-  str = str.trim();
-
-  // S4.1.1 Trailing semi-colons are not part of the specification.
-  // If we are not in strict mode we remove the trailing semi-colons.
-  var semiColonCheck = TRAILING_SEMICOLON.exec(str);
-  if (semiColonCheck) {
-    if (strict) {
-      return;
-    }
-    str = str.slice(0, semiColonCheck.index);
-  }
-
-  // We use a regex to parse the "name-value-pair" part of S5.2
-  var firstSemi = str.indexOf(';'); // S5.2 step 1
-  var pairRx = strict ? COOKIE_PAIR_STRICT : COOKIE_PAIR;
-  var result = pairRx.exec(firstSemi === -1 ? str : str.substr(0,firstSemi));
-
-  // Rx satisfies the "the name string is empty" and "lacks a %x3D ("=")"
-  // constraints as well as trimming any whitespace.
-  if (!result) {
-    return;
-  }
-
-  var c = new Cookie();
-  c.key = result[1]; // the regexp should trim() already
-  c.value = result[3]; // [2] is quotes or empty-string
-
-  if (firstSemi === -1) {
-    return c;
-  }
-
-  // S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
-  // (including the %x3B (";") in question)." plus later on in the same section
-  // "discard the first ";" and trim".
-  var unparsed = str.slice(firstSemi).replace(/^\s*;\s*/,'').trim();
-
-  // "If the unparsed-attributes string is empty, skip the rest of these
-  // steps."
-  if (unparsed.length === 0) {
-    return c;
-  }
-
-  /*
-   * S5.2 says that when looping over the items "[p]rocess the attribute-name
-   * and attribute-value according to the requirements in the following
-   * subsections" for every item.  Plus, for many of the individual attributes
-   * in S5.3 it says to use the "attribute-value of the last attribute in the
-   * cookie-attribute-list".  Therefore, in this implementation, we overwrite
-   * the previous value.
-   */
-  var cookie_avs = unparsed.split(/\s*;\s*/);
-  while (cookie_avs.length) {
-    var av = cookie_avs.shift();
-
-    if (strict && !EXTENSION_AV.test(av)) {
-      return;
-    }
-
-    var av_sep = av.indexOf('=');
-    var av_key, av_value;
-    if (av_sep === -1) {
-      av_key = av;
-      av_value = null;
-    } else {
-      av_key = av.substr(0,av_sep);
-      av_value = av.substr(av_sep+1);
-    }
-
-    av_key = av_key.trim().toLowerCase();
-    if (av_value) {
-      av_value = av_value.trim();
-    }
-
-    switch(av_key) {
-    case 'expires': // S5.2.1
-      if (!av_value) {if(strict){return;}else{break;} }
-      var exp = parseDate(av_value,strict);
-      // "If the attribute-value failed to parse as a cookie date, ignore the
-      // cookie-av."
-      if (exp == null) { if(strict){return;}else{break;} }
-      c.expires = exp;
-      // over and underflow not realistically a concern: V8's getTime() seems to
-      // store something larger than a 32-bit time_t (even with 32-bit node)
-      break;
-
-    case 'max-age': // S5.2.2
-      if (!av_value) { if(strict){return;}else{break;} }
-      // "If the first character of the attribute-value is not a DIGIT or a "-"
-      // character ...[or]... If the remainder of attribute-value contains a
-      // non-DIGIT character, ignore the cookie-av."
-      if (!/^-?[0-9]+$/.test(av_value)) { if(strict){return;}else{break;} }
-      var delta = parseInt(av_value,10);
-      if (strict && delta <= 0) {
-        return; // S4.1.1
-      }
-      // "If delta-seconds is less than or equal to zero (0), let expiry-time
-      // be the earliest representable date and time."
-      c.setMaxAge(delta);
-      break;
-
-    case 'domain': // S5.2.3
-      // "If the attribute-value is empty, the behavior is undefined.  However,
-      // the user agent SHOULD ignore the cookie-av entirely."
-      if (!av_value) { if(strict){return;}else{break;} }
-      // S5.2.3 "Let cookie-domain be the attribute-value without the leading %x2E
-      // (".") character."
-      var domain = av_value.trim().replace(/^\./,'');
-      if (!domain) { if(strict){return;}else{break;} } // see "is empty" above
-      // "Convert the cookie-domain to lower case."
-      c.domain = domain.toLowerCase();
-      break;
-
-    case 'path': // S5.2.4
-      /*
-       * "If the attribute-value is empty or if the first character of the
-       * attribute-value is not %x2F ("/"):
-       *   Let cookie-path be the default-path.
-       * Otherwise:
-       *   Let cookie-path be the attribute-value."
-       *
-       * We'll represent the default-path as null since it depends on the
-       * context of the parsing.
-       */
-      if (!av_value || av_value.substr(0,1) != "/") {
-        if(strict){return;}else{break;}
-      }
-      c.path = av_value;
-      break;
-
-    case 'secure': // S5.2.5
-      /*
-       * "If the attribute-name case-insensitively matches the string "Secure",
-       * the user agent MUST append an attribute to the cookie-attribute-list
-       * with an attribute-name of Secure and an empty attribute-value."
-       */
-      if (av_value != null) { if(strict){return;} }
-      c.secure = true;
-      break;
-
-    case 'httponly': // S5.2.6 -- effectively the same as 'secure'
-      if (av_value != null) { if(strict){return;} }
-      c.httpOnly = true;
-      break;
-
-    default:
-      c.extensions = c.extensions || [];
-      c.extensions.push(av);
-      break;
-    }
-  }
-
-  // ensure a default date for sorting:
-  c.creation = new Date();
-  return c;
-}
-
-function fromJSON(str) {
-  if (!str) {
-    return null;
-  }
-
-  var obj;
-  try {
-    obj = JSON.parse(str);
-  } catch (e) {
-    return null;
-  }
-
-  var c = new Cookie();
-  for (var i=0; i<numCookieProperties; i++) {
-    var prop = cookieProperties[i];
-    if (obj[prop] == null) {
-      continue;
-    }
-    if (prop === 'expires' ||
-        prop === 'creation' ||
-        prop === 'lastAccessed')
-    {
-      c[prop] = obj[prop] == "Infinity" ? "Infinity" : new Date(obj[prop]);
-    } else {
-      c[prop] = obj[prop];
-    }
-  }
-
-
-  // ensure a default date for sorting:
-  c.creation = c.creation || new Date();
-
-  return c;
-}
-
-/* Section 5.4 part 2:
- * "*  Cookies with longer paths are listed before cookies with
- *     shorter paths.
- *
- *  *  Among cookies that have equal-length path fields, cookies with
- *     earlier creation-times are listed before cookies with later
- *     creation-times."
- */
-
-function cookieCompare(a,b) {
-  // descending for length: b CMP a
-  var deltaLen = (b.path ? b.path.length : 0) - (a.path ? a.path.length : 0);
-  if (deltaLen !== 0) {
-    return deltaLen;
-  }
-  // ascending for time: a CMP b
-  return (a.creation ? a.creation.getTime() : MAX_TIME) -
-         (b.creation ? b.creation.getTime() : MAX_TIME);
-}
-
-// Gives the permutation of all possible domainMatch()es of a given domain. The
-// array is in shortest-to-longest order.  Handy for indexing.
-function permuteDomain(domain) {
-  var pubSuf = pubsuffix.getPublicSuffix(domain);
-  if (!pubSuf) {
-    return null;
-  }
-  if (pubSuf == domain) {
-    return [domain];
-  }
-
-  var prefix = domain.slice(0,-(pubSuf.length+1)); // ".example.com"
-  var parts = prefix.split('.').reverse();
-  var cur = pubSuf;
-  var permutations = [cur];
-  while (parts.length) {
-    cur = parts.shift()+'.'+cur;
-    permutations.push(cur);
-  }
-  return permutations;
-}
-
-// Gives the permutation of all possible pathMatch()es of a given path. The
-// array is in longest-to-shortest order.  Handy for indexing.
-function permutePath(path) {
-  if (path === '/') {
-    return ['/'];
-  }
-  if (path.lastIndexOf('/') === path.length-1) {
-    path = path.substr(0,path.length-1);
-  }
-  var permutations = [path];
-  while (path.length > 1) {
-    var lindex = path.lastIndexOf('/');
-    if (lindex === 0) {
-      break;
-    }
-    path = path.substr(0,lindex);
-    permutations.push(path);
-  }
-  permutations.push('/');
-  return permutations;
-}
-
-
-function Cookie (opts) {
-  if (typeof opts !== "object") {
-    return;
-  }
-  Object.keys(opts).forEach(function (key) {
-    if (Cookie.prototype.hasOwnProperty(key)) {
-      this[key] = opts[key] || Cookie.prototype[key];
-    }
-  }.bind(this));
-}
-
-Cookie.parse = parse;
-Cookie.fromJSON = fromJSON;
-
-Cookie.prototype.key = "";
-Cookie.prototype.value = "";
-
-// the order in which the RFC has them:
-Cookie.prototype.expires = "Infinity"; // coerces to literal Infinity
-Cookie.prototype.maxAge = null; // takes precedence over expires for TTL
-Cookie.prototype.domain = null;
-Cookie.prototype.path = null;
-Cookie.prototype.secure = false;
-Cookie.prototype.httpOnly = false;
-Cookie.prototype.extensions = null;
-
-// set by the CookieJar:
-Cookie.prototype.hostOnly = null; // boolean when set
-Cookie.prototype.pathIsDefault = null; // boolean when set
-Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
-Cookie.prototype.lastAccessed = null; // Date when set
-
-var cookieProperties = Object.freeze(Object.keys(Cookie.prototype).map(function(p) {
-  if (p instanceof Function) {
-    return;
-  }
-  return p;
-}));
-var numCookieProperties = cookieProperties.length;
-
-Cookie.prototype.inspect = function inspect() {
-  var now = Date.now();
-  return 'Cookie="'+this.toString() +
-    '; hostOnly='+(this.hostOnly != null ? this.hostOnly : '?') +
-    '; aAge='+(this.lastAccessed ? (now-this.lastAccessed.getTime())+'ms' : '?') +
-    '; cAge='+(this.creation ? (now-this.creation.getTime())+'ms' : '?') +
-    '"';
-};
-
-Cookie.prototype.validate = function validate() {
-  if (!COOKIE_OCTETS.test(this.value)) {
-    return false;
-  }
-  if (this.expires != Infinity && !(this.expires instanceof Date) && !parseDate(this.expires,true)) {
-    return false;
-  }
-  if (this.maxAge != null && this.maxAge <= 0) {
-    return false; // "Max-Age=" non-zero-digit *DIGIT
-  }
-  if (this.path != null && !PATH_VALUE.test(this.path)) {
-    return false;
-  }
-
-  var cdomain = this.cdomain();
-  if (cdomain) {
-    if (cdomain.match(/\.$/)) {
-      return false; // S4.1.2.3 suggests that this is bad. domainMatch() tests confirm this
-    }
-    var suffix = pubsuffix.getPublicSuffix(cdomain);
-    if (suffix == null) { // it's a public suffix
-      return false;
-    }
-  }
-  return true;
-};
-
-Cookie.prototype.setExpires = function setExpires(exp) {
-  if (exp instanceof Date) {
-    this.expires = exp;
-  } else {
-    this.expires = parseDate(exp) || "Infinity";
-  }
-};
-
-Cookie.prototype.setMaxAge = function setMaxAge(age) {
-  if (age === Infinity || age === -Infinity) {
-    this.maxAge = age.toString(); // so JSON.stringify() works
-  } else {
-    this.maxAge = age;
-  }
-};
-
-// gives Cookie header format
-Cookie.prototype.cookieString = function cookieString() {
-  var val = this.value;
-  if (val == null) {
-    val = '';
-  }
-  return this.key+'='+val;
-};
-
-// gives Set-Cookie header format
-Cookie.prototype.toString = function toString() {
-  var str = this.cookieString();
-
-  if (this.expires != Infinity) {
-    if (this.expires instanceof Date) {
-      str += '; Expires='+formatDate(this.expires);
-    } else {
-      str += '; Expires='+this.expires;
-    }
-  }
-
-  if (this.maxAge != null && this.maxAge != Infinity) {
-    str += '; Max-Age='+this.maxAge;
-  }
-
-  if (this.domain && !this.hostOnly) {
-    str += '; Domain='+this.domain;
-  }
-  if (this.path) {
-    str += '; Path='+this.path;
-  }
-
-  if (this.secure) {
-    str += '; Secure';
-  }
-  if (this.httpOnly) {
-    str += '; HttpOnly';
-  }
-  if (this.extensions) {
-    this.extensions.forEach(function(ext) {
-      str += '; '+ext;
-    });
-  }
-
-  return str;
-};
-
-// TTL() partially replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
-// elsewhere)
-// S5.3 says to give the "latest representable date" for which we use Infinity
-// For "expired" we use 0
-Cookie.prototype.TTL = function TTL(now) {
-  /* RFC6265 S4.1.2.2 If a cookie has both the Max-Age and the Expires
-   * attribute, the Max-Age attribute has precedence and controls the
-   * expiration date of the cookie.
-   * (Concurs with S5.3 step 3)
-   */
-  if (this.maxAge != null) {
-    return this.maxAge<=0 ? 0 : this.maxAge*1000;
-  }
-
-  var expires = this.expires;
-  if (expires != Infinity) {
-    if (!(expires instanceof Date)) {
-      expires = parseDate(expires) || Infinity;
-    }
-
-    if (expires == Infinity) {
-      return Infinity;
-    }
-
-    return expires.getTime() - (now || Date.now());
-  }
-
-  return Infinity;
-};
-
-// expiryTime() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
-// elsewhere)
-Cookie.prototype.expiryTime = function expiryTime(now) {
-  if (this.maxAge != null) {
-    var relativeTo = this.creation || now || new Date();
-    var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
-    return relativeTo.getTime() + age;
-  }
-
-  if (this.expires == Infinity) {
-    return Infinity;
-  }
-  return this.expires.getTime();
-};
-
-// expiryDate() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
-// elsewhere), except it returns a Date
-Cookie.prototype.expiryDate = function expiryDate(now) {
-  var millisec = this.expiryTime(now);
-  if (millisec == Infinity) {
-    return new Date(MAX_TIME);
-  } else if (millisec == -Infinity) {
-    return new Date(MIN_TIME);
-  } else {
-    return new Date(millisec);
-  }
-};
-
-// This replaces the "persistent-flag" parts of S5.3 step 3
-Cookie.prototype.isPersistent = function isPersistent() {
-  return (this.maxAge != null || this.expires != Infinity);
-};
-
-// Mostly S5.1.2 and S5.2.3:
-Cookie.prototype.cdomain =
-Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
-  if (this.domain == null) {
-    return null;
-  }
-  return canonicalDomain(this.domain);
-};
-
-
-var memstore;
-function CookieJar(store, rejectPublicSuffixes) {
-  if (rejectPublicSuffixes != null) {
-    this.rejectPublicSuffixes = rejectPublicSuffixes;
-  }
-
-  if (!store) {
-    memstore = memstore || require('./memstore');
-    store = new memstore.MemoryCookieStore();
-  }
-  this.store = store;
-}
-CookieJar.prototype.store = null;
-CookieJar.prototype.rejectPublicSuffixes = true;
-var CAN_BE_SYNC = [];
-
-CAN_BE_SYNC.push('setCookie');
-CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
-  var err;
-  var context = (url instanceof Object) ? url : urlParse(url);
-  if (options instanceof Function) {
-    cb = options;
-    options = {};
-  }
-
-  var host = canonicalDomain(context.hostname);
-
-  // S5.3 step 1
-  if (!(cookie instanceof Cookie)) {
-    cookie = Cookie.parse(cookie, options.strict === true);
-  }
-  if (!cookie) {
-    err = new Error("Cookie failed to parse");
-    return cb(options.ignoreError ? null : err);
-  }
-
-  // S5.3 step 2
-  var now = options.now || new Date(); // will assign later to save effort in the face of errors
-
-  // S5.3 step 3: NOOP; persistent-flag and expiry-time is handled by getCookie()
-
-  // S5.3 step 4: NOOP; domain is null by default
-
-  // S5.3 step 5: public suffixes
-  if (this.rejectPublicSuffixes && cookie.domain) {
-    var suffix = pubsuffix.getPublicSuffix(cookie.cdomain());
-    if (suffix == null) { // e.g. "com"
-      err = new Error("Cookie has domain set to a public suffix");
-      return cb(options.ignoreError ? null : err);
-    }
-  }
-
-  // S5.3 step 6:
-  if (cookie.domain) {
-    if (!domainMatch(host, cookie.cdomain(), false)) {
-      err = new Error("Cookie not in this host's domain. Cookie:"+cookie.cdomain()+" Request:"+host);
-      return cb(options.ignoreError ? null : err);
-    }
-
-    if (cookie.hostOnly == null) { // don't reset if already set
-      cookie.hostOnly = false;
-    }
-
-  } else {
-    cookie.hostOnly = true;
-    cookie.domain = host;
-  }
-
-  // S5.3 step 7: "Otherwise, set the cookie's path to the default-path of the
-  // request-uri"
-  if (!cookie.path) {
-    cookie.path = defaultPath(context.pathname);
-    cookie.pathIsDefault = true;
-  } else {
-    if (cookie.path.length > 1 && cookie.path.substr(-1) == '/') {
-      cookie.path = cookie.path.slice(0,-1);
-    }
-  }
-
-  // S5.3 step 8: NOOP; secure attribute
-  // S5.3 step 9: NOOP; httpOnly attribute
-
-  // S5.3 step 10
-  if (options.http === false && cookie.httpOnly) {
-    err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
-    return cb(options.ignoreError ? null : err);
-  }
-
-  var store = this.store;
-
-  if (!store.updateCookie) {
-    store.updateCookie = function(oldCookie, newCookie, cb) {
-      this.putCookie(newCookie, cb);
-    };
-  }
-
-  function withCookie(err, oldCookie) {
-    if (err) {
-      return cb(err);
-    }
-
-    var next = function(err) {
-      if (err) {
-        return cb(err);
-      } else {
-        cb(null, cookie);
-      }
-    };
-
-    if (oldCookie) {
-      // S5.3 step 11 - "If the cookie store contains a cookie with the same name,
-      // domain, and path as the newly created cookie:"
-      if (options.http === false && oldCookie.httpOnly) { // step 11.2
-        err = new Error("old Cookie is HttpOnly and this isn't an HTTP API");
-        return cb(options.ignoreError ? null : err);
-      }
-      cookie.creation = oldCookie.creation; // step 11.3
-      cookie.lastAccessed = now;
-      // Step 11.4 (delete cookie) is implied by just setting the new one:
-      store.updateCookie(oldCookie, cookie, next); // step 12
-
-    } else {
-      cookie.creation = cookie.lastAccessed = now;
-      store.putCookie(cookie, next); // step 12
-    }
-  }
-
-  store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie);
-};
-
-// RFC6365 S5.4
-CAN_BE_SYNC.push('getCookies');
-CookieJar.prototype.getCookies = function(url, options, cb) {
-  var context = (url instanceof Object) ? url : urlParse(url);
-  if (options instanceof Function) {
-    cb = options;
-    options = {};
-  }
-
-  var host = canonicalDomain(context.hostname);
-  var path = context.pathname || '/';
-
-  var secure = options.secure;
-  if (secure == null && context.protocol &&
-      (context.protocol == 'https:' || context.protocol == 'wss:'))
-  {
-    secure = true;
-  }
-
-  var http = options.http;
-  if (http == null) {
-    http = true;
-  }
-
-  var now = options.now || Date.now();
-  var expireCheck = options.expire !== false;
-  var allPaths = !!options.allPaths;
-  var store = this.store;
-
-  function matchingCookie(c) {
-    // "Either:
-    //   The cookie's host-only-flag is true and the canonicalized
-    //   request-host is identical to the cookie's domain.
-    // Or:
-    //   The cookie's host-only-flag is false and the canonicalized
-    //   request-host domain-matches the cookie's domain."
-    if (c.hostOnly) {
-      if (c.domain != host) {
-        return false;
-      }
-    } else {
-      if (!domainMatch(host, c.domain, false)) {
-        return false;
-      }
-    }
-
-    // "The request-uri's path path-matches the cookie's path."
-    if (!allPaths && !pathMatch(path, c.path)) {
-      return false;
-    }
-
-    // "If the cookie's secure-only-flag is true, then the request-uri's
-    // scheme must denote a "secure" protocol"
-    if (c.secure && !secure) {
-      return false;
-    }
-
-    // "If the cookie's http-only-flag is true, then exclude the cookie if the
-    // cookie-string is being generated for a "non-HTTP" API"
-    if (c.httpOnly && !http) {
-      return false;
-    }
-
-    // deferred from S5.3
-    // non-RFC: allow retention of expired cookies by choice
-    if (expireCheck && c.expiryTime() <= now) {
-      store.removeCookie(c.domain, c.path, c.key, function(){}); // result ignored
-      return false;
-    }
-
-    return true;
-  }
-
-  store.findCookies(host, allPaths ? null : path, function(err,cookies) {
-    if (err) {
-      return cb(err);
-    }
-
-    cookies = cookies.filter(matchingCookie);
-
-    // sorting of S5.4 part 2
-    if (options.sort !== false) {
-      cookies = cookies.sort(cookieCompare);
-    }
-
-    // S5.4 part 3
-    var now = new Date();
-    cookies.forEach(function(c) {
-      c.lastAccessed = now;
-    });
-    // TODO persist lastAccessed
-
-    cb(null,cookies);
-  });
-};
-
-CAN_BE_SYNC.push('getCookieString');
-CookieJar.prototype.getCookieString = function(/*..., cb*/) {
-  var args = Array.prototype.slice.call(arguments,0);
-  var cb = args.pop();
-  var next = function(err,cookies) {
-    if (err) {
-      cb(err);
-    } else {
-      cb(null, cookies.map(function(c){
-        return c.cookieString();
-      }).join('; '));
-    }
-  };
-  args.push(next);
-  this.getCookies.apply(this,args);
-};
-
-CAN_BE_SYNC.push('getSetCookieStrings');
-CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
-  var args = Array.prototype.slice.call(arguments,0);
-  var cb = args.pop();
-  var next = function(err,cookies) {
-    if (err) {
-      cb(err);
-    } else {
-      cb(null, cookies.map(function(c){
-        return c.toString();
-      }));
-    }
-  };
-  args.push(next);
-  this.getCookies.apply(this,args);
-};
-
-// Use a closure to provide a true imperative API for synchronous stores.
-function syncWrap(method) {
-  return function() {
-    if (!this.store.synchronous) {
-      throw new Error('CookieJar store is not synchronous; use async API instead.');
-    }
-
-    var args = Array.prototype.slice.call(arguments);
-    var syncErr, syncResult;
-    args.push(function syncCb(err, result) {
-      syncErr = err;
-      syncResult = result;
-    });
-    this[method].apply(this, args);
-
-    if (syncErr) {
-      throw syncErr;
-    }
-    return syncResult;
-  };
-}
-
-// wrap all declared CAN_BE_SYNC methods in the sync wrapper
-CAN_BE_SYNC.forEach(function(method) {
-  CookieJar.prototype[method+'Sync'] = syncWrap(method);
-});
-
-module.exports = {
-  CookieJar: CookieJar,
-  Cookie: Cookie,
-  Store: Store,
-  parseDate: parseDate,
-  formatDate: formatDate,
-  parse: parse,
-  fromJSON: fromJSON,
-  domainMatch: domainMatch,
-  defaultPath: defaultPath,
-  pathMatch: pathMatch,
-  getPublicSuffix: pubsuffix.getPublicSuffix,
-  cookieCompare: cookieCompare,
-  permuteDomain: permuteDomain,
-  permutePath: permutePath,
-  canonicalDomain: canonicalDomain,
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/memstore.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/memstore.js
deleted file mode 100644
index fc5774c8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/memstore.js
+++ /dev/null
@@ -1,123 +0,0 @@
-'use strict';
-var tough = require('./cookie');
-var Store = require('./store').Store;
-var permuteDomain = tough.permuteDomain;
-var permutePath = tough.permutePath;
-var util = require('util');
-
-function MemoryCookieStore() {
-  Store.call(this);
-  this.idx = {};
-}
-util.inherits(MemoryCookieStore, Store);
-exports.MemoryCookieStore = MemoryCookieStore;
-MemoryCookieStore.prototype.idx = null;
-MemoryCookieStore.prototype.synchronous = true;
-
-// force a default depth:
-MemoryCookieStore.prototype.inspect = function() {
-  return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
-};
-
-MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
-  if (!this.idx[domain]) {
-    return cb(null,undefined);
-  }
-  if (!this.idx[domain][path]) {
-    return cb(null,undefined);
-  }
-  return cb(null,this.idx[domain][path][key]||null);
-};
-
-MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
-  var results = [];
-  if (!domain) {
-    return cb(null,[]);
-  }
-
-  var pathMatcher;
-  if (!path) {
-    // null or '/' means "all paths"
-    pathMatcher = function matchAll(domainIndex) {
-      for (var curPath in domainIndex) {
-        var pathIndex = domainIndex[curPath];
-        for (var key in pathIndex) {
-          results.push(pathIndex[key]);
-        }
-      }
-    };
-
-  } else if (path === '/') {
-    pathMatcher = function matchSlash(domainIndex) {
-      var pathIndex = domainIndex['/'];
-      if (!pathIndex) {
-        return;
-      }
-      for (var key in pathIndex) {
-        results.push(pathIndex[key]);
-      }
-    };
-
-  } else {
-    var paths = permutePath(path) || [path];
-    pathMatcher = function matchRFC(domainIndex) {
-      paths.forEach(function(curPath) {
-        var pathIndex = domainIndex[curPath];
-        if (!pathIndex) {
-          return;
-        }
-        for (var key in pathIndex) {
-          results.push(pathIndex[key]);
-        }
-      });
-    };
-  }
-
-  var domains = permuteDomain(domain) || [domain];
-  var idx = this.idx;
-  domains.forEach(function(curDomain) {
-    var domainIndex = idx[curDomain];
-    if (!domainIndex) {
-      return;
-    }
-    pathMatcher(domainIndex);
-  });
-
-  cb(null,results);
-};
-
-MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
-  if (!this.idx[cookie.domain]) {
-    this.idx[cookie.domain] = {};
-  }
-  if (!this.idx[cookie.domain][cookie.path]) {
-    this.idx[cookie.domain][cookie.path] = {};
-  }
-  this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
-  cb(null);
-};
-
-MemoryCookieStore.prototype.updateCookie = function updateCookie(oldCookie, newCookie, cb) {
-  // updateCookie() may avoid updating cookies that are identical.  For example,
-  // lastAccessed may not be important to some stores and an equality
-  // comparison could exclude that field.
-  this.putCookie(newCookie,cb);
-};
-
-MemoryCookieStore.prototype.removeCookie = function removeCookie(domain, path, key, cb) {
-  if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
-    delete this.idx[domain][path][key];
-  }
-  cb(null);
-};
-
-MemoryCookieStore.prototype.removeCookies = function removeCookies(domain, path, cb) {
-  if (this.idx[domain]) {
-    if (path) {
-      delete this.idx[domain][path];
-    } else {
-      delete this.idx[domain];
-    }
-  }
-  return cb(null);
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/pubsuffix.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/pubsuffix.js
deleted file mode 100644
index a7031473..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/pubsuffix.js
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************
- * AUTOMATICALLY GENERATED by generate-pubsuffix.js *
- *                  DO NOT EDIT!                    *
- ****************************************************/
-
-module.exports.getPublicSuffix = function getPublicSuffix(domain) {
-  /*
-   * Copyright GoInstant, Inc. and other contributors. All rights reserved.
-   * 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.
-   */
-  if (!domain) return null;
-  if (domain.match(/^\./)) return null;
-
-  domain = domain.toLowerCase();
-  var parts = domain.split('.').reverse();
-
-  var suffix = '';
-  var suffixLen = 0;
-  for (var i=0; i<parts.length; i++) {
-    var part = parts[i];
-    var starstr = '*'+suffix;
-    var partstr = part+suffix;
-
-    if (index[starstr]) { // star rule matches
-      suffixLen = i+1;
-      if (index[partstr] === false) { // exception rule matches (NB: false, not undefined)
-        suffixLen--;
-      }
-    } else if (index[partstr]) { // exact match, not exception
-      suffixLen = i+1;
-    }
-
-    suffix = '.'+part+suffix;
-  }
-
-  if (index['*'+suffix]) { // *.domain exists (e.g. *.kyoto.jp for domain='kyoto.jp');
-    return null;
-  }
-
-  if (suffixLen && parts.length > suffixLen) {
-    return parts.slice(0,suffixLen+1).reverse().join('.');
-  }
-
-  return null;
-};
-
-// The following generated structure is used under the MPL version 1.1
-// See public-suffix.txt for more information
-
-var index = module.exports.index = Object.freeze(
-{"ac":true,"com.ac":true,"edu.ac":true,"gov.ac":true,"net.ac":true,"mil.ac":true,"org.ac":true,"ad":true,"nom.ad":true,"ae":true,"co.ae":true,"net.ae":true,"org.ae":true,"sch.ae":true,"ac.ae":true,"gov.ae":true,"mil.ae":true,"aero":true,"accident-investigation.aero":true,"accident-prevention.aero":true,"aerobatic.aero":true,"aeroclub.aero":true,"aerodrome.aero":true,"agents.aero":true,"aircraft.aero":true,"airline.aero":true,"airport.aero":true,"air-surveillance.aero":true,"airtraffic.aero":true,"air-traffic-control.aero":true,"ambulance.aero":true,"amusement.aero":true,"association.aero":true,"author.aero":true,"ballooning.aero":true,"broker.aero":true,"caa.aero":true,"cargo.aero":true,"catering.aero":true,"certification.aero":true,"championship.aero":true,"charter.aero":true,"civilaviation.aero":true,"club.aero":true,"conference.aero":true,"consultant.aero":true,"consulting.aero":true,"control.aero":true,"council.aero":true,"crew.aero":true,"design.aero":true,"dgca.aero":true,"educator.aero":true,"emergency.aero":true,"engine.aero":true,"engineer.aero":true,"entertainment.aero":true,"equipment.aero":true,"exchange.aero":true,"express.aero":true,"federation.aero":true,"flight.aero":true,"freight.aero":true,"fuel.aero":true,"gliding.aero":true,"government.aero":true,"groundhandling.aero":true,"group.aero":true,"hanggliding.aero":true,"homebuilt.aero":true,"insurance.aero":true,"journal.aero":true,"journalist.aero":true,"leasing.aero":true,"logistics.aero":true,"magazine.aero":true,"maintenance.aero":true,"marketplace.aero":true,"media.aero":true,"microlight.aero":true,"modelling.aero":true,"navigation.aero":true,"parachuting.aero":true,"paragliding.aero":true,"passenger-association.aero":true,"pilot.aero":true,"press.aero":true,"production.aero":true,"recreation.aero":true,"repbody.aero":true,"res.aero":true,"research.aero":true,"rotorcraft.aero":true,"safety.aero":true,"scientist.aero":true,"services.aero":true,"show.aero":true,"skydiving.aero":true,"software.aero":true,"student.aero":true,"taxi.aero":true,"trader.aero":true,"trading.aero":true,"trainer.aero":true,"union.aero":true,"workinggroup.aero":true,"works.aero":true,"af":true,"gov.af":true,"com.af":true,"org.af":true,"net.af":true,"edu.af":true,"ag":true,"com.ag":true,"org.ag":true,"net.ag":true,"co.ag":true,"nom.ag":true,"ai":true,"off.ai":true,"com.ai":true,"net.ai":true,"org.ai":true,"al":true,"com.al":true,"edu.al":true,"gov.al":true,"mil.al":true,"net.al":true,"org.al":true,"am":true,"an":true,"com.an":true,"net.an":true,"org.an":true,"edu.an":true,"ao":true,"ed.ao":true,"gv.ao":true,"og.ao":true,"co.ao":true,"pb.ao":true,"it.ao":true,"aq":true,"*.ar":true,"congresodelalengua3.ar":false,"educ.ar":false,"gobiernoelectronico.ar":false,"mecon.ar":false,"nacion.ar":false,"nic.ar":false,"promocion.ar":false,"retina.ar":false,"uba.ar":false,"e164.arpa":true,"in-addr.arpa":true,"ip6.arpa":true,"iris.arpa":true,"uri.arpa":true,"urn.arpa":true,"as":true,"gov.as":true,"asia":true,"at":true,"ac.at":true,"co.at":true,"gv.at":true,"or.at":true,"com.au":true,"net.au":true,"org.au":true,"edu.au":true,"gov.au":true,"csiro.au":true,"asn.au":true,"id.au":true,"info.au":true,"conf.au":true,"oz.au":true,"act.au":true,"nsw.au":true,"nt.au":true,"qld.au":true,"sa.au":true,"tas.au":true,"vic.au":true,"wa.au":true,"act.edu.au":true,"nsw.edu.au":true,"nt.edu.au":true,"qld.edu.au":true,"sa.edu.au":true,"tas.edu.au":true,"vic.edu.au":true,"wa.edu.au":true,"act.gov.au":true,"nt.gov.au":true,"qld.gov.au":true,"sa.gov.au":true,"tas.gov.au":true,"vic.gov.au":true,"wa.gov.au":true,"aw":true,"com.aw":true,"ax":true,"az":true,"com.az":true,"net.az":true,"int.az":true,"gov.az":true,"org.az":true,"edu.az":true,"info.az":true,"pp.az":true,"mil.az":true,"name.az":true,"pro.az":true,"biz.az":true,"ba":true,"org.ba":true,"net.ba":true,"edu.ba":true,"gov.ba":true,"mil.ba":true,"unsa.ba":true,"unbi.ba":true,"co.ba":true,"com.ba":true,"rs.ba":true,"bb":true,"biz.bb":true,"com.bb":true,"edu.bb":true,"gov.bb":true,"info.bb":true,"net.bb":true,"org.bb":true,"store.bb":true,"*.bd":true,"be":true,"ac.be":true,"bf":true,"gov.bf":true,"bg":true,"a.bg":true,"b.bg":true,"c.bg":true,"d.bg":true,"e.bg":true,"f.bg":true,"g.bg":true,"h.bg":true,"i.bg":true,"j.bg":true,"k.bg":true,"l.bg":true,"m.bg":true,"n.bg":true,"o.bg":true,"p.bg":true,"q.bg":true,"r.bg":true,"s.bg":true,"t.bg":true,"u.bg":true,"v.bg":true,"w.bg":true,"x.bg":true,"y.bg":true,"z.bg":true,"0.bg":true,"1.bg":true,"2.bg":true,"3.bg":true,"4.bg":true,"5.bg":true,"6.bg":true,"7.bg":true,"8.bg":true,"9.bg":true,"bh":true,"com.bh":true,"edu.bh":true,"net.bh":true,"org.bh":true,"gov.bh":true,"bi":true,"co.bi":true,"com.bi":true,"edu.bi":true,"or.bi":true,"org.bi":true,"biz":true,"bj":true,"asso.bj":true,"barreau.bj":true,"gouv.bj":true,"bm":true,"com.bm":true,"edu.bm":true,"gov.bm":true,"net.bm":true,"org.bm":true,"*.bn":true,"bo":true,"com.bo":true,"edu.bo":true,"gov.bo":true,"gob.bo":true,"int.bo":true,"org.bo":true,"net.bo":true,"mil.bo":true,"tv.bo":true,"br":true,"adm.br":true,"adv.br":true,"agr.br":true,"am.br":true,"arq.br":true,"art.br":true,"ato.br":true,"b.br":true,"bio.br":true,"blog.br":true,"bmd.br":true,"can.br":true,"cim.br":true,"cng.br":true,"cnt.br":true,"com.br":true,"coop.br":true,"ecn.br":true,"edu.br":true,"emp.br":true,"eng.br":true,"esp.br":true,"etc.br":true,"eti.br":true,"far.br":true,"flog.br":true,"fm.br":true,"fnd.br":true,"fot.br":true,"fst.br":true,"g12.br":true,"ggf.br":true,"gov.br":true,"imb.br":true,"ind.br":true,"inf.br":true,"jor.br":true,"jus.br":true,"lel.br":true,"mat.br":true,"med.br":true,"mil.br":true,"mus.br":true,"net.br":true,"nom.br":true,"not.br":true,"ntr.br":true,"odo.br":true,"org.br":true,"ppg.br":true,"pro.br":true,"psc.br":true,"psi.br":true,"qsl.br":true,"radio.br":true,"rec.br":true,"slg.br":true,"srv.br":true,"taxi.br":true,"teo.br":true,"tmp.br":true,"trd.br":true,"tur.br":true,"tv.br":true,"vet.br":true,"vlog.br":true,"wiki.br":true,"zlg.br":true,"bs":true,"com.bs":true,"net.bs":true,"org.bs":true,"edu.bs":true,"gov.bs":true,"bt":true,"com.bt":true,"edu.bt":true,"gov.bt":true,"net.bt":true,"org.bt":true,"bw":true,"co.bw":true,"org.bw":true,"by":true,"gov.by":true,"mil.by":true,"com.by":true,"of.by":true,"bz":true,"com.bz":true,"net.bz":true,"org.bz":true,"edu.bz":true,"gov.bz":true,"ca":true,"ab.ca":true,"bc.ca":true,"mb.ca":true,"nb.ca":true,"nf.ca":true,"nl.ca":true,"ns.ca":true,"nt.ca":true,"nu.ca":true,"on.ca":true,"pe.ca":true,"qc.ca":true,"sk.ca":true,"yk.ca":true,"gc.ca":true,"cat":true,"cc":true,"cd":true,"gov.cd":true,"cf":true,"cg":true,"ch":true,"ci":true,"org.ci":true,"or.ci":true,"com.ci":true,"co.ci":true,"edu.ci":true,"ed.ci":true,"ac.ci":true,"net.ci":true,"go.ci":true,"asso.ci":true,"xn--aroport-bya.ci":true,"int.ci":true,"presse.ci":true,"md.ci":true,"gouv.ci":true,"*.ck":true,"www.ck":false,"cl":true,"gov.cl":true,"gob.cl":true,"co.cl":true,"mil.cl":true,"cm":true,"gov.cm":true,"cn":true,"ac.cn":true,"com.cn":true,"edu.cn":true,"gov.cn":true,"net.cn":true,"org.cn":true,"mil.cn":true,"xn--55qx5d.cn":true,"xn--io0a7i.cn":true,"xn--od0alg.cn":true,"ah.cn":true,"bj.cn":true,"cq.cn":true,"fj.cn":true,"gd.cn":true,"gs.cn":true,"gz.cn":true,"gx.cn":true,"ha.cn":true,"hb.cn":true,"he.cn":true,"hi.cn":true,"hl.cn":true,"hn.cn":true,"jl.cn":true,"js.cn":true,"jx.cn":true,"ln.cn":true,"nm.cn":true,"nx.cn":true,"qh.cn":true,"sc.cn":true,"sd.cn":true,"sh.cn":true,"sn.cn":true,"sx.cn":true,"tj.cn":true,"xj.cn":true,"xz.cn":true,"yn.cn":true,"zj.cn":true,"hk.cn":true,"mo.cn":true,"tw.cn":true,"co":true,"arts.co":true,"com.co":true,"edu.co":true,"firm.co":true,"gov.co":true,"info.co":true,"int.co":true,"mil.co":true,"net.co":true,"nom.co":true,"org.co":true,"rec.co":true,"web.co":true,"com":true,"coop":true,"cr":true,"ac.cr":true,"co.cr":true,"ed.cr":true,"fi.cr":true,"go.cr":true,"or.cr":true,"sa.cr":true,"cu":true,"com.cu":true,"edu.cu":true,"org.cu":true,"net.cu":true,"gov.cu":true,"inf.cu":true,"cv":true,"cx":true,"gov.cx":true,"*.cy":true,"cz":true,"de":true,"dj":true,"dk":true,"dm":true,"com.dm":true,"net.dm":true,"org.dm":true,"edu.dm":true,"gov.dm":true,"do":true,"art.do":true,"com.do":true,"edu.do":true,"gob.do":true,"gov.do":true,"mil.do":true,"net.do":true,"org.do":true,"sld.do":true,"web.do":true,"dz":true,"com.dz":true,"org.dz":true,"net.dz":true,"gov.dz":true,"edu.dz":true,"asso.dz":true,"pol.dz":true,"art.dz":true,"ec":true,"com.ec":true,"info.ec":true,"net.ec":true,"fin.ec":true,"k12.ec":true,"med.ec":true,"pro.ec":true,"org.ec":true,"edu.ec":true,"gov.ec":true,"gob.ec":true,"mil.ec":true,"edu":true,"ee":true,"edu.ee":true,"gov.ee":true,"riik.ee":true,"lib.ee":true,"med.ee":true,"com.ee":true,"pri.ee":true,"aip.ee":true,"org.ee":true,"fie.ee":true,"eg":true,"com.eg":true,"edu.eg":true,"eun.eg":true,"gov.eg":true,"mil.eg":true,"name.eg":true,"net.eg":true,"org.eg":true,"sci.eg":true,"*.er":true,"es":true,"com.es":true,"nom.es":true,"org.es":true,"gob.es":true,"edu.es":true,"*.et":true,"eu":true,"fi":true,"aland.fi":true,"*.fj":true,"*.fk":true,"fm":true,"fo":true,"fr":true,"com.fr":true,"asso.fr":true,"nom.fr":true,"prd.fr":true,"presse.fr":true,"tm.fr":true,"aeroport.fr":true,"assedic.fr":true,"avocat.fr":true,"avoues.fr":true,"cci.fr":true,"chambagri.fr":true,"chirurgiens-dentistes.fr":true,"experts-comptables.fr":true,"geometre-expert.fr":true,"gouv.fr":true,"greta.fr":true,"huissier-justice.fr":true,"medecin.fr":true,"notaires.fr":true,"pharmacien.fr":true,"port.fr":true,"veterinaire.fr":true,"ga":true,"gd":true,"ge":true,"com.ge":true,"edu.ge":true,"gov.ge":true,"org.ge":true,"mil.ge":true,"net.ge":true,"pvt.ge":true,"gf":true,"gg":true,"co.gg":true,"org.gg":true,"net.gg":true,"sch.gg":true,"gov.gg":true,"gh":true,"com.gh":true,"edu.gh":true,"gov.gh":true,"org.gh":true,"mil.gh":true,"gi":true,"com.gi":true,"ltd.gi":true,"gov.gi":true,"mod.gi":true,"edu.gi":true,"org.gi":true,"gl":true,"gm":true,"ac.gn":true,"com.gn":true,"edu.gn":true,"gov.gn":true,"org.gn":true,"net.gn":true,"gov":true,"gp":true,"com.gp":true,"net.gp":true,"mobi.gp":true,"edu.gp":true,"org.gp":true,"asso.gp":true,"gq":true,"gr":true,"com.gr":true,"edu.gr":true,"net.gr":true,"org.gr":true,"gov.gr":true,"gs":true,"*.gt":true,"www.gt":false,"*.gu":true,"gw":true,"gy":true,"co.gy":true,"com.gy":true,"net.gy":true,"hk":true,"com.hk":true,"edu.hk":true,"gov.hk":true,"idv.hk":true,"net.hk":true,"org.hk":true,"xn--55qx5d.hk":true,"xn--wcvs22d.hk":true,"xn--lcvr32d.hk":true,"xn--mxtq1m.hk":true,"xn--gmqw5a.hk":true,"xn--ciqpn.hk":true,"xn--gmq050i.hk":true,"xn--zf0avx.hk":true,"xn--io0a7i.hk":true,"xn--mk0axi.hk":true,"xn--od0alg.hk":true,"xn--od0aq3b.hk":true,"xn--tn0ag.hk":true,"xn--uc0atv.hk":true,"xn--uc0ay4a.hk":true,"hm":true,"hn":true,"com.hn":true,"edu.hn":true,"org.hn":true,"net.hn":true,"mil.hn":true,"gob.hn":true,"hr":true,"iz.hr":true,"from.hr":true,"name.hr":true,"com.hr":true,"ht":true,"com.ht":true,"shop.ht":true,"firm.ht":true,"info.ht":true,"adult.ht":true,"net.ht":true,"pro.ht":true,"org.ht":true,"med.ht":true,"art.ht":true,"coop.ht":true,"pol.ht":true,"asso.ht":true,"edu.ht":true,"rel.ht":true,"gouv.ht":true,"perso.ht":true,"hu":true,"co.hu":true,"info.hu":true,"org.hu":true,"priv.hu":true,"sport.hu":true,"tm.hu":true,"2000.hu":true,"agrar.hu":true,"bolt.hu":true,"casino.hu":true,"city.hu":true,"erotica.hu":true,"erotika.hu":true,"film.hu":true,"forum.hu":true,"games.hu":true,"hotel.hu":true,"ingatlan.hu":true,"jogasz.hu":true,"konyvelo.hu":true,"lakas.hu":true,"media.hu":true,"news.hu":true,"reklam.hu":true,"sex.hu":true,"shop.hu":true,"suli.hu":true,"szex.hu":true,"tozsde.hu":true,"utazas.hu":true,"video.hu":true,"id":true,"ac.id":true,"co.id":true,"go.id":true,"mil.id":true,"net.id":true,"or.id":true,"sch.id":true,"web.id":true,"ie":true,"gov.ie":true,"*.il":true,"im":true,"co.im":true,"ltd.co.im":true,"plc.co.im":true,"net.im":true,"gov.im":true,"org.im":true,"nic.im":true,"ac.im":true,"in":true,"co.in":true,"firm.in":true,"net.in":true,"org.in":true,"gen.in":true,"ind.in":true,"nic.in":true,"ac.in":true,"edu.in":true,"res.in":true,"gov.in":true,"mil.in":true,"info":true,"int":true,"eu.int":true,"io":true,"com.io":true,"iq":true,"gov.iq":true,"edu.iq":true,"mil.iq":true,"com.iq":true,"org.iq":true,"net.iq":true,"ir":true,"ac.ir":true,"co.ir":true,"gov.ir":true,"id.ir":true,"net.ir":true,"org.ir":true,"sch.ir":true,"xn--mgba3a4f16a.ir":true,"xn--mgba3a4fra.ir":true,"is":true,"net.is":true,"com.is":true,"edu.is":true,"gov.is":true,"org.is":true,"int.is":true,"it":true,"gov.it":true,"edu.it":true,"agrigento.it":true,"ag.it":true,"alessandria.it":true,"al.it":true,"ancona.it":true,"an.it":true,"aosta.it":true,"aoste.it":true,"ao.it":true,"arezzo.it":true,"ar.it":true,"ascoli-piceno.it":true,"ascolipiceno.it":true,"ap.it":true,"asti.it":true,"at.it":true,"avellino.it":true,"av.it":true,"bari.it":true,"ba.it":true,"andria-barletta-trani.it":true,"andriabarlettatrani.it":true,"trani-barletta-andria.it":true,"tranibarlettaandria.it":true,"barletta-trani-andria.it":true,"barlettatraniandria.it":true,"andria-trani-barletta.it":true,"andriatranibarletta.it":true,"trani-andria-barletta.it":true,"traniandriabarletta.it":true,"bt.it":true,"belluno.it":true,"bl.it":true,"benevento.it":true,"bn.it":true,"bergamo.it":true,"bg.it":true,"biella.it":true,"bi.it":true,"bologna.it":true,"bo.it":true,"bolzano.it":true,"bozen.it":true,"balsan.it":true,"alto-adige.it":true,"altoadige.it":true,"suedtirol.it":true,"bz.it":true,"brescia.it":true,"bs.it":true,"brindisi.it":true,"br.it":true,"cagliari.it":true,"ca.it":true,"caltanissetta.it":true,"cl.it":true,"campobasso.it":true,"cb.it":true,"carboniaiglesias.it":true,"carbonia-iglesias.it":true,"iglesias-carbonia.it":true,"iglesiascarbonia.it":true,"ci.it":true,"caserta.it":true,"ce.it":true,"catania.it":true,"ct.it":true,"catanzaro.it":true,"cz.it":true,"chieti.it":true,"ch.it":true,"como.it":true,"co.it":true,"cosenza.it":true,"cs.it":true,"cremona.it":true,"cr.it":true,"crotone.it":true,"kr.it":true,"cuneo.it":true,"cn.it":true,"dell-ogliastra.it":true,"dellogliastra.it":true,"ogliastra.it":true,"og.it":true,"enna.it":true,"en.it":true,"ferrara.it":true,"fe.it":true,"fermo.it":true,"fm.it":true,"firenze.it":true,"florence.it":true,"fi.it":true,"foggia.it":true,"fg.it":true,"forli-cesena.it":true,"forlicesena.it":true,"cesena-forli.it":true,"cesenaforli.it":true,"fc.it":true,"frosinone.it":true,"fr.it":true,"genova.it":true,"genoa.it":true,"ge.it":true,"gorizia.it":true,"go.it":true,"grosseto.it":true,"gr.it":true,"imperia.it":true,"im.it":true,"isernia.it":true,"is.it":true,"laquila.it":true,"aquila.it":true,"aq.it":true,"la-spezia.it":true,"laspezia.it":true,"sp.it":true,"latina.it":true,"lt.it":true,"lecce.it":true,"le.it":true,"lecco.it":true,"lc.it":true,"livorno.it":true,"li.it":true,"lodi.it":true,"lo.it":true,"lucca.it":true,"lu.it":true,"macerata.it":true,"mc.it":true,"mantova.it":true,"mn.it":true,"massa-carrara.it":true,"massacarrara.it":true,"carrara-massa.it":true,"carraramassa.it":true,"ms.it":true,"matera.it":true,"mt.it":true,"medio-campidano.it":true,"mediocampidano.it":true,"campidano-medio.it":true,"campidanomedio.it":true,"vs.it":true,"messina.it":true,"me.it":true,"milano.it":true,"milan.it":true,"mi.it":true,"modena.it":true,"mo.it":true,"monza.it":true,"monza-brianza.it":true,"monzabrianza.it":true,"monzaebrianza.it":true,"monzaedellabrianza.it":true,"monza-e-della-brianza.it":true,"mb.it":true,"napoli.it":true,"naples.it":true,"na.it":true,"novara.it":true,"no.it":true,"nuoro.it":true,"nu.it":true,"oristano.it":true,"or.it":true,"padova.it":true,"padua.it":true,"pd.it":true,"palermo.it":true,"pa.it":true,"parma.it":true,"pr.it":true,"pavia.it":true,"pv.it":true,"perugia.it":true,"pg.it":true,"pescara.it":true,"pe.it":true,"pesaro-urbino.it":true,"pesarourbino.it":true,"urbino-pesaro.it":true,"urbinopesaro.it":true,"pu.it":true,"piacenza.it":true,"pc.it":true,"pisa.it":true,"pi.it":true,"pistoia.it":true,"pt.it":true,"pordenone.it":true,"pn.it":true,"potenza.it":true,"pz.it":true,"prato.it":true,"po.it":true,"ragusa.it":true,"rg.it":true,"ravenna.it":true,"ra.it":true,"reggio-calabria.it":true,"reggiocalabria.it":true,"rc.it":true,"reggio-emilia.it":true,"reggioemilia.it":true,"re.it":true,"rieti.it":true,"ri.it":true,"rimini.it":true,"rn.it":true,"roma.it":true,"rome.it":true,"rm.it":true,"rovigo.it":true,"ro.it":true,"salerno.it":true,"sa.it":true,"sassari.it":true,"ss.it":true,"savona.it":true,"sv.it":true,"siena.it":true,"si.it":true,"siracusa.it":true,"sr.it":true,"sondrio.it":true,"so.it":true,"taranto.it":true,"ta.it":true,"tempio-olbia.it":true,"tempioolbia.it":true,"olbia-tempio.it":true,"olbiatempio.it":true,"ot.it":true,"teramo.it":true,"te.it":true,"terni.it":true,"tr.it":true,"torino.it":true,"turin.it":true,"to.it":true,"trapani.it":true,"tp.it":true,"trento.it":true,"trentino.it":true,"tn.it":true,"treviso.it":true,"tv.it":true,"trieste.it":true,"ts.it":true,"udine.it":true,"ud.it":true,"varese.it":true,"va.it":true,"venezia.it":true,"venice.it":true,"ve.it":true,"verbania.it":true,"vb.it":true,"vercelli.it":true,"vc.it":true,"verona.it":true,"vr.it":true,"vibo-valentia.it":true,"vibovalentia.it":true,"vv.it":true,"vicenza.it":true,"vi.it":true,"viterbo.it":true,"vt.it":true,"je":true,"co.je":true,"org.je":true,"net.je":true,"sch.je":true,"gov.je":true,"*.jm":true,"jo":true,"com.jo":true,"org.jo":true,"net.jo":true,"edu.jo":true,"sch.jo":true,"gov.jo":true,"mil.jo":true,"name.jo":true,"jobs":true,"jp":true,"ac.jp":true,"ad.jp":true,"co.jp":true,"ed.jp":true,"go.jp":true,"gr.jp":true,"lg.jp":true,"ne.jp":true,"or.jp":true,"*.aichi.jp":true,"*.akita.jp":true,"*.aomori.jp":true,"*.chiba.jp":true,"*.ehime.jp":true,"*.fukui.jp":true,"*.fukuoka.jp":true,"*.fukushima.jp":true,"*.gifu.jp":true,"*.gunma.jp":true,"*.hiroshima.jp":true,"*.hokkaido.jp":true,"*.hyogo.jp":true,"*.ibaraki.jp":true,"*.ishikawa.jp":true,"*.iwate.jp":true,"*.kagawa.jp":true,"*.kagoshima.jp":true,"*.kanagawa.jp":true,"*.kawasaki.jp":true,"*.kitakyushu.jp":true,"*.kobe.jp":true,"*.kochi.jp":true,"*.kumamoto.jp":true,"*.kyoto.jp":true,"*.mie.jp":true,"*.miyagi.jp":true,"*.miyazaki.jp":true,"*.nagano.jp":true,"*.nagasaki.jp":true,"*.nagoya.jp":true,"*.nara.jp":true,"*.niigata.jp":true,"*.oita.jp":true,"*.okayama.jp":true,"*.okinawa.jp":true,"*.osaka.jp":true,"*.saga.jp":true,"*.saitama.jp":true,"*.sapporo.jp":true,"*.sendai.jp":true,"*.shiga.jp":true,"*.shimane.jp":true,"*.shizuoka.jp":true,"*.tochigi.jp":true,"*.tokushima.jp":true,"*.tokyo.jp":true,"*.tottori.jp":true,"*.toyama.jp":true,"*.wakayama.jp":true,"*.yamagata.jp":true,"*.yamaguchi.jp":true,"*.yamanashi.jp":true,"*.yokohama.jp":true,"metro.tokyo.jp":false,"pref.aichi.jp":false,"pref.akita.jp":false,"pref.aomori.jp":false,"pref.chiba.jp":false,"pref.ehime.jp":false,"pref.fukui.jp":false,"pref.fukuoka.jp":false,"pref.fukushima.jp":false,"pref.gifu.jp":false,"pref.gunma.jp":false,"pref.hiroshima.jp":false,"pref.hokkaido.jp":false,"pref.hyogo.jp":false,"pref.ibaraki.jp":false,"pref.ishikawa.jp":false,"pref.iwate.jp":false,"pref.kagawa.jp":false,"pref.kagoshima.jp":false,"pref.kanagawa.jp":false,"pref.kochi.jp":false,"pref.kumamoto.jp":false,"pref.kyoto.jp":false,"pref.mie.jp":false,"pref.miyagi.jp":false,"pref.miyazaki.jp":false,"pref.nagano.jp":false,"pref.nagasaki.jp":false,"pref.nara.jp":false,"pref.niigata.jp":false,"pref.oita.jp":false,"pref.okayama.jp":false,"pref.okinawa.jp":false,"pref.osaka.jp":false,"pref.saga.jp":false,"pref.saitama.jp":false,"pref.shiga.jp":false,"pref.shimane.jp":false,"pref.shizuoka.jp":false,"pref.tochigi.jp":false,"pref.tokushima.jp":false,"pref.tottori.jp":false,"pref.toyama.jp":false,"pref.wakayama.jp":false,"pref.yamagata.jp":false,"pref.yamaguchi.jp":false,"pref.yamanashi.jp":false,"city.chiba.jp":false,"city.fukuoka.jp":false,"city.hiroshima.jp":false,"city.kawasaki.jp":false,"city.kitakyushu.jp":false,"city.kobe.jp":false,"city.kyoto.jp":false,"city.nagoya.jp":false,"city.niigata.jp":false,"city.okayama.jp":false,"city.osaka.jp":false,"city.saitama.jp":false,"city.sapporo.jp":false,"city.sendai.jp":false,"city.shizuoka.jp":false,"city.yokohama.jp":false,"*.ke":true,"kg":true,"org.kg":true,"net.kg":true,"com.kg":true,"edu.kg":true,"gov.kg":true,"mil.kg":true,"*.kh":true,"ki":true,"edu.ki":true,"biz.ki":true,"net.ki":true,"org.ki":true,"gov.ki":true,"info.ki":true,"com.ki":true,"km":true,"org.km":true,"nom.km":true,"gov.km":true,"prd.km":true,"tm.km":true,"edu.km":true,"mil.km":true,"ass.km":true,"com.km":true,"coop.km":true,"asso.km":true,"presse.km":true,"medecin.km":true,"notaires.km":true,"pharmaciens.km":true,"veterinaire.km":true,"gouv.km":true,"kn":true,"net.kn":true,"org.kn":true,"edu.kn":true,"gov.kn":true,"com.kp":true,"edu.kp":true,"gov.kp":true,"org.kp":true,"rep.kp":true,"tra.kp":true,"kr":true,"ac.kr":true,"co.kr":true,"es.kr":true,"go.kr":true,"hs.kr":true,"kg.kr":true,"mil.kr":true,"ms.kr":true,"ne.kr":true,"or.kr":true,"pe.kr":true,"re.kr":true,"sc.kr":true,"busan.kr":true,"chungbuk.kr":true,"chungnam.kr":true,"daegu.kr":true,"daejeon.kr":true,"gangwon.kr":true,"gwangju.kr":true,"gyeongbuk.kr":true,"gyeonggi.kr":true,"gyeongnam.kr":true,"incheon.kr":true,"jeju.kr":true,"jeonbuk.kr":true,"jeonnam.kr":true,"seoul.kr":true,"ulsan.kr":true,"*.kw":true,"ky":true,"edu.ky":true,"gov.ky":true,"com.ky":true,"org.ky":true,"net.ky":true,"kz":true,"org.kz":true,"edu.kz":true,"net.kz":true,"gov.kz":true,"mil.kz":true,"com.kz":true,"la":true,"int.la":true,"net.la":true,"info.la":true,"edu.la":true,"gov.la":true,"per.la":true,"com.la":true,"org.la":true,"com.lb":true,"edu.lb":true,"gov.lb":true,"net.lb":true,"org.lb":true,"lc":true,"com.lc":true,"net.lc":true,"co.lc":true,"org.lc":true,"edu.lc":true,"gov.lc":true,"li":true,"lk":true,"gov.lk":true,"sch.lk":true,"net.lk":true,"int.lk":true,"com.lk":true,"org.lk":true,"edu.lk":true,"ngo.lk":true,"soc.lk":true,"web.lk":true,"ltd.lk":true,"assn.lk":true,"grp.lk":true,"hotel.lk":true,"com.lr":true,"edu.lr":true,"gov.lr":true,"org.lr":true,"net.lr":true,"ls":true,"co.ls":true,"org.ls":true,"lt":true,"gov.lt":true,"lu":true,"lv":true,"com.lv":true,"edu.lv":true,"gov.lv":true,"org.lv":true,"mil.lv":true,"id.lv":true,"net.lv":true,"asn.lv":true,"conf.lv":true,"ly":true,"com.ly":true,"net.ly":true,"gov.ly":true,"plc.ly":true,"edu.ly":true,"sch.ly":true,"med.ly":true,"org.ly":true,"id.ly":true,"ma":true,"co.ma":true,"net.ma":true,"gov.ma":true,"org.ma":true,"ac.ma":true,"press.ma":true,"mc":true,"tm.mc":true,"asso.mc":true,"md":true,"me":true,"co.me":true,"net.me":true,"org.me":true,"edu.me":true,"ac.me":true,"gov.me":true,"its.me":true,"priv.me":true,"mg":true,"org.mg":true,"nom.mg":true,"gov.mg":true,"prd.mg":true,"tm.mg":true,"edu.mg":true,"mil.mg":true,"com.mg":true,"mh":true,"mil":true,"mk":true,"com.mk":true,"org.mk":true,"net.mk":true,"edu.mk":true,"gov.mk":true,"inf.mk":true,"name.mk":true,"ml":true,"com.ml":true,"edu.ml":true,"gouv.ml":true,"gov.ml":true,"net.ml":true,"org.ml":true,"presse.ml":true,"*.mm":true,"mn":true,"gov.mn":true,"edu.mn":true,"org.mn":true,"mo":true,"com.mo":true,"net.mo":true,"org.mo":true,"edu.mo":true,"gov.mo":true,"mobi":true,"mp":true,"mq":true,"mr":true,"gov.mr":true,"ms":true,"*.mt":true,"mu":true,"com.mu":true,"net.mu":true,"org.mu":true,"gov.mu":true,"ac.mu":true,"co.mu":true,"or.mu":true,"museum":true,"academy.museum":true,"agriculture.museum":true,"air.museum":true,"airguard.museum":true,"alabama.museum":true,"alaska.museum":true,"amber.museum":true,"ambulance.museum":true,"american.museum":true,"americana.museum":true,"americanantiques.museum":true,"americanart.museum":true,"amsterdam.museum":true,"and.museum":true,"annefrank.museum":true,"anthro.museum":true,"anthropology.museum":true,"antiques.museum":true,"aquarium.museum":true,"arboretum.museum":true,"archaeological.museum":true,"archaeology.museum":true,"architecture.museum":true,"art.museum":true,"artanddesign.museum":true,"artcenter.museum":true,"artdeco.museum":true,"arteducation.museum":true,"artgallery.museum":true,"arts.museum":true,"artsandcrafts.museum":true,"asmatart.museum":true,"assassination.museum":true,"assisi.museum":true,"association.museum":true,"astronomy.museum":true,"atlanta.museum":true,"austin.museum":true,"australia.museum":true,"automotive.museum":true,"aviation.museum":true,"axis.museum":true,"badajoz.museum":true,"baghdad.museum":true,"bahn.museum":true,"bale.museum":true,"baltimore.museum":true,"barcelona.museum":true,"baseball.museum":true,"basel.museum":true,"baths.museum":true,"bauern.museum":true,"beauxarts.museum":true,"beeldengeluid.museum":true,"bellevue.museum":true,"bergbau.museum":true,"berkeley.museum":true,"berlin.museum":true,"bern.museum":true,"bible.museum":true,"bilbao.museum":true,"bill.museum":true,"birdart.museum":true,"birthplace.museum":true,"bonn.museum":true,"boston.museum":true,"botanical.museum":true,"botanicalgarden.museum":true,"botanicgarden.museum":true,"botany.museum":true,"brandywinevalley.museum":true,"brasil.museum":true,"bristol.museum":true,"british.museum":true,"britishcolumbia.museum":true,"broadcast.museum":true,"brunel.museum":true,"brussel.museum":true,"brussels.museum":true,"bruxelles.museum":true,"building.museum":true,"burghof.museum":true,"bus.museum":true,"bushey.museum":true,"cadaques.museum":true,"california.museum":true,"cambridge.museum":true,"can.museum":true,"canada.museum":true,"capebreton.museum":true,"carrier.museum":true,"cartoonart.museum":true,"casadelamoneda.museum":true,"castle.museum":true,"castres.museum":true,"celtic.museum":true,"center.museum":true,"chattanooga.museum":true,"cheltenham.museum":true,"chesapeakebay.museum":true,"chicago.museum":true,"children.museum":true,"childrens.museum":true,"childrensgarden.museum":true,"chiropractic.museum":true,"chocolate.museum":true,"christiansburg.museum":true,"cincinnati.museum":true,"cinema.museum":true,"circus.museum":true,"civilisation.museum":true,"civilization.museum":true,"civilwar.museum":true,"clinton.museum":true,"clock.museum":true,"coal.museum":true,"coastaldefence.museum":true,"cody.museum":true,"coldwar.museum":true,"collection.museum":true,"colonialwilliamsburg.museum":true,"coloradoplateau.museum":true,"columbia.museum":true,"columbus.museum":true,"communication.museum":true,"communications.museum":true,"community.museum":true,"computer.museum":true,"computerhistory.museum":true,"xn--comunicaes-v6a2o.museum":true,"contemporary.museum":true,"contemporaryart.museum":true,"convent.museum":true,"copenhagen.museum":true,"corporation.museum":true,"xn--correios-e-telecomunicaes-ghc29a.museum":true,"corvette.museum":true,"costume.museum":true,"countryestate.museum":true,"county.museum":true,"crafts.museum":true,"cranbrook.museum":true,"creation.museum":true,"cultural.museum":true,"culturalcenter.museum":true,"culture.museum":true,"cyber.museum":true,"cymru.museum":true,"dali.museum":true,"dallas.museum":true,"database.museum":true,"ddr.museum":true,"decorativearts.museum":true,"delaware.museum":true,"delmenhorst.museum":true,"denmark.museum":true,"depot.museum":true,"design.museum":true,"detroit.museum":true,"dinosaur.museum":true,"discovery.museum":true,"dolls.museum":true,"donostia.museum":true,"durham.museum":true,"eastafrica.museum":true,"eastcoast.museum":true,"education.museum":true,"educational.museum":true,"egyptian.museum":true,"eisenbahn.museum":true,"elburg.museum":true,"elvendrell.museum":true,"embroidery.museum":true,"encyclopedic.museum":true,"england.museum":true,"entomology.museum":true,"environment.museum":true,"environmentalconservation.museum":true,"epilepsy.museum":true,"essex.museum":true,"estate.museum":true,"ethnology.museum":true,"exeter.museum":true,"exhibition.museum":true,"family.museum":true,"farm.museum":true,"farmequipment.museum":true,"farmers.museum":true,"farmstead.museum":true,"field.museum":true,"figueres.museum":true,"filatelia.museum":true,"film.museum":true,"fineart.museum":true,"finearts.museum":true,"finland.museum":true,"flanders.museum":true,"florida.museum":true,"force.museum":true,"fortmissoula.museum":true,"fortworth.museum":true,"foundation.museum":true,"francaise.museum":true,"frankfurt.museum":true,"franziskaner.museum":true,"freemasonry.museum":true,"freiburg.museum":true,"fribourg.museum":true,"frog.museum":true,"fundacio.museum":true,"furniture.museum":true,"gallery.museum":true,"garden.museum":true,"gateway.museum":true,"geelvinck.museum":true,"gemological.museum":true,"geology.museum":true,"georgia.museum":true,"giessen.museum":true,"glas.museum":true,"glass.museum":true,"gorge.museum":true,"grandrapids.museum":true,"graz.museum":true,"guernsey.museum":true,"halloffame.museum":true,"hamburg.museum":true,"handson.museum":true,"harvestcelebration.museum":true,"hawaii.museum":true,"health.museum":true,"heimatunduhren.museum":true,"hellas.museum":true,"helsinki.museum":true,"hembygdsforbund.museum":true,"heritage.museum":true,"histoire.museum":true,"historical.museum":true,"historicalsociety.museum":true,"historichouses.museum":true,"historisch.museum":true,"historisches.museum":true,"history.museum":true,"historyofscience.museum":true,"horology.museum":true,"house.museum":true,"humanities.museum":true,"illustration.museum":true,"imageandsound.museum":true,"indian.museum":true,"indiana.museum":true,"indianapolis.museum":true,"indianmarket.museum":true,"intelligence.museum":true,"interactive.museum":true,"iraq.museum":true,"iron.museum":true,"isleofman.museum":true,"jamison.museum":true,"jefferson.museum":true,"jerusalem.museum":true,"jewelry.museum":true,"jewish.museum":true,"jewishart.museum":true,"jfk.museum":true,"journalism.museum":true,"judaica.museum":true,"judygarland.museum":true,"juedisches.museum":true,"juif.museum":true,"karate.museum":true,"karikatur.museum":true,"kids.museum":true,"koebenhavn.museum":true,"koeln.museum":true,"kunst.museum":true,"kunstsammlung.museum":true,"kunstunddesign.museum":true,"labor.museum":true,"labour.museum":true,"lajolla.museum":true,"lancashire.museum":true,"landes.museum":true,"lans.museum":true,"xn--lns-qla.museum":true,"larsson.museum":true,"lewismiller.museum":true,"lincoln.museum":true,"linz.museum":true,"living.museum":true,"livinghistory.museum":true,"localhistory.museum":true,"london.museum":true,"losangeles.museum":true,"louvre.museum":true,"loyalist.museum":true,"lucerne.museum":true,"luxembourg.museum":true,"luzern.museum":true,"mad.museum":true,"madrid.museum":true,"mallorca.museum":true,"manchester.museum":true,"mansion.museum":true,"mansions.museum":true,"manx.museum":true,"marburg.museum":true,"maritime.museum":true,"maritimo.museum":true,"maryland.museum":true,"marylhurst.museum":true,"media.museum":true,"medical.museum":true,"medizinhistorisches.museum":true,"meeres.museum":true,"memorial.museum":true,"mesaverde.museum":true,"michigan.museum":true,"midatlantic.museum":true,"military.museum":true,"mill.museum":true,"miners.museum":true,"mining.museum":true,"minnesota.museum":true,"missile.museum":true,"missoula.museum":true,"modern.museum":true,"moma.museum":true,"money.museum":true,"monmouth.museum":true,"monticello.museum":true,"montreal.museum":true,"moscow.museum":true,"motorcycle.museum":true,"muenchen.museum":true,"muenster.museum":true,"mulhouse.museum":true,"muncie.museum":true,"museet.museum":true,"museumcenter.museum":true,"museumvereniging.museum":true,"music.museum":true,"national.museum":true,"nationalfirearms.museum":true,"nationalheritage.museum":true,"nativeamerican.museum":true,"naturalhistory.museum":true,"naturalhistorymuseum.museum":true,"naturalsciences.museum":true,"nature.museum":true,"naturhistorisches.museum":true,"natuurwetenschappen.museum":true,"naumburg.museum":true,"naval.museum":true,"nebraska.museum":true,"neues.museum":true,"newhampshire.museum":true,"newjersey.museum":true,"newmexico.museum":true,"newport.museum":true,"newspaper.museum":true,"newyork.museum":true,"niepce.museum":true,"norfolk.museum":true,"north.museum":true,"nrw.museum":true,"nuernberg.museum":true,"nuremberg.museum":true,"nyc.museum":true,"nyny.museum":true,"oceanographic.museum":true,"oceanographique.museum":true,"omaha.museum":true,"online.museum":true,"ontario.museum":true,"openair.museum":true,"oregon.museum":true,"oregontrail.museum":true,"otago.museum":true,"oxford.museum":true,"pacific.museum":true,"paderborn.museum":true,"palace.museum":true,"paleo.museum":true,"palmsprings.museum":true,"panama.museum":true,"paris.museum":true,"pasadena.museum":true,"pharmacy.museum":true,"philadelphia.museum":true,"philadelphiaarea.museum":true,"philately.museum":true,"phoenix.museum":true,"photography.museum":true,"pilots.museum":true,"pittsburgh.museum":true,"planetarium.museum":true,"plantation.museum":true,"plants.museum":true,"plaza.museum":true,"portal.museum":true,"portland.museum":true,"portlligat.museum":true,"posts-and-telecommunications.museum":true,"preservation.museum":true,"presidio.museum":true,"press.museum":true,"project.museum":true,"public.museum":true,"pubol.museum":true,"quebec.museum":true,"railroad.museum":true,"railway.museum":true,"research.museum":true,"resistance.museum":true,"riodejaneiro.museum":true,"rochester.museum":true,"rockart.museum":true,"roma.museum":true,"russia.museum":true,"saintlouis.museum":true,"salem.museum":true,"salvadordali.museum":true,"salzburg.museum":true,"sandiego.museum":true,"sanfrancisco.museum":true,"santabarbara.museum":true,"santacruz.museum":true,"santafe.museum":true,"saskatchewan.museum":true,"satx.museum":true,"savannahga.museum":true,"schlesisches.museum":true,"schoenbrunn.museum":true,"schokoladen.museum":true,"school.museum":true,"schweiz.museum":true,"science.museum":true,"scienceandhistory.museum":true,"scienceandindustry.museum":true,"sciencecenter.museum":true,"sciencecenters.museum":true,"science-fiction.museum":true,"sciencehistory.museum":true,"sciences.museum":true,"sciencesnaturelles.museum":true,"scotland.museum":true,"seaport.museum":true,"settlement.museum":true,"settlers.museum":true,"shell.museum":true,"sherbrooke.museum":true,"sibenik.museum":true,"silk.museum":true,"ski.museum":true,"skole.museum":true,"society.museum":true,"sologne.museum":true,"soundandvision.museum":true,"southcarolina.museum":true,"southwest.museum":true,"space.museum":true,"spy.museum":true,"square.museum":true,"stadt.museum":true,"stalbans.museum":true,"starnberg.museum":true,"state.museum":true,"stateofdelaware.museum":true,"station.museum":true,"steam.museum":true,"steiermark.museum":true,"stjohn.museum":true,"stockholm.museum":true,"stpetersburg.museum":true,"stuttgart.museum":true,"suisse.museum":true,"surgeonshall.museum":true,"surrey.museum":true,"svizzera.museum":true,"sweden.museum":true,"sydney.museum":true,"tank.museum":true,"tcm.museum":true,"technology.museum":true,"telekommunikation.museum":true,"television.museum":true,"texas.museum":true,"textile.museum":true,"theater.museum":true,"time.museum":true,"timekeeping.museum":true,"topology.museum":true,"torino.museum":true,"touch.museum":true,"town.museum":true,"transport.museum":true,"tree.museum":true,"trolley.museum":true,"trust.museum":true,"trustee.museum":true,"uhren.museum":true,"ulm.museum":true,"undersea.museum":true,"university.museum":true,"usa.museum":true,"usantiques.museum":true,"usarts.museum":true,"uscountryestate.museum":true,"usculture.museum":true,"usdecorativearts.museum":true,"usgarden.museum":true,"ushistory.museum":true,"ushuaia.museum":true,"uslivinghistory.museum":true,"utah.museum":true,"uvic.museum":true,"valley.museum":true,"vantaa.museum":true,"versailles.museum":true,"viking.museum":true,"village.museum":true,"virginia.museum":true,"virtual.museum":true,"virtuel.museum":true,"vlaanderen.museum":true,"volkenkunde.museum":true,"wales.museum":true,"wallonie.museum":true,"war.museum":true,"washingtondc.museum":true,"watchandclock.museum":true,"watch-and-clock.museum":true,"western.museum":true,"westfalen.museum":true,"whaling.museum":true,"wildlife.museum":true,"williamsburg.museum":true,"windmill.museum":true,"workshop.museum":true,"york.museum":true,"yorkshire.museum":true,"yosemite.museum":true,"youth.museum":true,"zoological.museum":true,"zoology.museum":true,"xn--9dbhblg6di.museum":true,"xn--h1aegh.museum":true,"mv":true,"aero.mv":true,"biz.mv":true,"com.mv":true,"coop.mv":true,"edu.mv":true,"gov.mv":true,"info.mv":true,"int.mv":true,"mil.mv":true,"museum.mv":true,"name.mv":true,"net.mv":true,"org.mv":true,"pro.mv":true,"mw":true,"ac.mw":true,"biz.mw":true,"co.mw":true,"com.mw":true,"coop.mw":true,"edu.mw":true,"gov.mw":true,"int.mw":true,"museum.mw":true,"net.mw":true,"org.mw":true,"mx":true,"com.mx":true,"org.mx":true,"gob.mx":true,"edu.mx":true,"net.mx":true,"my":true,"com.my":true,"net.my":true,"org.my":true,"gov.my":true,"edu.my":true,"mil.my":true,"name.my":true,"*.mz":true,"na":true,"info.na":true,"pro.na":true,"name.na":true,"school.na":true,"or.na":true,"dr.na":true,"us.na":true,"mx.na":true,"ca.na":true,"in.na":true,"cc.na":true,"tv.na":true,"ws.na":true,"mobi.na":true,"co.na":true,"com.na":true,"org.na":true,"name":true,"nc":true,"asso.nc":true,"ne":true,"net":true,"nf":true,"com.nf":true,"net.nf":true,"per.nf":true,"rec.nf":true,"web.nf":true,"arts.nf":true,"firm.nf":true,"info.nf":true,"other.nf":true,"store.nf":true,"ac.ng":true,"com.ng":true,"edu.ng":true,"gov.ng":true,"net.ng":true,"org.ng":true,"*.ni":true,"nl":true,"bv.nl":true,"no":true,"fhs.no":true,"vgs.no":true,"fylkesbibl.no":true,"folkebibl.no":true,"museum.no":true,"idrett.no":true,"priv.no":true,"mil.no":true,"stat.no":true,"dep.no":true,"kommune.no":true,"herad.no":true,"aa.no":true,"ah.no":true,"bu.no":true,"fm.no":true,"hl.no":true,"hm.no":true,"jan-mayen.no":true,"mr.no":true,"nl.no":true,"nt.no":true,"of.no":true,"ol.no":true,"oslo.no":true,"rl.no":true,"sf.no":true,"st.no":true,"svalbard.no":true,"tm.no":true,"tr.no":true,"va.no":true,"vf.no":true,"gs.aa.no":true,"gs.ah.no":true,"gs.bu.no":true,"gs.fm.no":true,"gs.hl.no":true,"gs.hm.no":true,"gs.jan-mayen.no":true,"gs.mr.no":true,"gs.nl.no":true,"gs.nt.no":true,"gs.of.no":true,"gs.ol.no":true,"gs.oslo.no":true,"gs.rl.no":true,"gs.sf.no":true,"gs.st.no":true,"gs.svalbard.no":true,"gs.tm.no":true,"gs.tr.no":true,"gs.va.no":true,"gs.vf.no":true,"akrehamn.no":true,"xn--krehamn-dxa.no":true,"algard.no":true,"xn--lgrd-poac.no":true,"arna.no":true,"brumunddal.no":true,"bryne.no":true,"bronnoysund.no":true,"xn--brnnysund-m8ac.no":true,"drobak.no":true,"xn--drbak-wua.no":true,"egersund.no":true,"fetsund.no":true,"floro.no":true,"xn--flor-jra.no":true,"fredrikstad.no":true,"hokksund.no":true,"honefoss.no":true,"xn--hnefoss-q1a.no":true,"jessheim.no":true,"jorpeland.no":true,"xn--jrpeland-54a.no":true,"kirkenes.no":true,"kopervik.no":true,"krokstadelva.no":true,"langevag.no":true,"xn--langevg-jxa.no":true,"leirvik.no":true,"mjondalen.no":true,"xn--mjndalen-64a.no":true,"mo-i-rana.no":true,"mosjoen.no":true,"xn--mosjen-eya.no":true,"nesoddtangen.no":true,"orkanger.no":true,"osoyro.no":true,"xn--osyro-wua.no":true,"raholt.no":true,"xn--rholt-mra.no":true,"sandnessjoen.no":true,"xn--sandnessjen-ogb.no":true,"skedsmokorset.no":true,"slattum.no":true,"spjelkavik.no":true,"stathelle.no":true,"stavern.no":true,"stjordalshalsen.no":true,"xn--stjrdalshalsen-sqb.no":true,"tananger.no":true,"tranby.no":true,"vossevangen.no":true,"afjord.no":true,"xn--fjord-lra.no":true,"agdenes.no":true,"al.no":true,"xn--l-1fa.no":true,"alesund.no":true,"xn--lesund-hua.no":true,"alstahaug.no":true,"alta.no":true,"xn--lt-liac.no":true,"alaheadju.no":true,"xn--laheadju-7ya.no":true,"alvdal.no":true,"amli.no":true,"xn--mli-tla.no":true,"amot.no":true,"xn--mot-tla.no":true,"andebu.no":true,"andoy.no":true,"xn--andy-ira.no":true,"andasuolo.no":true,"ardal.no":true,"xn--rdal-poa.no":true,"aremark.no":true,"arendal.no":true,"xn--s-1fa.no":true,"aseral.no":true,"xn--seral-lra.no":true,"asker.no":true,"askim.no":true,"askvoll.no":true,"askoy.no":true,"xn--asky-ira.no":true,"asnes.no":true,"xn--snes-poa.no":true,"audnedaln.no":true,"aukra.no":true,"aure.no":true,"aurland.no":true,"aurskog-holand.no":true,"xn--aurskog-hland-jnb.no":true,"austevoll.no":true,"austrheim.no":true,"averoy.no":true,"xn--avery-yua.no":true,"balestrand.no":true,"ballangen.no":true,"balat.no":true,"xn--blt-elab.no":true,"balsfjord.no":true,"bahccavuotna.no":true,"xn--bhccavuotna-k7a.no":true,"bamble.no":true,"bardu.no":true,"beardu.no":true,"beiarn.no":true,"bajddar.no":true,"xn--bjddar-pta.no":true,"baidar.no":true,"xn--bidr-5nac.no":true,"berg.no":true,"bergen.no":true,"berlevag.no":true,"xn--berlevg-jxa.no":true,"bearalvahki.no":true,"xn--bearalvhki-y4a.no":true,"bindal.no":true,"birkenes.no":true,"bjarkoy.no":true,"xn--bjarky-fya.no":true,"bjerkreim.no":true,"bjugn.no":true,"bodo.no":true,"xn--bod-2na.no":true,"badaddja.no":true,"xn--bdddj-mrabd.no":true,"budejju.no":true,"bokn.no":true,"bremanger.no":true,"bronnoy.no":true,"xn--brnny-wuac.no":true,"bygland.no":true,"bykle.no":true,"barum.no":true,"xn--brum-voa.no":true,"bo.telemark.no":true,"xn--b-5ga.telemark.no":true,"bo.nordland.no":true,"xn--b-5ga.nordland.no":true,"bievat.no":true,"xn--bievt-0qa.no":true,"bomlo.no":true,"xn--bmlo-gra.no":true,"batsfjord.no":true,"xn--btsfjord-9za.no":true,"bahcavuotna.no":true,"xn--bhcavuotna-s4a.no":true,"dovre.no":true,"drammen.no":true,"drangedal.no":true,"dyroy.no":true,"xn--dyry-ira.no":true,"donna.no":true,"xn--dnna-gra.no":true,"eid.no":true,"eidfjord.no":true,"eidsberg.no":true,"eidskog.no":true,"eidsvoll.no":true,"eigersund.no":true,"elverum.no":true,"enebakk.no":true,"engerdal.no":true,"etne.no":true,"etnedal.no":true,"evenes.no":true,"evenassi.no":true,"xn--eveni-0qa01ga.no":true,"evje-og-hornnes.no":true,"farsund.no":true,"fauske.no":true,"fuossko.no":true,"fuoisku.no":true,"fedje.no":true,"fet.no":true,"finnoy.no":true,"xn--finny-yua.no":true,"fitjar.no":true,"fjaler.no":true,"fjell.no":true,"flakstad.no":true,"flatanger.no":true,"flekkefjord.no":true,"flesberg.no":true,"flora.no":true,"fla.no":true,"xn--fl-zia.no":true,"folldal.no":true,"forsand.no":true,"fosnes.no":true,"frei.no":true,"frogn.no":true,"froland.no":true,"frosta.no":true,"frana.no":true,"xn--frna-woa.no":true,"froya.no":true,"xn--frya-hra.no":true,"fusa.no":true,"fyresdal.no":true,"forde.no":true,"xn--frde-gra.no":true,"gamvik.no":true,"gangaviika.no":true,"xn--ggaviika-8ya47h.no":true,"gaular.no":true,"gausdal.no":true,"gildeskal.no":true,"xn--gildeskl-g0a.no":true,"giske.no":true,"gjemnes.no":true,"gjerdrum.no":true,"gjerstad.no":true,"gjesdal.no":true,"gjovik.no":true,"xn--gjvik-wua.no":true,"gloppen.no":true,"gol.no":true,"gran.no":true,"grane.no":true,"granvin.no":true,"gratangen.no":true,"grimstad.no":true,"grong.no":true,"kraanghke.no":true,"xn--kranghke-b0a.no":true,"grue.no":true,"gulen.no":true,"hadsel.no":true,"halden.no":true,"halsa.no":true,"hamar.no":true,"hamaroy.no":true,"habmer.no":true,"xn--hbmer-xqa.no":true,"hapmir.no":true,"xn--hpmir-xqa.no":true,"hammerfest.no":true,"hammarfeasta.no":true,"xn--hmmrfeasta-s4ac.no":true,"haram.no":true,"hareid.no":true,"harstad.no":true,"hasvik.no":true,"aknoluokta.no":true,"xn--koluokta-7ya57h.no":true,"hattfjelldal.no":true,"aarborte.no":true,"haugesund.no":true,"hemne.no":true,"hemnes.no":true,"hemsedal.no":true,"heroy.more-og-romsdal.no":true,"xn--hery-ira.xn--mre-og-romsdal-qqb.no":true,"heroy.nordland.no":true,"xn--hery-ira.nordland.no":true,"hitra.no":true,"hjartdal.no":true,"hjelmeland.no":true,"hobol.no":true,"xn--hobl-ira.no":true,"hof.no":true,"hol.no":true,"hole.no":true,"holmestrand.no":true,"holtalen.no":true,"xn--holtlen-hxa.no":true,"hornindal.no":true,"horten.no":true,"hurdal.no":true,"hurum.no":true,"hvaler.no":true,"hyllestad.no":true,"hagebostad.no":true,"xn--hgebostad-g3a.no":true,"hoyanger.no":true,"xn--hyanger-q1a.no":true,"hoylandet.no":true,"xn--hylandet-54a.no":true,"ha.no":true,"xn--h-2fa.no":true,"ibestad.no":true,"inderoy.no":true,"xn--indery-fya.no":true,"iveland.no":true,"jevnaker.no":true,"jondal.no":true,"jolster.no":true,"xn--jlster-bya.no":true,"karasjok.no":true,"karasjohka.no":true,"xn--krjohka-hwab49j.no":true,"karlsoy.no":true,"galsa.no":true,"xn--gls-elac.no":true,"karmoy.no":true,"xn--karmy-yua.no":true,"kautokeino.no":true,"guovdageaidnu.no":true,"klepp.no":true,"klabu.no":true,"xn--klbu-woa.no":true,"kongsberg.no":true,"kongsvinger.no":true,"kragero.no":true,"xn--krager-gya.no":true,"kristiansand.no":true,"kristiansund.no":true,"krodsherad.no":true,"xn--krdsherad-m8a.no":true,"kvalsund.no":true,"rahkkeravju.no":true,"xn--rhkkervju-01af.no":true,"kvam.no":true,"kvinesdal.no":true,"kvinnherad.no":true,"kviteseid.no":true,"kvitsoy.no":true,"xn--kvitsy-fya.no":true,"kvafjord.no":true,"xn--kvfjord-nxa.no":true,"giehtavuoatna.no":true,"kvanangen.no":true,"xn--kvnangen-k0a.no":true,"navuotna.no":true,"xn--nvuotna-hwa.no":true,"kafjord.no":true,"xn--kfjord-iua.no":true,"gaivuotna.no":true,"xn--givuotna-8ya.no":true,"larvik.no":true,"lavangen.no":true,"lavagis.no":true,"loabat.no":true,"xn--loabt-0qa.no":true,"lebesby.no":true,"davvesiida.no":true,"leikanger.no":true,"leirfjord.no":true,"leka.no":true,"leksvik.no":true,"lenvik.no":true,"leangaviika.no":true,"xn--leagaviika-52b.no":true,"lesja.no":true,"levanger.no":true,"lier.no":true,"lierne.no":true,"lillehammer.no":true,"lillesand.no":true,"lindesnes.no":true,"lindas.no":true,"xn--linds-pra.no":true,"lom.no":true,"loppa.no":true,"lahppi.no":true,"xn--lhppi-xqa.no":true,"lund.no":true,"lunner.no":true,"luroy.no":true,"xn--lury-ira.no":true,"luster.no":true,"lyngdal.no":true,"lyngen.no":true,"ivgu.no":true,"lardal.no":true,"lerdal.no":true,"xn--lrdal-sra.no":true,"lodingen.no":true,"xn--ldingen-q1a.no":true,"lorenskog.no":true,"xn--lrenskog-54a.no":true,"loten.no":true,"xn--lten-gra.no":true,"malvik.no":true,"masoy.no":true,"xn--msy-ula0h.no":true,"muosat.no":true,"xn--muost-0qa.no":true,"mandal.no":true,"marker.no":true,"marnardal.no":true,"masfjorden.no":true,"meland.no":true,"meldal.no":true,"melhus.no":true,"meloy.no":true,"xn--mely-ira.no":true,"meraker.no":true,"xn--merker-kua.no":true,"moareke.no":true,"xn--moreke-jua.no":true,"midsund.no":true,"midtre-gauldal.no":true,"modalen.no":true,"modum.no":true,"molde.no":true,"moskenes.no":true,"moss.no":true,"mosvik.no":true,"malselv.no":true,"xn--mlselv-iua.no":true,"malatvuopmi.no":true,"xn--mlatvuopmi-s4a.no":true,"namdalseid.no":true,"aejrie.no":true,"namsos.no":true,"namsskogan.no":true,"naamesjevuemie.no":true,"xn--nmesjevuemie-tcba.no":true,"laakesvuemie.no":true,"nannestad.no":true,"narvik.no":true,"narviika.no":true,"naustdal.no":true,"nedre-eiker.no":true,"nes.akershus.no":true,"nes.buskerud.no":true,"nesna.no":true,"nesodden.no":true,"nesseby.no":true,"unjarga.no":true,"xn--unjrga-rta.no":true,"nesset.no":true,"nissedal.no":true,"nittedal.no":true,"nord-aurdal.no":true,"nord-fron.no":true,"nord-odal.no":true,"norddal.no":true,"nordkapp.no":true,"davvenjarga.no":true,"xn--davvenjrga-y4a.no":true,"nordre-land.no":true,"nordreisa.no":true,"raisa.no":true,"xn--risa-5na.no":true,"nore-og-uvdal.no":true,"notodden.no":true,"naroy.no":true,"xn--nry-yla5g.no":true,"notteroy.no":true,"xn--nttery-byae.no":true,"odda.no":true,"oksnes.no":true,"xn--ksnes-uua.no":true,"oppdal.no":true,"oppegard.no":true,"xn--oppegrd-ixa.no":true,"orkdal.no":true,"orland.no":true,"xn--rland-uua.no":true,"orskog.no":true,"xn--rskog-uua.no":true,"orsta.no":true,"xn--rsta-fra.no":true,"os.hedmark.no":true,"os.hordaland.no":true,"osen.no":true,"osteroy.no":true,"xn--ostery-fya.no":true,"ostre-toten.no":true,"xn--stre-toten-zcb.no":true,"overhalla.no":true,"ovre-eiker.no":true,"xn--vre-eiker-k8a.no":true,"oyer.no":true,"xn--yer-zna.no":true,"oygarden.no":true,"xn--ygarden-p1a.no":true,"oystre-slidre.no":true,"xn--ystre-slidre-ujb.no":true,"porsanger.no":true,"porsangu.no":true,"xn--porsgu-sta26f.no":true,"porsgrunn.no":true,"radoy.no":true,"xn--rady-ira.no":true,"rakkestad.no":true,"rana.no":true,"ruovat.no":true,"randaberg.no":true,"rauma.no":true,"rendalen.no":true,"rennebu.no":true,"rennesoy.no":true,"xn--rennesy-v1a.no":true,"rindal.no":true,"ringebu.no":true,"ringerike.no":true,"ringsaker.no":true,"rissa.no":true,"risor.no":true,"xn--risr-ira.no":true,"roan.no":true,"rollag.no":true,"rygge.no":true,"ralingen.no":true,"xn--rlingen-mxa.no":true,"rodoy.no":true,"xn--rdy-0nab.no":true,"romskog.no":true,"xn--rmskog-bya.no":true,"roros.no":true,"xn--rros-gra.no":true,"rost.no":true,"xn--rst-0na.no":true,"royken.no":true,"xn--ryken-vua.no":true,"royrvik.no":true,"xn--ryrvik-bya.no":true,"rade.no":true,"xn--rde-ula.no":true,"salangen.no":true,"siellak.no":true,"saltdal.no":true,"salat.no":true,"xn--slt-elab.no":true,"xn--slat-5na.no":true,"samnanger.no":true,"sande.more-og-romsdal.no":true,"sande.xn--mre-og-romsdal-qqb.no":true,"sande.vestfold.no":true,"sandefjord.no":true,"sandnes.no":true,"sandoy.no":true,"xn--sandy-yua.no":true,"sarpsborg.no":true,"sauda.no":true,"sauherad.no":true,"sel.no":true,"selbu.no":true,"selje.no":true,"seljord.no":true,"sigdal.no":true,"siljan.no":true,"sirdal.no":true,"skaun.no":true,"skedsmo.no":true,"ski.no":true,"skien.no":true,"skiptvet.no":true,"skjervoy.no":true,"xn--skjervy-v1a.no":true,"skierva.no":true,"xn--skierv-uta.no":true,"skjak.no":true,"xn--skjk-soa.no":true,"skodje.no":true,"skanland.no":true,"xn--sknland-fxa.no":true,"skanit.no":true,"xn--sknit-yqa.no":true,"smola.no":true,"xn--smla-hra.no":true,"snillfjord.no":true,"snasa.no":true,"xn--snsa-roa.no":true,"snoasa.no":true,"snaase.no":true,"xn--snase-nra.no":true,"sogndal.no":true,"sokndal.no":true,"sola.no":true,"solund.no":true,"songdalen.no":true,"sortland.no":true,"spydeberg.no":true,"stange.no":true,"stavanger.no":true,"steigen.no":true,"steinkjer.no":true,"stjordal.no":true,"xn--stjrdal-s1a.no":true,"stokke.no":true,"stor-elvdal.no":true,"stord.no":true,"stordal.no":true,"storfjord.no":true,"omasvuotna.no":true,"strand.no":true,"stranda.no":true,"stryn.no":true,"sula.no":true,"suldal.no":true,"sund.no":true,"sunndal.no":true,"surnadal.no":true,"sveio.no":true,"svelvik.no":true,"sykkylven.no":true,"sogne.no":true,"xn--sgne-gra.no":true,"somna.no":true,"xn--smna-gra.no":true,"sondre-land.no":true,"xn--sndre-land-0cb.no":true,"sor-aurdal.no":true,"xn--sr-aurdal-l8a.no":true,"sor-fron.no":true,"xn--sr-fron-q1a.no":true,"sor-odal.no":true,"xn--sr-odal-q1a.no":true,"sor-varanger.no":true,"xn--sr-varanger-ggb.no":true,"matta-varjjat.no":true,"xn--mtta-vrjjat-k7af.no":true,"sorfold.no":true,"xn--srfold-bya.no":true,"sorreisa.no":true,"xn--srreisa-q1a.no":true,"sorum.no":true,"xn--srum-gra.no":true,"tana.no":true,"deatnu.no":true,"time.no":true,"tingvoll.no":true,"tinn.no":true,"tjeldsund.no":true,"dielddanuorri.no":true,"tjome.no":true,"xn--tjme-hra.no":true,"tokke.no":true,"tolga.no":true,"torsken.no":true,"tranoy.no":true,"xn--trany-yua.no":true,"tromso.no":true,"xn--troms-zua.no":true,"tromsa.no":true,"romsa.no":true,"trondheim.no":true,"troandin.no":true,"trysil.no":true,"trana.no":true,"xn--trna-woa.no":true,"trogstad.no":true,"xn--trgstad-r1a.no":true,"tvedestrand.no":true,"tydal.no":true,"tynset.no":true,"tysfjord.no":true,"divtasvuodna.no":true,"divttasvuotna.no":true,"tysnes.no":true,"tysvar.no":true,"xn--tysvr-vra.no":true,"tonsberg.no":true,"xn--tnsberg-q1a.no":true,"ullensaker.no":true,"ullensvang.no":true,"ulvik.no":true,"utsira.no":true,"vadso.no":true,"xn--vads-jra.no":true,"cahcesuolo.no":true,"xn--hcesuolo-7ya35b.no":true,"vaksdal.no":true,"valle.no":true,"vang.no":true,"vanylven.no":true,"vardo.no":true,"xn--vard-jra.no":true,"varggat.no":true,"xn--vrggt-xqad.no":true,"vefsn.no":true,"vaapste.no":true,"vega.no":true,"vegarshei.no":true,"xn--vegrshei-c0a.no":true,"vennesla.no":true,"verdal.no":true,"verran.no":true,"vestby.no":true,"vestnes.no":true,"vestre-slidre.no":true,"vestre-toten.no":true,"vestvagoy.no":true,"xn--vestvgy-ixa6o.no":true,"vevelstad.no":true,"vik.no":true,"vikna.no":true,"vindafjord.no":true,"volda.no":true,"voss.no":true,"varoy.no":true,"xn--vry-yla5g.no":true,"vagan.no":true,"xn--vgan-qoa.no":true,"voagat.no":true,"vagsoy.no":true,"xn--vgsy-qoa0j.no":true,"vaga.no":true,"xn--vg-yiab.no":true,"valer.ostfold.no":true,"xn--vler-qoa.xn--stfold-9xa.no":true,"valer.hedmark.no":true,"xn--vler-qoa.hedmark.no":true,"*.np":true,"nr":true,"biz.nr":true,"info.nr":true,"gov.nr":true,"edu.nr":true,"org.nr":true,"net.nr":true,"com.nr":true,"nu":true,"*.nz":true,"*.om":true,"mediaphone.om":false,"nawrastelecom.om":false,"nawras.om":false,"omanmobile.om":false,"omanpost.om":false,"omantel.om":false,"rakpetroleum.om":false,"siemens.om":false,"songfest.om":false,"statecouncil.om":false,"org":true,"pa":true,"ac.pa":true,"gob.pa":true,"com.pa":true,"org.pa":true,"sld.pa":true,"edu.pa":true,"net.pa":true,"ing.pa":true,"abo.pa":true,"med.pa":true,"nom.pa":true,"pe":true,"edu.pe":true,"gob.pe":true,"nom.pe":true,"mil.pe":true,"org.pe":true,"com.pe":true,"net.pe":true,"pf":true,"com.pf":true,"org.pf":true,"edu.pf":true,"*.pg":true,"ph":true,"com.ph":true,"net.ph":true,"org.ph":true,"gov.ph":true,"edu.ph":true,"ngo.ph":true,"mil.ph":true,"i.ph":true,"pk":true,"com.pk":true,"net.pk":true,"edu.pk":true,"org.pk":true,"fam.pk":true,"biz.pk":true,"web.pk":true,"gov.pk":true,"gob.pk":true,"gok.pk":true,"gon.pk":true,"gop.pk":true,"gos.pk":true,"info.pk":true,"pl":true,"aid.pl":true,"agro.pl":true,"atm.pl":true,"auto.pl":true,"biz.pl":true,"com.pl":true,"edu.pl":true,"gmina.pl":true,"gsm.pl":true,"info.pl":true,"mail.pl":true,"miasta.pl":true,"media.pl":true,"mil.pl":true,"net.pl":true,"nieruchomosci.pl":true,"nom.pl":true,"org.pl":true,"pc.pl":true,"powiat.pl":true,"priv.pl":true,"realestate.pl":true,"rel.pl":true,"sex.pl":true,"shop.pl":true,"sklep.pl":true,"sos.pl":true,"szkola.pl":true,"targi.pl":true,"tm.pl":true,"tourism.pl":true,"travel.pl":true,"turystyka.pl":true,"6bone.pl":true,"art.pl":true,"mbone.pl":true,"gov.pl":true,"uw.gov.pl":true,"um.gov.pl":true,"ug.gov.pl":true,"upow.gov.pl":true,"starostwo.gov.pl":true,"so.gov.pl":true,"sr.gov.pl":true,"po.gov.pl":true,"pa.gov.pl":true,"ngo.pl":true,"irc.pl":true,"usenet.pl":true,"augustow.pl":true,"babia-gora.pl":true,"bedzin.pl":true,"beskidy.pl":true,"bialowieza.pl":true,"bialystok.pl":true,"bielawa.pl":true,"bieszczady.pl":true,"boleslawiec.pl":true,"bydgoszcz.pl":true,"bytom.pl":true,"cieszyn.pl":true,"czeladz.pl":true,"czest.pl":true,"dlugoleka.pl":true,"elblag.pl":true,"elk.pl":true,"glogow.pl":true,"gniezno.pl":true,"gorlice.pl":true,"grajewo.pl":true,"ilawa.pl":true,"jaworzno.pl":true,"jelenia-gora.pl":true,"jgora.pl":true,"kalisz.pl":true,"kazimierz-dolny.pl":true,"karpacz.pl":true,"kartuzy.pl":true,"kaszuby.pl":true,"katowice.pl":true,"kepno.pl":true,"ketrzyn.pl":true,"klodzko.pl":true,"kobierzyce.pl":true,"kolobrzeg.pl":true,"konin.pl":true,"konskowola.pl":true,"kutno.pl":true,"lapy.pl":true,"lebork.pl":true,"legnica.pl":true,"lezajsk.pl":true,"limanowa.pl":true,"lomza.pl":true,"lowicz.pl":true,"lubin.pl":true,"lukow.pl":true,"malbork.pl":true,"malopolska.pl":true,"mazowsze.pl":true,"mazury.pl":true,"mielec.pl":true,"mielno.pl":true,"mragowo.pl":true,"naklo.pl":true,"nowaruda.pl":true,"nysa.pl":true,"olawa.pl":true,"olecko.pl":true,"olkusz.pl":true,"olsztyn.pl":true,"opoczno.pl":true,"opole.pl":true,"ostroda.pl":true,"ostroleka.pl":true,"ostrowiec.pl":true,"ostrowwlkp.pl":true,"pila.pl":true,"pisz.pl":true,"podhale.pl":true,"podlasie.pl":true,"polkowice.pl":true,"pomorze.pl":true,"pomorskie.pl":true,"prochowice.pl":true,"pruszkow.pl":true,"przeworsk.pl":true,"pulawy.pl":true,"radom.pl":true,"rawa-maz.pl":true,"rybnik.pl":true,"rzeszow.pl":true,"sanok.pl":true,"sejny.pl":true,"siedlce.pl":true,"slask.pl":true,"slupsk.pl":true,"sosnowiec.pl":true,"stalowa-wola.pl":true,"skoczow.pl":true,"starachowice.pl":true,"stargard.pl":true,"suwalki.pl":true,"swidnica.pl":true,"swiebodzin.pl":true,"swinoujscie.pl":true,"szczecin.pl":true,"szczytno.pl":true,"tarnobrzeg.pl":true,"tgory.pl":true,"turek.pl":true,"tychy.pl":true,"ustka.pl":true,"walbrzych.pl":true,"warmia.pl":true,"warszawa.pl":true,"waw.pl":true,"wegrow.pl":true,"wielun.pl":true,"wlocl.pl":true,"wloclawek.pl":true,"wodzislaw.pl":true,"wolomin.pl":true,"wroclaw.pl":true,"zachpomor.pl":true,"zagan.pl":true,"zarow.pl":true,"zgora.pl":true,"zgorzelec.pl":true,"gda.pl":true,"gdansk.pl":true,"gdynia.pl":true,"med.pl":true,"sopot.pl":true,"gliwice.pl":true,"krakow.pl":true,"poznan.pl":true,"wroc.pl":true,"zakopane.pl":true,"pm":true,"pn":true,"gov.pn":true,"co.pn":true,"org.pn":true,"edu.pn":true,"net.pn":true,"pr":true,"com.pr":true,"net.pr":true,"org.pr":true,"gov.pr":true,"edu.pr":true,"isla.pr":true,"pro.pr":true,"biz.pr":true,"info.pr":true,"name.pr":true,"est.pr":true,"prof.pr":true,"ac.pr":true,"pro":true,"aca.pro":true,"bar.pro":true,"cpa.pro":true,"jur.pro":true,"law.pro":true,"med.pro":true,"eng.pro":true,"ps":true,"edu.ps":true,"gov.ps":true,"sec.ps":true,"plo.ps":true,"com.ps":true,"org.ps":true,"net.ps":true,"pt":true,"net.pt":true,"gov.pt":true,"org.pt":true,"edu.pt":true,"int.pt":true,"publ.pt":true,"com.pt":true,"nome.pt":true,"pw":true,"co.pw":true,"ne.pw":true,"or.pw":true,"ed.pw":true,"go.pw":true,"belau.pw":true,"*.py":true,"qa":true,"com.qa":true,"edu.qa":true,"gov.qa":true,"mil.qa":true,"name.qa":true,"net.qa":true,"org.qa":true,"sch.qa":true,"re":true,"com.re":true,"asso.re":true,"nom.re":true,"ro":true,"com.ro":true,"org.ro":true,"tm.ro":true,"nt.ro":true,"nom.ro":true,"info.ro":true,"rec.ro":true,"arts.ro":true,"firm.ro":true,"store.ro":true,"www.ro":true,"rs":true,"co.rs":true,"org.rs":true,"edu.rs":true,"ac.rs":true,"gov.rs":true,"in.rs":true,"ru":true,"ac.ru":true,"com.ru":true,"edu.ru":true,"int.ru":true,"net.ru":true,"org.ru":true,"pp.ru":true,"adygeya.ru":true,"altai.ru":true,"amur.ru":true,"arkhangelsk.ru":true,"astrakhan.ru":true,"bashkiria.ru":true,"belgorod.ru":true,"bir.ru":true,"bryansk.ru":true,"buryatia.ru":true,"cbg.ru":true,"chel.ru":true,"chelyabinsk.ru":true,"chita.ru":true,"chukotka.ru":true,"chuvashia.ru":true,"dagestan.ru":true,"dudinka.ru":true,"e-burg.ru":true,"grozny.ru":true,"irkutsk.ru":true,"ivanovo.ru":true,"izhevsk.ru":true,"jar.ru":true,"joshkar-ola.ru":true,"kalmykia.ru":true,"kaluga.ru":true,"kamchatka.ru":true,"karelia.ru":true,"kazan.ru":true,"kchr.ru":true,"kemerovo.ru":true,"khabarovsk.ru":true,"khakassia.ru":true,"khv.ru":true,"kirov.ru":true,"koenig.ru":true,"komi.ru":true,"kostroma.ru":true,"krasnoyarsk.ru":true,"kuban.ru":true,"kurgan.ru":true,"kursk.ru":true,"lipetsk.ru":true,"magadan.ru":true,"mari.ru":true,"mari-el.ru":true,"marine.ru":true,"mordovia.ru":true,"mosreg.ru":true,"msk.ru":true,"murmansk.ru":true,"nalchik.ru":true,"nnov.ru":true,"nov.ru":true,"novosibirsk.ru":true,"nsk.ru":true,"omsk.ru":true,"orenburg.ru":true,"oryol.ru":true,"palana.ru":true,"penza.ru":true,"perm.ru":true,"pskov.ru":true,"ptz.ru":true,"rnd.ru":true,"ryazan.ru":true,"sakhalin.ru":true,"samara.ru":true,"saratov.ru":true,"simbirsk.ru":true,"smolensk.ru":true,"spb.ru":true,"stavropol.ru":true,"stv.ru":true,"surgut.ru":true,"tambov.ru":true,"tatarstan.ru":true,"tom.ru":true,"tomsk.ru":true,"tsaritsyn.ru":true,"tsk.ru":true,"tula.ru":true,"tuva.ru":true,"tver.ru":true,"tyumen.ru":true,"udm.ru":true,"udmurtia.ru":true,"ulan-ude.ru":true,"vladikavkaz.ru":true,"vladimir.ru":true,"vladivostok.ru":true,"volgograd.ru":true,"vologda.ru":true,"voronezh.ru":true,"vrn.ru":true,"vyatka.ru":true,"yakutia.ru":true,"yamal.ru":true,"yaroslavl.ru":true,"yekaterinburg.ru":true,"yuzhno-sakhalinsk.ru":true,"amursk.ru":true,"baikal.ru":true,"cmw.ru":true,"fareast.ru":true,"jamal.ru":true,"kms.ru":true,"k-uralsk.ru":true,"kustanai.ru":true,"kuzbass.ru":true,"magnitka.ru":true,"mytis.ru":true,"nakhodka.ru":true,"nkz.ru":true,"norilsk.ru":true,"oskol.ru":true,"pyatigorsk.ru":true,"rubtsovsk.ru":true,"snz.ru":true,"syzran.ru":true,"vdonsk.ru":true,"zgrad.ru":true,"gov.ru":true,"mil.ru":true,"test.ru":true,"rw":true,"gov.rw":true,"net.rw":true,"edu.rw":true,"ac.rw":true,"com.rw":true,"co.rw":true,"int.rw":true,"mil.rw":true,"gouv.rw":true,"sa":true,"com.sa":true,"net.sa":true,"org.sa":true,"gov.sa":true,"med.sa":true,"pub.sa":true,"edu.sa":true,"sch.sa":true,"sb":true,"com.sb":true,"edu.sb":true,"gov.sb":true,"net.sb":true,"org.sb":true,"sc":true,"com.sc":true,"gov.sc":true,"net.sc":true,"org.sc":true,"edu.sc":true,"sd":true,"com.sd":true,"net.sd":true,"org.sd":true,"edu.sd":true,"med.sd":true,"gov.sd":true,"info.sd":true,"se":true,"a.se":true,"ac.se":true,"b.se":true,"bd.se":true,"brand.se":true,"c.se":true,"d.se":true,"e.se":true,"f.se":true,"fh.se":true,"fhsk.se":true,"fhv.se":true,"g.se":true,"h.se":true,"i.se":true,"k.se":true,"komforb.se":true,"kommunalforbund.se":true,"komvux.se":true,"l.se":true,"lanbib.se":true,"m.se":true,"n.se":true,"naturbruksgymn.se":true,"o.se":true,"org.se":true,"p.se":true,"parti.se":true,"pp.se":true,"press.se":true,"r.se":true,"s.se":true,"sshn.se":true,"t.se":true,"tm.se":true,"u.se":true,"w.se":true,"x.se":true,"y.se":true,"z.se":true,"sg":true,"com.sg":true,"net.sg":true,"org.sg":true,"gov.sg":true,"edu.sg":true,"per.sg":true,"sh":true,"si":true,"sk":true,"sl":true,"com.sl":true,"net.sl":true,"edu.sl":true,"gov.sl":true,"org.sl":true,"sm":true,"sn":true,"art.sn":true,"com.sn":true,"edu.sn":true,"gouv.sn":true,"org.sn":true,"perso.sn":true,"univ.sn":true,"so":true,"com.so":true,"net.so":true,"org.so":true,"sr":true,"st":true,"co.st":true,"com.st":true,"consulado.st":true,"edu.st":true,"embaixada.st":true,"gov.st":true,"mil.st":true,"net.st":true,"org.st":true,"principe.st":true,"saotome.st":true,"store.st":true,"su":true,"*.sv":true,"sy":true,"edu.sy":true,"gov.sy":true,"net.sy":true,"mil.sy":true,"com.sy":true,"org.sy":true,"sz":true,"co.sz":true,"ac.sz":true,"org.sz":true,"tc":true,"td":true,"tel":true,"tf":true,"tg":true,"th":true,"ac.th":true,"co.th":true,"go.th":true,"in.th":true,"mi.th":true,"net.th":true,"or.th":true,"tj":true,"ac.tj":true,"biz.tj":true,"co.tj":true,"com.tj":true,"edu.tj":true,"go.tj":true,"gov.tj":true,"int.tj":true,"mil.tj":true,"name.tj":true,"net.tj":true,"nic.tj":true,"org.tj":true,"test.tj":true,"web.tj":true,"tk":true,"tl":true,"gov.tl":true,"tm":true,"tn":true,"com.tn":true,"ens.tn":true,"fin.tn":true,"gov.tn":true,"ind.tn":true,"intl.tn":true,"nat.tn":true,"net.tn":true,"org.tn":true,"info.tn":true,"perso.tn":true,"tourism.tn":true,"edunet.tn":true,"rnrt.tn":true,"rns.tn":true,"rnu.tn":true,"mincom.tn":true,"agrinet.tn":true,"defense.tn":true,"turen.tn":true,"to":true,"com.to":true,"gov.to":true,"net.to":true,"org.to":true,"edu.to":true,"mil.to":true,"*.tr":true,"nic.tr":false,"gov.nc.tr":true,"travel":true,"tt":true,"co.tt":true,"com.tt":true,"org.tt":true,"net.tt":true,"biz.tt":true,"info.tt":true,"pro.tt":true,"int.tt":true,"coop.tt":true,"jobs.tt":true,"mobi.tt":true,"travel.tt":true,"museum.tt":true,"aero.tt":true,"name.tt":true,"gov.tt":true,"edu.tt":true,"tv":true,"tw":true,"edu.tw":true,"gov.tw":true,"mil.tw":true,"com.tw":true,"net.tw":true,"org.tw":true,"idv.tw":true,"game.tw":true,"ebiz.tw":true,"club.tw":true,"xn--zf0ao64a.tw":true,"xn--uc0atv.tw":true,"xn--czrw28b.tw":true,"ac.tz":true,"co.tz":true,"go.tz":true,"mil.tz":true,"ne.tz":true,"or.tz":true,"sc.tz":true,"ua":true,"com.ua":true,"edu.ua":true,"gov.ua":true,"in.ua":true,"net.ua":true,"org.ua":true,"cherkassy.ua":true,"chernigov.ua":true,"chernovtsy.ua":true,"ck.ua":true,"cn.ua":true,"crimea.ua":true,"cv.ua":true,"dn.ua":true,"dnepropetrovsk.ua":true,"donetsk.ua":true,"dp.ua":true,"if.ua":true,"ivano-frankivsk.ua":true,"kh.ua":true,"kharkov.ua":true,"kherson.ua":true,"khmelnitskiy.ua":true,"kiev.ua":true,"kirovograd.ua":true,"km.ua":true,"kr.ua":true,"ks.ua":true,"kv.ua":true,"lg.ua":true,"lugansk.ua":true,"lutsk.ua":true,"lviv.ua":true,"mk.ua":true,"nikolaev.ua":true,"od.ua":true,"odessa.ua":true,"pl.ua":true,"poltava.ua":true,"rovno.ua":true,"rv.ua":true,"sebastopol.ua":true,"sumy.ua":true,"te.ua":true,"ternopil.ua":true,"uzhgorod.ua":true,"vinnica.ua":true,"vn.ua":true,"zaporizhzhe.ua":true,"zp.ua":true,"zhitomir.ua":true,"zt.ua":true,"co.ua":true,"pp.ua":true,"ug":true,"co.ug":true,"ac.ug":true,"sc.ug":true,"go.ug":true,"ne.ug":true,"or.ug":true,"*.uk":true,"*.sch.uk":true,"bl.uk":false,"british-library.uk":false,"icnet.uk":false,"jet.uk":false,"mod.uk":false,"nel.uk":false,"nhs.uk":false,"nic.uk":false,"nls.uk":false,"national-library-scotland.uk":false,"parliament.uk":false,"police.uk":false,"us":true,"dni.us":true,"fed.us":true,"isa.us":true,"kids.us":true,"nsn.us":true,"ak.us":true,"al.us":true,"ar.us":true,"as.us":true,"az.us":true,"ca.us":true,"co.us":true,"ct.us":true,"dc.us":true,"de.us":true,"fl.us":true,"ga.us":true,"gu.us":true,"hi.us":true,"ia.us":true,"id.us":true,"il.us":true,"in.us":true,"ks.us":true,"ky.us":true,"la.us":true,"ma.us":true,"md.us":true,"me.us":true,"mi.us":true,"mn.us":true,"mo.us":true,"ms.us":true,"mt.us":true,"nc.us":true,"nd.us":true,"ne.us":true,"nh.us":true,"nj.us":true,"nm.us":true,"nv.us":true,"ny.us":true,"oh.us":true,"ok.us":true,"or.us":true,"pa.us":true,"pr.us":true,"ri.us":true,"sc.us":true,"sd.us":true,"tn.us":true,"tx.us":true,"ut.us":true,"vi.us":true,"vt.us":true,"va.us":true,"wa.us":true,"wi.us":true,"wv.us":true,"wy.us":true,"k12.ak.us":true,"k12.al.us":true,"k12.ar.us":true,"k12.as.us":true,"k12.az.us":true,"k12.ca.us":true,"k12.co.us":true,"k12.ct.us":true,"k12.dc.us":true,"k12.de.us":true,"k12.fl.us":true,"k12.ga.us":true,"k12.gu.us":true,"k12.ia.us":true,"k12.id.us":true,"k12.il.us":true,"k12.in.us":true,"k12.ks.us":true,"k12.ky.us":true,"k12.la.us":true,"k12.ma.us":true,"k12.md.us":true,"k12.me.us":true,"k12.mi.us":true,"k12.mn.us":true,"k12.mo.us":true,"k12.ms.us":true,"k12.mt.us":true,"k12.nc.us":true,"k12.nd.us":true,"k12.ne.us":true,"k12.nh.us":true,"k12.nj.us":true,"k12.nm.us":true,"k12.nv.us":true,"k12.ny.us":true,"k12.oh.us":true,"k12.ok.us":true,"k12.or.us":true,"k12.pa.us":true,"k12.pr.us":true,"k12.ri.us":true,"k12.sc.us":true,"k12.sd.us":true,"k12.tn.us":true,"k12.tx.us":true,"k12.ut.us":true,"k12.vi.us":true,"k12.vt.us":true,"k12.va.us":true,"k12.wa.us":true,"k12.wi.us":true,"k12.wv.us":true,"k12.wy.us":true,"cc.ak.us":true,"cc.al.us":true,"cc.ar.us":true,"cc.as.us":true,"cc.az.us":true,"cc.ca.us":true,"cc.co.us":true,"cc.ct.us":true,"cc.dc.us":true,"cc.de.us":true,"cc.fl.us":true,"cc.ga.us":true,"cc.gu.us":true,"cc.hi.us":true,"cc.ia.us":true,"cc.id.us":true,"cc.il.us":true,"cc.in.us":true,"cc.ks.us":true,"cc.ky.us":true,"cc.la.us":true,"cc.ma.us":true,"cc.md.us":true,"cc.me.us":true,"cc.mi.us":true,"cc.mn.us":true,"cc.mo.us":true,"cc.ms.us":true,"cc.mt.us":true,"cc.nc.us":true,"cc.nd.us":true,"cc.ne.us":true,"cc.nh.us":true,"cc.nj.us":true,"cc.nm.us":true,"cc.nv.us":true,"cc.ny.us":true,"cc.oh.us":true,"cc.ok.us":true,"cc.or.us":true,"cc.pa.us":true,"cc.pr.us":true,"cc.ri.us":true,"cc.sc.us":true,"cc.sd.us":true,"cc.tn.us":true,"cc.tx.us":true,"cc.ut.us":true,"cc.vi.us":true,"cc.vt.us":true,"cc.va.us":true,"cc.wa.us":true,"cc.wi.us":true,"cc.wv.us":true,"cc.wy.us":true,"lib.ak.us":true,"lib.al.us":true,"lib.ar.us":true,"lib.as.us":true,"lib.az.us":true,"lib.ca.us":true,"lib.co.us":true,"lib.ct.us":true,"lib.dc.us":true,"lib.de.us":true,"lib.fl.us":true,"lib.ga.us":true,"lib.gu.us":true,"lib.hi.us":true,"lib.ia.us":true,"lib.id.us":true,"lib.il.us":true,"lib.in.us":true,"lib.ks.us":true,"lib.ky.us":true,"lib.la.us":true,"lib.ma.us":true,"lib.md.us":true,"lib.me.us":true,"lib.mi.us":true,"lib.mn.us":true,"lib.mo.us":true,"lib.ms.us":true,"lib.mt.us":true,"lib.nc.us":true,"lib.nd.us":true,"lib.ne.us":true,"lib.nh.us":true,"lib.nj.us":true,"lib.nm.us":true,"lib.nv.us":true,"lib.ny.us":true,"lib.oh.us":true,"lib.ok.us":true,"lib.or.us":true,"lib.pa.us":true,"lib.pr.us":true,"lib.ri.us":true,"lib.sc.us":true,"lib.sd.us":true,"lib.tn.us":true,"lib.tx.us":true,"lib.ut.us":true,"lib.vi.us":true,"lib.vt.us":true,"lib.va.us":true,"lib.wa.us":true,"lib.wi.us":true,"lib.wv.us":true,"lib.wy.us":true,"pvt.k12.ma.us":true,"chtr.k12.ma.us":true,"paroch.k12.ma.us":true,"*.uy":true,"uz":true,"com.uz":true,"co.uz":true,"va":true,"vc":true,"com.vc":true,"net.vc":true,"org.vc":true,"gov.vc":true,"mil.vc":true,"edu.vc":true,"*.ve":true,"vg":true,"vi":true,"co.vi":true,"com.vi":true,"k12.vi":true,"net.vi":true,"org.vi":true,"vn":true,"com.vn":true,"net.vn":true,"org.vn":true,"edu.vn":true,"gov.vn":true,"int.vn":true,"ac.vn":true,"biz.vn":true,"info.vn":true,"name.vn":true,"pro.vn":true,"health.vn":true,"vu":true,"wf":true,"ws":true,"com.ws":true,"net.ws":true,"org.ws":true,"gov.ws":true,"edu.ws":true,"yt":true,"xn--mgbaam7a8h":true,"xn--54b7fta0cc":true,"xn--fiqs8s":true,"xn--fiqz9s":true,"xn--lgbbat1ad8j":true,"xn--wgbh1c":true,"xn--node":true,"xn--j6w193g":true,"xn--h2brj9c":true,"xn--mgbbh1a71e":true,"xn--fpcrj9c3d":true,"xn--gecrj9c":true,"xn--s9brj9c":true,"xn--45brj9c":true,"xn--xkc2dl3a5ee0h":true,"xn--mgba3a4f16a":true,"xn--mgba3a4fra":true,"xn--mgbayh7gpa":true,"xn--3e0b707e":true,"xn--fzc2c9e2c":true,"xn--xkc2al3hye2a":true,"xn--mgbc0a9azcg":true,"xn--mgb9awbf":true,"xn--ygbi2ammx":true,"xn--90a3ac":true,"xn--p1ai":true,"xn--wgbl6a":true,"xn--mgberp4a5d4ar":true,"xn--mgberp4a5d4a87g":true,"xn--mgbqly7c0a67fbc":true,"xn--mgbqly7cvafr":true,"xn--ogbpf8fl":true,"xn--mgbtf8fl":true,"xn--yfro4i67o":true,"xn--clchc0ea0b2g2a9gcd":true,"xn--o3cw4h":true,"xn--pgbs0dh":true,"xn--kpry57d":true,"xn--kprw13d":true,"xn--nnx388a":true,"xn--j1amh":true,"xn--mgb2ddes":true,"xxx":true,"*.ye":true,"*.za":true,"*.zm":true,"*.zw":true,"biz.at":true,"info.at":true,"priv.at":true,"co.ca":true,"ar.com":true,"br.com":true,"cn.com":true,"de.com":true,"eu.com":true,"gb.com":true,"gr.com":true,"hu.com":true,"jpn.com":true,"kr.com":true,"no.com":true,"qc.com":true,"ru.com":true,"sa.com":true,"se.com":true,"uk.com":true,"us.com":true,"uy.com":true,"za.com":true,"gb.net":true,"jp.net":true,"se.net":true,"uk.net":true,"ae.org":true,"us.org":true,"com.de":true,"operaunite.com":true,"appspot.com":true,"iki.fi":true,"c.la":true,"za.net":true,"za.org":true,"co.nl":true,"co.no":true,"co.pl":true,"dyndns-at-home.com":true,"dyndns-at-work.com":true,"dyndns-blog.com":true,"dyndns-free.com":true,"dyndns-home.com":true,"dyndns-ip.com":true,"dyndns-mail.com":true,"dyndns-office.com":true,"dyndns-pics.com":true,"dyndns-remote.com":true,"dyndns-server.com":true,"dyndns-web.com":true,"dyndns-wiki.com":true,"dyndns-work.com":true,"dyndns.biz":true,"dyndns.info":true,"dyndns.org":true,"dyndns.tv":true,"at-band-camp.net":true,"ath.cx":true,"barrel-of-knowledge.info":true,"barrell-of-knowledge.info":true,"better-than.tv":true,"blogdns.com":true,"blogdns.net":true,"blogdns.org":true,"blogsite.org":true,"boldlygoingnowhere.org":true,"broke-it.net":true,"buyshouses.net":true,"cechire.com":true,"dnsalias.com":true,"dnsalias.net":true,"dnsalias.org":true,"dnsdojo.com":true,"dnsdojo.net":true,"dnsdojo.org":true,"does-it.net":true,"doesntexist.com":true,"doesntexist.org":true,"dontexist.com":true,"dontexist.net":true,"dontexist.org":true,"doomdns.com":true,"doomdns.org":true,"dvrdns.org":true,"dyn-o-saur.com":true,"dynalias.com":true,"dynalias.net":true,"dynalias.org":true,"dynathome.net":true,"dyndns.ws":true,"endofinternet.net":true,"endofinternet.org":true,"endoftheinternet.org":true,"est-a-la-maison.com":true,"est-a-la-masion.com":true,"est-le-patron.com":true,"est-mon-blogueur.com":true,"for-better.biz":true,"for-more.biz":true,"for-our.info":true,"for-some.biz":true,"for-the.biz":true,"forgot.her.name":true,"forgot.his.name":true,"from-ak.com":true,"from-al.com":true,"from-ar.com":true,"from-az.net":true,"from-ca.com":true,"from-co.net":true,"from-ct.com":true,"from-dc.com":true,"from-de.com":true,"from-fl.com":true,"from-ga.com":true,"from-hi.com":true,"from-ia.com":true,"from-id.com":true,"from-il.com":true,"from-in.com":true,"from-ks.com":true,"from-ky.com":true,"from-la.net":true,"from-ma.com":true,"from-md.com":true,"from-me.org":true,"from-mi.com":true,"from-mn.com":true,"from-mo.com":true,"from-ms.com":true,"from-mt.com":true,"from-nc.com":true,"from-nd.com":true,"from-ne.com":true,"from-nh.com":true,"from-nj.com":true,"from-nm.com":true,"from-nv.com":true,"from-ny.net":true,"from-oh.com":true,"from-ok.com":true,"from-or.com":true,"from-pa.com":true,"from-pr.com":true,"from-ri.com":true,"from-sc.com":true,"from-sd.com":true,"from-tn.com":true,"from-tx.com":true,"from-ut.com":true,"from-va.com":true,"from-vt.com":true,"from-wa.com":true,"from-wi.com":true,"from-wv.com":true,"from-wy.com":true,"ftpaccess.cc":true,"fuettertdasnetz.de":true,"game-host.org":true,"game-server.cc":true,"getmyip.com":true,"gets-it.net":true,"go.dyndns.org":true,"gotdns.com":true,"gotdns.org":true,"groks-the.info":true,"groks-this.info":true,"ham-radio-op.net":true,"here-for-more.info":true,"hobby-site.com":true,"hobby-site.org":true,"home.dyndns.org":true,"homedns.org":true,"homeftp.net":true,"homeftp.org":true,"homeip.net":true,"homelinux.com":true,"homelinux.net":true,"homelinux.org":true,"homeunix.com":true,"homeunix.net":true,"homeunix.org":true,"iamallama.com":true,"in-the-band.net":true,"is-a-anarchist.com":true,"is-a-blogger.com":true,"is-a-bookkeeper.com":true,"is-a-bruinsfan.org":true,"is-a-bulls-fan.com":true,"is-a-candidate.org":true,"is-a-caterer.com":true,"is-a-celticsfan.org":true,"is-a-chef.com":true,"is-a-chef.net":true,"is-a-chef.org":true,"is-a-conservative.com":true,"is-a-cpa.com":true,"is-a-cubicle-slave.com":true,"is-a-democrat.com":true,"is-a-designer.com":true,"is-a-doctor.com":true,"is-a-financialadvisor.com":true,"is-a-geek.com":true,"is-a-geek.net":true,"is-a-geek.org":true,"is-a-green.com":true,"is-a-guru.com":true,"is-a-hard-worker.com":true,"is-a-hunter.com":true,"is-a-knight.org":true,"is-a-landscaper.com":true,"is-a-lawyer.com":true,"is-a-liberal.com":true,"is-a-libertarian.com":true,"is-a-linux-user.org":true,"is-a-llama.com":true,"is-a-musician.com":true,"is-a-nascarfan.com":true,"is-a-nurse.com":true,"is-a-painter.com":true,"is-a-patsfan.org":true,"is-a-personaltrainer.com":true,"is-a-photographer.com":true,"is-a-player.com":true,"is-a-republican.com":true,"is-a-rockstar.com":true,"is-a-socialist.com":true,"is-a-soxfan.org":true,"is-a-student.com":true,"is-a-teacher.com":true,"is-a-techie.com":true,"is-a-therapist.com":true,"is-an-accountant.com":true,"is-an-actor.com":true,"is-an-actress.com":true,"is-an-anarchist.com":true,"is-an-artist.com":true,"is-an-engineer.com":true,"is-an-entertainer.com":true,"is-by.us":true,"is-certified.com":true,"is-found.org":true,"is-gone.com":true,"is-into-anime.com":true,"is-into-cars.com":true,"is-into-cartoons.com":true,"is-into-games.com":true,"is-leet.com":true,"is-lost.org":true,"is-not-certified.com":true,"is-saved.org":true,"is-slick.com":true,"is-uberleet.com":true,"is-very-bad.org":true,"is-very-evil.org":true,"is-very-good.org":true,"is-very-nice.org":true,"is-very-sweet.org":true,"is-with-theband.com":true,"isa-geek.com":true,"isa-geek.net":true,"isa-geek.org":true,"isa-hockeynut.com":true,"issmarterthanyou.com":true,"isteingeek.de":true,"istmein.de":true,"kicks-ass.net":true,"kicks-ass.org":true,"knowsitall.info":true,"land-4-sale.us":true,"lebtimnetz.de":true,"leitungsen.de":true,"likes-pie.com":true,"likescandy.com":true,"merseine.nu":true,"mine.nu":true,"misconfused.org":true,"mypets.ws":true,"myphotos.cc":true,"neat-url.com":true,"office-on-the.net":true,"on-the-web.tv":true,"podzone.net":true,"podzone.org":true,"readmyblog.org":true,"saves-the-whales.com":true,"scrapper-site.net":true,"scrapping.cc":true,"selfip.biz":true,"selfip.com":true,"selfip.info":true,"selfip.net":true,"selfip.org":true,"sells-for-less.com":true,"sells-for-u.com":true,"sells-it.net":true,"sellsyourhome.org":true,"servebbs.com":true,"servebbs.net":true,"servebbs.org":true,"serveftp.net":true,"serveftp.org":true,"servegame.org":true,"shacknet.nu":true,"simple-url.com":true,"space-to-rent.com":true,"stuff-4-sale.org":true,"stuff-4-sale.us":true,"teaches-yoga.com":true,"thruhere.net":true,"traeumtgerade.de":true,"webhop.biz":true,"webhop.info":true,"webhop.net":true,"webhop.org":true,"worse-than.tv":true,"writesthisblog.com":true});
-
-// END of automatically generated file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/store.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/store.js
deleted file mode 100644
index f8433dfc..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/lib/store.js
+++ /dev/null
@@ -1,37 +0,0 @@
-'use strict';
-/*jshint unused:false */
-
-function Store() {
-}
-exports.Store = Store;
-
-// Stores may be synchronous, but are still required to use a
-// Continuation-Passing Style API.  The CookieJar itself will expose a "*Sync"
-// API that converts from synchronous-callbacks to imperative style.
-Store.prototype.synchronous = false;
-
-Store.prototype.findCookie = function(domain, path, key, cb) {
-  throw new Error('findCookie is not implemented');
-};
-
-Store.prototype.findCookies = function(domain, path, cb) {
-  throw new Error('findCookies is not implemented');
-};
-
-Store.prototype.putCookie = function(cookie, cb) {
-  throw new Error('putCookie is not implemented');
-};
-
-Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
-  // recommended default implementation:
-  // return this.putCookie(newCookie, cb);
-  throw new Error('updateCookie is not implemented');
-};
-
-Store.prototype.removeCookie = function(domain, path, key, cb) {
-  throw new Error('removeCookie is not implemented');
-};
-
-Store.prototype.removeCookies = function removeCookies(domain, path, cb) {
-  throw new Error('removeCookies is not implemented');
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-GPL.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-GPL.txt
deleted file mode 100644
index 11dddd00..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-GPL.txt
+++ /dev/null
@@ -1,278 +0,0 @@
-        GNU GENERAL PUBLIC LICENSE
-           Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-          Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-        GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-          NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-MIT.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-MIT.txt
deleted file mode 100644
index 97067e54..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/LICENSE-MIT.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright Mathias Bynens <http://mathiasbynens.be/>
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/README.md
deleted file mode 100644
index 6dae5c4a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/README.md
+++ /dev/null
@@ -1,162 +0,0 @@
-# Punycode.js [![Build status](https://travis-ci.org/bestiejs/punycode.js.png?branch=master)](https://travis-ci.org/bestiejs/punycode.js) [![Dependency status](https://gemnasium.com/bestiejs/punycode.js.png)](https://gemnasium.com/bestiejs/punycode.js)
-
-A robust Punycode converter that fully complies to [RFC 3492](http://tools.ietf.org/html/rfc3492) and [RFC 5891](http://tools.ietf.org/html/rfc5891), and works on nearly all JavaScript platforms.
-
-This JavaScript library is the result of comparing, optimizing and documenting different open-source implementations of the Punycode algorithm:
-
-* [The C example code from RFC 3492](http://tools.ietf.org/html/rfc3492#appendix-C)
-* [`punycode.c` by _Markus W. Scherer_ (IBM)](http://opensource.apple.com/source/ICU/ICU-400.42/icuSources/common/punycode.c)
-* [`punycode.c` by _Ben Noordhuis_](https://github.com/bnoordhuis/punycode/blob/master/punycode.c)
-* [JavaScript implementation by _some_](http://stackoverflow.com/questions/183485/can-anyone-recommend-a-good-free-javascript-for-punycode-to-unicode-conversion/301287#301287)
-* [`punycode.js` by _Ben Noordhuis_](https://github.com/joyent/node/blob/426298c8c1c0d5b5224ac3658c41e7c2a3fe9377/lib/punycode.js) (note: [not fully compliant](https://github.com/joyent/node/issues/2072))
-
-This project is [bundled](https://github.com/joyent/node/blob/master/lib/punycode.js) with [Node.js v0.6.2+](https://github.com/joyent/node/compare/975f1930b1...61e796decc).
-
-## Installation
-
-Via [npm](http://npmjs.org/) (only required for Node.js releases older than v0.6.2):
-
-```bash
-npm install punycode
-```
-
-Via [Bower](http://bower.io/):
-
-```bash
-bower install punycode
-```
-
-Via [Component](https://github.com/component/component):
-
-```bash
-component install bestiejs/punycode.js
-```
-
-In a browser:
-
-```html
-<script src="punycode.js"></script>
-```
-
-In [Narwhal](http://narwhaljs.org/), [Node.js](http://nodejs.org/), and [RingoJS](http://ringojs.org/):
-
-```js
-var punycode = require('punycode');
-```
-
-In [Rhino](http://www.mozilla.org/rhino/):
-
-```js
-load('punycode.js');
-```
-
-Using an AMD loader like [RequireJS](http://requirejs.org/):
-
-```js
-require(
-  {
-    'paths': {
-      'punycode': 'path/to/punycode'
-    }
-  },
-  ['punycode'],
-  function(punycode) {
-    console.log(punycode);
-  }
-);
-```
-
-## API
-
-### `punycode.decode(string)`
-
-Converts a Punycode string of ASCII symbols to a string of Unicode symbols.
-
-```js
-// decode domain name parts
-punycode.decode('maana-pta'); // 'mañana'
-punycode.decode('--dqo34k'); // '☃-⌘'
-```
-
-### `punycode.encode(string)`
-
-Converts a string of Unicode symbols to a Punycode string of ASCII symbols.
-
-```js
-// encode domain name parts
-punycode.encode('mañana'); // 'maana-pta'
-punycode.encode('☃-⌘'); // '--dqo34k'
-```
-
-### `punycode.toUnicode(domain)`
-
-Converts a Punycode string representing a domain name to Unicode. Only the Punycoded parts of the domain name will be converted, i.e. it doesn’t matter if you call it on a string that has already been converted to Unicode.
-
-```js
-// decode domain names
-punycode.toUnicode('xn--maana-pta.com'); // 'mañana.com'
-punycode.toUnicode('xn----dqo34k.com'); // '☃-⌘.com'
-```
-
-### `punycode.toASCII(domain)`
-
-Converts a Unicode string representing a domain name to Punycode. Only the non-ASCII parts of the domain name will be converted, i.e. it doesn’t matter if you call it with a domain that's already in ASCII.
-
-```js
-// encode domain names
-punycode.toASCII('mañana.com'); // 'xn--maana-pta.com'
-punycode.toASCII('☃-⌘.com'); // 'xn----dqo34k.com'
-```
-
-### `punycode.ucs2`
-
-#### `punycode.ucs2.decode(string)`
-
-Creates an array containing the numeric code point values of each Unicode symbol in the string. While [JavaScript uses UCS-2 internally](http://mathiasbynens.be/notes/javascript-encoding), this function will convert a pair of surrogate halves (each of which UCS-2 exposes as separate characters) into a single code point, matching UTF-16.
-
-```js
-punycode.ucs2.decode('abc'); // [0x61, 0x62, 0x63]
-// surrogate pair for U+1D306 TETRAGRAM FOR CENTRE:
-punycode.ucs2.decode('\uD834\uDF06'); // [0x1D306]
-```
-
-#### `punycode.ucs2.encode(codePoints)`
-
-Creates a string based on an array of numeric code point values.
-
-```js
-punycode.ucs2.encode([0x61, 0x62, 0x63]); // 'abc'
-punycode.ucs2.encode([0x1D306]); // '\uD834\uDF06'
-```
-
-### `punycode.version`
-
-A string representing the current Punycode.js version number.
-
-[Full API documentation is available.](https://github.com/bestiejs/punycode.js/tree/master/docs#readme)
-
-## Unit tests & code coverage
-
-After cloning this repository, run `npm install --dev` to install the dependencies needed for Punycode.js development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`.
-
-Once that’s done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, PhantomJS, and web browsers as well, use `grunt test`.
-
-To generate [the code coverage report](http://rawgithub.com/bestiejs/punycode.js/master/coverage/punycode.js/punycode.js.html), use `grunt cover`.
-
-Feel free to fork if you see possible improvements!
-
-## Author
-
-| [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") |
-|---|
-| [Mathias Bynens](http://mathiasbynens.be/) |
-
-## Contributors
-
-| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") |
-|---|
-| [John-David Dalton](http://allyoucanleet.com/) |
-
-## License
-
-Punycode.js is dual licensed under the [MIT](http://mths.be/mit) and [GPL](http://mths.be/gpl) licenses.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/package.json
deleted file mode 100644
index 05222de3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/package.json
+++ /dev/null
@@ -1,76 +0,0 @@
-{
-  "name": "punycode",
-  "version": "1.2.4",
-  "description": "A robust Punycode converter that fully complies to RFC 3492 and RFC 5891, and works on nearly all JavaScript platforms.",
-  "homepage": "http://mths.be/punycode",
-  "main": "punycode.js",
-  "keywords": [
-    "punycode",
-    "unicode",
-    "idn",
-    "idna",
-    "dns",
-    "url",
-    "domain"
-  ],
-  "licenses": [
-    {
-      "type": "MIT",
-      "url": "http://mths.be/mit"
-    },
-    {
-      "type": "GPL",
-      "url": "http://mths.be/gpl"
-    }
-  ],
-  "author": {
-    "name": "Mathias Bynens",
-    "email": "mathias@qiwi.be",
-    "url": "http://mathiasbynens.be/"
-  },
-  "contributors": [
-    {
-      "name": "Mathias Bynens",
-      "email": "mathias@qiwi.be",
-      "url": "http://mathiasbynens.be/"
-    },
-    {
-      "name": "John-David Dalton",
-      "email": "john.david.dalton@gmail.com",
-      "url": "http://allyoucanleet.com/"
-    }
-  ],
-  "bugs": {
-    "url": "https://github.com/bestiejs/punycode.js/issues"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/bestiejs/punycode.js.git"
-  },
-  "engines": [
-    "node",
-    "rhino"
-  ],
-  "directories": {
-    "doc": "docs",
-    "test": "tests"
-  },
-  "scripts": {
-    "test": "node tests/tests.js"
-  },
-  "devDependencies": {
-    "grunt": "~0.4.1",
-    "grunt-contrib-uglify": "~0.2.2",
-    "grunt-shell": "~0.6.4",
-    "istanbul": "~0.2.4",
-    "qunit-clib": "~1.3.0",
-    "qunitjs": "~1.11.0",
-    "requirejs": "~2.1.6"
-  },
-  "readme": "# Punycode.js [![Build status](https://travis-ci.org/bestiejs/punycode.js.png?branch=master)](https://travis-ci.org/bestiejs/punycode.js) [![Dependency status](https://gemnasium.com/bestiejs/punycode.js.png)](https://gemnasium.com/bestiejs/punycode.js)\n\nA robust Punycode converter that fully complies to [RFC 3492](http://tools.ietf.org/html/rfc3492) and [RFC 5891](http://tools.ietf.org/html/rfc5891), and works on nearly all JavaScript platforms.\n\nThis JavaScript library is the result of comparing, optimizing and documenting different open-source implementations of the Punycode algorithm:\n\n* [The C example code from RFC 3492](http://tools.ietf.org/html/rfc3492#appendix-C)\n* [`punycode.c` by _Markus W. Scherer_ (IBM)](http://opensource.apple.com/source/ICU/ICU-400.42/icuSources/common/punycode.c)\n* [`punycode.c` by _Ben Noordhuis_](https://github.com/bnoordhuis/punycode/blob/master/punycode.c)\n* [JavaScript implementation by _some_](http://stackoverflow.com/questions/183485/can-anyone-recommend-a-good-free-javascript-for-punycode-to-unicode-conversion/301287#301287)\n* [`punycode.js` by _Ben Noordhuis_](https://github.com/joyent/node/blob/426298c8c1c0d5b5224ac3658c41e7c2a3fe9377/lib/punycode.js) (note: [not fully compliant](https://github.com/joyent/node/issues/2072))\n\nThis project is [bundled](https://github.com/joyent/node/blob/master/lib/punycode.js) with [Node.js v0.6.2+](https://github.com/joyent/node/compare/975f1930b1...61e796decc).\n\n## Installation\n\nVia [npm](http://npmjs.org/) (only required for Node.js releases older than v0.6.2):\n\n```bash\nnpm install punycode\n```\n\nVia [Bower](http://bower.io/):\n\n```bash\nbower install punycode\n```\n\nVia [Component](https://github.com/component/component):\n\n```bash\ncomponent install bestiejs/punycode.js\n```\n\nIn a browser:\n\n```html\n<script src=\"punycode.js\"></script>\n```\n\nIn [Narwhal](http://narwhaljs.org/), [Node.js](http://nodejs.org/), and [RingoJS](http://ringojs.org/):\n\n```js\nvar punycode = require('punycode');\n```\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n```js\nload('punycode.js');\n```\n\nUsing an AMD loader like [RequireJS](http://requirejs.org/):\n\n```js\nrequire(\n  {\n    'paths': {\n      'punycode': 'path/to/punycode'\n    }\n  },\n  ['punycode'],\n  function(punycode) {\n    console.log(punycode);\n  }\n);\n```\n\n## API\n\n### `punycode.decode(string)`\n\nConverts a Punycode string of ASCII symbols to a string of Unicode symbols.\n\n```js\n// decode domain name parts\npunycode.decode('maana-pta'); // 'mañana'\npunycode.decode('--dqo34k'); // '☃-⌘'\n```\n\n### `punycode.encode(string)`\n\nConverts a string of Unicode symbols to a Punycode string of ASCII symbols.\n\n```js\n// encode domain name parts\npunycode.encode('mañana'); // 'maana-pta'\npunycode.encode('☃-⌘'); // '--dqo34k'\n```\n\n### `punycode.toUnicode(domain)`\n\nConverts a Punycode string representing a domain name to Unicode. Only the Punycoded parts of the domain name will be converted, i.e. it doesn’t matter if you call it on a string that has already been converted to Unicode.\n\n```js\n// decode domain names\npunycode.toUnicode('xn--maana-pta.com'); // 'mañana.com'\npunycode.toUnicode('xn----dqo34k.com'); // '☃-⌘.com'\n```\n\n### `punycode.toASCII(domain)`\n\nConverts a Unicode string representing a domain name to Punycode. Only the non-ASCII parts of the domain name will be converted, i.e. it doesn’t matter if you call it with a domain that's already in ASCII.\n\n```js\n// encode domain names\npunycode.toASCII('mañana.com'); // 'xn--maana-pta.com'\npunycode.toASCII('☃-⌘.com'); // 'xn----dqo34k.com'\n```\n\n### `punycode.ucs2`\n\n#### `punycode.ucs2.decode(string)`\n\nCreates an array containing the numeric code point values of each Unicode symbol in the string. While [JavaScript uses UCS-2 internally](http://mathiasbynens.be/notes/javascript-encoding), this function will convert a pair of surrogate halves (each of which UCS-2 exposes as separate characters) into a single code point, matching UTF-16.\n\n```js\npunycode.ucs2.decode('abc'); // [0x61, 0x62, 0x63]\n// surrogate pair for U+1D306 TETRAGRAM FOR CENTRE:\npunycode.ucs2.decode('\\uD834\\uDF06'); // [0x1D306]\n```\n\n#### `punycode.ucs2.encode(codePoints)`\n\nCreates a string based on an array of numeric code point values.\n\n```js\npunycode.ucs2.encode([0x61, 0x62, 0x63]); // 'abc'\npunycode.ucs2.encode([0x1D306]); // '\\uD834\\uDF06'\n```\n\n### `punycode.version`\n\nA string representing the current Punycode.js version number.\n\n[Full API documentation is available.](https://github.com/bestiejs/punycode.js/tree/master/docs#readme)\n\n## Unit tests & code coverage\n\nAfter cloning this repository, run `npm install --dev` to install the dependencies needed for Punycode.js development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`.\n\nOnce that’s done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, PhantomJS, and web browsers as well, use `grunt test`.\n\nTo generate [the code coverage report](http://rawgithub.com/bestiejs/punycode.js/master/coverage/punycode.js/punycode.js.html), use `grunt cover`.\n\nFeel free to fork if you see possible improvements!\n\n## Author\n\n| [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias \"Follow @mathias on Twitter\") |\n|---|\n| [Mathias Bynens](http://mathiasbynens.be/) |\n\n## Contributors\n\n| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton \"Follow @jdalton on Twitter\") |\n|---|\n| [John-David Dalton](http://allyoucanleet.com/) |\n\n## License\n\nPunycode.js is dual licensed under the [MIT](http://mths.be/mit) and [GPL](http://mths.be/gpl) licenses.\n",
-  "readmeFilename": "README.md",
-  "_id": "punycode@1.2.4",
-  "_shasum": "54008ac972aec74175def9cba6df7fa9d3918740",
-  "_from": "punycode@>=0.2.0",
-  "_resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.js
deleted file mode 100644
index d5b9bc21..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.js
+++ /dev/null
@@ -1,507 +0,0 @@
-/*! http://mths.be/punycode v1.2.4 by @mathias */
-;(function(root) {
-
-	/** Detect free variables */
-	var freeExports = typeof exports == 'object' && exports;
-	var freeModule = typeof module == 'object' && module &&
-		module.exports == freeExports && module;
-	var freeGlobal = typeof global == 'object' && global;
-	if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
-		root = freeGlobal;
-	}
-
-	/**
-	 * The `punycode` object.
-	 * @name punycode
-	 * @type Object
-	 */
-	var punycode,
-
-	/** Highest positive signed 32-bit float value */
-	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
-
-	/** Bootstring parameters */
-	base = 36,
-	tMin = 1,
-	tMax = 26,
-	skew = 38,
-	damp = 700,
-	initialBias = 72,
-	initialN = 128, // 0x80
-	delimiter = '-', // '\x2D'
-
-	/** Regular expressions */
-	regexPunycode = /^xn--/,
-	regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
-	regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
-
-	/** Error messages */
-	errors = {
-		'overflow': 'Overflow: input needs wider integers to process',
-		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
-		'invalid-input': 'Invalid input'
-	},
-
-	/** Convenience shortcuts */
-	baseMinusTMin = base - tMin,
-	floor = Math.floor,
-	stringFromCharCode = String.fromCharCode,
-
-	/** Temporary variable */
-	key;
-
-	/*--------------------------------------------------------------------------*/
-
-	/**
-	 * A generic error utility function.
-	 * @private
-	 * @param {String} type The error type.
-	 * @returns {Error} Throws a `RangeError` with the applicable error message.
-	 */
-	function error(type) {
-		throw RangeError(errors[type]);
-	}
-
-	/**
-	 * A generic `Array#map` utility function.
-	 * @private
-	 * @param {Array} array The array to iterate over.
-	 * @param {Function} callback The function that gets called for every array
-	 * item.
-	 * @returns {Array} A new array of values returned by the callback function.
-	 */
-	function map(array, fn) {
-		var length = array.length;
-		while (length--) {
-			array[length] = fn(array[length]);
-		}
-		return array;
-	}
-
-	/**
-	 * A simple `Array#map`-like wrapper to work with domain name strings.
-	 * @private
-	 * @param {String} domain The domain name.
-	 * @param {Function} callback The function that gets called for every
-	 * character.
-	 * @returns {Array} A new string of characters returned by the callback
-	 * function.
-	 */
-	function mapDomain(string, fn) {
-		return map(string.split(regexSeparators), fn).join('.');
-	}
-
-	/**
-	 * Creates an array containing the numeric code points of each Unicode
-	 * character in the string. While JavaScript uses UCS-2 internally,
-	 * this function will convert a pair of surrogate halves (each of which
-	 * UCS-2 exposes as separate characters) into a single code point,
-	 * matching UTF-16.
-	 * @see `punycode.ucs2.encode`
-	 * @see <http://mathiasbynens.be/notes/javascript-encoding>
-	 * @memberOf punycode.ucs2
-	 * @name decode
-	 * @param {String} string The Unicode input string (UCS-2).
-	 * @returns {Array} The new array of code points.
-	 */
-	function ucs2decode(string) {
-		var output = [],
-		    counter = 0,
-		    length = string.length,
-		    value,
-		    extra;
-		while (counter < length) {
-			value = string.charCodeAt(counter++);
-			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
-				// high surrogate, and there is a next character
-				extra = string.charCodeAt(counter++);
-				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
-					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
-				} else {
-					// unmatched surrogate; only append this code unit, in case the next
-					// code unit is the high surrogate of a surrogate pair
-					output.push(value);
-					counter--;
-				}
-			} else {
-				output.push(value);
-			}
-		}
-		return output;
-	}
-
-	/**
-	 * Creates a string based on an array of numeric code points.
-	 * @see `punycode.ucs2.decode`
-	 * @memberOf punycode.ucs2
-	 * @name encode
-	 * @param {Array} codePoints The array of numeric code points.
-	 * @returns {String} The new Unicode string (UCS-2).
-	 */
-	function ucs2encode(array) {
-		return map(array, function(value) {
-			var output = '';
-			if (value > 0xFFFF) {
-				value -= 0x10000;
-				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
-				value = 0xDC00 | value & 0x3FF;
-			}
-			output += stringFromCharCode(value);
-			return output;
-		}).join('');
-	}
-
-	/**
-	 * Converts a basic code point into a digit/integer.
-	 * @see `digitToBasic()`
-	 * @private
-	 * @param {Number} codePoint The basic numeric code point value.
-	 * @returns {Number} The numeric value of a basic code point (for use in
-	 * representing integers) in the range `0` to `base - 1`, or `base` if
-	 * the code point does not represent a value.
-	 */
-	function basicToDigit(codePoint) {
-		if (codePoint - 48 < 10) {
-			return codePoint - 22;
-		}
-		if (codePoint - 65 < 26) {
-			return codePoint - 65;
-		}
-		if (codePoint - 97 < 26) {
-			return codePoint - 97;
-		}
-		return base;
-	}
-
-	/**
-	 * Converts a digit/integer into a basic code point.
-	 * @see `basicToDigit()`
-	 * @private
-	 * @param {Number} digit The numeric value of a basic code point.
-	 * @returns {Number} The basic code point whose value (when used for
-	 * representing integers) is `digit`, which needs to be in the range
-	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
-	 * used; else, the lowercase form is used. The behavior is undefined
-	 * if `flag` is non-zero and `digit` has no uppercase form.
-	 */
-	function digitToBasic(digit, flag) {
-		//  0..25 map to ASCII a..z or A..Z
-		// 26..35 map to ASCII 0..9
-		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
-	}
-
-	/**
-	 * Bias adaptation function as per section 3.4 of RFC 3492.
-	 * http://tools.ietf.org/html/rfc3492#section-3.4
-	 * @private
-	 */
-	function adapt(delta, numPoints, firstTime) {
-		var k = 0;
-		delta = firstTime ? floor(delta / damp) : delta >> 1;
-		delta += floor(delta / numPoints);
-		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
-			delta = floor(delta / baseMinusTMin);
-		}
-		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
-	}
-
-	/**
-	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
-	 * symbols.
-	 * @memberOf punycode
-	 * @param {String} input The Punycode string of ASCII-only symbols.
-	 * @returns {String} The resulting string of Unicode symbols.
-	 */
-	function decode(input) {
-		// Don't use UCS-2
-		var output = [],
-		    inputLength = input.length,
-		    out,
-		    i = 0,
-		    n = initialN,
-		    bias = initialBias,
-		    basic,
-		    j,
-		    index,
-		    oldi,
-		    w,
-		    k,
-		    digit,
-		    t,
-		    /** Cached calculation results */
-		    baseMinusT;
-
-		// Handle the basic code points: let `basic` be the number of input code
-		// points before the last delimiter, or `0` if there is none, then copy
-		// the first basic code points to the output.
-
-		basic = input.lastIndexOf(delimiter);
-		if (basic < 0) {
-			basic = 0;
-		}
-
-		for (j = 0; j < basic; ++j) {
-			// if it's not a basic code point
-			if (input.charCodeAt(j) >= 0x80) {
-				error('not-basic');
-			}
-			output.push(input.charCodeAt(j));
-		}
-
-		// Main decoding loop: start just after the last delimiter if any basic code
-		// points were copied; start at the beginning otherwise.
-
-		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
-
-			// `index` is the index of the next character to be consumed.
-			// Decode a generalized variable-length integer into `delta`,
-			// which gets added to `i`. The overflow checking is easier
-			// if we increase `i` as we go, then subtract off its starting
-			// value at the end to obtain `delta`.
-			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
-
-				if (index >= inputLength) {
-					error('invalid-input');
-				}
-
-				digit = basicToDigit(input.charCodeAt(index++));
-
-				if (digit >= base || digit > floor((maxInt - i) / w)) {
-					error('overflow');
-				}
-
-				i += digit * w;
-				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
-
-				if (digit < t) {
-					break;
-				}
-
-				baseMinusT = base - t;
-				if (w > floor(maxInt / baseMinusT)) {
-					error('overflow');
-				}
-
-				w *= baseMinusT;
-
-			}
-
-			out = output.length + 1;
-			bias = adapt(i - oldi, out, oldi == 0);
-
-			// `i` was supposed to wrap around from `out` to `0`,
-			// incrementing `n` each time, so we'll fix that now:
-			if (floor(i / out) > maxInt - n) {
-				error('overflow');
-			}
-
-			n += floor(i / out);
-			i %= out;
-
-			// Insert `n` at position `i` of the output
-			output.splice(i++, 0, n);
-
-		}
-
-		return ucs2encode(output);
-	}
-
-	/**
-	 * Converts a string of Unicode symbols to a Punycode string of ASCII-only
-	 * symbols.
-	 * @memberOf punycode
-	 * @param {String} input The string of Unicode symbols.
-	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
-	 */
-	function encode(input) {
-		var n,
-		    delta,
-		    handledCPCount,
-		    basicLength,
-		    bias,
-		    j,
-		    m,
-		    q,
-		    k,
-		    t,
-		    currentValue,
-		    output = [],
-		    /** `inputLength` will hold the number of code points in `input`. */
-		    inputLength,
-		    /** Cached calculation results */
-		    handledCPCountPlusOne,
-		    baseMinusT,
-		    qMinusT;
-
-		// Convert the input in UCS-2 to Unicode
-		input = ucs2decode(input);
-
-		// Cache the length
-		inputLength = input.length;
-
-		// Initialize the state
-		n = initialN;
-		delta = 0;
-		bias = initialBias;
-
-		// Handle the basic code points
-		for (j = 0; j < inputLength; ++j) {
-			currentValue = input[j];
-			if (currentValue < 0x80) {
-				output.push(stringFromCharCode(currentValue));
-			}
-		}
-
-		handledCPCount = basicLength = output.length;
-
-		// `handledCPCount` is the number of code points that have been handled;
-		// `basicLength` is the number of basic code points.
-
-		// Finish the basic string - if it is not empty - with a delimiter
-		if (basicLength) {
-			output.push(delimiter);
-		}
-
-		// Main encoding loop:
-		while (handledCPCount < inputLength) {
-
-			// All non-basic code points < n have been handled already. Find the next
-			// larger one:
-			for (m = maxInt, j = 0; j < inputLength; ++j) {
-				currentValue = input[j];
-				if (currentValue >= n && currentValue < m) {
-					m = currentValue;
-				}
-			}
-
-			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
-			// but guard against overflow
-			handledCPCountPlusOne = handledCPCount + 1;
-			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
-				error('overflow');
-			}
-
-			delta += (m - n) * handledCPCountPlusOne;
-			n = m;
-
-			for (j = 0; j < inputLength; ++j) {
-				currentValue = input[j];
-
-				if (currentValue < n && ++delta > maxInt) {
-					error('overflow');
-				}
-
-				if (currentValue == n) {
-					// Represent delta as a generalized variable-length integer
-					for (q = delta, k = base; /* no condition */; k += base) {
-						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
-						if (q < t) {
-							break;
-						}
-						qMinusT = q - t;
-						baseMinusT = base - t;
-						output.push(
-							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
-						);
-						q = floor(qMinusT / baseMinusT);
-					}
-
-					output.push(stringFromCharCode(digitToBasic(q, 0)));
-					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
-					delta = 0;
-					++handledCPCount;
-				}
-			}
-
-			++delta;
-			++n;
-
-		}
-		return output.join('');
-	}
-
-	/**
-	 * Converts a Punycode string representing a domain name to Unicode. Only the
-	 * Punycoded parts of the domain name will be converted, i.e. it doesn't
-	 * matter if you call it on a string that has already been converted to
-	 * Unicode.
-	 * @memberOf punycode
-	 * @param {String} domain The Punycode domain name to convert to Unicode.
-	 * @returns {String} The Unicode representation of the given Punycode
-	 * string.
-	 */
-	function toUnicode(domain) {
-		return mapDomain(domain, function(string) {
-			return regexPunycode.test(string)
-				? decode(string.slice(4).toLowerCase())
-				: string;
-		});
-	}
-
-	/**
-	 * Converts a Unicode string representing a domain name to Punycode. Only the
-	 * non-ASCII parts of the domain name will be converted, i.e. it doesn't
-	 * matter if you call it with a domain that's already in ASCII.
-	 * @memberOf punycode
-	 * @param {String} domain The domain name to convert, as a Unicode string.
-	 * @returns {String} The Punycode representation of the given domain name.
-	 */
-	function toASCII(domain) {
-		return mapDomain(domain, function(string) {
-			return regexNonASCII.test(string)
-				? 'xn--' + encode(string)
-				: string;
-		});
-	}
-
-	/*--------------------------------------------------------------------------*/
-
-	/** Define the public API */
-	punycode = {
-		/**
-		 * A string representing the current Punycode.js version number.
-		 * @memberOf punycode
-		 * @type String
-		 */
-		'version': '1.2.4',
-		/**
-		 * An object of methods to convert from JavaScript's internal character
-		 * representation (UCS-2) to Unicode code points, and back.
-		 * @see <http://mathiasbynens.be/notes/javascript-encoding>
-		 * @memberOf punycode
-		 * @type Object
-		 */
-		'ucs2': {
-			'decode': ucs2decode,
-			'encode': ucs2encode
-		},
-		'decode': decode,
-		'encode': encode,
-		'toASCII': toASCII,
-		'toUnicode': toUnicode
-	};
-
-	/** Expose `punycode` */
-	// Some AMD build optimizers, like r.js, check for specific condition patterns
-	// like the following:
-	if (
-		typeof define == 'function' &&
-		typeof define.amd == 'object' &&
-		define.amd
-	) {
-		define('punycode', function() {
-			return punycode;
-		});
-	} else if (freeExports && !freeExports.nodeType) {
-		if (freeModule) { // in Node.js or RingoJS v0.8.0+
-			freeModule.exports = punycode;
-		} else { // in Narwhal or RingoJS v0.7.0-
-			for (key in punycode) {
-				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
-			}
-		}
-	} else { // in Rhino or a web browser
-		root.punycode = punycode;
-	}
-
-}(this));
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.min.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.min.js
deleted file mode 100644
index 24c8af24..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/node_modules/punycode/punycode.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! http://mths.be/punycode v1.2.4 by @mathias */
-!function(a){function b(a){throw RangeError(E[a])}function c(a,b){for(var c=a.length;c--;)a[c]=b(a[c]);return a}function d(a,b){return c(a.split(D),b).join(".")}function e(a){for(var b,c,d=[],e=0,f=a.length;f>e;)b=a.charCodeAt(e++),b>=55296&&56319>=b&&f>e?(c=a.charCodeAt(e++),56320==(64512&c)?d.push(((1023&b)<<10)+(1023&c)+65536):(d.push(b),e--)):d.push(b);return d}function f(a){return c(a,function(a){var b="";return a>65535&&(a-=65536,b+=H(a>>>10&1023|55296),a=56320|1023&a),b+=H(a)}).join("")}function g(a){return 10>a-48?a-22:26>a-65?a-65:26>a-97?a-97:t}function h(a,b){return a+22+75*(26>a)-((0!=b)<<5)}function i(a,b,c){var d=0;for(a=c?G(a/x):a>>1,a+=G(a/b);a>F*v>>1;d+=t)a=G(a/F);return G(d+(F+1)*a/(a+w))}function j(a){var c,d,e,h,j,k,l,m,n,o,p=[],q=a.length,r=0,w=z,x=y;for(d=a.lastIndexOf(A),0>d&&(d=0),e=0;d>e;++e)a.charCodeAt(e)>=128&&b("not-basic"),p.push(a.charCodeAt(e));for(h=d>0?d+1:0;q>h;){for(j=r,k=1,l=t;h>=q&&b("invalid-input"),m=g(a.charCodeAt(h++)),(m>=t||m>G((s-r)/k))&&b("overflow"),r+=m*k,n=x>=l?u:l>=x+v?v:l-x,!(n>m);l+=t)o=t-n,k>G(s/o)&&b("overflow"),k*=o;c=p.length+1,x=i(r-j,c,0==j),G(r/c)>s-w&&b("overflow"),w+=G(r/c),r%=c,p.splice(r++,0,w)}return f(p)}function k(a){var c,d,f,g,j,k,l,m,n,o,p,q,r,w,x,B=[];for(a=e(a),q=a.length,c=z,d=0,j=y,k=0;q>k;++k)p=a[k],128>p&&B.push(H(p));for(f=g=B.length,g&&B.push(A);q>f;){for(l=s,k=0;q>k;++k)p=a[k],p>=c&&l>p&&(l=p);for(r=f+1,l-c>G((s-d)/r)&&b("overflow"),d+=(l-c)*r,c=l,k=0;q>k;++k)if(p=a[k],c>p&&++d>s&&b("overflow"),p==c){for(m=d,n=t;o=j>=n?u:n>=j+v?v:n-j,!(o>m);n+=t)x=m-o,w=t-o,B.push(H(h(o+x%w,0))),m=G(x/w);B.push(H(h(m,0))),j=i(d,r,f==g),d=0,++f}++d,++c}return B.join("")}function l(a){return d(a,function(a){return B.test(a)?j(a.slice(4).toLowerCase()):a})}function m(a){return d(a,function(a){return C.test(a)?"xn--"+k(a):a})}var n="object"==typeof exports&&exports,o="object"==typeof module&&module&&module.exports==n&&module,p="object"==typeof global&&global;(p.global===p||p.window===p)&&(a=p);var q,r,s=2147483647,t=36,u=1,v=26,w=38,x=700,y=72,z=128,A="-",B=/^xn--/,C=/[^ -~]/,D=/\x2E|\u3002|\uFF0E|\uFF61/g,E={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},F=t-u,G=Math.floor,H=String.fromCharCode;if(q={version:"1.2.4",ucs2:{decode:e,encode:f},decode:j,encode:k,toASCII:m,toUnicode:l},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define("punycode",function(){return q});else if(n&&!n.nodeType)if(o)o.exports=q;else for(r in q)q.hasOwnProperty(r)&&(n[r]=q[r]);else a.punycode=q}(this);
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/package.json
deleted file mode 100644
index 03718716..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/package.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
-  "author": {
-    "name": "GoInstant Inc., a salesforce.com company"
-  },
-  "license": "MIT",
-  "name": "tough-cookie",
-  "description": "RFC6265 Cookies and Cookie Jar for node.js",
-  "keywords": [
-    "HTTP",
-    "cookie",
-    "cookies",
-    "set-cookie",
-    "cookiejar",
-    "jar",
-    "RFC6265",
-    "RFC2965"
-  ],
-  "version": "0.12.1",
-  "homepage": "https://github.com/goinstant/tough-cookie",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/goinstant/tough-cookie.git"
-  },
-  "bugs": {
-    "url": "https://github.com/goinstant/tough-cookie/issues"
-  },
-  "main": "./lib/cookie",
-  "scripts": {
-    "test": "vows test.js"
-  },
-  "engines": {
-    "node": ">=0.4.12"
-  },
-  "dependencies": {
-    "punycode": ">=0.2.0"
-  },
-  "devDependencies": {
-    "vows": "0.7.0",
-    "async": ">=0.1.12"
-  },
-  "readme": "[RFC6265](http://tools.ietf.org/html/rfc6265) Cookies and CookieJar for Node.js\n\n![Tough Cookie](http://www.goinstant.com.s3.amazonaws.com/tough-cookie.jpg)\n\n[![Build Status](https://travis-ci.org/goinstant/node-cookie.png?branch=master)](https://travis-ci.org/goinstant/node-cookie)\n\n[![NPM Stats](https://nodei.co/npm/tough-cookie.png?downloads=true&stars=true)](https://npmjs.org/package/tough-cookie)\n![NPM Downloads](https://nodei.co/npm-dl/tough-cookie.png?months=9)\n\n# Synopsis\n\n``` javascript\nvar tough = require('tough-cookie'); // note: not 'cookie', 'cookies' or 'node-cookie'\nvar Cookie = tough.Cookie;\nvar cookie = Cookie.parse(header);\ncookie.value = 'somethingdifferent';\nheader = cookie.toString();\n\nvar cookiejar = new tough.CookieJar();\ncookiejar.setCookie(cookie, 'http://currentdomain.example.com/path', cb);\n// ...\ncookiejar.getCookies('http://example.com/otherpath',function(err,cookies) {\n  res.headers['cookie'] = cookies.join('; ');\n});\n```\n\n# Installation\n\nIt's _so_ easy!\n\n`npm install tough-cookie`\n\nRequires `punycode`, which should get installed automatically for you.  Note that node.js v0.6.2+ bundles punycode by default.\n\nWhy the name?  NPM modules `cookie`, `cookies` and `cookiejar` were already taken.\n\n# API\n\ntough\n=====\n\nFunctions on the module you get from `require('tough-cookie')`.  All can be used as pure functions and don't need to be \"bound\".\n\nparseDate(string[,strict])\n-----------------\n\nParse a cookie date string into a `Date`.  Parses according to RFC6265 Section 5.1.1, not `Date.parse()`.  If strict is set to true then leading/trailing non-seperator characters around the time part will cause the parsing to fail (e.g. \"Thu, 01 Jan 1970 00:00:010 GMT\" has an extra trailing zero but Chrome, an assumedly RFC-compliant browser, treats this as valid).\n\nformatDate(date)\n----------------\n\nFormat a Date into a RFC1123 string (the RFC6265-recommended format).\n\ncanonicalDomain(str)\n--------------------\n\nTransforms a domain-name into a canonical domain-name.  The canonical domain-name is a trimmed, lowercased, stripped-of-leading-dot and optionally punycode-encoded domain-name (Section 5.1.2 of RFC6265).  For the most part, this function is idempotent (can be run again on its output without ill effects).\n\ndomainMatch(str,domStr[,canonicalize=true])\n-------------------------------------------\n\nAnswers \"does this real domain match the domain in a cookie?\".  The `str` is the \"current\" domain-name and the `domStr` is the \"cookie\" domain-name.  Matches according to RFC6265 Section 5.1.3, but it helps to think of it as a \"suffix match\".\n\nThe `canonicalize` parameter will run the other two paramters through `canonicalDomain` or not.\n\ndefaultPath(path)\n-----------------\n\nGiven a current request/response path, gives the Path apropriate for storing in a cookie.  This is basically the \"directory\" of a \"file\" in the path, but is specified by Section 5.1.4 of the RFC.\n\nThe `path` parameter MUST be _only_ the pathname part of a URI (i.e. excludes the hostname, query, fragment, etc.).  This is the `.pathname` property of node's `uri.parse()` output.\n\npathMatch(reqPath,cookiePath)\n-----------------------------\n\nAnswers \"does the request-path path-match a given cookie-path?\" as per RFC6265 Section 5.1.4.  Returns a boolean.\n\nThis is essentially a prefix-match where `cookiePath` is a prefix of `reqPath`.\n\nparse(header[,strict=false])\n----------------------------\n\nalias for `Cookie.parse(header[,strict])`\n\nfromJSON(string)\n----------------\n\nalias for `Cookie.fromJSON(string)`\n\ngetPublicSuffix(hostname)\n-------------------------\n\nReturns the public suffix of this hostname.  The public suffix is the shortest domain-name upon which a cookie can be set.  Returns `null` if the hostname cannot have cookies set for it.\n\nFor example: `www.example.com` and `www.subdomain.example.com` both have public suffix `example.com`.\n\nFor further information, see http://publicsuffix.org/.  This module derives its list from that site.\n\ncookieCompare(a,b)\n------------------\n\nFor use with `.sort()`, sorts a list of cookies into the recommended order given in the RFC (Section 5.4 step 2).  Longest `.path`s go first, then sorted oldest to youngest.\n\n``` javascript\nvar cookies = [ /* unsorted array of Cookie objects */ ];\ncookies = cookies.sort(cookieCompare);\n```\n\npermuteDomain(domain)\n---------------------\n\nGenerates a list of all possible domains that `domainMatch()` the parameter.  May be handy for implementing cookie stores.\n\n\npermutePath(path)\n-----------------\n\nGenerates a list of all possible paths that `pathMatch()` the parameter.  May be handy for implementing cookie stores.\n\nCookie\n======\n\nCookie.parse(header[,strict=false])\n-----------------------------------\n\nParses a single Cookie or Set-Cookie HTTP header into a `Cookie` object.  Returns `undefined` if the string can't be parsed.  If in strict mode, returns `undefined` if the cookie doesn't follow the guidelines in section 4 of RFC6265.  Generally speaking, strict mode can be used to validate your own generated Set-Cookie headers, but acting as a client you want to be lenient and leave strict mode off.\n\nHere's how to process the Set-Cookie header(s) on a node HTTP/HTTPS response:\n\n``` javascript\nif (res.headers['set-cookie'] instanceof Array)\n  cookies = res.headers['set-cookie'].map(function (c) { return (Cookie.parse(c)); });\nelse\n  cookies = [Cookie.parse(res.headers['set-cookie'])];\n```\n\nCookie.fromJSON(string)\n-----------------------\n\nConvert a JSON string to a `Cookie` object.  Does a `JSON.parse()` and converts the `.created`, `.lastAccessed` and `.expires` properties into `Date` objects.\n\nProperties\n==========\n\n  * _key_ - string - the name or key of the cookie (default \"\")\n  * _value_ - string - the value of the cookie (default \"\")\n  * _expires_ - `Date` - if set, the `Expires=` attribute of the cookie (defaults to the string `\"Infinity\"`). See `setExpires()`\n  * _maxAge_ - seconds - if set, the `Max-Age=` attribute _in seconds_ of the cookie.  May also be set to strings `\"Infinity\"` and `\"-Infinity\"` for non-expiry and immediate-expiry, respectively.  See `setMaxAge()`\n  * _domain_ - string - the `Domain=` attribute of the cookie\n  * _path_ - string - the `Path=` of the cookie\n  * _secure_ - boolean - the `Secure` cookie flag\n  * _httpOnly_ - boolean - the `HttpOnly` cookie flag\n  * _extensions_ - `Array` - any unrecognized cookie attributes as strings (even if equal-signs inside)\n\nAfter a cookie has been passed through `CookieJar.setCookie()` it will have the following additional attributes:\n\n  * _hostOnly_ - boolean - is this a host-only cookie (i.e. no Domain field was set, but was instead implied)\n  * _pathIsDefault_ - boolean - if true, there was no Path field on the cookie and `defaultPath()` was used to derive one.\n  * _created_ - `Date` - when this cookie was added to the jar\n  * _lastAccessed_ - `Date` - last time the cookie got accessed. Will affect cookie cleaning once implemented.  Using `cookiejar.getCookies(...)` will update this attribute.\n\nConstruction([{options}])\n------------\n\nReceives an options object that can contain any Cookie properties, uses the default for unspecified properties.\n\n.toString()\n-----------\n\nencode to a Set-Cookie header value.  The Expires cookie field is set using `formatDate()`, but is omitted entirely if `.expires` is `Infinity`.\n\n.cookieString()\n---------------\n\nencode to a Cookie header value (i.e. the `.key` and `.value` properties joined with '=').\n\n.setExpires(String)\n-------------------\n\nsets the expiry based on a date-string passed through `parseDate()`.  If parseDate returns `null` (i.e. can't parse this date string), `.expires` is set to `\"Infinity\"` (a string) is set.\n\n.setMaxAge(number)\n-------------------\n\nsets the maxAge in seconds.  Coerces `-Infinity` to `\"-Infinity\"` and `Infinity` to `\"Infinity\"` so it JSON serializes correctly.\n\n.expiryTime([now=Date.now()])\n-----------------------------\n\n.expiryDate([now=Date.now()])\n-----------------------------\n\nexpiryTime() Computes the absolute unix-epoch milliseconds that this cookie expires. expiryDate() works similarly, except it returns a `Date` object.  Note that in both cases the `now` parameter should be milliseconds.\n\nMax-Age takes precedence over Expires (as per the RFC). The `.created` attribute -- or, by default, the `now` paramter -- is used to offset the `.maxAge` attribute.\n\nIf Expires (`.expires`) is set, that's returned.\n\nOtherwise, `expiryTime()` returns `Infinity` and `expiryDate()` returns a `Date` object for \"Tue, 19 Jan 2038 03:14:07 GMT\" (latest date that can be expressed by a 32-bit `time_t`; the common limit for most user-agents).\n\n.TTL([now=Date.now()])\n---------\n\ncompute the TTL relative to `now` (milliseconds).  The same precedence rules as for `expiryTime`/`expiryDate` apply.\n\nThe \"number\" `Infinity` is returned for cookies without an explicit expiry and `0` is returned if the cookie is expired.  Otherwise a time-to-live in milliseconds is returned.\n\n.canonicalizedDoman()\n---------------------\n\n.cdomain()\n----------\n\nreturn the canonicalized `.domain` field.  This is lower-cased and punycode (RFC3490) encoded if the domain has any non-ASCII characters.\n\n.validate()\n-----------\n\nStatus: *IN PROGRESS*. Works for a few things, but is by no means comprehensive.\n\nvalidates cookie attributes for semantic correctness.  Useful for \"lint\" checking any Set-Cookie headers you generate.  For now, it returns a boolean, but eventually could return a reason string -- you can future-proof with this construct:\n\n``` javascript\nif (cookie.validate() === true) {\n  // it's tasty\n} else {\n  // yuck!\n}\n```\n\nCookieJar\n=========\n\nConstruction([store = new MemoryCookieStore()][, rejectPublicSuffixes])\n------------\n\nSimply use `new CookieJar()`.  If you'd like to use a custom store, pass that to the constructor otherwise a `MemoryCookieStore` will be created and used.\n\n\nAttributes\n----------\n\n  * _rejectPublicSuffixes_ - boolean - reject cookies with domains like \"com\" and \"co.uk\" (default: `true`)\n\nSince eventually this module would like to support database/remote/etc. CookieJars, continuation passing style is used for CookieJar methods.\n\n.setCookie(cookieOrString, currentUrl, [{options},] cb(err,cookie))\n-------------------------------------------------------------------\n\nAttempt to set the cookie in the cookie jar.  If the operation fails, an error will be given to the callback `cb`, otherwise the cookie is passed through.  The cookie will have updated `.created`, `.lastAccessed` and `.hostOnly` properties.\n\nThe `options` object can be omitted and can have the following properties:\n\n  * _http_ - boolean - default `true` - indicates if this is an HTTP or non-HTTP API.  Affects HttpOnly cookies.\n  * _secure_ - boolean - autodetect from url - indicates if this is a \"Secure\" API.  If the currentUrl starts with `https:` or `wss:` then this is defaulted to `true`, otherwise `false`.\n  * _now_ - Date - default `new Date()` - what to use for the creation/access time of cookies\n  * _strict_ - boolean - default `false` - perform extra checks\n  * _ignoreError_ - boolean - default `false` - silently ignore things like parse errors and invalid domains.  CookieStore errors aren't ignored by this option.\n\nAs per the RFC, the `.hostOnly` property is set if there was no \"Domain=\" parameter in the cookie string (or `.domain` was null on the Cookie object).  The `.domain` property is set to the fully-qualified hostname of `currentUrl` in this case.  Matching this cookie requires an exact hostname match (not a `domainMatch` as per usual).\n\n.setCookieSync(cookieOrString, currentUrl, [{options}])\n-------------------------------------------------------\n\nSynchronous version of `setCookie`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).\n\n.storeCookie(cookie, [{options},] cb(err,cookie))\n-------------------------------------------------\n\n__REMOVED__ removed in lieu of the CookieStore API below\n\n.getCookies(currentUrl, [{options},] cb(err,cookies))\n-----------------------------------------------------\n\nRetrieve the list of cookies that can be sent in a Cookie header for the current url.\n\nIf an error is encountered, that's passed as `err` to the callback, otherwise an `Array` of `Cookie` objects is passed.  The array is sorted with `cookieCompare()` unless the `{sort:false}` option is given.\n\nThe `options` object can be omitted and can have the following properties:\n\n  * _http_ - boolean - default `true` - indicates if this is an HTTP or non-HTTP API.  Affects HttpOnly cookies.\n  * _secure_ - boolean - autodetect from url - indicates if this is a \"Secure\" API.  If the currentUrl starts with `https:` or `wss:` then this is defaulted to `true`, otherwise `false`.\n  * _now_ - Date - default `new Date()` - what to use for the creation/access time of cookies\n  * _expire_ - boolean - default `true` - perform expiry-time checking of cookies and asynchronously remove expired cookies from the store.  Using `false` will return expired cookies and **not** remove them from the store (which is useful for replaying Set-Cookie headers, potentially).\n  * _allPaths_ - boolean - default `false` - if `true`, do not scope cookies by path. The default uses RFC-compliant path scoping. **Note**: may not be supported by the CookieStore `fetchCookies` function (the default MemoryCookieStore supports it).\n\nThe `.lastAccessed` property of the returned cookies will have been updated.\n\n.getCookiesSync(currentUrl, [{options}])\n----------------------------------------\n\nSynchronous version of `getCookies`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).\n\n.getCookieString(...)\n---------------------\n\nAccepts the same options as `.getCookies()` but passes a string suitable for a Cookie header rather than an array to the callback.  Simply maps the `Cookie` array via `.cookieString()`.\n\n.getCookieStringSync(...)\n-------------------------\n\nSynchronous version of `getCookieString`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).\n\n.getSetCookieStrings(...)\n-------------------------\n\nReturns an array of strings suitable for **Set-Cookie** headers. Accepts the same options as `.getCookies()`.  Simply maps the cookie array via `.toString()`.\n\n.getSetCookieStringsSync(...)\n-----------------------------\n\nSynchronous version of `getSetCookieStrings`; only works with synchronous stores (e.g. the default `MemoryCookieStore`).\n\nStore\n=====\n\nBase class for CookieJar stores.\n\n# CookieStore API\n\nThe storage model for each `CookieJar` instance can be replaced with a custom implementation.  The default is `MemoryCookieStore` which can be found in the `lib/memstore.js` file.  The API uses continuation-passing-style to allow for asynchronous stores.\n\nStores should inherit from the base `Store` class, which is available as `require('tough-cookie').Store`.  Stores are asynchronous by default, but if `store.synchronous` is set, then the `*Sync` methods on the CookieJar can be used.\n\nAll `domain` parameters will have been normalized before calling.\n\nThe Cookie store must have all of the following methods.\n\nstore.findCookie(domain, path, key, cb(err,cookie))\n---------------------------------------------------\n\nRetrieve a cookie with the given domain, path and key (a.k.a. name).  The RFC maintains that exactly one of these cookies should exist in a store.  If the store is using versioning, this means that the latest/newest such cookie should be returned.\n\nCallback takes an error and the resulting `Cookie` object.  If no cookie is found then `null` MUST be passed instead (i.e. not an error).\n\nstore.findCookies(domain, path, cb(err,cookies))\n------------------------------------------------\n\nLocates cookies matching the given domain and path.  This is most often called in the context of `cookiejar.getCookies()` above.\n\nIf no cookies are found, the callback MUST be passed an empty array.\n\nThe resulting list will be checked for applicability to the current request according to the RFC (domain-match, path-match, http-only-flag, secure-flag, expiry, etc.), so it's OK to use an optimistic search algorithm when implementing this method.  However, the search algorithm used SHOULD try to find cookies that `domainMatch()` the domain and `pathMatch()` the path in order to limit the amount of checking that needs to be done.\n\nAs of version 0.9.12, the `allPaths` option to `cookiejar.getCookies()` above will cause the path here to be `null`.  If the path is `null`, path-matching MUST NOT be performed (i.e. domain-matching only).\n\nstore.putCookie(cookie, cb(err))\n--------------------------------\n\nAdds a new cookie to the store.  The implementation SHOULD replace any existing cookie with the same `.domain`, `.path`, and `.key` properties -- depending on the nature of the implementation, it's possible that between the call to `fetchCookie` and `putCookie` that a duplicate `putCookie` can occur.\n\nThe `cookie` object MUST NOT be modified; the caller will have already updated the `.creation` and `.lastAccessed` properties.\n\nPass an error if the cookie cannot be stored.\n\nstore.updateCookie(oldCookie, newCookie, cb(err))\n-------------------------------------------------\n\nUpdate an existing cookie.  The implementation MUST update the `.value` for a cookie with the same `domain`, `.path` and `.key`.  The implementation SHOULD check that the old value in the store is equivalent to `oldCookie` - how the conflict is resolved is up to the store.\n\nThe `.lastAccessed` property will always be different between the two objects and `.created` will always be the same.  Stores MAY ignore or defer the `.lastAccessed` change at the cost of affecting how cookies are sorted (or selected for deletion).\n\nStores may wish to optimize changing the `.value` of the cookie in the store versus storing a new cookie.  If the implementation doesn't define this method a stub that calls `putCookie(newCookie,cb)` will be added to the store object.\n\nThe `newCookie` and `oldCookie` objects MUST NOT be modified.\n\nPass an error if the newCookie cannot be stored.\n\nstore.removeCookie(domain, path, key, cb(err))\n----------------------------------------------\n\nRemove a cookie from the store (see notes on `findCookie` about the uniqueness constraint).\n\nThe implementation MUST NOT pass an error if the cookie doesn't exist; only pass an error due to the failure to remove an existing cookie.\n\nstore.removeCookies(domain, path, cb(err))\n------------------------------------------\n\nRemoves matching cookies from the store.  The `path` paramter is optional, and if missing means all paths in a domain should be removed.\n\nPass an error ONLY if removing any existing cookies failed.\n\n# TODO\n\n  * _full_ RFC5890/RFC5891 canonicalization for domains in `cdomain()`\n    * the optional `punycode` requirement implements RFC3492, but RFC6265 requires RFC5891\n  * better tests for `validate()`?\n\n# Copyright and License\n\n(tl;dr: MIT with some MPL/1.1)\n\nCopyright 2012- GoInstant, Inc. and other contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\nPortions may be licensed under different licenses (in particular public-suffix.txt is MPL/1.1); please read the LICENSE file for full details.\n",
-  "readmeFilename": "README.md",
-  "_id": "tough-cookie@0.12.1",
-  "_shasum": "8220c7e21abd5b13d96804254bd5a81ebf2c7d62",
-  "_from": "tough-cookie@>=0.12.0",
-  "_resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/public-suffix.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/public-suffix.txt
deleted file mode 100644
index 2c201312..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/public-suffix.txt
+++ /dev/null
@@ -1,5229 +0,0 @@
-// ***** BEGIN LICENSE BLOCK *****
-// Version: MPL 1.1/GPL 2.0/LGPL 2.1
-// 
-// The contents of this file are subject to the Mozilla Public License Version 
-// 1.1 (the "License"); you may not use this file except in compliance with 
-// the License. You may obtain a copy of the License at 
-// http://www.mozilla.org/MPL/
-// 
-// Software distributed under the License is distributed on an "AS IS" basis,
-// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-// for the specific language governing rights and limitations under the
-// License.
-// 
-// The Original Code is the Public Suffix List.
-// 
-// The Initial Developer of the Original Code is
-// Jo Hermans <jo.hermans@gmail.com>.
-// Portions created by the Initial Developer are Copyright (C) 2007
-// the Initial Developer. All Rights Reserved.
-// 
-// Contributor(s):
-//   Ruben Arakelyan <ruben@rubenarakelyan.com>
-//   Gervase Markham <gerv@gerv.net>
-//   Pamela Greene <pamg.bugs@gmail.com>
-//   David Triendl <david@triendl.name>
-//   Jothan Frakes <jothan@gmail.com>
-//   The kind representatives of many TLD registries
-// 
-// Alternatively, the contents of this file may be used under the terms of
-// either the GNU General Public License Version 2 or later (the "GPL"), or
-// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-// in which case the provisions of the GPL or the LGPL are applicable instead
-// of those above. If you wish to allow use of your version of this file only
-// under the terms of either the GPL or the LGPL, and not to allow others to
-// use your version of this file under the terms of the MPL, indicate your
-// decision by deleting the provisions above and replace them with the notice
-// and other provisions required by the GPL or the LGPL. If you do not delete
-// the provisions above, a recipient may use your version of this file under
-// the terms of any one of the MPL, the GPL or the LGPL.
-// 
-// ***** END LICENSE BLOCK *****
-
-// ===BEGIN ICANN DOMAINS===
-
-// ac : http://en.wikipedia.org/wiki/.ac
-ac
-com.ac
-edu.ac
-gov.ac
-net.ac
-mil.ac
-org.ac
-
-// ad : http://en.wikipedia.org/wiki/.ad
-ad
-nom.ad
-
-// ae : http://en.wikipedia.org/wiki/.ae
-// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php
-ae
-co.ae
-net.ae
-org.ae
-sch.ae
-ac.ae
-gov.ae
-mil.ae
-
-// aero : see http://www.information.aero/index.php?id=66
-aero
-accident-investigation.aero
-accident-prevention.aero
-aerobatic.aero
-aeroclub.aero
-aerodrome.aero
-agents.aero
-aircraft.aero
-airline.aero
-airport.aero
-air-surveillance.aero
-airtraffic.aero
-air-traffic-control.aero
-ambulance.aero
-amusement.aero
-association.aero
-author.aero
-ballooning.aero
-broker.aero
-caa.aero
-cargo.aero
-catering.aero
-certification.aero
-championship.aero
-charter.aero
-civilaviation.aero
-club.aero
-conference.aero
-consultant.aero
-consulting.aero
-control.aero
-council.aero
-crew.aero
-design.aero
-dgca.aero
-educator.aero
-emergency.aero
-engine.aero
-engineer.aero
-entertainment.aero
-equipment.aero
-exchange.aero
-express.aero
-federation.aero
-flight.aero
-freight.aero
-fuel.aero
-gliding.aero
-government.aero
-groundhandling.aero
-group.aero
-hanggliding.aero
-homebuilt.aero
-insurance.aero
-journal.aero
-journalist.aero
-leasing.aero
-logistics.aero
-magazine.aero
-maintenance.aero
-marketplace.aero
-media.aero
-microlight.aero
-modelling.aero
-navigation.aero
-parachuting.aero
-paragliding.aero
-passenger-association.aero
-pilot.aero
-press.aero
-production.aero
-recreation.aero
-repbody.aero
-res.aero
-research.aero
-rotorcraft.aero
-safety.aero
-scientist.aero
-services.aero
-show.aero
-skydiving.aero
-software.aero
-student.aero
-taxi.aero
-trader.aero
-trading.aero
-trainer.aero
-union.aero
-workinggroup.aero
-works.aero
-
-// af : http://www.nic.af/help.jsp
-af
-gov.af
-com.af
-org.af
-net.af
-edu.af
-
-// ag : http://www.nic.ag/prices.htm
-ag
-com.ag
-org.ag
-net.ag
-co.ag
-nom.ag
-
-// ai : http://nic.com.ai/
-ai
-off.ai
-com.ai
-net.ai
-org.ai
-
-// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31
-al
-com.al
-edu.al
-gov.al
-mil.al
-net.al
-org.al
-
-// am : http://en.wikipedia.org/wiki/.am
-am
-
-// an : http://www.una.an/an_domreg/default.asp
-an
-com.an
-net.an
-org.an
-edu.an
-
-// ao : http://en.wikipedia.org/wiki/.ao
-// http://www.dns.ao/REGISTR.DOC
-ao
-ed.ao
-gv.ao
-og.ao
-co.ao
-pb.ao
-it.ao
-
-// aq : http://en.wikipedia.org/wiki/.aq
-aq
-
-// ar : http://en.wikipedia.org/wiki/.ar
-*.ar
-!congresodelalengua3.ar
-!educ.ar
-!gobiernoelectronico.ar
-!mecon.ar
-!nacion.ar
-!nic.ar
-!promocion.ar
-!retina.ar
-!uba.ar
-
-// arpa : http://en.wikipedia.org/wiki/.arpa
-// Confirmed by registry <iana-questions@icann.org> 2008-06-18
-e164.arpa
-in-addr.arpa
-ip6.arpa
-iris.arpa
-uri.arpa
-urn.arpa
-
-// as : http://en.wikipedia.org/wiki/.as
-as
-gov.as
-
-// asia : http://en.wikipedia.org/wiki/.asia
-asia
-
-// at : http://en.wikipedia.org/wiki/.at
-// Confirmed by registry <it@nic.at> 2008-06-17
-at
-ac.at
-co.at
-gv.at
-or.at
-
-// au : http://en.wikipedia.org/wiki/.au
-// http://www.auda.org.au/
-// 2LDs
-com.au
-net.au
-org.au
-edu.au
-gov.au
-csiro.au
-asn.au
-id.au
-// Historic 2LDs (closed to new registration, but sites still exist)
-info.au
-conf.au
-oz.au
-// CGDNs - http://www.cgdn.org.au/
-act.au
-nsw.au
-nt.au
-qld.au
-sa.au
-tas.au
-vic.au
-wa.au
-// 3LDs
-act.edu.au
-nsw.edu.au
-nt.edu.au
-qld.edu.au
-sa.edu.au
-tas.edu.au
-vic.edu.au
-wa.edu.au
-act.gov.au
-// Removed at request of Shae.Donelan@services.nsw.gov.au, 2010-03-04
-// nsw.gov.au
-nt.gov.au
-qld.gov.au
-sa.gov.au
-tas.gov.au
-vic.gov.au
-wa.gov.au
-
-// aw : http://en.wikipedia.org/wiki/.aw
-aw
-com.aw
-
-// ax : http://en.wikipedia.org/wiki/.ax
-ax
-
-// az : http://en.wikipedia.org/wiki/.az
-az
-com.az
-net.az
-int.az
-gov.az
-org.az
-edu.az
-info.az
-pp.az
-mil.az
-name.az
-pro.az
-biz.az
-
-// ba : http://en.wikipedia.org/wiki/.ba
-ba
-org.ba
-net.ba
-edu.ba
-gov.ba
-mil.ba
-unsa.ba
-unbi.ba
-co.ba
-com.ba
-rs.ba
-
-// bb : http://en.wikipedia.org/wiki/.bb
-bb
-biz.bb
-com.bb
-edu.bb
-gov.bb
-info.bb
-net.bb
-org.bb
-store.bb
-
-// bd : http://en.wikipedia.org/wiki/.bd
-*.bd
-
-// be : http://en.wikipedia.org/wiki/.be
-// Confirmed by registry <tech@dns.be> 2008-06-08
-be
-ac.be
-
-// bf : http://en.wikipedia.org/wiki/.bf
-bf
-gov.bf
-
-// bg : http://en.wikipedia.org/wiki/.bg
-// https://www.register.bg/user/static/rules/en/index.html
-bg
-a.bg
-b.bg
-c.bg
-d.bg
-e.bg
-f.bg
-g.bg
-h.bg
-i.bg
-j.bg
-k.bg
-l.bg
-m.bg
-n.bg
-o.bg
-p.bg
-q.bg
-r.bg
-s.bg
-t.bg
-u.bg
-v.bg
-w.bg
-x.bg
-y.bg
-z.bg
-0.bg
-1.bg
-2.bg
-3.bg
-4.bg
-5.bg
-6.bg
-7.bg
-8.bg
-9.bg	 	 	
-
-// bh : http://en.wikipedia.org/wiki/.bh
-bh
-com.bh
-edu.bh
-net.bh
-org.bh
-gov.bh
-
-// bi : http://en.wikipedia.org/wiki/.bi
-// http://whois.nic.bi/
-bi
-co.bi
-com.bi
-edu.bi
-or.bi
-org.bi
-
-// biz : http://en.wikipedia.org/wiki/.biz
-biz
-
-// bj : http://en.wikipedia.org/wiki/.bj
-bj
-asso.bj
-barreau.bj
-gouv.bj
-
-// bm : http://www.bermudanic.bm/dnr-text.txt
-bm
-com.bm
-edu.bm
-gov.bm
-net.bm
-org.bm
-
-// bn : http://en.wikipedia.org/wiki/.bn
-*.bn
-
-// bo : http://www.nic.bo/
-bo
-com.bo
-edu.bo
-gov.bo
-gob.bo
-int.bo
-org.bo
-net.bo
-mil.bo
-tv.bo
-
-// br : http://registro.br/dominio/dpn.html
-// Updated by registry <fneves@registro.br> 2011-03-01
-br
-adm.br
-adv.br
-agr.br
-am.br
-arq.br
-art.br
-ato.br
-b.br
-bio.br
-blog.br
-bmd.br
-can.br
-cim.br
-cng.br
-cnt.br
-com.br
-coop.br
-ecn.br
-edu.br
-emp.br
-eng.br
-esp.br
-etc.br
-eti.br
-far.br
-flog.br
-fm.br
-fnd.br
-fot.br
-fst.br
-g12.br
-ggf.br
-gov.br
-imb.br
-ind.br
-inf.br
-jor.br
-jus.br
-lel.br
-mat.br
-med.br
-mil.br
-mus.br
-net.br
-nom.br
-not.br
-ntr.br
-odo.br
-org.br
-ppg.br
-pro.br
-psc.br
-psi.br
-qsl.br
-radio.br
-rec.br
-slg.br
-srv.br
-taxi.br
-teo.br
-tmp.br
-trd.br
-tur.br
-tv.br
-vet.br
-vlog.br
-wiki.br
-zlg.br
-
-// bs : http://www.nic.bs/rules.html
-bs
-com.bs
-net.bs
-org.bs
-edu.bs
-gov.bs
-
-// bt : http://en.wikipedia.org/wiki/.bt
-bt
-com.bt
-edu.bt
-gov.bt
-net.bt
-org.bt
-
-// bv : No registrations at this time.
-// Submitted by registry <jarle@uninett.no> 2006-06-16
-
-// bw : http://en.wikipedia.org/wiki/.bw
-// http://www.gobin.info/domainname/bw.doc
-// list of other 2nd level tlds ?
-bw
-co.bw
-org.bw
-
-// by : http://en.wikipedia.org/wiki/.by
-// http://tld.by/rules_2006_en.html
-// list of other 2nd level tlds ?
-by
-gov.by
-mil.by
-// Official information does not indicate that com.by is a reserved
-// second-level domain, but it's being used as one (see www.google.com.by and
-// www.yahoo.com.by, for example), so we list it here for safety's sake.
-com.by
-
-// http://hoster.by/
-of.by
-
-// bz : http://en.wikipedia.org/wiki/.bz
-// http://www.belizenic.bz/
-bz
-com.bz
-net.bz
-org.bz
-edu.bz
-gov.bz
-
-// ca : http://en.wikipedia.org/wiki/.ca
-ca
-// ca geographical names
-ab.ca
-bc.ca
-mb.ca
-nb.ca
-nf.ca
-nl.ca
-ns.ca
-nt.ca
-nu.ca
-on.ca
-pe.ca
-qc.ca
-sk.ca
-yk.ca
-// gc.ca: http://en.wikipedia.org/wiki/.gc.ca
-// see also: http://registry.gc.ca/en/SubdomainFAQ
-gc.ca
-
-// cat : http://en.wikipedia.org/wiki/.cat
-cat
-
-// cc : http://en.wikipedia.org/wiki/.cc
-cc
-
-// cd : http://en.wikipedia.org/wiki/.cd
-// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1
-cd
-gov.cd
-
-// cf : http://en.wikipedia.org/wiki/.cf
-cf
-
-// cg : http://en.wikipedia.org/wiki/.cg
-cg
-
-// ch : http://en.wikipedia.org/wiki/.ch
-ch
-
-// ci : http://en.wikipedia.org/wiki/.ci
-// http://www.nic.ci/index.php?page=charte
-ci
-org.ci
-or.ci
-com.ci
-co.ci
-edu.ci
-ed.ci
-ac.ci
-net.ci
-go.ci
-asso.ci
-aéroport.ci
-int.ci
-presse.ci
-md.ci
-gouv.ci
-
-// ck : http://en.wikipedia.org/wiki/.ck
-*.ck
-!www.ck
-
-// cl : http://en.wikipedia.org/wiki/.cl
-cl
-gov.cl
-gob.cl
-co.cl
-mil.cl
-
-// cm : http://en.wikipedia.org/wiki/.cm
-cm
-gov.cm
-
-// cn : http://en.wikipedia.org/wiki/.cn
-// Submitted by registry <tanyaling@cnnic.cn> 2008-06-11
-cn
-ac.cn
-com.cn
-edu.cn
-gov.cn
-net.cn
-org.cn
-mil.cn
-公司.cn
-网络.cn
-網絡.cn
-// cn geographic names
-ah.cn
-bj.cn
-cq.cn
-fj.cn
-gd.cn
-gs.cn
-gz.cn
-gx.cn
-ha.cn
-hb.cn
-he.cn
-hi.cn
-hl.cn
-hn.cn
-jl.cn
-js.cn
-jx.cn
-ln.cn
-nm.cn
-nx.cn
-qh.cn
-sc.cn
-sd.cn
-sh.cn
-sn.cn
-sx.cn
-tj.cn
-xj.cn
-xz.cn
-yn.cn
-zj.cn
-hk.cn
-mo.cn
-tw.cn
-
-// co : http://en.wikipedia.org/wiki/.co
-// Submitted by registry <tecnico@uniandes.edu.co> 2008-06-11
-co
-arts.co
-com.co
-edu.co
-firm.co
-gov.co
-info.co
-int.co
-mil.co
-net.co
-nom.co
-org.co
-rec.co
-web.co
-
-// com : http://en.wikipedia.org/wiki/.com
-com
-
-// coop : http://en.wikipedia.org/wiki/.coop
-coop
-
-// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do
-cr
-ac.cr
-co.cr
-ed.cr
-fi.cr
-go.cr
-or.cr
-sa.cr
-
-// cu : http://en.wikipedia.org/wiki/.cu
-cu
-com.cu
-edu.cu
-org.cu
-net.cu
-gov.cu
-inf.cu
-
-// cv : http://en.wikipedia.org/wiki/.cv
-cv
-
-// cx : http://en.wikipedia.org/wiki/.cx
-// list of other 2nd level tlds ?
-cx
-gov.cx
-
-// cy : http://en.wikipedia.org/wiki/.cy
-*.cy
-
-// cz : http://en.wikipedia.org/wiki/.cz
-cz
-
-// de : http://en.wikipedia.org/wiki/.de
-// Confirmed by registry <ops@denic.de> (with technical
-// reservations) 2008-07-01
-de
-
-// dj : http://en.wikipedia.org/wiki/.dj
-dj
-
-// dk : http://en.wikipedia.org/wiki/.dk
-// Confirmed by registry <robert@dk-hostmaster.dk> 2008-06-17
-dk
-
-// dm : http://en.wikipedia.org/wiki/.dm
-dm
-com.dm
-net.dm
-org.dm
-edu.dm
-gov.dm
-
-// do : http://en.wikipedia.org/wiki/.do
-do
-art.do
-com.do
-edu.do
-gob.do
-gov.do
-mil.do
-net.do
-org.do
-sld.do
-web.do
-
-// dz : http://en.wikipedia.org/wiki/.dz
-dz
-com.dz
-org.dz
-net.dz
-gov.dz
-edu.dz
-asso.dz
-pol.dz
-art.dz
-
-// ec : http://www.nic.ec/reg/paso1.asp
-// Submitted by registry <vabboud@nic.ec> 2008-07-04
-ec
-com.ec
-info.ec
-net.ec
-fin.ec
-k12.ec
-med.ec
-pro.ec
-org.ec
-edu.ec
-gov.ec
-gob.ec
-mil.ec
-
-// edu : http://en.wikipedia.org/wiki/.edu
-edu
-
-// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B
-ee
-edu.ee
-gov.ee
-riik.ee
-lib.ee
-med.ee
-com.ee
-pri.ee
-aip.ee
-org.ee
-fie.ee
-
-// eg : http://en.wikipedia.org/wiki/.eg
-eg  
-com.eg
-edu.eg
-eun.eg
-gov.eg
-mil.eg
-name.eg
-net.eg
-org.eg
-sci.eg
-
-// er : http://en.wikipedia.org/wiki/.er
-*.er
-
-// es : https://www.nic.es/site_ingles/ingles/dominios/index.html
-es
-com.es
-nom.es
-org.es
-gob.es
-edu.es
-
-// et : http://en.wikipedia.org/wiki/.et
-*.et
-
-// eu : http://en.wikipedia.org/wiki/.eu
-eu
-
-// fi : http://en.wikipedia.org/wiki/.fi
-fi
-// aland.fi : http://en.wikipedia.org/wiki/.ax
-// This domain is being phased out in favor of .ax. As there are still many
-// domains under aland.fi, we still keep it on the list until aland.fi is
-// completely removed.
-// TODO: Check for updates (expected to be phased out around Q1/2009)
-aland.fi
-
-// fj : http://en.wikipedia.org/wiki/.fj
-*.fj
-
-// fk : http://en.wikipedia.org/wiki/.fk
-*.fk
-
-// fm : http://en.wikipedia.org/wiki/.fm
-fm
-
-// fo : http://en.wikipedia.org/wiki/.fo
-fo
-
-// fr : http://www.afnic.fr/
-// domaines descriptifs : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-descriptifs
-fr
-com.fr
-asso.fr
-nom.fr
-prd.fr
-presse.fr
-tm.fr
-// domaines sectoriels : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-sectoriels
-aeroport.fr
-assedic.fr
-avocat.fr
-avoues.fr
-cci.fr
-chambagri.fr
-chirurgiens-dentistes.fr
-experts-comptables.fr
-geometre-expert.fr
-gouv.fr
-greta.fr
-huissier-justice.fr
-medecin.fr
-notaires.fr
-pharmacien.fr
-port.fr
-veterinaire.fr
-
-// ga : http://en.wikipedia.org/wiki/.ga
-ga
-
-// gb : This registry is effectively dormant
-// Submitted by registry <Damien.Shaw@ja.net> 2008-06-12
-
-// gd : http://en.wikipedia.org/wiki/.gd
-gd
-
-// ge : http://www.nic.net.ge/policy_en.pdf
-ge
-com.ge
-edu.ge
-gov.ge
-org.ge
-mil.ge
-net.ge
-pvt.ge
-
-// gf : http://en.wikipedia.org/wiki/.gf
-gf
-
-// gg : http://www.channelisles.net/applic/avextn.shtml
-gg
-co.gg
-org.gg
-net.gg
-sch.gg
-gov.gg
-
-// gh : http://en.wikipedia.org/wiki/.gh
-// see also: http://www.nic.gh/reg_now.php
-// Although domains directly at second level are not possible at the moment,
-// they have been possible for some time and may come back.
-gh
-com.gh
-edu.gh
-gov.gh
-org.gh
-mil.gh
-
-// gi : http://www.nic.gi/rules.html
-gi
-com.gi
-ltd.gi
-gov.gi
-mod.gi
-edu.gi
-org.gi
-
-// gl : http://en.wikipedia.org/wiki/.gl
-// http://nic.gl
-gl
-
-// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm
-gm
-
-// gn : http://psg.com/dns/gn/gn.txt
-// Submitted by registry <randy@psg.com> 2008-06-17
-ac.gn
-com.gn
-edu.gn
-gov.gn
-org.gn
-net.gn
-
-// gov : http://en.wikipedia.org/wiki/.gov
-gov
-
-// gp : http://www.nic.gp/index.php?lang=en
-gp
-com.gp
-net.gp
-mobi.gp
-edu.gp
-org.gp
-asso.gp
-
-// gq : http://en.wikipedia.org/wiki/.gq
-gq
-
-// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html
-// Submitted by registry <segred@ics.forth.gr> 2008-06-09
-gr
-com.gr
-edu.gr
-net.gr
-org.gr
-gov.gr
-
-// gs : http://en.wikipedia.org/wiki/.gs
-gs
-
-// gt : http://www.gt/politicas.html
-*.gt
-!www.gt
-
-// gu : http://gadao.gov.gu/registration.txt
-*.gu
-
-// gw : http://en.wikipedia.org/wiki/.gw
-gw
-
-// gy : http://en.wikipedia.org/wiki/.gy
-// http://registry.gy/
-gy
-co.gy
-com.gy
-net.gy
-
-// hk : https://www.hkdnr.hk
-// Submitted by registry <hk.tech@hkirc.hk> 2008-06-11
-hk
-com.hk
-edu.hk
-gov.hk
-idv.hk
-net.hk
-org.hk
-公司.hk
-教育.hk
-敎育.hk
-政府.hk
-個人.hk
-个人.hk
-箇人.hk
-網络.hk
-网络.hk
-组織.hk
-網絡.hk
-网絡.hk
-组织.hk
-組織.hk
-組织.hk 
-
-// hm : http://en.wikipedia.org/wiki/.hm
-hm
-
-// hn : http://www.nic.hn/politicas/ps02,,05.html
-hn
-com.hn
-edu.hn
-org.hn
-net.hn
-mil.hn
-gob.hn
-
-// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf
-hr
-iz.hr
-from.hr
-name.hr
-com.hr
-
-// ht : http://www.nic.ht/info/charte.cfm
-ht
-com.ht
-shop.ht
-firm.ht
-info.ht
-adult.ht
-net.ht
-pro.ht
-org.ht
-med.ht
-art.ht
-coop.ht
-pol.ht
-asso.ht
-edu.ht
-rel.ht
-gouv.ht
-perso.ht
-
-// hu : http://www.domain.hu/domain/English/sld.html
-// Confirmed by registry <pasztor@iszt.hu> 2008-06-12
-hu
-co.hu
-info.hu
-org.hu
-priv.hu
-sport.hu
-tm.hu
-2000.hu
-agrar.hu
-bolt.hu
-casino.hu
-city.hu
-erotica.hu
-erotika.hu
-film.hu
-forum.hu
-games.hu
-hotel.hu
-ingatlan.hu
-jogasz.hu
-konyvelo.hu
-lakas.hu
-media.hu
-news.hu
-reklam.hu
-sex.hu
-shop.hu
-suli.hu
-szex.hu
-tozsde.hu
-utazas.hu
-video.hu
-
-// id : http://en.wikipedia.org/wiki/.id
-// see also: https://register.pandi.or.id/
-id
-ac.id
-co.id
-go.id
-mil.id
-net.id
-or.id
-sch.id
-web.id
-
-// ie : http://en.wikipedia.org/wiki/.ie
-ie
-gov.ie
-
-// il : http://en.wikipedia.org/wiki/.il
-*.il
-
-// im : https://www.nic.im/pdfs/imfaqs.pdf
-im
-co.im
-ltd.co.im
-plc.co.im
-net.im
-gov.im
-org.im
-nic.im
-ac.im
-
-// in : http://en.wikipedia.org/wiki/.in
-// see also: http://www.inregistry.in/policies/
-// Please note, that nic.in is not an offical eTLD, but used by most
-// government institutions.
-in
-co.in
-firm.in
-net.in
-org.in
-gen.in
-ind.in
-nic.in
-ac.in
-edu.in
-res.in
-gov.in
-mil.in
-
-// info : http://en.wikipedia.org/wiki/.info
-info
-
-// int : http://en.wikipedia.org/wiki/.int
-// Confirmed by registry <iana-questions@icann.org> 2008-06-18
-int
-eu.int
-
-// io : http://www.nic.io/rules.html
-// list of other 2nd level tlds ?
-io
-com.io
-
-// iq : http://www.cmc.iq/english/iq/iqregister1.htm
-iq
-gov.iq
-edu.iq
-mil.iq
-com.iq
-org.iq
-net.iq
-
-// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules
-// Also see http://www.nic.ir/Internationalized_Domain_Names
-// Two <iran>.ir entries added at request of <tech-team@nic.ir>, 2010-04-16
-ir
-ac.ir
-co.ir
-gov.ir
-id.ir
-net.ir
-org.ir
-sch.ir
-// xn--mgba3a4f16a.ir (<iran>.ir, Persian YEH)
-ایران.ir
-// xn--mgba3a4fra.ir (<iran>.ir, Arabic YEH)
-ايران.ir
-
-// is : http://www.isnic.is/domain/rules.php
-// Confirmed by registry <marius@isgate.is> 2008-12-06
-is
-net.is
-com.is
-edu.is
-gov.is
-org.is
-int.is
-
-// it : http://en.wikipedia.org/wiki/.it
-it
-gov.it
-edu.it
-// list of reserved geo-names : 
-// http://www.nic.it/documenti/regolamenti-e-linee-guida/regolamento-assegnazione-versione-6.0.pdf
-// (There is also a list of reserved geo-names corresponding to Italian 
-// municipalities : http://www.nic.it/documenti/appendice-c.pdf , but it is
-// not included here.)
-agrigento.it
-ag.it
-alessandria.it
-al.it
-ancona.it
-an.it
-aosta.it
-aoste.it
-ao.it
-arezzo.it
-ar.it
-ascoli-piceno.it
-ascolipiceno.it
-ap.it
-asti.it
-at.it
-avellino.it
-av.it
-bari.it
-ba.it
-andria-barletta-trani.it
-andriabarlettatrani.it
-trani-barletta-andria.it
-tranibarlettaandria.it
-barletta-trani-andria.it
-barlettatraniandria.it
-andria-trani-barletta.it
-andriatranibarletta.it
-trani-andria-barletta.it
-traniandriabarletta.it
-bt.it
-belluno.it
-bl.it
-benevento.it
-bn.it
-bergamo.it
-bg.it
-biella.it
-bi.it
-bologna.it
-bo.it
-bolzano.it
-bozen.it
-balsan.it
-alto-adige.it
-altoadige.it
-suedtirol.it
-bz.it
-brescia.it
-bs.it
-brindisi.it
-br.it
-cagliari.it
-ca.it
-caltanissetta.it
-cl.it
-campobasso.it
-cb.it
-carboniaiglesias.it
-carbonia-iglesias.it
-iglesias-carbonia.it
-iglesiascarbonia.it
-ci.it
-caserta.it
-ce.it
-catania.it
-ct.it
-catanzaro.it
-cz.it
-chieti.it
-ch.it
-como.it
-co.it
-cosenza.it
-cs.it
-cremona.it
-cr.it
-crotone.it
-kr.it
-cuneo.it
-cn.it
-dell-ogliastra.it
-dellogliastra.it
-ogliastra.it
-og.it
-enna.it
-en.it
-ferrara.it
-fe.it
-fermo.it
-fm.it
-firenze.it
-florence.it
-fi.it
-foggia.it
-fg.it
-forli-cesena.it
-forlicesena.it
-cesena-forli.it
-cesenaforli.it
-fc.it
-frosinone.it
-fr.it
-genova.it
-genoa.it
-ge.it
-gorizia.it
-go.it
-grosseto.it
-gr.it
-imperia.it
-im.it
-isernia.it
-is.it
-laquila.it
-aquila.it
-aq.it
-la-spezia.it
-laspezia.it
-sp.it
-latina.it
-lt.it
-lecce.it
-le.it
-lecco.it
-lc.it
-livorno.it
-li.it
-lodi.it
-lo.it
-lucca.it
-lu.it
-macerata.it
-mc.it
-mantova.it
-mn.it
-massa-carrara.it
-massacarrara.it
-carrara-massa.it
-carraramassa.it
-ms.it
-matera.it
-mt.it
-medio-campidano.it
-mediocampidano.it
-campidano-medio.it
-campidanomedio.it
-vs.it
-messina.it
-me.it
-milano.it
-milan.it
-mi.it
-modena.it
-mo.it
-monza.it
-monza-brianza.it
-monzabrianza.it
-monzaebrianza.it
-monzaedellabrianza.it
-monza-e-della-brianza.it
-mb.it
-napoli.it
-naples.it
-na.it
-novara.it
-no.it
-nuoro.it
-nu.it
-oristano.it
-or.it
-padova.it
-padua.it
-pd.it
-palermo.it
-pa.it
-parma.it
-pr.it
-pavia.it
-pv.it
-perugia.it
-pg.it
-pescara.it
-pe.it
-pesaro-urbino.it
-pesarourbino.it
-urbino-pesaro.it
-urbinopesaro.it
-pu.it
-piacenza.it
-pc.it
-pisa.it
-pi.it
-pistoia.it
-pt.it
-pordenone.it
-pn.it
-potenza.it
-pz.it
-prato.it
-po.it
-ragusa.it
-rg.it
-ravenna.it
-ra.it
-reggio-calabria.it
-reggiocalabria.it
-rc.it
-reggio-emilia.it
-reggioemilia.it
-re.it
-rieti.it
-ri.it
-rimini.it
-rn.it
-roma.it
-rome.it
-rm.it
-rovigo.it
-ro.it
-salerno.it
-sa.it
-sassari.it
-ss.it
-savona.it
-sv.it
-siena.it
-si.it
-siracusa.it
-sr.it
-sondrio.it
-so.it
-taranto.it
-ta.it
-tempio-olbia.it
-tempioolbia.it
-olbia-tempio.it
-olbiatempio.it
-ot.it
-teramo.it
-te.it
-terni.it
-tr.it
-torino.it
-turin.it
-to.it
-trapani.it
-tp.it
-trento.it
-trentino.it
-tn.it
-treviso.it
-tv.it
-trieste.it
-ts.it
-udine.it
-ud.it
-varese.it
-va.it
-venezia.it
-venice.it
-ve.it
-verbania.it
-vb.it
-vercelli.it
-vc.it
-verona.it
-vr.it
-vibo-valentia.it
-vibovalentia.it
-vv.it
-vicenza.it
-vi.it
-viterbo.it
-vt.it
-
-// je : http://www.channelisles.net/applic/avextn.shtml
-je
-co.je
-org.je
-net.je
-sch.je
-gov.je
-
-// jm : http://www.com.jm/register.html
-*.jm
-
-// jo : http://www.dns.jo/Registration_policy.aspx
-jo
-com.jo
-org.jo
-net.jo
-edu.jo
-sch.jo
-gov.jo
-mil.jo
-name.jo
-
-// jobs : http://en.wikipedia.org/wiki/.jobs
-jobs
-
-// jp : http://en.wikipedia.org/wiki/.jp
-// http://jprs.co.jp/en/jpdomain.html
-// Submitted by registry <yone@jprs.co.jp> 2008-06-11
-// Updated by registry <yone@jprs.co.jp> 2008-12-04
-jp
-// jp organizational type names 
-ac.jp
-ad.jp
-co.jp
-ed.jp
-go.jp
-gr.jp
-lg.jp
-ne.jp
-or.jp
-// jp geographic type names
-// http://jprs.jp/doc/rule/saisoku-1.html
-*.aichi.jp
-*.akita.jp
-*.aomori.jp
-*.chiba.jp
-*.ehime.jp
-*.fukui.jp
-*.fukuoka.jp
-*.fukushima.jp
-*.gifu.jp
-*.gunma.jp
-*.hiroshima.jp
-*.hokkaido.jp
-*.hyogo.jp
-*.ibaraki.jp
-*.ishikawa.jp
-*.iwate.jp
-*.kagawa.jp
-*.kagoshima.jp
-*.kanagawa.jp
-*.kawasaki.jp
-*.kitakyushu.jp
-*.kobe.jp
-*.kochi.jp
-*.kumamoto.jp
-*.kyoto.jp
-*.mie.jp
-*.miyagi.jp
-*.miyazaki.jp
-*.nagano.jp
-*.nagasaki.jp
-*.nagoya.jp
-*.nara.jp
-*.niigata.jp
-*.oita.jp
-*.okayama.jp
-*.okinawa.jp
-*.osaka.jp
-*.saga.jp
-*.saitama.jp
-*.sapporo.jp
-*.sendai.jp
-*.shiga.jp
-*.shimane.jp
-*.shizuoka.jp
-*.tochigi.jp
-*.tokushima.jp
-*.tokyo.jp
-*.tottori.jp
-*.toyama.jp
-*.wakayama.jp
-*.yamagata.jp
-*.yamaguchi.jp
-*.yamanashi.jp
-*.yokohama.jp
-!metro.tokyo.jp
-!pref.aichi.jp
-!pref.akita.jp
-!pref.aomori.jp
-!pref.chiba.jp
-!pref.ehime.jp
-!pref.fukui.jp
-!pref.fukuoka.jp
-!pref.fukushima.jp
-!pref.gifu.jp
-!pref.gunma.jp
-!pref.hiroshima.jp
-!pref.hokkaido.jp
-!pref.hyogo.jp
-!pref.ibaraki.jp
-!pref.ishikawa.jp
-!pref.iwate.jp
-!pref.kagawa.jp
-!pref.kagoshima.jp
-!pref.kanagawa.jp
-!pref.kochi.jp
-!pref.kumamoto.jp
-!pref.kyoto.jp
-!pref.mie.jp
-!pref.miyagi.jp
-!pref.miyazaki.jp
-!pref.nagano.jp
-!pref.nagasaki.jp
-!pref.nara.jp
-!pref.niigata.jp
-!pref.oita.jp
-!pref.okayama.jp
-!pref.okinawa.jp
-!pref.osaka.jp
-!pref.saga.jp
-!pref.saitama.jp
-!pref.shiga.jp
-!pref.shimane.jp
-!pref.shizuoka.jp
-!pref.tochigi.jp
-!pref.tokushima.jp
-!pref.tottori.jp
-!pref.toyama.jp
-!pref.wakayama.jp
-!pref.yamagata.jp
-!pref.yamaguchi.jp
-!pref.yamanashi.jp
-!city.chiba.jp
-!city.fukuoka.jp
-!city.hiroshima.jp
-!city.kawasaki.jp
-!city.kitakyushu.jp
-!city.kobe.jp
-!city.kyoto.jp
-!city.nagoya.jp
-!city.niigata.jp
-!city.okayama.jp
-!city.osaka.jp
-!city.saitama.jp
-!city.sapporo.jp
-!city.sendai.jp
-!city.shizuoka.jp
-!city.yokohama.jp
-
-// ke : http://www.kenic.or.ke/index.php?option=com_content&task=view&id=117&Itemid=145
-*.ke
-
-// kg : http://www.domain.kg/dmn_n.html
-kg
-org.kg
-net.kg
-com.kg
-edu.kg
-gov.kg
-mil.kg
-
-// kh : http://www.mptc.gov.kh/dns_registration.htm
-*.kh
-
-// ki : http://www.ki/dns/index.html
-ki
-edu.ki
-biz.ki
-net.ki
-org.ki
-gov.ki
-info.ki
-com.ki
-
-// km : http://en.wikipedia.org/wiki/.km
-// http://www.domaine.km/documents/charte.doc
-km
-org.km
-nom.km
-gov.km
-prd.km
-tm.km
-edu.km
-mil.km
-ass.km
-com.km
-// These are only mentioned as proposed suggestions at domaine.km, but
-// http://en.wikipedia.org/wiki/.km says they're available for registration:
-coop.km
-asso.km
-presse.km
-medecin.km
-notaires.km
-pharmaciens.km
-veterinaire.km
-gouv.km
-
-// kn : http://en.wikipedia.org/wiki/.kn
-// http://www.dot.kn/domainRules.html
-kn
-net.kn
-org.kn
-edu.kn
-gov.kn
-
-// kp : http://www.kcce.kp/en_index.php
-com.kp
-edu.kp
-gov.kp
-org.kp
-rep.kp
-tra.kp
-
-// kr : http://en.wikipedia.org/wiki/.kr
-// see also: http://domain.nida.or.kr/eng/registration.jsp
-kr
-ac.kr
-co.kr
-es.kr
-go.kr
-hs.kr
-kg.kr
-mil.kr
-ms.kr
-ne.kr
-or.kr
-pe.kr
-re.kr
-sc.kr
-// kr geographical names
-busan.kr
-chungbuk.kr
-chungnam.kr
-daegu.kr
-daejeon.kr
-gangwon.kr
-gwangju.kr
-gyeongbuk.kr
-gyeonggi.kr
-gyeongnam.kr
-incheon.kr
-jeju.kr
-jeonbuk.kr
-jeonnam.kr
-seoul.kr
-ulsan.kr
-
-// kw : http://en.wikipedia.org/wiki/.kw
-*.kw
-
-// ky : http://www.icta.ky/da_ky_reg_dom.php
-// Confirmed by registry <kysupport@perimeterusa.com> 2008-06-17
-ky
-edu.ky
-gov.ky
-com.ky
-org.ky
-net.ky
-
-// kz : http://en.wikipedia.org/wiki/.kz
-// see also: http://www.nic.kz/rules/index.jsp
-kz
-org.kz
-edu.kz
-net.kz
-gov.kz
-mil.kz
-com.kz
-
-// la : http://en.wikipedia.org/wiki/.la
-// Submitted by registry <gavin.brown@nic.la> 2008-06-10
-la
-int.la
-net.la
-info.la
-edu.la
-gov.la
-per.la
-com.la
-org.la
-
-// lb : http://en.wikipedia.org/wiki/.lb
-// Submitted by registry <randy@psg.com> 2008-06-17
-com.lb
-edu.lb
-gov.lb
-net.lb
-org.lb
-
-// lc : http://en.wikipedia.org/wiki/.lc
-// see also: http://www.nic.lc/rules.htm
-lc
-com.lc
-net.lc
-co.lc
-org.lc
-edu.lc
-gov.lc
-
-// li : http://en.wikipedia.org/wiki/.li
-li
-
-// lk : http://www.nic.lk/seclevpr.html
-lk
-gov.lk
-sch.lk
-net.lk
-int.lk
-com.lk
-org.lk
-edu.lk
-ngo.lk
-soc.lk
-web.lk
-ltd.lk
-assn.lk
-grp.lk
-hotel.lk
-
-// lr : http://psg.com/dns/lr/lr.txt
-// Submitted by registry <randy@psg.com> 2008-06-17
-com.lr
-edu.lr
-gov.lr
-org.lr
-net.lr
-
-// ls : http://en.wikipedia.org/wiki/.ls
-ls
-co.ls
-org.ls
-
-// lt : http://en.wikipedia.org/wiki/.lt
-lt
-// gov.lt : http://www.gov.lt/index_en.php
-gov.lt
-
-// lu : http://www.dns.lu/en/
-lu
-
-// lv : http://www.nic.lv/DNS/En/generic.php
-lv
-com.lv
-edu.lv
-gov.lv
-org.lv
-mil.lv
-id.lv
-net.lv
-asn.lv
-conf.lv
-
-// ly : http://www.nic.ly/regulations.php
-ly
-com.ly
-net.ly
-gov.ly
-plc.ly
-edu.ly
-sch.ly
-med.ly
-org.ly
-id.ly
-
-// ma : http://en.wikipedia.org/wiki/.ma
-// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf
-ma
-co.ma
-net.ma
-gov.ma
-org.ma
-ac.ma
-press.ma
-
-// mc : http://www.nic.mc/
-mc
-tm.mc
-asso.mc
-
-// md : http://en.wikipedia.org/wiki/.md
-md
-
-// me : http://en.wikipedia.org/wiki/.me
-me
-co.me
-net.me
-org.me
-edu.me
-ac.me
-gov.me
-its.me
-priv.me
-
-// mg : http://www.nic.mg/tarif.htm
-mg
-org.mg
-nom.mg
-gov.mg
-prd.mg
-tm.mg
-edu.mg
-mil.mg
-com.mg
-
-// mh : http://en.wikipedia.org/wiki/.mh
-mh
-
-// mil : http://en.wikipedia.org/wiki/.mil
-mil
-
-// mk : http://en.wikipedia.org/wiki/.mk
-// see also: http://dns.marnet.net.mk/postapka.php
-mk
-com.mk
-org.mk
-net.mk
-edu.mk
-gov.mk
-inf.mk
-name.mk
-
-// ml : http://www.gobin.info/domainname/ml-template.doc
-// see also: http://en.wikipedia.org/wiki/.ml
-ml
-com.ml
-edu.ml
-gouv.ml
-gov.ml
-net.ml
-org.ml
-presse.ml
-
-// mm : http://en.wikipedia.org/wiki/.mm
-*.mm
-
-// mn : http://en.wikipedia.org/wiki/.mn
-mn
-gov.mn
-edu.mn
-org.mn
-
-// mo : http://www.monic.net.mo/
-mo
-com.mo
-net.mo
-org.mo
-edu.mo
-gov.mo
-
-// mobi : http://en.wikipedia.org/wiki/.mobi
-mobi
-
-// mp : http://www.dot.mp/
-// Confirmed by registry <dcamacho@saipan.com> 2008-06-17
-mp
-
-// mq : http://en.wikipedia.org/wiki/.mq
-mq
-
-// mr : http://en.wikipedia.org/wiki/.mr
-mr
-gov.mr
-
-// ms : http://en.wikipedia.org/wiki/.ms
-ms
-
-// mt : https://www.nic.org.mt/dotmt/
-*.mt
-
-// mu : http://en.wikipedia.org/wiki/.mu
-mu
-com.mu
-net.mu
-org.mu
-gov.mu
-ac.mu
-co.mu
-or.mu
-
-// museum : http://about.museum/naming/
-// http://index.museum/
-museum
-academy.museum
-agriculture.museum
-air.museum
-airguard.museum
-alabama.museum
-alaska.museum
-amber.museum
-ambulance.museum
-american.museum
-americana.museum
-americanantiques.museum
-americanart.museum
-amsterdam.museum
-and.museum
-annefrank.museum
-anthro.museum
-anthropology.museum
-antiques.museum
-aquarium.museum
-arboretum.museum
-archaeological.museum
-archaeology.museum
-architecture.museum
-art.museum
-artanddesign.museum
-artcenter.museum
-artdeco.museum
-arteducation.museum
-artgallery.museum
-arts.museum
-artsandcrafts.museum
-asmatart.museum
-assassination.museum
-assisi.museum
-association.museum
-astronomy.museum
-atlanta.museum
-austin.museum
-australia.museum
-automotive.museum
-aviation.museum
-axis.museum
-badajoz.museum
-baghdad.museum
-bahn.museum
-bale.museum
-baltimore.museum
-barcelona.museum
-baseball.museum
-basel.museum
-baths.museum
-bauern.museum
-beauxarts.museum
-beeldengeluid.museum
-bellevue.museum
-bergbau.museum
-berkeley.museum
-berlin.museum
-bern.museum
-bible.museum
-bilbao.museum
-bill.museum
-birdart.museum
-birthplace.museum
-bonn.museum
-boston.museum
-botanical.museum
-botanicalgarden.museum
-botanicgarden.museum
-botany.museum
-brandywinevalley.museum
-brasil.museum
-bristol.museum
-british.museum
-britishcolumbia.museum
-broadcast.museum
-brunel.museum
-brussel.museum
-brussels.museum
-bruxelles.museum
-building.museum
-burghof.museum
-bus.museum
-bushey.museum
-cadaques.museum
-california.museum
-cambridge.museum
-can.museum
-canada.museum
-capebreton.museum
-carrier.museum
-cartoonart.museum
-casadelamoneda.museum
-castle.museum
-castres.museum
-celtic.museum
-center.museum
-chattanooga.museum
-cheltenham.museum
-chesapeakebay.museum
-chicago.museum
-children.museum
-childrens.museum
-childrensgarden.museum
-chiropractic.museum
-chocolate.museum
-christiansburg.museum
-cincinnati.museum
-cinema.museum
-circus.museum
-civilisation.museum
-civilization.museum
-civilwar.museum
-clinton.museum
-clock.museum
-coal.museum
-coastaldefence.museum
-cody.museum
-coldwar.museum
-collection.museum
-colonialwilliamsburg.museum
-coloradoplateau.museum
-columbia.museum
-columbus.museum
-communication.museum
-communications.museum
-community.museum
-computer.museum
-computerhistory.museum
-comunicações.museum
-contemporary.museum
-contemporaryart.museum
-convent.museum
-copenhagen.museum
-corporation.museum
-correios-e-telecomunicações.museum
-corvette.museum
-costume.museum
-countryestate.museum
-county.museum
-crafts.museum
-cranbrook.museum
-creation.museum
-cultural.museum
-culturalcenter.museum
-culture.museum
-cyber.museum
-cymru.museum
-dali.museum
-dallas.museum
-database.museum
-ddr.museum
-decorativearts.museum
-delaware.museum
-delmenhorst.museum
-denmark.museum
-depot.museum
-design.museum
-detroit.museum
-dinosaur.museum
-discovery.museum
-dolls.museum
-donostia.museum
-durham.museum
-eastafrica.museum
-eastcoast.museum
-education.museum
-educational.museum
-egyptian.museum
-eisenbahn.museum
-elburg.museum
-elvendrell.museum
-embroidery.museum
-encyclopedic.museum
-england.museum
-entomology.museum
-environment.museum
-environmentalconservation.museum
-epilepsy.museum
-essex.museum
-estate.museum
-ethnology.museum
-exeter.museum
-exhibition.museum
-family.museum
-farm.museum
-farmequipment.museum
-farmers.museum
-farmstead.museum
-field.museum
-figueres.museum
-filatelia.museum
-film.museum
-fineart.museum
-finearts.museum
-finland.museum
-flanders.museum
-florida.museum
-force.museum
-fortmissoula.museum
-fortworth.museum
-foundation.museum
-francaise.museum
-frankfurt.museum
-franziskaner.museum
-freemasonry.museum
-freiburg.museum
-fribourg.museum
-frog.museum
-fundacio.museum
-furniture.museum
-gallery.museum
-garden.museum
-gateway.museum
-geelvinck.museum
-gemological.museum
-geology.museum
-georgia.museum
-giessen.museum
-glas.museum
-glass.museum
-gorge.museum
-grandrapids.museum
-graz.museum
-guernsey.museum
-halloffame.museum
-hamburg.museum
-handson.museum
-harvestcelebration.museum
-hawaii.museum
-health.museum
-heimatunduhren.museum
-hellas.museum
-helsinki.museum
-hembygdsforbund.museum
-heritage.museum
-histoire.museum
-historical.museum
-historicalsociety.museum
-historichouses.museum
-historisch.museum
-historisches.museum
-history.museum
-historyofscience.museum
-horology.museum
-house.museum
-humanities.museum
-illustration.museum
-imageandsound.museum
-indian.museum
-indiana.museum
-indianapolis.museum
-indianmarket.museum
-intelligence.museum
-interactive.museum
-iraq.museum
-iron.museum
-isleofman.museum
-jamison.museum
-jefferson.museum
-jerusalem.museum
-jewelry.museum
-jewish.museum
-jewishart.museum
-jfk.museum
-journalism.museum
-judaica.museum
-judygarland.museum
-juedisches.museum
-juif.museum
-karate.museum
-karikatur.museum
-kids.museum
-koebenhavn.museum
-koeln.museum
-kunst.museum
-kunstsammlung.museum
-kunstunddesign.museum
-labor.museum
-labour.museum
-lajolla.museum
-lancashire.museum
-landes.museum
-lans.museum
-läns.museum
-larsson.museum
-lewismiller.museum
-lincoln.museum
-linz.museum
-living.museum
-livinghistory.museum
-localhistory.museum
-london.museum
-losangeles.museum
-louvre.museum
-loyalist.museum
-lucerne.museum
-luxembourg.museum
-luzern.museum
-mad.museum
-madrid.museum
-mallorca.museum
-manchester.museum
-mansion.museum
-mansions.museum
-manx.museum
-marburg.museum
-maritime.museum
-maritimo.museum
-maryland.museum
-marylhurst.museum
-media.museum
-medical.museum
-medizinhistorisches.museum
-meeres.museum
-memorial.museum
-mesaverde.museum
-michigan.museum
-midatlantic.museum
-military.museum
-mill.museum
-miners.museum
-mining.museum
-minnesota.museum
-missile.museum
-missoula.museum
-modern.museum
-moma.museum
-money.museum
-monmouth.museum
-monticello.museum
-montreal.museum
-moscow.museum
-motorcycle.museum
-muenchen.museum
-muenster.museum
-mulhouse.museum
-muncie.museum
-museet.museum
-museumcenter.museum
-museumvereniging.museum
-music.museum
-national.museum
-nationalfirearms.museum
-nationalheritage.museum
-nativeamerican.museum
-naturalhistory.museum
-naturalhistorymuseum.museum
-naturalsciences.museum
-nature.museum
-naturhistorisches.museum
-natuurwetenschappen.museum
-naumburg.museum
-naval.museum
-nebraska.museum
-neues.museum
-newhampshire.museum
-newjersey.museum
-newmexico.museum
-newport.museum
-newspaper.museum
-newyork.museum
-niepce.museum
-norfolk.museum
-north.museum
-nrw.museum
-nuernberg.museum
-nuremberg.museum
-nyc.museum
-nyny.museum
-oceanographic.museum
-oceanographique.museum
-omaha.museum
-online.museum
-ontario.museum
-openair.museum
-oregon.museum
-oregontrail.museum
-otago.museum
-oxford.museum
-pacific.museum
-paderborn.museum
-palace.museum
-paleo.museum
-palmsprings.museum
-panama.museum
-paris.museum
-pasadena.museum
-pharmacy.museum
-philadelphia.museum
-philadelphiaarea.museum
-philately.museum
-phoenix.museum
-photography.museum
-pilots.museum
-pittsburgh.museum
-planetarium.museum
-plantation.museum
-plants.museum
-plaza.museum
-portal.museum
-portland.museum
-portlligat.museum
-posts-and-telecommunications.museum
-preservation.museum
-presidio.museum
-press.museum
-project.museum
-public.museum
-pubol.museum
-quebec.museum
-railroad.museum
-railway.museum
-research.museum
-resistance.museum
-riodejaneiro.museum
-rochester.museum
-rockart.museum
-roma.museum
-russia.museum
-saintlouis.museum
-salem.museum
-salvadordali.museum
-salzburg.museum
-sandiego.museum
-sanfrancisco.museum
-santabarbara.museum
-santacruz.museum
-santafe.museum
-saskatchewan.museum
-satx.museum
-savannahga.museum
-schlesisches.museum
-schoenbrunn.museum
-schokoladen.museum
-school.museum
-schweiz.museum
-science.museum
-scienceandhistory.museum
-scienceandindustry.museum
-sciencecenter.museum
-sciencecenters.museum
-science-fiction.museum
-sciencehistory.museum
-sciences.museum
-sciencesnaturelles.museum
-scotland.museum
-seaport.museum
-settlement.museum
-settlers.museum
-shell.museum
-sherbrooke.museum
-sibenik.museum
-silk.museum
-ski.museum
-skole.museum
-society.museum
-sologne.museum
-soundandvision.museum
-southcarolina.museum
-southwest.museum
-space.museum
-spy.museum
-square.museum
-stadt.museum
-stalbans.museum
-starnberg.museum
-state.museum
-stateofdelaware.museum
-station.museum
-steam.museum
-steiermark.museum
-stjohn.museum
-stockholm.museum
-stpetersburg.museum
-stuttgart.museum
-suisse.museum
-surgeonshall.museum
-surrey.museum
-svizzera.museum
-sweden.museum
-sydney.museum
-tank.museum
-tcm.museum
-technology.museum
-telekommunikation.museum
-television.museum
-texas.museum
-textile.museum
-theater.museum
-time.museum
-timekeeping.museum
-topology.museum
-torino.museum
-touch.museum
-town.museum
-transport.museum
-tree.museum
-trolley.museum
-trust.museum
-trustee.museum
-uhren.museum
-ulm.museum
-undersea.museum
-university.museum
-usa.museum
-usantiques.museum
-usarts.museum
-uscountryestate.museum
-usculture.museum
-usdecorativearts.museum
-usgarden.museum
-ushistory.museum
-ushuaia.museum
-uslivinghistory.museum
-utah.museum
-uvic.museum
-valley.museum
-vantaa.museum
-versailles.museum
-viking.museum
-village.museum
-virginia.museum
-virtual.museum
-virtuel.museum
-vlaanderen.museum
-volkenkunde.museum
-wales.museum
-wallonie.museum
-war.museum
-washingtondc.museum
-watchandclock.museum
-watch-and-clock.museum
-western.museum
-westfalen.museum
-whaling.museum
-wildlife.museum
-williamsburg.museum
-windmill.museum
-workshop.museum
-york.museum
-yorkshire.museum
-yosemite.museum
-youth.museum
-zoological.museum
-zoology.museum
-ירושלים.museum
-иком.museum
-
-// mv : http://en.wikipedia.org/wiki/.mv
-// "mv" included because, contra Wikipedia, google.mv exists.
-mv
-aero.mv
-biz.mv
-com.mv
-coop.mv
-edu.mv
-gov.mv
-info.mv
-int.mv
-mil.mv
-museum.mv
-name.mv
-net.mv
-org.mv
-pro.mv
-
-// mw : http://www.registrar.mw/
-mw
-ac.mw
-biz.mw
-co.mw
-com.mw
-coop.mw
-edu.mw
-gov.mw
-int.mw
-museum.mw
-net.mw
-org.mw
-
-// mx : http://www.nic.mx/
-// Submitted by registry <farias@nic.mx> 2008-06-19
-mx
-com.mx
-org.mx
-gob.mx
-edu.mx
-net.mx
-
-// my : http://www.mynic.net.my/
-my
-com.my
-net.my
-org.my
-gov.my
-edu.my
-mil.my
-name.my
-
-// mz : http://www.gobin.info/domainname/mz-template.doc
-*.mz
-
-// na : http://www.na-nic.com.na/
-// http://www.info.na/domain/
-na
-info.na
-pro.na
-name.na
-school.na
-or.na
-dr.na
-us.na
-mx.na
-ca.na
-in.na
-cc.na
-tv.na
-ws.na
-mobi.na
-co.na
-com.na
-org.na
-
-// name : has 2nd-level tlds, but there's no list of them
-name
-
-// nc : http://www.cctld.nc/
-nc
-asso.nc
-
-// ne : http://en.wikipedia.org/wiki/.ne
-ne
-
-// net : http://en.wikipedia.org/wiki/.net
-net
-
-// nf : http://en.wikipedia.org/wiki/.nf
-nf
-com.nf
-net.nf
-per.nf
-rec.nf
-web.nf
-arts.nf
-firm.nf
-info.nf
-other.nf
-store.nf
-
-// ng : http://psg.com/dns/ng/
-// Submitted by registry <randy@psg.com> 2008-06-17
-ac.ng
-com.ng
-edu.ng
-gov.ng
-net.ng
-org.ng
-
-// ni : http://www.nic.ni/dominios.htm
-*.ni
-
-// nl : http://www.domain-registry.nl/ace.php/c,728,122,,,,Home.html
-// Confirmed by registry <Antoin.Verschuren@sidn.nl> (with technical
-// reservations) 2008-06-08
-nl
-
-// BV.nl will be a registry for dutch BV's (besloten vennootschap)
-bv.nl
-
-// no : http://www.norid.no/regelverk/index.en.html
-// The Norwegian registry has declined to notify us of updates. The web pages
-// referenced below are the official source of the data. There is also an
-// announce mailing list: 
-// https://postlister.uninett.no/sympa/info/norid-diskusjon
-no
-// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html
-fhs.no
-vgs.no
-fylkesbibl.no
-folkebibl.no
-museum.no
-idrett.no
-priv.no
-// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html
-mil.no
-stat.no
-dep.no
-kommune.no
-herad.no
-// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html
-// counties
-aa.no
-ah.no
-bu.no
-fm.no
-hl.no
-hm.no
-jan-mayen.no
-mr.no
-nl.no
-nt.no
-of.no
-ol.no
-oslo.no
-rl.no
-sf.no
-st.no
-svalbard.no
-tm.no
-tr.no
-va.no
-vf.no
-// primary and lower secondary schools per county
-gs.aa.no
-gs.ah.no
-gs.bu.no
-gs.fm.no
-gs.hl.no
-gs.hm.no
-gs.jan-mayen.no
-gs.mr.no
-gs.nl.no
-gs.nt.no
-gs.of.no
-gs.ol.no
-gs.oslo.no
-gs.rl.no
-gs.sf.no
-gs.st.no
-gs.svalbard.no
-gs.tm.no
-gs.tr.no
-gs.va.no
-gs.vf.no
-// cities
-akrehamn.no
-åkrehamn.no
-algard.no
-ålgård.no
-arna.no
-brumunddal.no
-bryne.no
-bronnoysund.no
-brønnøysund.no
-drobak.no
-drøbak.no
-egersund.no
-fetsund.no
-floro.no
-florø.no
-fredrikstad.no
-hokksund.no
-honefoss.no
-hønefoss.no
-jessheim.no
-jorpeland.no
-jørpeland.no
-kirkenes.no
-kopervik.no
-krokstadelva.no
-langevag.no
-langevåg.no
-leirvik.no
-mjondalen.no
-mjøndalen.no
-mo-i-rana.no
-mosjoen.no
-mosjøen.no
-nesoddtangen.no
-orkanger.no
-osoyro.no
-osøyro.no
-raholt.no
-råholt.no
-sandnessjoen.no
-sandnessjøen.no
-skedsmokorset.no
-slattum.no
-spjelkavik.no
-stathelle.no
-stavern.no
-stjordalshalsen.no
-stjørdalshalsen.no
-tananger.no
-tranby.no
-vossevangen.no
-// communities
-afjord.no
-åfjord.no
-agdenes.no
-al.no
-ål.no
-alesund.no
-ålesund.no
-alstahaug.no
-alta.no
-áltá.no
-alaheadju.no
-álaheadju.no
-alvdal.no
-amli.no
-åmli.no
-amot.no
-åmot.no
-andebu.no
-andoy.no
-andøy.no
-andasuolo.no
-ardal.no
-årdal.no
-aremark.no
-arendal.no
-ås.no
-aseral.no
-åseral.no
-asker.no
-askim.no
-askvoll.no
-askoy.no
-askøy.no
-asnes.no
-åsnes.no
-audnedaln.no
-aukra.no
-aure.no
-aurland.no
-aurskog-holand.no
-aurskog-høland.no
-austevoll.no
-austrheim.no
-averoy.no
-averøy.no
-balestrand.no
-ballangen.no
-balat.no
-bálát.no
-balsfjord.no
-bahccavuotna.no
-báhccavuotna.no
-bamble.no
-bardu.no
-beardu.no
-beiarn.no
-bajddar.no
-bájddar.no
-baidar.no
-báidár.no
-berg.no
-bergen.no
-berlevag.no
-berlevåg.no
-bearalvahki.no
-bearalváhki.no
-bindal.no
-birkenes.no
-bjarkoy.no
-bjarkøy.no
-bjerkreim.no
-bjugn.no
-bodo.no
-bodø.no
-badaddja.no
-bådåddjå.no
-budejju.no
-bokn.no
-bremanger.no
-bronnoy.no
-brønnøy.no
-bygland.no
-bykle.no
-barum.no
-bærum.no
-bo.telemark.no
-bø.telemark.no
-bo.nordland.no
-bø.nordland.no
-bievat.no
-bievát.no
-bomlo.no
-bømlo.no
-batsfjord.no
-båtsfjord.no
-bahcavuotna.no
-báhcavuotna.no
-dovre.no
-drammen.no
-drangedal.no
-dyroy.no
-dyrøy.no
-donna.no
-dønna.no
-eid.no
-eidfjord.no
-eidsberg.no
-eidskog.no
-eidsvoll.no
-eigersund.no
-elverum.no
-enebakk.no
-engerdal.no
-etne.no
-etnedal.no
-evenes.no
-evenassi.no
-evenášši.no
-evje-og-hornnes.no
-farsund.no
-fauske.no
-fuossko.no
-fuoisku.no
-fedje.no
-fet.no
-finnoy.no
-finnøy.no
-fitjar.no
-fjaler.no
-fjell.no
-flakstad.no
-flatanger.no
-flekkefjord.no
-flesberg.no
-flora.no
-fla.no
-flå.no
-folldal.no
-forsand.no
-fosnes.no
-frei.no
-frogn.no
-froland.no
-frosta.no
-frana.no
-fræna.no
-froya.no
-frøya.no
-fusa.no
-fyresdal.no
-forde.no
-førde.no
-gamvik.no
-gangaviika.no
-gáŋgaviika.no
-gaular.no
-gausdal.no
-gildeskal.no
-gildeskål.no
-giske.no
-gjemnes.no
-gjerdrum.no
-gjerstad.no
-gjesdal.no
-gjovik.no
-gjøvik.no
-gloppen.no
-gol.no
-gran.no
-grane.no
-granvin.no
-gratangen.no
-grimstad.no
-grong.no
-kraanghke.no
-kråanghke.no
-grue.no
-gulen.no
-hadsel.no
-halden.no
-halsa.no
-hamar.no
-hamaroy.no
-habmer.no
-hábmer.no
-hapmir.no
-hápmir.no
-hammerfest.no
-hammarfeasta.no
-hámmárfeasta.no
-haram.no
-hareid.no
-harstad.no
-hasvik.no
-aknoluokta.no
-ákŋoluokta.no
-hattfjelldal.no
-aarborte.no
-haugesund.no
-hemne.no
-hemnes.no
-hemsedal.no
-heroy.more-og-romsdal.no
-herøy.møre-og-romsdal.no
-heroy.nordland.no
-herøy.nordland.no
-hitra.no
-hjartdal.no
-hjelmeland.no
-hobol.no
-hobøl.no
-hof.no
-hol.no
-hole.no
-holmestrand.no
-holtalen.no
-holtålen.no
-hornindal.no
-horten.no
-hurdal.no
-hurum.no
-hvaler.no
-hyllestad.no
-hagebostad.no
-hægebostad.no
-hoyanger.no
-høyanger.no
-hoylandet.no
-høylandet.no
-ha.no
-hå.no
-ibestad.no
-inderoy.no
-inderøy.no
-iveland.no
-jevnaker.no
-jondal.no
-jolster.no
-jølster.no
-karasjok.no
-karasjohka.no
-kárášjohka.no
-karlsoy.no
-galsa.no
-gálsá.no
-karmoy.no
-karmøy.no
-kautokeino.no
-guovdageaidnu.no
-klepp.no
-klabu.no
-klæbu.no
-kongsberg.no
-kongsvinger.no
-kragero.no
-kragerø.no
-kristiansand.no
-kristiansund.no
-krodsherad.no
-krødsherad.no
-kvalsund.no
-rahkkeravju.no
-ráhkkerávju.no
-kvam.no
-kvinesdal.no
-kvinnherad.no
-kviteseid.no
-kvitsoy.no
-kvitsøy.no
-kvafjord.no
-kvæfjord.no
-giehtavuoatna.no
-kvanangen.no
-kvænangen.no
-navuotna.no
-návuotna.no
-kafjord.no
-kåfjord.no
-gaivuotna.no
-gáivuotna.no
-larvik.no
-lavangen.no
-lavagis.no
-loabat.no
-loabát.no
-lebesby.no
-davvesiida.no
-leikanger.no
-leirfjord.no
-leka.no
-leksvik.no
-lenvik.no
-leangaviika.no
-leaŋgaviika.no
-lesja.no
-levanger.no
-lier.no
-lierne.no
-lillehammer.no
-lillesand.no
-lindesnes.no
-lindas.no
-lindås.no
-lom.no
-loppa.no
-lahppi.no
-láhppi.no
-lund.no
-lunner.no
-luroy.no
-lurøy.no
-luster.no
-lyngdal.no
-lyngen.no
-ivgu.no
-lardal.no
-lerdal.no
-lærdal.no
-lodingen.no
-lødingen.no
-lorenskog.no
-lørenskog.no
-loten.no
-løten.no
-malvik.no
-masoy.no
-måsøy.no
-muosat.no
-muosát.no
-mandal.no
-marker.no
-marnardal.no
-masfjorden.no
-meland.no
-meldal.no
-melhus.no
-meloy.no
-meløy.no
-meraker.no
-meråker.no
-moareke.no
-moåreke.no
-midsund.no
-midtre-gauldal.no
-modalen.no
-modum.no
-molde.no
-moskenes.no
-moss.no
-mosvik.no
-malselv.no
-målselv.no
-malatvuopmi.no
-málatvuopmi.no
-namdalseid.no
-aejrie.no
-namsos.no
-namsskogan.no
-naamesjevuemie.no
-nååmesjevuemie.no
-laakesvuemie.no
-nannestad.no
-narvik.no
-narviika.no
-naustdal.no
-nedre-eiker.no
-nes.akershus.no
-nes.buskerud.no
-nesna.no
-nesodden.no
-nesseby.no
-unjarga.no
-unjárga.no
-nesset.no
-nissedal.no
-nittedal.no
-nord-aurdal.no
-nord-fron.no
-nord-odal.no
-norddal.no
-nordkapp.no
-davvenjarga.no
-davvenjárga.no
-nordre-land.no
-nordreisa.no
-raisa.no
-ráisa.no
-nore-og-uvdal.no
-notodden.no
-naroy.no
-nærøy.no
-notteroy.no
-nøtterøy.no
-odda.no
-oksnes.no
-øksnes.no
-oppdal.no
-oppegard.no
-oppegård.no
-orkdal.no
-orland.no
-ørland.no
-orskog.no
-ørskog.no
-orsta.no
-ørsta.no
-os.hedmark.no
-os.hordaland.no
-osen.no
-osteroy.no
-osterøy.no
-ostre-toten.no
-østre-toten.no
-overhalla.no
-ovre-eiker.no
-øvre-eiker.no
-oyer.no
-øyer.no
-oygarden.no
-øygarden.no
-oystre-slidre.no
-øystre-slidre.no
-porsanger.no
-porsangu.no
-porsáŋgu.no
-porsgrunn.no
-radoy.no
-radøy.no
-rakkestad.no
-rana.no
-ruovat.no
-randaberg.no
-rauma.no
-rendalen.no
-rennebu.no
-rennesoy.no
-rennesøy.no
-rindal.no
-ringebu.no
-ringerike.no
-ringsaker.no
-rissa.no
-risor.no
-risør.no
-roan.no
-rollag.no
-rygge.no
-ralingen.no
-rælingen.no
-rodoy.no
-rødøy.no
-romskog.no
-rømskog.no
-roros.no
-røros.no
-rost.no
-røst.no
-royken.no
-røyken.no
-royrvik.no
-røyrvik.no
-rade.no
-råde.no
-salangen.no
-siellak.no
-saltdal.no
-salat.no
-sálát.no
-sálat.no
-samnanger.no
-sande.more-og-romsdal.no
-sande.møre-og-romsdal.no
-sande.vestfold.no
-sandefjord.no
-sandnes.no
-sandoy.no
-sandøy.no
-sarpsborg.no
-sauda.no
-sauherad.no
-sel.no
-selbu.no
-selje.no
-seljord.no
-sigdal.no
-siljan.no
-sirdal.no
-skaun.no
-skedsmo.no
-ski.no
-skien.no
-skiptvet.no
-skjervoy.no
-skjervøy.no
-skierva.no
-skiervá.no
-skjak.no
-skjåk.no
-skodje.no
-skanland.no
-skånland.no
-skanit.no
-skánit.no
-smola.no
-smøla.no
-snillfjord.no
-snasa.no
-snåsa.no
-snoasa.no
-snaase.no
-snåase.no
-sogndal.no
-sokndal.no
-sola.no
-solund.no
-songdalen.no
-sortland.no
-spydeberg.no
-stange.no
-stavanger.no
-steigen.no
-steinkjer.no
-stjordal.no
-stjørdal.no
-stokke.no
-stor-elvdal.no
-stord.no
-stordal.no
-storfjord.no
-omasvuotna.no
-strand.no
-stranda.no
-stryn.no
-sula.no
-suldal.no
-sund.no
-sunndal.no
-surnadal.no
-sveio.no
-svelvik.no
-sykkylven.no
-sogne.no
-søgne.no
-somna.no
-sømna.no
-sondre-land.no
-søndre-land.no
-sor-aurdal.no
-sør-aurdal.no
-sor-fron.no
-sør-fron.no
-sor-odal.no
-sør-odal.no
-sor-varanger.no
-sør-varanger.no
-matta-varjjat.no
-mátta-várjjat.no
-sorfold.no
-sørfold.no
-sorreisa.no
-sørreisa.no
-sorum.no
-sørum.no
-tana.no
-deatnu.no
-time.no
-tingvoll.no
-tinn.no
-tjeldsund.no
-dielddanuorri.no
-tjome.no
-tjøme.no
-tokke.no
-tolga.no
-torsken.no
-tranoy.no
-tranøy.no
-tromso.no
-tromsø.no
-tromsa.no
-romsa.no
-trondheim.no
-troandin.no
-trysil.no
-trana.no
-træna.no
-trogstad.no
-trøgstad.no
-tvedestrand.no
-tydal.no
-tynset.no
-tysfjord.no
-divtasvuodna.no
-divttasvuotna.no
-tysnes.no
-tysvar.no
-tysvær.no
-tonsberg.no
-tønsberg.no
-ullensaker.no
-ullensvang.no
-ulvik.no
-utsira.no
-vadso.no
-vadsø.no
-cahcesuolo.no
-čáhcesuolo.no
-vaksdal.no
-valle.no
-vang.no
-vanylven.no
-vardo.no
-vardø.no
-varggat.no
-várggát.no
-vefsn.no
-vaapste.no
-vega.no
-vegarshei.no
-vegårshei.no
-vennesla.no
-verdal.no
-verran.no
-vestby.no
-vestnes.no
-vestre-slidre.no
-vestre-toten.no
-vestvagoy.no
-vestvågøy.no
-vevelstad.no
-vik.no
-vikna.no
-vindafjord.no
-volda.no
-voss.no
-varoy.no
-værøy.no
-vagan.no
-vågan.no
-voagat.no
-vagsoy.no
-vågsøy.no
-vaga.no
-vågå.no
-valer.ostfold.no
-våler.østfold.no
-valer.hedmark.no
-våler.hedmark.no
-
-// np : http://www.mos.com.np/register.html
-*.np
-
-// nr : http://cenpac.net.nr/dns/index.html
-// Confirmed by registry <technician@cenpac.net.nr> 2008-06-17
-nr
-biz.nr
-info.nr
-gov.nr
-edu.nr
-org.nr
-net.nr
-com.nr
-
-// nu : http://en.wikipedia.org/wiki/.nu
-nu
-
-// nz : http://en.wikipedia.org/wiki/.nz
-*.nz
-
-// om : http://en.wikipedia.org/wiki/.om
-*.om
-!mediaphone.om
-!nawrastelecom.om
-!nawras.om
-!omanmobile.om
-!omanpost.om
-!omantel.om
-!rakpetroleum.om
-!siemens.om
-!songfest.om
-!statecouncil.om
-
-// org : http://en.wikipedia.org/wiki/.org
-org
-
-// pa : http://www.nic.pa/
-// Some additional second level "domains" resolve directly as hostnames, such as
-// pannet.pa, so we add a rule for "pa".
-pa
-ac.pa
-gob.pa
-com.pa
-org.pa
-sld.pa
-edu.pa
-net.pa
-ing.pa
-abo.pa
-med.pa
-nom.pa
-
-// pe : https://www.nic.pe/InformeFinalComision.pdf
-pe
-edu.pe
-gob.pe
-nom.pe
-mil.pe
-org.pe
-com.pe
-net.pe
-
-// pf : http://www.gobin.info/domainname/formulaire-pf.pdf
-pf
-com.pf
-org.pf
-edu.pf
-
-// pg : http://en.wikipedia.org/wiki/.pg
-*.pg
-
-// ph : http://www.domains.ph/FAQ2.asp
-// Submitted by registry <jed@email.com.ph> 2008-06-13
-ph
-com.ph
-net.ph
-org.ph
-gov.ph
-edu.ph
-ngo.ph
-mil.ph
-i.ph
-
-// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK
-pk
-com.pk
-net.pk
-edu.pk
-org.pk
-fam.pk
-biz.pk
-web.pk
-gov.pk
-gob.pk
-gok.pk
-gon.pk
-gop.pk
-gos.pk
-info.pk
-
-// pl : http://www.dns.pl/english/
-pl
-// NASK functional domains (nask.pl / dns.pl) : http://www.dns.pl/english/dns-funk.html
-aid.pl
-agro.pl
-atm.pl
-auto.pl
-biz.pl
-com.pl
-edu.pl
-gmina.pl
-gsm.pl
-info.pl
-mail.pl
-miasta.pl
-media.pl
-mil.pl
-net.pl
-nieruchomosci.pl
-nom.pl
-org.pl
-pc.pl
-powiat.pl
-priv.pl
-realestate.pl
-rel.pl
-sex.pl
-shop.pl
-sklep.pl
-sos.pl
-szkola.pl
-targi.pl
-tm.pl
-tourism.pl
-travel.pl
-turystyka.pl
-// ICM functional domains (icm.edu.pl)
-6bone.pl
-art.pl
-mbone.pl
-// Government domains (administred by ippt.gov.pl)
-gov.pl
-uw.gov.pl
-um.gov.pl
-ug.gov.pl
-upow.gov.pl
-starostwo.gov.pl
-so.gov.pl
-sr.gov.pl
-po.gov.pl
-pa.gov.pl
-// other functional domains
-ngo.pl
-irc.pl
-usenet.pl
-// NASK geographical domains : http://www.dns.pl/english/dns-regiony.html
-augustow.pl
-babia-gora.pl
-bedzin.pl
-beskidy.pl
-bialowieza.pl
-bialystok.pl
-bielawa.pl
-bieszczady.pl
-boleslawiec.pl
-bydgoszcz.pl
-bytom.pl
-cieszyn.pl
-czeladz.pl
-czest.pl
-dlugoleka.pl
-elblag.pl
-elk.pl
-glogow.pl
-gniezno.pl
-gorlice.pl
-grajewo.pl
-ilawa.pl
-jaworzno.pl
-jelenia-gora.pl
-jgora.pl
-kalisz.pl
-kazimierz-dolny.pl
-karpacz.pl
-kartuzy.pl
-kaszuby.pl
-katowice.pl
-kepno.pl
-ketrzyn.pl
-klodzko.pl
-kobierzyce.pl
-kolobrzeg.pl
-konin.pl
-konskowola.pl
-kutno.pl
-lapy.pl
-lebork.pl
-legnica.pl
-lezajsk.pl
-limanowa.pl
-lomza.pl
-lowicz.pl
-lubin.pl
-lukow.pl
-malbork.pl
-malopolska.pl
-mazowsze.pl
-mazury.pl
-mielec.pl
-mielno.pl
-mragowo.pl
-naklo.pl
-nowaruda.pl
-nysa.pl
-olawa.pl
-olecko.pl
-olkusz.pl
-olsztyn.pl
-opoczno.pl
-opole.pl
-ostroda.pl
-ostroleka.pl
-ostrowiec.pl
-ostrowwlkp.pl
-pila.pl
-pisz.pl
-podhale.pl
-podlasie.pl
-polkowice.pl
-pomorze.pl
-pomorskie.pl
-prochowice.pl
-pruszkow.pl
-przeworsk.pl
-pulawy.pl
-radom.pl
-rawa-maz.pl
-rybnik.pl
-rzeszow.pl
-sanok.pl
-sejny.pl
-siedlce.pl
-slask.pl
-slupsk.pl
-sosnowiec.pl
-stalowa-wola.pl
-skoczow.pl
-starachowice.pl
-stargard.pl
-suwalki.pl
-swidnica.pl
-swiebodzin.pl
-swinoujscie.pl
-szczecin.pl
-szczytno.pl
-tarnobrzeg.pl
-tgory.pl
-turek.pl
-tychy.pl
-ustka.pl
-walbrzych.pl
-warmia.pl
-warszawa.pl
-waw.pl
-wegrow.pl
-wielun.pl
-wlocl.pl
-wloclawek.pl
-wodzislaw.pl
-wolomin.pl
-wroclaw.pl
-zachpomor.pl
-zagan.pl
-zarow.pl
-zgora.pl
-zgorzelec.pl
-// TASK geographical domains (www.task.gda.pl/uslugi/dns)
-gda.pl
-gdansk.pl
-gdynia.pl
-med.pl
-sopot.pl
-// other geographical domains
-gliwice.pl
-krakow.pl
-poznan.pl
-wroc.pl
-zakopane.pl
-
-// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
-pm
-
-// pn : http://www.government.pn/PnRegistry/policies.htm
-pn
-gov.pn
-co.pn
-org.pn
-edu.pn
-net.pn
-
-// pr : http://www.nic.pr/index.asp?f=1
-pr
-com.pr
-net.pr
-org.pr
-gov.pr
-edu.pr
-isla.pr
-pro.pr
-biz.pr
-info.pr
-name.pr
-// these aren't mentioned on nic.pr, but on http://en.wikipedia.org/wiki/.pr
-est.pr
-prof.pr
-ac.pr
-
-// pro : http://www.nic.pro/support_faq.htm
-pro
-aca.pro
-bar.pro
-cpa.pro
-jur.pro
-law.pro
-med.pro
-eng.pro
-
-// ps : http://en.wikipedia.org/wiki/.ps
-// http://www.nic.ps/registration/policy.html#reg
-ps
-edu.ps
-gov.ps
-sec.ps
-plo.ps
-com.ps
-org.ps
-net.ps
-
-// pt : http://online.dns.pt/dns/start_dns
-pt
-net.pt
-gov.pt
-org.pt
-edu.pt
-int.pt
-publ.pt
-com.pt
-nome.pt
-
-// pw : http://en.wikipedia.org/wiki/.pw
-pw
-co.pw
-ne.pw
-or.pw
-ed.pw
-go.pw
-belau.pw
-
-// py : http://www.nic.py/faq_a.html#faq_b
-*.py
-
-// qa : http://domains.qa/en/
-qa
-com.qa
-edu.qa
-gov.qa
-mil.qa
-name.qa
-net.qa
-org.qa
-sch.qa
-
-// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs
-re
-com.re
-asso.re
-nom.re
-
-// ro : http://www.rotld.ro/
-ro
-com.ro
-org.ro
-tm.ro
-nt.ro
-nom.ro
-info.ro
-rec.ro
-arts.ro
-firm.ro
-store.ro
-www.ro
-
-// rs : http://en.wikipedia.org/wiki/.rs
-rs
-co.rs
-org.rs
-edu.rs
-ac.rs
-gov.rs
-in.rs
-
-// ru : http://www.cctld.ru/ru/docs/aktiv_8.php
-// Industry domains
-ru
-ac.ru
-com.ru
-edu.ru
-int.ru
-net.ru
-org.ru
-pp.ru
-// Geographical domains
-adygeya.ru
-altai.ru
-amur.ru
-arkhangelsk.ru
-astrakhan.ru
-bashkiria.ru
-belgorod.ru
-bir.ru
-bryansk.ru
-buryatia.ru
-cbg.ru
-chel.ru
-chelyabinsk.ru
-chita.ru
-chukotka.ru
-chuvashia.ru
-dagestan.ru
-dudinka.ru
-e-burg.ru
-grozny.ru
-irkutsk.ru
-ivanovo.ru
-izhevsk.ru
-jar.ru
-joshkar-ola.ru
-kalmykia.ru
-kaluga.ru
-kamchatka.ru
-karelia.ru
-kazan.ru
-kchr.ru
-kemerovo.ru
-khabarovsk.ru
-khakassia.ru
-khv.ru
-kirov.ru
-koenig.ru
-komi.ru
-kostroma.ru
-krasnoyarsk.ru
-kuban.ru
-kurgan.ru
-kursk.ru
-lipetsk.ru
-magadan.ru
-mari.ru
-mari-el.ru
-marine.ru
-mordovia.ru
-mosreg.ru
-msk.ru
-murmansk.ru
-nalchik.ru
-nnov.ru
-nov.ru
-novosibirsk.ru
-nsk.ru
-omsk.ru
-orenburg.ru
-oryol.ru
-palana.ru
-penza.ru
-perm.ru
-pskov.ru
-ptz.ru
-rnd.ru
-ryazan.ru
-sakhalin.ru
-samara.ru
-saratov.ru
-simbirsk.ru
-smolensk.ru
-spb.ru
-stavropol.ru
-stv.ru
-surgut.ru
-tambov.ru
-tatarstan.ru
-tom.ru
-tomsk.ru
-tsaritsyn.ru
-tsk.ru
-tula.ru
-tuva.ru
-tver.ru
-tyumen.ru
-udm.ru
-udmurtia.ru
-ulan-ude.ru
-vladikavkaz.ru
-vladimir.ru
-vladivostok.ru
-volgograd.ru
-vologda.ru
-voronezh.ru
-vrn.ru
-vyatka.ru
-yakutia.ru
-yamal.ru
-yaroslavl.ru
-yekaterinburg.ru
-yuzhno-sakhalinsk.ru
-// More geographical domains
-amursk.ru
-baikal.ru
-cmw.ru
-fareast.ru
-jamal.ru
-kms.ru
-k-uralsk.ru
-kustanai.ru
-kuzbass.ru
-magnitka.ru
-mytis.ru
-nakhodka.ru
-nkz.ru
-norilsk.ru
-oskol.ru
-pyatigorsk.ru
-rubtsovsk.ru
-snz.ru
-syzran.ru
-vdonsk.ru
-zgrad.ru
-// State domains
-gov.ru
-mil.ru
-// Technical domains
-test.ru
-
-// rw : http://www.nic.rw/cgi-bin/policy.pl
-rw
-gov.rw
-net.rw
-edu.rw
-ac.rw
-com.rw
-co.rw
-int.rw
-mil.rw
-gouv.rw
-
-// sa : http://www.nic.net.sa/
-sa
-com.sa
-net.sa
-org.sa
-gov.sa
-med.sa
-pub.sa
-edu.sa
-sch.sa
-
-// sb : http://www.sbnic.net.sb/
-// Submitted by registry <lee.humphries@telekom.com.sb> 2008-06-08
-sb
-com.sb
-edu.sb
-gov.sb
-net.sb
-org.sb
-
-// sc : http://www.nic.sc/
-sc
-com.sc
-gov.sc
-net.sc
-org.sc
-edu.sc
-
-// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm
-// Submitted by registry <admin@isoc.sd> 2008-06-17
-sd
-com.sd
-net.sd
-org.sd
-edu.sd
-med.sd
-gov.sd
-info.sd
-
-// se : http://en.wikipedia.org/wiki/.se
-// Submitted by registry <Patrik.Wallstrom@iis.se> 2008-06-24
-se
-a.se
-ac.se
-b.se
-bd.se
-brand.se
-c.se
-d.se
-e.se
-f.se
-fh.se
-fhsk.se
-fhv.se
-g.se
-h.se
-i.se
-k.se
-komforb.se
-kommunalforbund.se
-komvux.se
-l.se
-lanbib.se
-m.se
-n.se
-naturbruksgymn.se
-o.se
-org.se
-p.se
-parti.se
-pp.se
-press.se
-r.se
-s.se
-sshn.se
-t.se
-tm.se
-u.se
-w.se
-x.se
-y.se
-z.se
-
-// sg : http://www.nic.net.sg/sub_policies_agreement/2ld.html
-sg
-com.sg
-net.sg
-org.sg
-gov.sg
-edu.sg
-per.sg
-
-// sh : http://www.nic.sh/rules.html
-// list of 2nd level domains ?
-sh
-
-// si : http://en.wikipedia.org/wiki/.si
-si
-
-// sj : No registrations at this time.
-// Submitted by registry <jarle@uninett.no> 2008-06-16
-
-// sk : http://en.wikipedia.org/wiki/.sk
-// list of 2nd level domains ?
-sk
-
-// sl : http://www.nic.sl
-// Submitted by registry <adam@neoip.com> 2008-06-12
-sl
-com.sl
-net.sl
-edu.sl
-gov.sl
-org.sl
-
-// sm : http://en.wikipedia.org/wiki/.sm
-sm
-
-// sn : http://en.wikipedia.org/wiki/.sn
-sn
-art.sn
-com.sn
-edu.sn
-gouv.sn
-org.sn
-perso.sn
-univ.sn
-
-// so : http://www.soregistry.com/
-so
-com.so
-net.so
-org.so
-
-// sr : http://en.wikipedia.org/wiki/.sr
-sr
-
-// st : http://www.nic.st/html/policyrules/
-st
-co.st
-com.st
-consulado.st
-edu.st
-embaixada.st
-gov.st
-mil.st
-net.st
-org.st
-principe.st
-saotome.st
-store.st
-
-// su : http://en.wikipedia.org/wiki/.su
-su
-
-// sv : http://www.svnet.org.sv/svpolicy.html
-*.sv
-
-// sy : http://en.wikipedia.org/wiki/.sy
-// see also: http://www.gobin.info/domainname/sy.doc
-sy
-edu.sy
-gov.sy
-net.sy
-mil.sy
-com.sy
-org.sy
-
-// sz : http://en.wikipedia.org/wiki/.sz
-// http://www.sispa.org.sz/
-sz
-co.sz
-ac.sz
-org.sz
-
-// tc : http://en.wikipedia.org/wiki/.tc
-tc
-
-// td : http://en.wikipedia.org/wiki/.td
-td
-
-// tel: http://en.wikipedia.org/wiki/.tel
-// http://www.telnic.org/
-tel
-
-// tf : http://en.wikipedia.org/wiki/.tf
-tf
-
-// tg : http://en.wikipedia.org/wiki/.tg
-// http://www.nic.tg/nictg/index.php implies no reserved 2nd-level domains,
-// although this contradicts wikipedia.
-tg
-
-// th : http://en.wikipedia.org/wiki/.th
-// Submitted by registry <krit@thains.co.th> 2008-06-17
-th
-ac.th
-co.th
-go.th
-in.th
-mi.th
-net.th
-or.th
-
-// tj : http://www.nic.tj/policy.htm
-tj
-ac.tj
-biz.tj
-co.tj
-com.tj
-edu.tj
-go.tj
-gov.tj
-int.tj
-mil.tj
-name.tj
-net.tj
-nic.tj
-org.tj
-test.tj
-web.tj
-
-// tk : http://en.wikipedia.org/wiki/.tk
-tk
-
-// tl : http://en.wikipedia.org/wiki/.tl
-tl
-gov.tl
-
-// tm : http://www.nic.tm/rules.html
-// list of 2nd level tlds ?
-tm
-
-// tn : http://en.wikipedia.org/wiki/.tn
-// http://whois.ati.tn/
-tn
-com.tn
-ens.tn
-fin.tn
-gov.tn
-ind.tn
-intl.tn
-nat.tn
-net.tn
-org.tn
-info.tn
-perso.tn
-tourism.tn
-edunet.tn
-rnrt.tn
-rns.tn
-rnu.tn
-mincom.tn
-agrinet.tn
-defense.tn
-turen.tn
-
-// to : http://en.wikipedia.org/wiki/.to
-// Submitted by registry <egullich@colo.to> 2008-06-17
-to
-com.to
-gov.to
-net.to
-org.to
-edu.to
-mil.to
-
-// tr : http://en.wikipedia.org/wiki/.tr
-*.tr
-!nic.tr
-// Used by government in the TRNC
-// http://en.wikipedia.org/wiki/.nc.tr
-gov.nc.tr
-
-// travel : http://en.wikipedia.org/wiki/.travel
-travel
-
-// tt : http://www.nic.tt/
-tt
-co.tt
-com.tt
-org.tt
-net.tt
-biz.tt
-info.tt
-pro.tt
-int.tt
-coop.tt
-jobs.tt
-mobi.tt
-travel.tt
-museum.tt
-aero.tt
-name.tt
-gov.tt
-edu.tt
-
-// tv : http://en.wikipedia.org/wiki/.tv
-// Not listing any 2LDs as reserved since none seem to exist in practice,
-// Wikipedia notwithstanding.
-tv
-
-// tw : http://en.wikipedia.org/wiki/.tw
-tw
-edu.tw
-gov.tw
-mil.tw
-com.tw
-net.tw
-org.tw
-idv.tw
-game.tw
-ebiz.tw
-club.tw
-網路.tw
-組織.tw
-商業.tw
-
-// tz : http://en.wikipedia.org/wiki/.tz
-// Submitted by registry <randy@psg.com> 2008-06-17
-// Updated from http://www.tznic.or.tz/index.php/domains.html 2010-10-25
-ac.tz
-co.tz
-go.tz
-mil.tz
-ne.tz
-or.tz
-sc.tz
-
-// ua : http://www.nic.net.ua/
-ua
-com.ua
-edu.ua
-gov.ua
-in.ua
-net.ua
-org.ua
-// ua geo-names
-cherkassy.ua
-chernigov.ua
-chernovtsy.ua
-ck.ua
-cn.ua
-crimea.ua
-cv.ua
-dn.ua
-dnepropetrovsk.ua
-donetsk.ua
-dp.ua
-if.ua
-ivano-frankivsk.ua
-kh.ua
-kharkov.ua
-kherson.ua
-khmelnitskiy.ua
-kiev.ua
-kirovograd.ua
-km.ua
-kr.ua
-ks.ua
-kv.ua
-lg.ua
-lugansk.ua
-lutsk.ua
-lviv.ua
-mk.ua
-nikolaev.ua
-od.ua
-odessa.ua
-pl.ua
-poltava.ua
-rovno.ua
-rv.ua
-sebastopol.ua
-sumy.ua
-te.ua
-ternopil.ua
-uzhgorod.ua
-vinnica.ua
-vn.ua
-zaporizhzhe.ua
-zp.ua
-zhitomir.ua
-zt.ua
-
-// Private registries in .ua
-co.ua
-pp.ua
-
-// ug : http://www.registry.co.ug/
-ug
-co.ug
-ac.ug
-sc.ug
-go.ug
-ne.ug
-or.ug
-
-// uk : http://en.wikipedia.org/wiki/.uk
-*.uk
-*.sch.uk
-!bl.uk
-!british-library.uk
-!icnet.uk
-!jet.uk
-!mod.uk
-!nel.uk
-!nhs.uk
-!nic.uk
-!nls.uk
-!national-library-scotland.uk
-!parliament.uk
-!police.uk
-
-// us : http://en.wikipedia.org/wiki/.us
-us
-dni.us
-fed.us
-isa.us
-kids.us
-nsn.us
-// us geographic names
-ak.us
-al.us
-ar.us
-as.us
-az.us
-ca.us
-co.us
-ct.us
-dc.us
-de.us
-fl.us
-ga.us
-gu.us
-hi.us
-ia.us
-id.us
-il.us
-in.us
-ks.us
-ky.us
-la.us
-ma.us
-md.us
-me.us
-mi.us
-mn.us
-mo.us
-ms.us
-mt.us
-nc.us
-nd.us
-ne.us
-nh.us
-nj.us
-nm.us
-nv.us
-ny.us
-oh.us
-ok.us
-or.us
-pa.us
-pr.us
-ri.us
-sc.us
-sd.us
-tn.us
-tx.us
-ut.us
-vi.us
-vt.us
-va.us
-wa.us
-wi.us
-wv.us
-wy.us
-// The registrar notes several more specific domains available in each state,
-// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat
-// haphazard; in some states these domains resolve as addresses, while in others
-// only subdomains are available, or even nothing at all. We include the
-// most common ones where it's clear that different sites are different
-// entities.
-k12.ak.us
-k12.al.us
-k12.ar.us
-k12.as.us
-k12.az.us
-k12.ca.us
-k12.co.us
-k12.ct.us
-k12.dc.us
-k12.de.us
-k12.fl.us
-k12.ga.us
-k12.gu.us
-// k12.hi.us  Hawaii has a state-wide DOE login: bug 614565
-k12.ia.us
-k12.id.us
-k12.il.us
-k12.in.us
-k12.ks.us
-k12.ky.us
-k12.la.us
-k12.ma.us
-k12.md.us
-k12.me.us
-k12.mi.us
-k12.mn.us
-k12.mo.us
-k12.ms.us
-k12.mt.us
-k12.nc.us
-k12.nd.us
-k12.ne.us
-k12.nh.us
-k12.nj.us
-k12.nm.us
-k12.nv.us
-k12.ny.us
-k12.oh.us
-k12.ok.us
-k12.or.us
-k12.pa.us
-k12.pr.us
-k12.ri.us
-k12.sc.us
-k12.sd.us
-k12.tn.us
-k12.tx.us
-k12.ut.us
-k12.vi.us
-k12.vt.us
-k12.va.us
-k12.wa.us
-k12.wi.us
-k12.wv.us
-k12.wy.us
-
-cc.ak.us
-cc.al.us
-cc.ar.us
-cc.as.us
-cc.az.us
-cc.ca.us
-cc.co.us
-cc.ct.us
-cc.dc.us
-cc.de.us
-cc.fl.us
-cc.ga.us
-cc.gu.us
-cc.hi.us
-cc.ia.us
-cc.id.us
-cc.il.us
-cc.in.us
-cc.ks.us
-cc.ky.us
-cc.la.us
-cc.ma.us
-cc.md.us
-cc.me.us
-cc.mi.us
-cc.mn.us
-cc.mo.us
-cc.ms.us
-cc.mt.us
-cc.nc.us
-cc.nd.us
-cc.ne.us
-cc.nh.us
-cc.nj.us
-cc.nm.us
-cc.nv.us
-cc.ny.us
-cc.oh.us
-cc.ok.us
-cc.or.us
-cc.pa.us
-cc.pr.us
-cc.ri.us
-cc.sc.us
-cc.sd.us
-cc.tn.us
-cc.tx.us
-cc.ut.us
-cc.vi.us
-cc.vt.us
-cc.va.us
-cc.wa.us
-cc.wi.us
-cc.wv.us
-cc.wy.us
-
-lib.ak.us
-lib.al.us
-lib.ar.us
-lib.as.us
-lib.az.us
-lib.ca.us
-lib.co.us
-lib.ct.us
-lib.dc.us
-lib.de.us
-lib.fl.us
-lib.ga.us
-lib.gu.us
-lib.hi.us
-lib.ia.us
-lib.id.us
-lib.il.us
-lib.in.us
-lib.ks.us
-lib.ky.us
-lib.la.us
-lib.ma.us
-lib.md.us
-lib.me.us
-lib.mi.us
-lib.mn.us
-lib.mo.us
-lib.ms.us
-lib.mt.us
-lib.nc.us
-lib.nd.us
-lib.ne.us
-lib.nh.us
-lib.nj.us
-lib.nm.us
-lib.nv.us
-lib.ny.us
-lib.oh.us
-lib.ok.us
-lib.or.us
-lib.pa.us
-lib.pr.us
-lib.ri.us
-lib.sc.us
-lib.sd.us
-lib.tn.us
-lib.tx.us
-lib.ut.us
-lib.vi.us
-lib.vt.us
-lib.va.us
-lib.wa.us
-lib.wi.us
-lib.wv.us
-lib.wy.us
-
-// k12.ma.us contains school districts in Massachusetts. The 4LDs are 
-//  managed indepedently except for private (PVT), charter (CHTR) and
-//  parochial (PAROCH) schools.  Those are delegated dorectly to the 
-//  5LD operators.   <k12-ma-hostmaster _ at _ rsuc.gweep.net>
-pvt.k12.ma.us
-chtr.k12.ma.us
-paroch.k12.ma.us
-
-// uy : http://www.antel.com.uy/
-*.uy
-
-// uz : http://www.reg.uz/registerr.html
-// are there other 2nd level tlds ?
-uz
-com.uz
-co.uz
-
-// va : http://en.wikipedia.org/wiki/.va
-va
-
-// vc : http://en.wikipedia.org/wiki/.vc
-// Submitted by registry <kshah@ca.afilias.info> 2008-06-13
-vc
-com.vc
-net.vc
-org.vc
-gov.vc
-mil.vc
-edu.vc
-
-// ve : http://registro.nic.ve/nicve/registro/index.html
-*.ve
-
-// vg : http://en.wikipedia.org/wiki/.vg
-vg
-
-// vi : http://www.nic.vi/newdomainform.htm
-// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other
-// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they
-// are available for registration (which they do not seem to be).
-vi
-co.vi
-com.vi
-k12.vi
-net.vi
-org.vi
-
-// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp
-vn
-com.vn
-net.vn
-org.vn
-edu.vn
-gov.vn
-int.vn
-ac.vn
-biz.vn
-info.vn
-name.vn
-pro.vn
-health.vn
-
-// vu : http://en.wikipedia.org/wiki/.vu
-// list of 2nd level tlds ?
-vu
-
-// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
-wf
-
-// ws : http://en.wikipedia.org/wiki/.ws
-// http://samoanic.ws/index.dhtml
-ws
-com.ws
-net.ws
-org.ws
-gov.ws
-edu.ws
-
-// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
-yt
-
-// IDN ccTLDs
-// Please sort by ISO 3166 ccTLD, then punicode string
-// when submitting patches and follow this format:
-// <Punicode> ("<english word>" <language>) : <ISO 3166 ccTLD>
-// [optional sponsoring org]
-// <URL>
-
-// xn--mgbaam7a8h ("Emerat" Arabic) : AE
-//http://nic.ae/english/arabicdomain/rules.jsp
-امارات
-
-// xn--54b7fta0cc ("Bangla" Bangla) : BD  
-বাংলা
-
-// xn--fiqs8s ("China" Chinese-Han-Simplified <.Zhonggou>) : CN 
-// CNNIC
-// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
-中国
-
-// xn--fiqz9s ("China" Chinese-Han-Traditional <.Zhonggou>) : CN
-// CNNIC
-// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
-中國
-
-// xn--lgbbat1ad8j ("Algeria / Al Jazair" Arabic) : DZ  
-الجزائر
-
-// xn--wgbh1c ("Egypt" Arabic .masr) : EG
-// http://www.dotmasr.eg/
-مصر
-
-// xn--node ("ge" Georgian (Mkhedruli)) : GE  
-გე
-
-// xn--j6w193g ("Hong Kong" Chinese-Han) : HK
-// https://www2.hkirc.hk/register/rules.jsp
-香港
-
-// xn--h2brj9c ("Bharat" Devanagari) : IN  
-// India
-भारत
-
-// xn--mgbbh1a71e ("Bharat" Arabic) : IN  
-// India
-بھارت
-
-// xn--fpcrj9c3d ("Bharat" Telugu) : IN  
-// India
-భారత్
-
-// xn--gecrj9c ("Bharat" Gujarati) : IN  
-// India
-ભારત
-
-// xn--s9brj9c ("Bharat" Gurmukhi) : IN  
-// India
-ਭਾਰਤ
-
-// xn--45brj9c ("Bharat" Bengali) : IN  
-// India
-ভারত
-
-// xn--xkc2dl3a5ee0h ("India" Tamil) : IN  
-// India
-இந்தியா
-
-// xn--mgba3a4f16a ("Iran" Persian) : IR  
-ایران
-
-// xn--mgba3a4fra ("Iran" Arabic) : IR  
-ايران
-
-//xn--mgbayh7gpa ("al-Ordon" Arabic) JO
-//National Information Technology Center (NITC) 
-//Royal Scientific Society, Al-Jubeiha
-الاردن
-
-// xn--3e0b707e ("Republic of Korea" Hangul) : KR  
-한국
-
-// xn--fzc2c9e2c ("Lanka" Sinhalese-Sinhala) : LK
-// http://nic.lk
-ලංකා
-
-// xn--xkc2al3hye2a ("Ilangai" Tamil) : LK
-// http://nic.lk
-இலங்கை
-
-// xn--mgbc0a9azcg ("Morocco / al-Maghrib" Arabic) : MA  
-المغرب
-
-// xn--mgb9awbf ("Oman" Arabic) : OM  
-عمان
-
-// xn--ygbi2ammx ("Falasteen" Arabic) : PS
-// The Palestinian National Internet Naming Authority (PNINA)
-// http://www.pnina.ps
-فلسطين
-
-// xn--90a3ac ("srb" Cyrillic) : RS  
-срб
-
-// xn--p1ai ("rf" Russian-Cyrillic) : RU
-// http://www.cctld.ru/en/docs/rulesrf.php
-рф
-
-// xn--wgbl6a ("Qatar" Arabic) : QA
-// http://www.ict.gov.qa/
-قطر
-
-// xn--mgberp4a5d4ar ("AlSaudiah" Arabic) : SA
-// http://www.nic.net.sa/
-السعودية
-
-// xn--mgberp4a5d4a87g ("AlSaudiah" Arabic) variant : SA  
-السعودیة
-
-// xn--mgbqly7c0a67fbc ("AlSaudiah" Arabic) variant : SA  
-السعودیۃ
-
-// xn--mgbqly7cvafr ("AlSaudiah" Arabic) variant : SA  
-السعوديه
-
-// xn--ogbpf8fl ("Syria" Arabic) : SY  
-سورية
-
-// xn--mgbtf8fl ("Syria" Arabic) variant : SY  
-سوريا
-
-// xn--yfro4i67o Singapore ("Singapore" Chinese-Han) : SG
-新加坡
-
-// xn--clchc0ea0b2g2a9gcd ("Singapore" Tamil) : SG
-சிங்கப்பூர்
-
-// xn--o3cw4h ("Thai" Thai) : TH
-// http://www.thnic.co.th
-ไทย
-
-// xn--pgbs0dh ("Tunis") : TN
-// http://nic.tn
-تونس
-
-// xn--kpry57d ("Taiwan" Chinese-Han-Traditional) : TW
-// http://www.twnic.net/english/dn/dn_07a.htm
-台灣
-
-// xn--kprw13d ("Taiwan" Chinese-Han-Simplified) : TW
-// http://www.twnic.net/english/dn/dn_07a.htm
-台湾
-
-// xn--nnx388a ("Taiwan") variant : TW  
-臺灣
-
-// xn--j1amh ("ukr" Cyrillic) : UA  
-укр
-
-// xn--mgb2ddes ("AlYemen" Arabic) : YE  
-اليمن
-
-// xxx : http://icmregistry.com
-xxx
-
-// ye : http://www.y.net.ye/services/domain_name.htm
-*.ye
-
-// za : http://www.zadna.org.za/slds.html
-*.za
-
-// zm : http://en.wikipedia.org/wiki/.zm
-*.zm
-
-// zw : http://en.wikipedia.org/wiki/.zw
-*.zw
-
-// ===END ICANN DOMAINS===
-// ===BEGIN PRIVATE DOMAINS===
-
-// info.at : http://www.info.at/
-biz.at
-info.at
-
-// priv.at : http://www.nic.priv.at/
-// Submitted by registry <lendl@nic.at> 2008-06-09
-priv.at
-
-// co.ca : http://registry.co.ca
-co.ca
-
-// CentralNic : http://www.centralnic.com/names/domains
-// Confirmed by registry <gavin.brown@centralnic.com> 2008-06-09
-ar.com
-br.com
-cn.com
-de.com
-eu.com
-gb.com
-gr.com
-hu.com
-jpn.com
-kr.com
-no.com
-qc.com
-ru.com
-sa.com
-se.com
-uk.com
-us.com
-uy.com
-za.com
-gb.net
-jp.net
-se.net
-uk.net
-ae.org
-us.org
-com.de
-
-// Opera Software, A.S.A.
-// Requested by Yngve Pettersen <yngve@opera.com> 2009-11-26
-operaunite.com
-
-// Google, Inc.
-// Requested by Eduardo Vela <evn@google.com> 2010-09-06
-appspot.com
-
-// iki.fi : Submitted by Hannu Aronsson <haa@iki.fi> 2009-11-05
-iki.fi
-
-// c.la : http://www.c.la/
-c.la
-
-// ZaNiC : http://www.za.net/
-// Confirmed by registry <hostmaster@nic.za.net> 2009-10-03
-za.net
-za.org
-
-// CoDNS B.V.
-// Added 2010-05-23.
-co.nl
-co.no
-
-// Mainseek Sp. z o.o. : http://www.co.pl/
-co.pl
-
-// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/
-dyndns-at-home.com
-dyndns-at-work.com
-dyndns-blog.com
-dyndns-free.com
-dyndns-home.com
-dyndns-ip.com
-dyndns-mail.com
-dyndns-office.com
-dyndns-pics.com
-dyndns-remote.com
-dyndns-server.com
-dyndns-web.com
-dyndns-wiki.com
-dyndns-work.com
-dyndns.biz
-dyndns.info
-dyndns.org
-dyndns.tv
-at-band-camp.net
-ath.cx
-barrel-of-knowledge.info
-barrell-of-knowledge.info
-better-than.tv
-blogdns.com
-blogdns.net
-blogdns.org
-blogsite.org
-boldlygoingnowhere.org
-broke-it.net
-buyshouses.net
-cechire.com
-dnsalias.com
-dnsalias.net
-dnsalias.org
-dnsdojo.com
-dnsdojo.net
-dnsdojo.org
-does-it.net
-doesntexist.com
-doesntexist.org
-dontexist.com
-dontexist.net
-dontexist.org
-doomdns.com
-doomdns.org
-dvrdns.org
-dyn-o-saur.com
-dynalias.com
-dynalias.net
-dynalias.org
-dynathome.net
-dyndns.ws
-endofinternet.net
-endofinternet.org
-endoftheinternet.org
-est-a-la-maison.com
-est-a-la-masion.com
-est-le-patron.com
-est-mon-blogueur.com
-for-better.biz
-for-more.biz
-for-our.info
-for-some.biz
-for-the.biz
-forgot.her.name
-forgot.his.name
-from-ak.com
-from-al.com
-from-ar.com
-from-az.net
-from-ca.com
-from-co.net
-from-ct.com
-from-dc.com
-from-de.com
-from-fl.com
-from-ga.com
-from-hi.com
-from-ia.com
-from-id.com
-from-il.com
-from-in.com
-from-ks.com
-from-ky.com
-from-la.net
-from-ma.com
-from-md.com
-from-me.org
-from-mi.com
-from-mn.com
-from-mo.com
-from-ms.com
-from-mt.com
-from-nc.com
-from-nd.com
-from-ne.com
-from-nh.com
-from-nj.com
-from-nm.com
-from-nv.com
-from-ny.net
-from-oh.com
-from-ok.com
-from-or.com
-from-pa.com
-from-pr.com
-from-ri.com
-from-sc.com
-from-sd.com
-from-tn.com
-from-tx.com
-from-ut.com
-from-va.com
-from-vt.com
-from-wa.com
-from-wi.com
-from-wv.com
-from-wy.com
-ftpaccess.cc
-fuettertdasnetz.de
-game-host.org
-game-server.cc
-getmyip.com
-gets-it.net
-go.dyndns.org
-gotdns.com
-gotdns.org
-groks-the.info
-groks-this.info
-ham-radio-op.net
-here-for-more.info
-hobby-site.com
-hobby-site.org
-home.dyndns.org
-homedns.org
-homeftp.net
-homeftp.org
-homeip.net
-homelinux.com
-homelinux.net
-homelinux.org
-homeunix.com
-homeunix.net
-homeunix.org
-iamallama.com
-in-the-band.net
-is-a-anarchist.com
-is-a-blogger.com
-is-a-bookkeeper.com
-is-a-bruinsfan.org
-is-a-bulls-fan.com
-is-a-candidate.org
-is-a-caterer.com
-is-a-celticsfan.org
-is-a-chef.com
-is-a-chef.net
-is-a-chef.org
-is-a-conservative.com
-is-a-cpa.com
-is-a-cubicle-slave.com
-is-a-democrat.com
-is-a-designer.com
-is-a-doctor.com
-is-a-financialadvisor.com
-is-a-geek.com
-is-a-geek.net
-is-a-geek.org
-is-a-green.com
-is-a-guru.com
-is-a-hard-worker.com
-is-a-hunter.com
-is-a-knight.org
-is-a-landscaper.com
-is-a-lawyer.com
-is-a-liberal.com
-is-a-libertarian.com
-is-a-linux-user.org
-is-a-llama.com
-is-a-musician.com
-is-a-nascarfan.com
-is-a-nurse.com
-is-a-painter.com
-is-a-patsfan.org
-is-a-personaltrainer.com
-is-a-photographer.com
-is-a-player.com
-is-a-republican.com
-is-a-rockstar.com
-is-a-socialist.com
-is-a-soxfan.org
-is-a-student.com
-is-a-teacher.com
-is-a-techie.com
-is-a-therapist.com
-is-an-accountant.com
-is-an-actor.com
-is-an-actress.com
-is-an-anarchist.com
-is-an-artist.com
-is-an-engineer.com
-is-an-entertainer.com
-is-by.us
-is-certified.com
-is-found.org
-is-gone.com
-is-into-anime.com
-is-into-cars.com
-is-into-cartoons.com
-is-into-games.com
-is-leet.com
-is-lost.org
-is-not-certified.com
-is-saved.org
-is-slick.com
-is-uberleet.com
-is-very-bad.org
-is-very-evil.org
-is-very-good.org
-is-very-nice.org
-is-very-sweet.org
-is-with-theband.com
-isa-geek.com
-isa-geek.net
-isa-geek.org
-isa-hockeynut.com
-issmarterthanyou.com
-isteingeek.de
-istmein.de
-kicks-ass.net
-kicks-ass.org
-knowsitall.info
-land-4-sale.us
-lebtimnetz.de
-leitungsen.de
-likes-pie.com
-likescandy.com
-merseine.nu
-mine.nu
-misconfused.org
-mypets.ws
-myphotos.cc
-neat-url.com
-office-on-the.net
-on-the-web.tv
-podzone.net
-podzone.org
-readmyblog.org
-saves-the-whales.com
-scrapper-site.net
-scrapping.cc
-selfip.biz
-selfip.com
-selfip.info
-selfip.net
-selfip.org
-sells-for-less.com
-sells-for-u.com
-sells-it.net
-sellsyourhome.org
-servebbs.com
-servebbs.net
-servebbs.org
-serveftp.net
-serveftp.org
-servegame.org
-shacknet.nu
-simple-url.com
-space-to-rent.com
-stuff-4-sale.org
-stuff-4-sale.us
-teaches-yoga.com
-thruhere.net
-traeumtgerade.de
-webhop.biz
-webhop.info
-webhop.net
-webhop.org
-worse-than.tv
-writesthisblog.com
-
-// ===END PRIVATE DOMAINS===
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/test.js
deleted file mode 100644
index 5cbf536c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tough-cookie/test.js
+++ /dev/null
@@ -1,1625 +0,0 @@
-/*
- * Copyright GoInstant, Inc. and other contributors. All rights reserved.
- * 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.
- */
-'use strict';
-var vows = require('vows');
-var assert = require('assert');
-var async = require('async');
-
-// NOTE use require("tough-cookie") in your own code:
-var tough = require('./lib/cookie');
-var Cookie = tough.Cookie;
-var CookieJar = tough.CookieJar;
-
-
-function dateVows(table) {
-  var theVows = { };
-  Object.keys(table).forEach(function(date) {
-    var expect = table[date];
-    theVows[date] = function() {
-      var got = tough.parseDate(date) ? 'valid' : 'invalid';
-      assert.equal(got, expect ? 'valid' : 'invalid');
-    };
-  });
-  return { "date parsing": theVows };
-}
-
-function matchVows(func,table) {
-  var theVows = {};
-  table.forEach(function(item) {
-    var str = item[0];
-    var dom = item[1];
-    var expect = item[2];
-    var label = str+(expect?" matches ":" doesn't match ")+dom;
-    theVows[label] = function() {
-      assert.equal(func(str,dom),expect);
-    };
-  });
-  return theVows;
-}
-
-function defaultPathVows(table) {
-  var theVows = {};
-  table.forEach(function(item) {
-    var str = item[0];
-    var expect = item[1];
-    var label = str+" gives "+expect;
-    theVows[label] = function() {
-      assert.equal(tough.defaultPath(str),expect);
-    };
-  });
-  return theVows;
-}
-
-var atNow = Date.now();
-function at(offset) { return {now: new Date(atNow+offset)}; }
-
-vows.describe('Cookie Jar')
-.addBatch({
-  "all defined": function() {
-    assert.ok(Cookie);
-    assert.ok(CookieJar);
-  },
-})
-.addBatch(
-  dateVows({
-    "Wed, 09 Jun 2021 10:18:14 GMT": true,
-    "Wed, 09 Jun 2021 22:18:14 GMT": true,
-    "Tue, 18 Oct 2011 07:42:42.123 GMT": true,
-    "18 Oct 2011 07:42:42 GMT": true,
-    "8 Oct 2011 7:42:42 GMT": true,
-    "8 Oct 2011 7:2:42 GMT": false,
-    "Oct 18 2011 07:42:42 GMT": true,
-    "Tue Oct 18 2011 07:05:03 GMT+0000 (GMT)": true,
-    "09 Jun 2021 10:18:14 GMT": true,
-    "99 Jix 3038 48:86:72 ZMT": false,
-    '01 Jan 1970 00:00:00 GMT': true,
-    '01 Jan 1600 00:00:00 GMT': false, // before 1601
-    '01 Jan 1601 00:00:00 GMT': true,
-    '10 Feb 81 13:00:00 GMT': true, // implicit year
-    'Thu, 01 Jan 1970 00:00:010 GMT': true, // strange time, non-strict OK
-    'Thu, 17-Apr-2014 02:12:29 GMT': true, // dashes
-    'Thu, 17-Apr-2014 02:12:29 UTC': true, // dashes and UTC
-  })
-)
-.addBatch({
-  "strict date parse of Thu, 01 Jan 1970 00:00:010 GMT": {
-    topic: function() {
-      return tough.parseDate('Thu, 01 Jan 1970 00:00:010 GMT', true) ? true : false;
-    },
-    "invalid": function(date) {
-      assert.equal(date,false);
-    },
-  }
-})
-.addBatch({
-  "formatting": {
-    "a simple cookie": {
-      topic: function() {
-        var c = new Cookie();
-        c.key = 'a';
-        c.value = 'b';
-        return c;
-      },
-      "validates": function(c) {
-        assert.ok(c.validate());
-      },
-      "to string": function(c) {
-        assert.equal(c.toString(), 'a=b');
-      },
-    },
-    "a cookie with spaces in the value": {
-      topic: function() {
-        var c = new Cookie();
-        c.key = 'a';
-        c.value = 'beta gamma';
-        return c;
-      },
-      "doesn't validate": function(c) {
-        assert.ok(!c.validate());
-      },
-      "'garbage in, garbage out'": function(c) {
-        assert.equal(c.toString(), 'a=beta gamma');
-      },
-    },
-    "with an empty value and HttpOnly": {
-      topic: function() {
-        var c = new Cookie();
-        c.key = 'a';
-        c.httpOnly = true;
-        return c;
-      },
-      "to string": function(c) {
-        assert.equal(c.toString(), 'a=; HttpOnly');
-      }
-    },
-    "with an expiry": {
-      topic: function() {
-        var c = new Cookie();
-        c.key = 'a';
-        c.value = 'b';
-        c.setExpires("Oct 18 2011 07:05:03 GMT");
-        return c;
-      },
-      "validates": function(c) {
-        assert.ok(c.validate());
-      },
-      "to string": function(c) {
-        assert.equal(c.toString(), 'a=b; Expires=Tue, 18 Oct 2011 07:05:03 GMT');
-      },
-      "to short string": function(c) {
-        assert.equal(c.cookieString(), 'a=b');
-      },
-    },
-    "with a max-age": {
-      topic: function() {
-        var c = new Cookie();
-        c.key = 'a';
-        c.value = 'b';
-        c.setExpires("Oct 18 2011 07:05:03 GMT");
-        c.maxAge = 12345;
-        return c;
-      },
-      "validates": function(c) {
-        assert.ok(c.validate()); // mabe this one *shouldn't*?
-      },
-      "to string": function(c) {
-        assert.equal(c.toString(), 'a=b; Expires=Tue, 18 Oct 2011 07:05:03 GMT; Max-Age=12345');
-      },
-    },
-    "with a bunch of things": function() {
-      var c = new Cookie();
-      c.key = 'a';
-      c.value = 'b';
-      c.setExpires("Oct 18 2011 07:05:03 GMT");
-      c.maxAge = 12345;
-      c.domain = 'example.com';
-      c.path = '/foo';
-      c.secure = true;
-      c.httpOnly = true;
-      c.extensions = ['MyExtension'];
-      assert.equal(c.toString(), 'a=b; Expires=Tue, 18 Oct 2011 07:05:03 GMT; Max-Age=12345; Domain=example.com; Path=/foo; Secure; HttpOnly; MyExtension');
-    },
-    "a host-only cookie": {
-      topic: function() {
-        var c = new Cookie();
-        c.key = 'a';
-        c.value = 'b';
-        c.hostOnly = true;
-        c.domain = 'shouldnt-stringify.example.com';
-        c.path = '/should-stringify';
-        return c;
-      },
-      "validates": function(c) {
-        assert.ok(c.validate());
-      },
-      "to string": function(c) {
-        assert.equal(c.toString(), 'a=b; Path=/should-stringify');
-      },
-    },
-    "minutes are '10'": {
-      topic: function() {
-        var c = new Cookie();
-        c.key = 'a';
-        c.value = 'b';
-        c.expires = new Date(1284113410000);
-        return c;
-      },
-      "validates": function(c) {
-        assert.ok(c.validate());
-      },
-      "to string": function(c) {
-        var str = c.toString();
-        assert.notEqual(str, 'a=b; Expires=Fri, 010 Sep 2010 010:010:010 GMT');
-        assert.equal(str, 'a=b; Expires=Fri, 10 Sep 2010 10:10:10 GMT');
-      },
-    }
-  }
-})
-.addBatch({
-  "TTL with max-age": function() {
-    var c = new Cookie();
-    c.maxAge = 123;
-    assert.equal(c.TTL(), 123000);
-    assert.equal(c.expiryTime(new Date(9000000)), 9123000);
-  },
-  "TTL with zero max-age": function() {
-    var c = new Cookie();
-    c.key = 'a'; c.value = 'b';
-    c.maxAge = 0; // should be treated as "earliest representable"
-    assert.equal(c.TTL(), 0);
-    assert.equal(c.expiryTime(new Date(9000000)), -Infinity);
-    assert.ok(!c.validate()); // not valid, really: non-zero-digit *DIGIT
-  },
-  "TTL with negative max-age": function() {
-    var c = new Cookie();
-    c.key = 'a'; c.value = 'b';
-    c.maxAge = -1; // should be treated as "earliest representable"
-    assert.equal(c.TTL(), 0);
-    assert.equal(c.expiryTime(new Date(9000000)), -Infinity);
-    assert.ok(!c.validate()); // not valid, really: non-zero-digit *DIGIT
-  },
-  "TTL with max-age and expires": function() {
-    var c = new Cookie();
-    c.maxAge = 123;
-    c.expires = new Date(Date.now()+9000);
-    assert.equal(c.TTL(), 123000);
-    assert.ok(c.isPersistent());
-  },
-  "TTL with expires": function() {
-    var c = new Cookie();
-    var now = Date.now();
-    c.expires = new Date(now+9000);
-    assert.equal(c.TTL(now), 9000);
-    assert.equal(c.expiryTime(), c.expires.getTime());
-  },
-  "TTL with old expires": function() {
-    var c = new Cookie();
-    c.setExpires('17 Oct 2010 00:00:00 GMT');
-    assert.ok(c.TTL() < 0);
-    assert.ok(c.isPersistent());
-  },
-  "default TTL": {
-    topic: function() { return new Cookie(); },
-    "is Infinite-future": function(c) { assert.equal(c.TTL(), Infinity) },
-    "is a 'session' cookie": function(c) { assert.ok(!c.isPersistent()) },
-  },
-}).addBatch({
-  "Parsing": {
-    "simple": {
-      topic: function() {
-        return Cookie.parse('a=bcd',true) || null;
-      },
-      "parsed": function(c) { assert.ok(c) },
-      "key": function(c) { assert.equal(c.key, 'a') },
-      "value": function(c) { assert.equal(c.value, 'bcd') },
-      "no path": function(c) { assert.equal(c.path, null) },
-      "no domain": function(c) { assert.equal(c.domain, null) },
-      "no extensions": function(c) { assert.ok(!c.extensions) },
-    },
-    "with expiry": {
-      topic: function() {
-        return Cookie.parse('a=bcd; Expires=Tue, 18 Oct 2011 07:05:03 GMT',true) || null;
-      },
-      "parsed": function(c) { assert.ok(c) },
-      "key": function(c) { assert.equal(c.key, 'a') },
-      "value": function(c) { assert.equal(c.value, 'bcd') },
-      "has expires": function(c) {
-        assert.ok(c.expires !== Infinity, 'expiry is infinite when it shouldn\'t be');
-        assert.equal(c.expires.getTime(), 1318921503000);
-      },
-    },
-    "with expiry and path": {
-      topic: function() {
-        return Cookie.parse('abc="xyzzy!"; Expires=Tue, 18 Oct 2011 07:05:03 GMT; Path=/aBc',true) || null;
-      },
-      "parsed": function(c) { assert.ok(c) },
-      "key": function(c) { assert.equal(c.key, 'abc') },
-      "value": function(c) { assert.equal(c.value, 'xyzzy!') },
-      "has expires": function(c) {
-        assert.ok(c.expires !== Infinity, 'expiry is infinite when it shouldn\'t be');
-        assert.equal(c.expires.getTime(), 1318921503000);
-      },
-      "has path": function(c) { assert.equal(c.path, '/aBc'); },
-      "no httponly or secure": function(c) {
-        assert.ok(!c.httpOnly);
-        assert.ok(!c.secure);
-      },
-    },
-    "with everything": {
-      topic: function() {
-        return Cookie.parse('abc="xyzzy!"; Expires=Tue, 18 Oct 2011 07:05:03 GMT; Path=/aBc; Domain=example.com; Secure; HTTPOnly; Max-Age=1234; Foo=Bar; Baz', true) || null;
-      },
-      "parsed": function(c) { assert.ok(c) },
-      "key": function(c) { assert.equal(c.key, 'abc') },
-      "value": function(c) { assert.equal(c.value, 'xyzzy!') },
-      "has expires": function(c) {
-        assert.ok(c.expires !== Infinity, 'expiry is infinite when it shouldn\'t be');
-        assert.equal(c.expires.getTime(), 1318921503000);
-      },
-      "has path": function(c) { assert.equal(c.path, '/aBc'); },
-      "has domain": function(c) { assert.equal(c.domain, 'example.com'); },
-      "has httponly": function(c) { assert.equal(c.httpOnly, true); },
-      "has secure": function(c) { assert.equal(c.secure, true); },
-      "has max-age": function(c) { assert.equal(c.maxAge, 1234); },
-      "has extensions": function(c) {
-        assert.ok(c.extensions);
-        assert.equal(c.extensions[0], 'Foo=Bar');
-        assert.equal(c.extensions[1], 'Baz');
-      },
-    },
-    "invalid expires": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; Expires=xyzzy", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; Expires=xyzzy");
-        assert.ok(c);
-        assert.equal(c.expires, Infinity);
-      },
-    },
-    "zero max-age": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; Max-Age=0", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; Max-Age=0");
-        assert.ok(c);
-        assert.equal(c.maxAge, 0);
-      },
-    },
-    "negative max-age": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; Max-Age=-1", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; Max-Age=-1");
-        assert.ok(c);
-        assert.equal(c.maxAge, -1);
-      },
-    },
-    "empty domain": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; domain=", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; domain=");
-        assert.ok(c);
-        assert.equal(c.domain, null);
-      },
-    },
-    "dot domain": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; domain=.", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; domain=.");
-        assert.ok(c);
-        assert.equal(c.domain, null);
-      },
-    },
-    "uppercase domain": {
-      "strict lowercases": function() {
-        var c = Cookie.parse("a=b; domain=EXAMPLE.COM");
-        assert.ok(c);
-        assert.equal(c.domain, 'example.com');
-      },
-      "non-strict lowercases": function() {
-        var c = Cookie.parse("a=b; domain=EXAMPLE.COM");
-        assert.ok(c);
-        assert.equal(c.domain, 'example.com');
-      },
-    },
-    "trailing dot in domain": {
-      topic: function() {
-        return Cookie.parse("a=b; Domain=example.com.", true) || null;
-      },
-      "has the domain": function(c) { assert.equal(c.domain,"example.com.") },
-      "but doesn't validate": function(c) { assert.equal(c.validate(),false) },
-    },
-    "empty path": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; path=", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; path=");
-        assert.ok(c);
-        assert.equal(c.path, null);
-      },
-    },
-    "no-slash path": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; path=xyzzy", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; path=xyzzy");
-        assert.ok(c);
-        assert.equal(c.path, null);
-      },
-    },
-    "trailing semi-colons after path": {
-      topic: function () {
-        return [
-          "a=b; path=/;",
-          "c=d;;;;"
-        ];
-      },
-      "strict": function (t) {
-        assert.ok(!Cookie.parse(t[0], true));
-        assert.ok(!Cookie.parse(t[1], true));
-      },
-      "non-strict": function (t) {
-        var c1 = Cookie.parse(t[0]);
-        var c2 = Cookie.parse(t[1]);
-        assert.ok(c1);
-        assert.ok(c2);
-        assert.equal(c1.path, '/');
-      }
-    },
-    "secure-with-value": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; Secure=xyzzy", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; Secure=xyzzy");
-        assert.ok(c);
-        assert.equal(c.secure, true);
-      },
-    },
-    "httponly-with-value": {
-      "strict": function() { assert.ok(!Cookie.parse("a=b; HttpOnly=xyzzy", true)) },
-      "non-strict": function() {
-        var c = Cookie.parse("a=b; HttpOnly=xyzzy");
-        assert.ok(c);
-        assert.equal(c.httpOnly, true);
-      },
-    },
-    "garbage": {
-      topic: function() {
-        return Cookie.parse("\x08", true) || null;
-      },
-      "doesn't parse": function(c) { assert.equal(c,null) },
-    },
-    "public suffix domain": {
-      topic: function() {
-        return Cookie.parse("a=b; domain=kyoto.jp", true) || null;
-      },
-      "parses fine": function(c) {
-        assert.ok(c);
-        assert.equal(c.domain, 'kyoto.jp');
-      },
-      "but fails validation": function(c) {
-        assert.ok(c);
-        assert.ok(!c.validate());
-      },
-    },
-    "Ironically, Google 'GAPS' cookie has very little whitespace": {
-      topic: function() {
-        return Cookie.parse("GAPS=1:A1aaaaAaAAa1aaAaAaaAAAaaa1a11a:aaaAaAaAa-aaaA1-;Path=/;Expires=Thu, 17-Apr-2014 02:12:29 GMT;Secure;HttpOnly");
-      },
-      "parsed": function(c) { assert.ok(c) },
-      "key": function(c) { assert.equal(c.key, 'GAPS') },
-      "value": function(c) { assert.equal(c.value, '1:A1aaaaAaAAa1aaAaAaaAAAaaa1a11a:aaaAaAaAa-aaaA1-') },
-      "path": function(c) {
-        assert.notEqual(c.path, '/;Expires'); // BUG
-        assert.equal(c.path, '/');
-      },
-      "expires": function(c) {
-        assert.notEqual(c.expires, Infinity);
-        assert.equal(c.expires.getTime(), 1397700749000);
-      },
-      "secure": function(c) { assert.ok(c.secure) },
-      "httponly": function(c) { assert.ok(c.httpOnly) },
-    },
-    "lots of equal signs": {
-      topic: function() {
-        return Cookie.parse("queryPref=b=c&d=e; Path=/f=g; Expires=Thu, 17 Apr 2014 02:12:29 GMT; HttpOnly");
-      },
-      "parsed": function(c) { assert.ok(c) },
-      "key": function(c) { assert.equal(c.key, 'queryPref') },
-      "value": function(c) { assert.equal(c.value, 'b=c&d=e') },
-      "path": function(c) {
-        assert.equal(c.path, '/f=g');
-      },
-      "expires": function(c) {
-        assert.notEqual(c.expires, Infinity);
-        assert.equal(c.expires.getTime(), 1397700749000);
-      },
-      "httponly": function(c) { assert.ok(c.httpOnly) },
-    },
-    "spaces in value": {
-      "strict": {
-        topic: function() {
-          return Cookie.parse('a=one two three',true) || null;
-        },
-        "did not parse": function(c) { assert.isNull(c) },
-      },
-      "non-strict": {
-        topic: function() {
-          return Cookie.parse('a=one two three',false) || null;
-        },
-        "parsed": function(c) { assert.ok(c) },
-        "key": function(c) { assert.equal(c.key, 'a') },
-        "value": function(c) { assert.equal(c.value, 'one two three') },
-        "no path": function(c) { assert.equal(c.path, null) },
-        "no domain": function(c) { assert.equal(c.domain, null) },
-        "no extensions": function(c) { assert.ok(!c.extensions) },
-      },
-    },
-    "quoted spaces in value": {
-      "strict": {
-        topic: function() {
-          return Cookie.parse('a="one two three"',true) || null;
-        },
-        "did not parse": function(c) { assert.isNull(c) },
-      },
-      "non-strict": {
-        topic: function() {
-          return Cookie.parse('a="one two three"',false) || null;
-        },
-        "parsed": function(c) { assert.ok(c) },
-        "key": function(c) { assert.equal(c.key, 'a') },
-        "value": function(c) { assert.equal(c.value, 'one two three') },
-        "no path": function(c) { assert.equal(c.path, null) },
-        "no domain": function(c) { assert.equal(c.domain, null) },
-        "no extensions": function(c) { assert.ok(!c.extensions) },
-      }
-    },
-    "non-ASCII in value": {
-      "strict": {
-        topic: function() {
-          return Cookie.parse('farbe=weiß',true) || null;
-        },
-        "did not parse": function(c) { assert.isNull(c) },
-      },
-      "non-strict": {
-        topic: function() {
-          return Cookie.parse('farbe=weiß',false) || null;
-        },
-        "parsed": function(c) { assert.ok(c) },
-        "key": function(c) { assert.equal(c.key, 'farbe') },
-        "value": function(c) { assert.equal(c.value, 'weiß') },
-        "no path": function(c) { assert.equal(c.path, null) },
-        "no domain": function(c) { assert.equal(c.domain, null) },
-        "no extensions": function(c) { assert.ok(!c.extensions) },
-      },
-    },
-  }
-})
-.addBatch({
-  "domain normalization": {
-    "simple": function() {
-      var c = new Cookie();
-      c.domain = "EXAMPLE.com";
-      assert.equal(c.canonicalizedDomain(), "example.com");
-    },
-    "extra dots": function() {
-      var c = new Cookie();
-      c.domain = ".EXAMPLE.com";
-      assert.equal(c.cdomain(), "example.com");
-    },
-    "weird trailing dot": function() {
-      var c = new Cookie();
-      c.domain = "EXAMPLE.ca.";
-      assert.equal(c.canonicalizedDomain(), "example.ca.");
-    },
-    "weird internal dots": function() {
-      var c = new Cookie();
-      c.domain = "EXAMPLE...ca.";
-      assert.equal(c.canonicalizedDomain(), "example...ca.");
-    },
-    "IDN": function() {
-      var c = new Cookie();
-      c.domain = "δοκιμή.δοκιμή"; // "test.test" in greek
-      assert.equal(c.canonicalizedDomain(), "xn--jxalpdlp.xn--jxalpdlp");
-    }
-  }
-})
-.addBatch({
-  "Domain Match":matchVows(tough.domainMatch, [
-    // str,          dom,          expect
-    ["example.com", "example.com", true],
-    ["eXaMpLe.cOm", "ExAmPlE.CoM", true],
-    ["no.ca", "yes.ca", false],
-    ["wwwexample.com", "example.com", false],
-    ["www.example.com", "example.com", true],
-    ["example.com", "www.example.com", false],
-    ["www.subdom.example.com", "example.com", true],
-    ["www.subdom.example.com", "subdom.example.com", true],
-    ["example.com", "example.com.", false], // RFC6265 S4.1.2.3
-    ["192.168.0.1", "168.0.1", false], // S5.1.3 "The string is a host name"
-    [null, "example.com", null],
-    ["example.com", null, null],
-    [null, null, null],
-    [undefined, undefined, null],
-  ])
-})
-.addBatch({
-  "default-path": defaultPathVows([
-    [null,"/"],
-    ["/","/"],
-    ["/file","/"],
-    ["/dir/file","/dir"],
-    ["noslash","/"],
-  ])
-})
-.addBatch({
-  "Path-Match": matchVows(tough.pathMatch, [
-    // request, cookie, match
-    ["/","/",true],
-    ["/dir","/",true],
-    ["/","/dir",false],
-    ["/dir/","/dir/", true],
-    ["/dir/file","/dir/",true],
-    ["/dir/file","/dir",true],
-    ["/directory","/dir",false],
-  ])
-})
-.addBatch({
-  "Cookie Sorting": {
-    topic: function() {
-      var cookies = [];
-      var now = Date.now();
-      cookies.push(Cookie.parse("a=0; Domain=example.com"));
-      cookies.push(Cookie.parse("b=1; Domain=www.example.com"));
-      cookies.push(Cookie.parse("c=2; Domain=example.com; Path=/pathA"));
-      cookies.push(Cookie.parse("d=3; Domain=www.example.com; Path=/pathA"));
-      cookies.push(Cookie.parse("e=4; Domain=example.com; Path=/pathA/pathB"));
-      cookies.push(Cookie.parse("f=5; Domain=www.example.com; Path=/pathA/pathB"));
-
-      // force a stable creation time consistent with the order above since
-      // some may have been created at now + 1ms.
-      var i = cookies.length;
-      cookies.forEach(function(cookie) {
-        cookie.creation = new Date(now - 100*(i--));
-      });
-
-      // weak shuffle:
-      cookies = cookies.sort(function(){return Math.random()-0.5});
-
-      cookies = cookies.sort(tough.cookieCompare);
-      return cookies;
-    },
-    "got": function(cookies) {
-      assert.lengthOf(cookies, 6);
-      var names = cookies.map(function(c) {return c.key});
-      assert.deepEqual(names, ['e','f','c','d','a','b']);
-    },
-  }
-})
-.addBatch({
-  "CookieJar": {
-    "Setting a basic cookie": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=example.com; Path=/");
-        assert.strictEqual(c.hostOnly, null);
-        assert.instanceOf(c.creation, Date);
-        assert.strictEqual(c.lastAccessed, null);
-        c.creation = new Date(Date.now()-10000);
-        cj.setCookie(c, 'http://example.com/index.html', this.callback);
-      },
-      "works": function(c) { assert.instanceOf(c,Cookie) }, // C is for Cookie, good enough for me
-      "gets timestamped": function(c) {
-        assert.ok(c.creation);
-        assert.ok(Date.now() - c.creation.getTime() < 5000); // recently stamped
-        assert.ok(c.lastAccessed);
-        assert.equal(c.creation, c.lastAccessed);
-        assert.equal(c.TTL(), Infinity);
-        assert.ok(!c.isPersistent());
-      },
-    },
-    "Setting a no-path cookie": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=example.com");
-        assert.strictEqual(c.hostOnly, null);
-        assert.instanceOf(c.creation, Date);
-        assert.strictEqual(c.lastAccessed, null);
-        c.creation = new Date(Date.now()-10000);
-        cj.setCookie(c, 'http://example.com/index.html', this.callback);
-      },
-      "domain": function(c) { assert.equal(c.domain, 'example.com') },
-      "path is /": function(c) { assert.equal(c.path, '/') },
-      "path was derived": function(c) { assert.strictEqual(c.pathIsDefault, true) },
-    },
-    "Setting a cookie already marked as host-only": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=example.com");
-        assert.strictEqual(c.hostOnly, null);
-        assert.instanceOf(c.creation, Date);
-        assert.strictEqual(c.lastAccessed, null);
-        c.creation = new Date(Date.now()-10000);
-        c.hostOnly = true;
-        cj.setCookie(c, 'http://example.com/index.html', this.callback);
-      },
-      "domain": function(c) { assert.equal(c.domain, 'example.com') },
-      "still hostOnly": function(c) { assert.strictEqual(c.hostOnly, true) },
-    },
-    "Setting a session cookie": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b");
-        assert.strictEqual(c.path, null);
-        cj.setCookie(c, 'http://www.example.com/dir/index.html', this.callback);
-      },
-      "works": function(c) { assert.instanceOf(c,Cookie) },
-      "gets the domain": function(c) { assert.equal(c.domain, 'www.example.com') },
-      "gets the default path": function(c) { assert.equal(c.path, '/dir') },
-      "is 'hostOnly'": function(c) { assert.ok(c.hostOnly) },
-    },
-    "Setting wrong domain cookie": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=fooxample.com; Path=/");
-        cj.setCookie(c, 'http://example.com/index.html', this.callback);
-      },
-      "fails": function(err,c) {
-        assert.ok(err.message.match(/domain/i));
-        assert.ok(!c);
-      },
-    },
-    "Setting sub-domain cookie": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=www.example.com; Path=/");
-        cj.setCookie(c, 'http://example.com/index.html', this.callback);
-      },
-      "fails": function(err,c) {
-        assert.ok(err.message.match(/domain/i));
-        assert.ok(!c);
-      },
-    },
-    "Setting super-domain cookie": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=example.com; Path=/");
-        cj.setCookie(c, 'http://www.app.example.com/index.html', this.callback);
-      },
-      "success": function(err,c) {
-        assert.ok(!err);
-        assert.equal(c.domain, 'example.com');
-      },
-    },
-    "Setting a sub-path cookie on a super-domain": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=example.com; Path=/subpath");
-        assert.strictEqual(c.hostOnly, null);
-        assert.instanceOf(c.creation, Date);
-        assert.strictEqual(c.lastAccessed, null);
-        c.creation = new Date(Date.now()-10000);
-        cj.setCookie(c, 'http://www.example.com/index.html', this.callback);
-      },
-      "domain is super-domain": function(c) { assert.equal(c.domain, 'example.com') },
-      "path is /subpath": function(c) { assert.equal(c.path, '/subpath') },
-      "path was NOT derived": function(c) { assert.strictEqual(c.pathIsDefault, null) },
-    },
-    "Setting HttpOnly cookie over non-HTTP API": {
-      topic: function() {
-        var cj = new CookieJar();
-        var c = Cookie.parse("a=b; Domain=example.com; Path=/; HttpOnly");
-        cj.setCookie(c, 'http://example.com/index.html', {http:false}, this.callback);
-      },
-      "fails": function(err,c) {
-        assert.match(err.message, /HttpOnly/i);
-        assert.ok(!c);
-      },
-    },
-  },
-  "Cookie Jar store eight cookies": {
-    topic: function() {
-      var cj = new CookieJar();
-      var ex = 'http://example.com/index.html';
-      var tasks = [];
-      tasks.push(function(next) {
-        cj.setCookie('a=1; Domain=example.com; Path=/',ex,at(0),next);
-      });
-      tasks.push(function(next) {
-        cj.setCookie('b=2; Domain=example.com; Path=/; HttpOnly',ex,at(1000),next);
-      });
-      tasks.push(function(next) {
-        cj.setCookie('c=3; Domain=example.com; Path=/; Secure',ex,at(2000),next);
-      });
-      tasks.push(function(next) { // path
-        cj.setCookie('d=4; Domain=example.com; Path=/foo',ex,at(3000),next);
-      });
-      tasks.push(function(next) { // host only
-        cj.setCookie('e=5',ex,at(4000),next);
-      });
-      tasks.push(function(next) { // other domain
-        cj.setCookie('f=6; Domain=nodejs.org; Path=/','http://nodejs.org',at(5000),next);
-      });
-      tasks.push(function(next) { // expired
-        cj.setCookie('g=7; Domain=example.com; Path=/; Expires=Tue, 18 Oct 2011 00:00:00 GMT',ex,at(6000),next);
-      });
-      tasks.push(function(next) { // expired via Max-Age
-        cj.setCookie('h=8; Domain=example.com; Path=/; Max-Age=1',ex,next);
-      });
-      var cb = this.callback;
-      async.parallel(tasks, function(err,results){
-        setTimeout(function() {
-          cb(err,cj,results);
-        }, 2000); // so that 'h=8' expires
-      });
-    },
-    "setup ok": function(err,cj,results) {
-      assert.ok(!err);
-      assert.ok(cj);
-      assert.ok(results);
-    },
-    "then retrieving for http://nodejs.org": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('http://nodejs.org',this.callback);
-      },
-      "get a nodejs cookie": function(cookies) {
-        assert.lengthOf(cookies, 1);
-        var cookie = cookies[0];
-        assert.equal(cookie.domain, 'nodejs.org');
-      },
-    },
-    "then retrieving for https://example.com": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('https://example.com',{secure:true},this.callback);
-      },
-      "get a secure example cookie with others": function(cookies) {
-        var names = cookies.map(function(c) {return c.key});
-        assert.deepEqual(names, ['a','b','c','e']);
-      },
-    },
-    "then retrieving for https://example.com (missing options)": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('https://example.com',this.callback);
-      },
-      "get a secure example cookie with others": function(cookies) {
-        var names = cookies.map(function(c) {return c.key});
-        assert.deepEqual(names, ['a','b','c','e']);
-      },
-    },
-    "then retrieving for http://example.com": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('http://example.com',this.callback);
-      },
-      "get a bunch of cookies": function(cookies) {
-        var names = cookies.map(function(c) {return c.key});
-        assert.deepEqual(names, ['a','b','e']);
-      },
-    },
-    "then retrieving for http://EXAMPlE.com": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('http://EXAMPlE.com',this.callback);
-      },
-      "get a bunch of cookies": function(cookies) {
-        var names = cookies.map(function(c) {return c.key});
-        assert.deepEqual(names, ['a','b','e']);
-      },
-    },
-    "then retrieving for http://example.com, non-HTTP": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('http://example.com',{http:false},this.callback);
-      },
-      "get a bunch of cookies": function(cookies) {
-        var names = cookies.map(function(c) {return c.key});
-        assert.deepEqual(names, ['a','e']);
-      },
-    },
-    "then retrieving for http://example.com/foo/bar": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('http://example.com/foo/bar',this.callback);
-      },
-      "get a bunch of cookies": function(cookies) {
-        var names = cookies.map(function(c) {return c.key});
-        assert.deepEqual(names, ['d','a','b','e']);
-      },
-    },
-    "then retrieving for http://example.com as a string": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookieString('http://example.com',this.callback);
-      },
-      "get a single string": function(cookieHeader) {
-        assert.equal(cookieHeader, "a=1; b=2; e=5");
-      },
-    },
-    "then retrieving for http://example.com as a set-cookie header": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getSetCookieStrings('http://example.com',this.callback);
-      },
-      "get a single string": function(cookieHeaders) {
-        assert.lengthOf(cookieHeaders, 3);
-        assert.equal(cookieHeaders[0], "a=1; Domain=example.com; Path=/");
-        assert.equal(cookieHeaders[1], "b=2; Domain=example.com; Path=/; HttpOnly");
-        assert.equal(cookieHeaders[2], "e=5; Path=/");
-      },
-    },
-    "then retrieving for http://www.example.com/": {
-      topic: function(cj,oldResults) {
-        assert.ok(oldResults);
-        cj.getCookies('http://www.example.com/foo/bar',this.callback);
-      },
-      "get a bunch of cookies": function(cookies) {
-        var names = cookies.map(function(c) {return c.key});
-        assert.deepEqual(names, ['d','a','b']); // note lack of 'e'
-      },
-    },
-  },
-  "Repeated names": {
-    topic: function() {
-      var cb = this.callback;
-      var cj = new CookieJar();
-      var ex = 'http://www.example.com/';
-      var sc = cj.setCookie;
-      var tasks = [];
-      var now = Date.now();
-      tasks.push(sc.bind(cj,'aaaa=xxxx',ex,at(0)));
-      tasks.push(sc.bind(cj,'aaaa=1111; Domain=www.example.com',ex,at(1000)));
-      tasks.push(sc.bind(cj,'aaaa=2222; Domain=example.com',ex,at(2000)));
-      tasks.push(sc.bind(cj,'aaaa=3333; Domain=www.example.com; Path=/pathA',ex,at(3000)));
-      async.series(tasks,function(err,results) {
-        results = results.filter(function(e) {return e !== undefined});
-        cb(err,{cj:cj, cookies:results, now:now});
-      });
-    },
-    "all got set": function(err,t) {
-      assert.lengthOf(t.cookies,4);
-    },
-    "then getting 'em back": {
-      topic: function(t) {
-        var cj = t.cj;
-        cj.getCookies('http://www.example.com/pathA',this.callback);
-      },
-      "there's just three": function (err,cookies) {
-        var vals = cookies.map(function(c) {return c.value});
-        // may break with sorting; sorting should put 3333 first due to longest path:
-        assert.deepEqual(vals, ['3333','1111','2222']);
-      }
-    },
-  },
-  "CookieJar setCookie errors": {
-    "public-suffix domain": {
-      topic: function() {
-        var cj = new CookieJar();
-        cj.setCookie('i=9; Domain=kyoto.jp; Path=/','kyoto.jp',this.callback);
-      },
-      "errors": function(err,cookie) {
-        assert.ok(err);
-        assert.ok(!cookie);
-        assert.match(err.message, /public suffix/i);
-      },
-    },
-    "wrong domain": {
-      topic: function() {
-        var cj = new CookieJar();
-        cj.setCookie('j=10; Domain=google.com; Path=/','google.ca',this.callback);
-      },
-      "errors": function(err,cookie) {
-        assert.ok(err);
-        assert.ok(!cookie);
-        assert.match(err.message, /not in this host's domain/i);
-      },
-    },
-    "old cookie is HttpOnly": {
-      topic: function() {
-        var cb = this.callback;
-        var next = function (err,c) {
-          c = null;
-          return cb(err,cj);
-        };
-        var cj = new CookieJar();
-        cj.setCookie('k=11; Domain=example.ca; Path=/; HttpOnly','http://example.ca',{http:true},next);
-      },
-      "initial cookie is set": function(err,cj) {
-        assert.ok(!err);
-        assert.ok(cj);
-      },
-      "but when trying to overwrite": {
-        topic: function(cj) {
-          var cb = this.callback;
-          var next = function(err,c) {
-            c = null;
-            cb(null,err);
-          };
-          cj.setCookie('k=12; Domain=example.ca; Path=/','http://example.ca',{http:false},next);
-        },
-        "it's an error": function(err) {
-          assert.ok(err);
-        },
-        "then, checking the original": {
-          topic: function(ignored,cj) {
-            assert.ok(cj instanceof CookieJar);
-            cj.getCookies('http://example.ca',{http:true},this.callback);
-          },
-          "cookie has original value": function(err,cookies) {
-            assert.equal(err,null);
-            assert.lengthOf(cookies, 1);
-            assert.equal(cookies[0].value,11);
-          },
-        },
-      },
-    },
-  },
-})
-.addBatch({
-  "JSON": {
-    "serialization": {
-      topic: function() {
-        var c = Cookie.parse('alpha=beta; Domain=example.com; Path=/foo; Expires=Tue, 19 Jan 2038 03:14:07 GMT; HttpOnly');
-        return JSON.stringify(c);
-      },
-      "gives a string": function(str) {
-        assert.equal(typeof str, "string");
-      },
-      "date is in ISO format": function(str) {
-        assert.match(str, /"expires":"2038-01-19T03:14:07\.000Z"/, 'expires is in ISO format');
-      },
-    },
-    "deserialization": {
-      topic: function() {
-        var json = '{"key":"alpha","value":"beta","domain":"example.com","path":"/foo","expires":"2038-01-19T03:14:07.000Z","httpOnly":true,"lastAccessed":2000000000123}';
-        return Cookie.fromJSON(json);
-      },
-      "works": function(c) {
-        assert.ok(c);
-      },
-      "key": function(c) { assert.equal(c.key, "alpha") },
-      "value": function(c) { assert.equal(c.value, "beta") },
-      "domain": function(c) { assert.equal(c.domain, "example.com") },
-      "path": function(c) { assert.equal(c.path, "/foo") },
-      "httpOnly": function(c) { assert.strictEqual(c.httpOnly, true) },
-      "secure": function(c) { assert.strictEqual(c.secure, false) },
-      "hostOnly": function(c) { assert.strictEqual(c.hostOnly, null) },
-      "expires is a date object": function(c) {
-        assert.equal(c.expires.getTime(), 2147483647000);
-      },
-      "lastAccessed is a date object": function(c) {
-        assert.equal(c.lastAccessed.getTime(), 2000000000123);
-      },
-      "creation defaulted": function(c) {
-        assert.ok(c.creation.getTime());
-      }
-    },
-    "null deserialization": {
-      topic: function() {
-        return Cookie.fromJSON(null);
-      },
-      "is null": function(cookie) {
-        assert.equal(cookie,null);
-      },
-    },
-  },
-  "expiry deserialization": {
-    "Infinity": {
-      topic: Cookie.fromJSON.bind(null, '{"expires":"Infinity"}'),
-      "is infinite": function(c) {
-        assert.strictEqual(c.expires, "Infinity");
-        assert.equal(c.expires, Infinity);
-      },
-    },
-  },
-  "maxAge serialization": {
-    topic: function() {
-      return function(toSet) {
-        var c = new Cookie();
-        c.key = 'foo'; c.value = 'bar';
-        c.setMaxAge(toSet);
-        return JSON.stringify(c);
-      };
-    },
-    "zero": {
-      topic: function(f) { return f(0) },
-      "looks good": function(str) {
-        assert.match(str, /"maxAge":0/);
-      },
-    },
-    "Infinity": {
-      topic: function(f) { return f(Infinity) },
-      "looks good": function(str) {
-        assert.match(str, /"maxAge":"Infinity"/);
-      },
-    },
-    "-Infinity": {
-      topic: function(f) { return f(-Infinity) },
-      "looks good": function(str) {
-        assert.match(str, /"maxAge":"-Infinity"/);
-      },
-    },
-    "null": {
-      topic: function(f) { return f(null) },
-      "looks good": function(str) {
-        assert.match(str, /"maxAge":null/);
-      },
-    },
-  },
-  "maxAge deserialization": {
-    "number": {
-      topic: Cookie.fromJSON.bind(null,'{"key":"foo","value":"bar","maxAge":123}'),
-      "is the number": function(c) {
-        assert.strictEqual(c.maxAge, 123);
-      },
-    },
-    "null": {
-      topic: Cookie.fromJSON.bind(null,'{"key":"foo","value":"bar","maxAge":null}'),
-      "is null": function(c) {
-        assert.strictEqual(c.maxAge, null);
-      },
-    },
-    "less than zero": {
-      topic: Cookie.fromJSON.bind(null,'{"key":"foo","value":"bar","maxAge":-123}'),
-      "is -123": function(c) {
-        assert.strictEqual(c.maxAge, -123);
-      },
-    },
-    "Infinity": {
-      topic: Cookie.fromJSON.bind(null,'{"key":"foo","value":"bar","maxAge":"Infinity"}'),
-      "is inf-as-string": function(c) {
-        assert.strictEqual(c.maxAge, "Infinity");
-      },
-    },
-    "-Infinity": {
-      topic: Cookie.fromJSON.bind(null,'{"key":"foo","value":"bar","maxAge":"-Infinity"}'),
-      "is inf-as-string": function(c) {
-        assert.strictEqual(c.maxAge, "-Infinity");
-      },
-    },
-  }
-})
-.addBatch({
-  "permuteDomain": {
-    "base case": {
-      topic: tough.permuteDomain.bind(null,'example.com'),
-      "got the domain": function(list) {
-        assert.deepEqual(list, ['example.com']);
-      },
-    },
-    "two levels": {
-      topic: tough.permuteDomain.bind(null,'foo.bar.example.com'),
-      "got three things": function(list) {
-        assert.deepEqual(list, ['example.com','bar.example.com','foo.bar.example.com']);
-      },
-    },
-    "invalid domain": {
-      topic: tough.permuteDomain.bind(null,'foo.bar.example.localduhmain'),
-      "got three things": function(list) {
-        assert.equal(list, null);
-      },
-    },
-  },
-  "permutePath": {
-    "base case": {
-      topic: tough.permutePath.bind(null,'/'),
-      "just slash": function(list) {
-        assert.deepEqual(list,['/']);
-      },
-    },
-    "single case": {
-      topic: tough.permutePath.bind(null,'/foo'),
-      "two things": function(list) {
-        assert.deepEqual(list,['/foo','/']);
-      },
-      "path matching": function(list) {
-        list.forEach(function(e) {
-          assert.ok(tough.pathMatch('/foo',e));
-        });
-      },
-    },
-    "double case": {
-      topic: tough.permutePath.bind(null,'/foo/bar'),
-      "four things": function(list) {
-        assert.deepEqual(list,['/foo/bar','/foo','/']);
-      },
-      "path matching": function(list) {
-        list.forEach(function(e) {
-          assert.ok(tough.pathMatch('/foo/bar',e));
-        });
-      },
-    },
-    "trailing slash": {
-      topic: tough.permutePath.bind(null,'/foo/bar/'),
-      "three things": function(list) {
-        assert.deepEqual(list,['/foo/bar','/foo','/']);
-      },
-      "path matching": function(list) {
-        list.forEach(function(e) {
-          assert.ok(tough.pathMatch('/foo/bar/',e));
-        });
-      },
-    },
-  }
-})
-.addBatch({
-  "Issue 1": {
-    topic: function() {
-      var cj = new CookieJar();
-      cj.setCookie('hello=world; path=/some/path/', 'http://domain/some/path/file', function(err,cookie) {
-        this.callback(err,{cj:cj, cookie:cookie});
-      }.bind(this));
-    },
-    "stored a cookie": function(t) {
-      assert.ok(t.cookie);
-    },
-    "cookie's path was modified to remove unnecessary slash": function(t) {
-      assert.equal(t.cookie.path, '/some/path');
-    },
-    "getting it back": {
-      topic: function(t) {
-        t.cj.getCookies('http://domain/some/path/file', function(err,cookies) {
-          this.callback(err, {cj:t.cj, cookies:cookies||[]});
-        }.bind(this));
-      },
-      "got one cookie": function(t) {
-        assert.lengthOf(t.cookies, 1);
-      },
-      "it's the right one": function(t) {
-        var c = t.cookies[0];
-        assert.equal(c.key, 'hello');
-        assert.equal(c.value, 'world');
-      },
-    }
-  }
-})
-.addBatch({
-  "expiry option": {
-    topic: function() {
-      var cb = this.callback;
-      var cj = new CookieJar();
-      cj.setCookie('near=expiry; Domain=example.com; Path=/; Max-Age=1','http://www.example.com',at(-1), function(err,cookie) {
-
-        cb(err, {cj:cj, cookie:cookie});
-      });
-    },
-    "set the cookie": function(t) {
-      assert.ok(t.cookie, "didn't set?!");
-      assert.equal(t.cookie.key, 'near');
-    },
-    "then, retrieving": {
-      topic: function(t) {
-        var cb = this.callback;
-        setTimeout(function() {
-          t.cj.getCookies('http://www.example.com', {http:true, expire:false}, function(err,cookies) {
-            t.cookies = cookies;
-            cb(err,t);
-          });
-        },2000);
-      },
-      "got the cookie": function(t) {
-        assert.lengthOf(t.cookies, 1);
-        assert.equal(t.cookies[0].key, 'near');
-      },
-    }
-  }
-})
-.addBatch({
-  "trailing semi-colon set into cj": {
-    topic: function () {
-      var cb = this.callback;
-      var cj = new CookieJar();
-      var ex = 'http://www.example.com';
-      var tasks = [];
-      tasks.push(function(next) {
-        cj.setCookie('broken_path=testme; path=/;',ex,at(-1),next);
-      });
-      tasks.push(function(next) {
-        cj.setCookie('b=2; Path=/;;;;',ex,at(-1),next);
-      });
-      async.parallel(tasks, function (err, cookies) {
-        cb(null, {
-          cj: cj,
-          cookies: cookies
-        });
-      });
-    },
-    "check number of cookies": function (t) {
-      assert.lengthOf(t.cookies, 2, "didn't set");
-    },
-    "check *broken_path* was set properly": function (t) {
-      assert.equal(t.cookies[0].key, "broken_path");
-      assert.equal(t.cookies[0].value, "testme");
-      assert.equal(t.cookies[0].path, "/");
-    },
-    "check *b* was set properly": function (t) {
-      assert.equal(t.cookies[1].key, "b");
-      assert.equal(t.cookies[1].value, "2");
-      assert.equal(t.cookies[1].path, "/");
-    },
-    "retrieve the cookie": {
-      topic: function (t) {
-        var cb = this.callback;
-        t.cj.getCookies('http://www.example.com', {}, function (err, cookies) {
-          t.cookies = cookies;
-          cb(err, t);
-        });
-      },
-      "get the cookie": function(t) {
-        assert.lengthOf(t.cookies, 2);
-        assert.equal(t.cookies[0].key, 'broken_path');
-        assert.equal(t.cookies[0].value, 'testme');
-        assert.equal(t.cookies[1].key, "b");
-        assert.equal(t.cookies[1].value, "2");
-        assert.equal(t.cookies[1].path, "/");
-      },
-    },
-  }
-})
-.addBatch({
-  "Constructor":{
-    topic: function () {
-      return new Cookie({
-        key: 'test',
-        value: 'b',
-        maxAge: 60
-      });
-    },
-    'check for key property': function (c) {
-      assert.ok(c);
-      assert.equal(c.key, 'test');
-    },
-    'check for value property': function (c) {
-      assert.equal(c.value, 'b');
-    },
-    'check for maxAge': function (c) {
-      assert.equal(c.maxAge, 60);
-    },
-    'check for default values for unspecified properties': function (c) {
-      assert.equal(c.expires, "Infinity");
-      assert.equal(c.secure, false);
-      assert.equal(c.httpOnly, false);
-    }
-  }
-})
-.addBatch({
-  "allPaths option": {
-    topic: function() {
-      var cj = new CookieJar();
-      var tasks = [];
-      tasks.push(cj.setCookie.bind(cj, 'nopath_dom=qq; Path=/; Domain=example.com', 'http://example.com', {}));
-      tasks.push(cj.setCookie.bind(cj, 'path_dom=qq; Path=/foo; Domain=example.com', 'http://example.com', {}));
-      tasks.push(cj.setCookie.bind(cj, 'nopath_host=qq; Path=/', 'http://www.example.com', {}));
-      tasks.push(cj.setCookie.bind(cj, 'path_host=qq; Path=/foo', 'http://www.example.com', {}));
-      tasks.push(cj.setCookie.bind(cj, 'other=qq; Path=/', 'http://other.example.com/', {}));
-      tasks.push(cj.setCookie.bind(cj, 'other2=qq; Path=/foo', 'http://other.example.com/foo', {}));
-      var cb = this.callback;
-      async.parallel(tasks, function(err,results) {
-        cb(err, {cj:cj, cookies: results});
-      });
-    },
-    "all set": function(t) {
-      assert.equal(t.cookies.length, 6);
-      assert.ok(t.cookies.every(function(c) { return !!c }));
-    },
-    "getting without allPaths": {
-      topic: function(t) {
-        var cb = this.callback;
-        var cj = t.cj;
-        cj.getCookies('http://www.example.com/', {}, function(err,cookies) {
-          cb(err, {cj:cj, cookies:cookies});
-        });
-      },
-      "found just two cookies": function(t) {
-        assert.equal(t.cookies.length, 2);
-      },
-      "all are path=/": function(t) {
-        assert.ok(t.cookies.every(function(c) { return c.path === '/' }));
-      },
-      "no 'other' cookies": function(t) {
-        assert.ok(!t.cookies.some(function(c) { return (/^other/).test(c.name) }));
-      },
-    },
-    "getting without allPaths for /foo": {
-      topic: function(t) {
-        var cb = this.callback;
-        var cj = t.cj;
-        cj.getCookies('http://www.example.com/foo', {}, function(err,cookies) {
-          cb(err, {cj:cj, cookies:cookies});
-        });
-      },
-      "found four cookies": function(t) {
-        assert.equal(t.cookies.length, 4);
-      },
-      "no 'other' cookies": function(t) {
-        assert.ok(!t.cookies.some(function(c) { return (/^other/).test(c.name) }));
-      },
-    },
-    "getting with allPaths:true": {
-      topic: function(t) {
-        var cb = this.callback;
-        var cj = t.cj;
-        cj.getCookies('http://www.example.com/', {allPaths:true}, function(err,cookies) {
-          cb(err, {cj:cj, cookies:cookies});
-        });
-      },
-      "found four cookies": function(t) {
-        assert.equal(t.cookies.length, 4);
-      },
-      "no 'other' cookies": function(t) {
-        assert.ok(!t.cookies.some(function(c) { return (/^other/).test(c.name) }));
-      },
-    },
-  }
-})
-.addBatch({
-  "remove cookies": {
-    topic: function() {
-      var jar = new CookieJar();
-      var cookie = Cookie.parse("a=b; Domain=example.com; Path=/");
-      var cookie2 = Cookie.parse("a=b; Domain=foo.com; Path=/");
-      var cookie3 = Cookie.parse("foo=bar; Domain=foo.com; Path=/");
-      jar.setCookie(cookie, 'http://example.com/index.html', function(){});
-      jar.setCookie(cookie2, 'http://foo.com/index.html', function(){});
-      jar.setCookie(cookie3, 'http://foo.com/index.html', function(){});
-      return jar;
-    },
-    "all from matching domain": function(jar){
-      jar.store.removeCookies('example.com',null, function(err) {
-        assert(err == null);
-
-        jar.store.findCookies('example.com', null, function(err, cookies){
-          assert(err == null);
-          assert(cookies != null);
-          assert(cookies.length === 0, 'cookie was not removed');
-        });
-
-        jar.store.findCookies('foo.com', null, function(err, cookies){
-          assert(err == null);
-          assert(cookies != null);
-          assert(cookies.length === 2, 'cookies should not have been removed');
-        });
-      });
-    },
-    "from cookie store matching domain and key": function(jar){
-      jar.store.removeCookie('foo.com', '/', 'foo', function(err) {
-        assert(err == null);
-
-        jar.store.findCookies('foo.com', null, function(err, cookies){
-          assert(err == null);
-          assert(cookies != null);
-          assert(cookies.length === 1, 'cookie was not removed correctly');
-          assert(cookies[0].key === 'a', 'wrong cookie was removed');
-        });
-      });
-    }
-  }
-})
-.addBatch({
-  "Synchronous CookieJar": {
-    "setCookieSync": {
-      topic: function() {
-        var jar = new CookieJar();
-        var cookie = Cookie.parse("a=b; Domain=example.com; Path=/");
-        cookie = jar.setCookieSync(cookie, 'http://example.com/index.html');
-        return cookie;
-      },
-      "returns a copy of the cookie": function(cookie) {
-        assert.instanceOf(cookie, Cookie);
-      }
-    },
-
-    "setCookieSync strict parse error": {
-      topic: function() {
-        var jar = new CookieJar();
-        var opts = { strict: true };
-        try {
-          jar.setCookieSync("farbe=weiß", 'http://example.com/index.html', opts);
-          return false;
-        } catch (e) {
-          return e;
-        }
-      },
-      "throws the error": function(err) {
-        assert.instanceOf(err, Error);
-        assert.equal(err.message, "Cookie failed to parse");
-      }
-    },
-
-    "getCookiesSync": {
-      topic: function() {
-        var jar = new CookieJar();
-        var url = 'http://example.com/index.html';
-        jar.setCookieSync("a=b; Domain=example.com; Path=/", url);
-        jar.setCookieSync("c=d; Domain=example.com; Path=/", url);
-        return jar.getCookiesSync(url);
-      },
-      "returns the cookie array": function(err, cookies) {
-        assert.ok(!err);
-        assert.ok(Array.isArray(cookies));
-        assert.lengthOf(cookies, 2);
-        cookies.forEach(function(cookie) {
-          assert.instanceOf(cookie, Cookie);
-        });
-      }
-    },
-
-    "getCookieStringSync": {
-      topic: function() {
-        var jar = new CookieJar();
-        var url = 'http://example.com/index.html';
-        jar.setCookieSync("a=b; Domain=example.com; Path=/", url);
-        jar.setCookieSync("c=d; Domain=example.com; Path=/", url);
-        return jar.getCookieStringSync(url);
-      },
-      "returns the cookie header string": function(err, str) {
-        assert.ok(!err);
-        assert.typeOf(str, 'string');
-      }
-    },
-
-    "getSetCookieStringsSync": {
-      topic: function() {
-        var jar = new CookieJar();
-        var url = 'http://example.com/index.html';
-        jar.setCookieSync("a=b; Domain=example.com; Path=/", url);
-        jar.setCookieSync("c=d; Domain=example.com; Path=/", url);
-        return jar.getSetCookieStringsSync(url);
-      },
-      "returns the cookie header string": function(err, headers) {
-        assert.ok(!err);
-        assert.ok(Array.isArray(headers));
-        assert.lengthOf(headers, 2);
-        headers.forEach(function(header) {
-          assert.typeOf(header, 'string');
-        });
-      }
-    },
-  }
-})
-.addBatch({
-  "Synchronous API on async CookieJar": {
-    topic: function() {
-      return new tough.Store();
-    },
-    "setCookieSync": {
-      topic: function(store) {
-        var jar = new CookieJar(store);
-        try {
-          jar.setCookieSync("a=b", 'http://example.com/index.html');
-          return false;
-        } catch(e) {
-          return e;
-        }
-      },
-      "fails": function(err) {
-        assert.instanceOf(err, Error);
-        assert.equal(err.message,
-                     'CookieJar store is not synchronous; use async API instead.');
-      }
-    },
-    "getCookiesSync": {
-      topic: function(store) {
-        var jar = new CookieJar(store);
-        try {
-          jar.getCookiesSync('http://example.com/index.html');
-          return false;
-        } catch(e) {
-          return e;
-        }
-      },
-      "fails": function(err) {
-        assert.instanceOf(err, Error);
-        assert.equal(err.message,
-                     'CookieJar store is not synchronous; use async API instead.');
-      }
-    },
-    "getCookieStringSync": {
-      topic: function(store) {
-        var jar = new CookieJar(store);
-        try {
-          jar.getCookieStringSync('http://example.com/index.html');
-          return false;
-        } catch(e) {
-          return e;
-        }
-      },
-      "fails": function(err) {
-        assert.instanceOf(err, Error);
-        assert.equal(err.message,
-                     'CookieJar store is not synchronous; use async API instead.');
-      }
-    },
-    "getSetCookieStringsSync": {
-      topic: function(store) {
-        var jar = new CookieJar(store);
-        try {
-          jar.getSetCookieStringsSync('http://example.com/index.html');
-          return false;
-        } catch(e) {
-          return e;
-        }
-      },
-      "fails": function(err) {
-        assert.instanceOf(err, Error);
-        assert.equal(err.message,
-                     'CookieJar store is not synchronous; use async API instead.');
-      }
-    },
-  }
-})
-.export(module);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/.jshintrc b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/.jshintrc
deleted file mode 100644
index 4c1c8d49..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/.jshintrc
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "node": true,
-  "asi": true,
-  "laxcomma": true
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/LICENSE
deleted file mode 100644
index a4a9aee0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/LICENSE
+++ /dev/null
@@ -1,55 +0,0 @@
-Apache License
-
-Version 2.0, January 2004
-
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
-
-"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of this License; and
-
-You must cause any modified files to carry prominent notices stating that You changed the files; and
-
-You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
-
-If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/index.js
deleted file mode 100644
index 13c04272..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/index.js
+++ /dev/null
@@ -1,236 +0,0 @@
-'use strict'
-
-var net = require('net')
-  , tls = require('tls')
-  , http = require('http')
-  , https = require('https')
-  , events = require('events')
-  , assert = require('assert')
-  , util = require('util')
-  ;
-
-exports.httpOverHttp = httpOverHttp
-exports.httpsOverHttp = httpsOverHttp
-exports.httpOverHttps = httpOverHttps
-exports.httpsOverHttps = httpsOverHttps
-
-
-function httpOverHttp(options) {
-  var agent = new TunnelingAgent(options)
-  agent.request = http.request
-  return agent
-}
-
-function httpsOverHttp(options) {
-  var agent = new TunnelingAgent(options)
-  agent.request = http.request
-  agent.createSocket = createSecureSocket
-  return agent
-}
-
-function httpOverHttps(options) {
-  var agent = new TunnelingAgent(options)
-  agent.request = https.request
-  return agent
-}
-
-function httpsOverHttps(options) {
-  var agent = new TunnelingAgent(options)
-  agent.request = https.request
-  agent.createSocket = createSecureSocket
-  return agent
-}
-
-
-function TunnelingAgent(options) {
-  var self = this
-  self.options = options || {}
-  self.proxyOptions = self.options.proxy || {}
-  self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets
-  self.requests = []
-  self.sockets = []
-
-  self.on('free', function onFree(socket, host, port) {
-    for (var i = 0, len = self.requests.length; i < len; ++i) {
-      var pending = self.requests[i]
-      if (pending.host === host && pending.port === port) {
-        // Detect the request to connect same origin server,
-        // reuse the connection.
-        self.requests.splice(i, 1)
-        pending.request.onSocket(socket)
-        return
-      }
-    }
-    socket.destroy()
-    self.removeSocket(socket)
-  })
-}
-util.inherits(TunnelingAgent, events.EventEmitter)
-
-TunnelingAgent.prototype.addRequest = function addRequest(req, options) {
-  var self = this
-
-   // Legacy API: addRequest(req, host, port, path)
-  if (typeof options === 'string') {
-    options = {
-      host: options,
-      port: arguments[2],
-      path: arguments[3]
-    };
-  }
-
-  if (self.sockets.length >= this.maxSockets) {
-    // We are over limit so we'll add it to the queue.
-    self.requests.push({host: host, port: port, request: req})
-    return
-  }
-
-  // If we are under maxSockets create a new one.
-  self.createSocket({host: options.host, port: options.port, request: req}, function(socket) {
-    socket.on('free', onFree)
-    socket.on('close', onCloseOrRemove)
-    socket.on('agentRemove', onCloseOrRemove)
-    req.onSocket(socket)
-
-    function onFree() {
-      self.emit('free', socket, options.host, options.port)
-    }
-
-    function onCloseOrRemove(err) {
-      self.removeSocket()
-      socket.removeListener('free', onFree)
-      socket.removeListener('close', onCloseOrRemove)
-      socket.removeListener('agentRemove', onCloseOrRemove)
-    }
-  })
-}
-
-TunnelingAgent.prototype.createSocket = function createSocket(options, cb) {
-  var self = this
-  var placeholder = {}
-  self.sockets.push(placeholder)
-
-  var connectOptions = mergeOptions({}, self.proxyOptions, 
-    { method: 'CONNECT'
-    , path: options.host + ':' + options.port
-    , agent: false
-    }
-  )
-  if (connectOptions.proxyAuth) {
-    connectOptions.headers = connectOptions.headers || {}
-    connectOptions.headers['Proxy-Authorization'] = 'Basic ' +
-        new Buffer(connectOptions.proxyAuth).toString('base64')
-  }
-
-  debug('making CONNECT request')
-  var connectReq = self.request(connectOptions)
-  connectReq.useChunkedEncodingByDefault = false // for v0.6
-  connectReq.once('response', onResponse) // for v0.6
-  connectReq.once('upgrade', onUpgrade)   // for v0.6
-  connectReq.once('connect', onConnect)   // for v0.7 or later
-  connectReq.once('error', onError)
-  connectReq.end()
-
-  function onResponse(res) {
-    // Very hacky. This is necessary to avoid http-parser leaks.
-    res.upgrade = true
-  }
-
-  function onUpgrade(res, socket, head) {
-    // Hacky.
-    process.nextTick(function() {
-      onConnect(res, socket, head)
-    })
-  }
-
-  function onConnect(res, socket, head) {
-    connectReq.removeAllListeners()
-    socket.removeAllListeners()
-
-    if (res.statusCode === 200) {
-      assert.equal(head.length, 0)
-      debug('tunneling connection has established')
-      self.sockets[self.sockets.indexOf(placeholder)] = socket
-      cb(socket)
-    } else {
-      debug('tunneling socket could not be established, statusCode=%d', res.statusCode)
-      var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode)
-      error.code = 'ECONNRESET'
-      options.request.emit('error', error)
-      self.removeSocket(placeholder)
-    }
-  }
-
-  function onError(cause) {
-    connectReq.removeAllListeners()
-
-    debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack)
-    var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message)
-    error.code = 'ECONNRESET'
-    options.request.emit('error', error)
-    self.removeSocket(placeholder)
-  }
-}
-
-TunnelingAgent.prototype.removeSocket = function removeSocket(socket) {
-  var pos = this.sockets.indexOf(socket)
-  if (pos === -1) return
-  
-  this.sockets.splice(pos, 1)
-
-  var pending = this.requests.shift()
-  if (pending) {
-    // If we have pending requests and a socket gets closed a new one
-    // needs to be created to take over in the pool for the one that closed.
-    this.createSocket(pending, function(socket) {
-      pending.request.onSocket(socket)
-    })
-  }
-}
-
-function createSecureSocket(options, cb) {
-  var self = this
-  TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
-    // 0 is dummy port for v0.6
-    var secureSocket = tls.connect(0, mergeOptions({}, self.options, 
-      { servername: options.host
-      , socket: socket
-      }
-    ))
-    cb(secureSocket)
-  })
-}
-
-
-function mergeOptions(target) {
-  for (var i = 1, len = arguments.length; i < len; ++i) {
-    var overrides = arguments[i]
-    if (typeof overrides === 'object') {
-      var keys = Object.keys(overrides)
-      for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {
-        var k = keys[j]
-        if (overrides[k] !== undefined) {
-          target[k] = overrides[k]
-        }
-      }
-    }
-  }
-  return target
-}
-
-
-var debug
-if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
-  debug = function() {
-    var args = Array.prototype.slice.call(arguments)
-    if (typeof args[0] === 'string') {
-      args[0] = 'TUNNEL: ' + args[0]
-    } else {
-      args.unshift('TUNNEL:')
-    }
-    console.error.apply(console, args)
-  }
-} else {
-  debug = function() {}
-}
-exports.debug = debug // for test
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/package.json
deleted file mode 100644
index 90c2a342..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/package.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "author": {
-    "name": "Mikeal Rogers",
-    "email": "mikeal.rogers@gmail.com",
-    "url": "http://www.futurealoof.com"
-  },
-  "name": "tunnel-agent",
-  "description": "HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.",
-  "version": "0.4.0",
-  "repository": {
-    "url": "https://github.com/mikeal/tunnel-agent"
-  },
-  "main": "index.js",
-  "dependencies": {},
-  "devDependencies": {},
-  "optionalDependencies": {},
-  "engines": {
-    "node": "*"
-  },
-  "readme": "tunnel-agent\n============\n\nHTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/mikeal/tunnel-agent/issues"
-  },
-  "homepage": "https://github.com/mikeal/tunnel-agent",
-  "_id": "tunnel-agent@0.4.0",
-  "_shasum": "b1184e312ffbcf70b3b4c78e8c219de7ebb1c550",
-  "_from": "tunnel-agent@~0.4.0",
-  "_resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/package.json
deleted file mode 100755
index 073b58da..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/package.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
-  "name": "request",
-  "description": "Simplified HTTP request client.",
-  "tags": [
-    "http",
-    "simple",
-    "util",
-    "utility"
-  ],
-  "version": "2.36.0",
-  "author": {
-    "name": "Mikeal Rogers",
-    "email": "mikeal.rogers@gmail.com"
-  },
-  "repository": {
-    "type": "git",
-    "url": "http://github.com/mikeal/request.git"
-  },
-  "bugs": {
-    "url": "http://github.com/mikeal/request/issues"
-  },
-  "license": "Apache, Version 2.0",
-  "engines": [
-    "node >= 0.8.0"
-  ],
-  "main": "index.js",
-  "dependencies": {
-    "qs": "~0.6.0",
-    "json-stringify-safe": "~5.0.0",
-    "mime": "~1.2.9",
-    "forever-agent": "~0.5.0",
-    "node-uuid": "~1.4.0",
-    "tough-cookie": ">=0.12.0",
-    "form-data": "~0.1.0",
-    "tunnel-agent": "~0.4.0",
-    "http-signature": "~0.10.0",
-    "oauth-sign": "~0.3.0",
-    "hawk": "~1.0.0",
-    "aws-sign2": "~0.5.0"
-  },
-  "optionalDependencies": {
-    "tough-cookie": ">=0.12.0",
-    "form-data": "~0.1.0",
-    "tunnel-agent": "~0.4.0",
-    "http-signature": "~0.10.0",
-    "oauth-sign": "~0.3.0",
-    "hawk": "~1.0.0",
-    "aws-sign2": "~0.5.0"
-  },
-  "scripts": {
-    "test": "node tests/run.js"
-  },
-  "readme": "# Request -- Simplified HTTP client\n\n[![NPM](https://nodei.co/npm/request.png)](https://nodei.co/npm/request/)\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n  if (!error && response.statusCode == 200) {\n    console.log(body) // Print the google web page.\n  }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types (in this case `application/json`) and use the proper `content-type` in the PUT request (if the headers don’t already provide one).\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also `pipe` to itself. When doing so, `content-type` and `content-length` are preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let’s get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    if (req.method === 'PUT') {\n      req.pipe(request.put('http://mysite.com/doodle.png'))\n    } else if (req.method === 'GET' || req.method === 'HEAD') {\n      request.get('http://mysite.com/doodle.png').pipe(resp)\n    }\n  }\n})\n```\n\nYou can also `pipe()` from `http.ServerRequest` instances, as well as to `http.ServerResponse` instances. The HTTP method, headers, and entity-body data will be sent. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    var x = request('http://mysite.com/doodle.png')\n    req.pipe(x)\n    x.pipe(resp)\n  }\n})\n```\n\nAnd since `pipe()` returns the destination stream in ≥ Node 0.5.x you can do one line proxying. :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    r.get('http://google.com/doodle.png').pipe(resp)\n  }\n})\n```\n\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## UNIX Socket \n\n`request` supports the `unix://` protocol for all requests. The path is assumed to be absolute to the root of the host file system. \n\nHTTP paths are extracted from the supplied URL by testing each level of the full URL against net.connect for a socket response.\n\nThus the following request will GET `/httppath` from the HTTP server listening on `/tmp/unix.socket`\n\n```javascript\nrequest.get('unix://tmp/unix.socket/httppath')\n```\n\n## Forms\n\n`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.\n\nURL-encoded forms are simple.\n\n```javascript\nrequest.post('http://service.com/upload', {form:{key:'value'}})\n// or\nrequest.post('http://service.com/upload').form({key:'value'})\n```\n\nFor `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don’t need to worry about piping the form object or setting the headers, `request` will handle that for you.\n\n```javascript\nvar r = request.post('http://service.com/upload', function optionalCallback (err, httpResponse, body) {\n  if (err) {\n    return console.error('upload failed:', err);\n  }\n  console.log('Upload successful!  Server responded with:', body);\n})\nvar form = r.form()\nform.append('my_field', 'my_value')\nform.append('my_buffer', new Buffer([1, 2, 3]))\nform.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')))\nform.append('remote_file', request('http://google.com/doodle.png'))\n\n// Just like always, `r` is a writable stream, and can be used as such (you have until nextTick to pipe it, etc.)\n// Alternatively, you can provide a callback (that's what this example does-- see `optionalCallback` above).\n```\n\n## HTTP Authentication\n\n```javascript\nrequest.get('http://some.server.com/').auth('username', 'password', false);\n// or\nrequest.get('http://some.server.com/', {\n  'auth': {\n    'user': 'username',\n    'pass': 'password',\n    'sendImmediately': false\n  }\n});\n// or\nrequest.get('http://some.server.com/').auth(null, null, true, 'bearerToken');\n// or\nrequest.get('http://some.server.com/', {\n  'auth': {\n    'bearer': 'bearerToken'\n  }\n});\n```\n\nIf passed as an option, `auth` should be a hash containing values `user` || `username`, `pass` || `password`, and `sendImmediately` (optional).  The method form takes parameters `auth(username, password, sendImmediately)`.\n\n`sendImmediately` defaults to `true`, which causes a basic authentication header to be sent.  If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a `401` response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).\n\nDigest authentication is supported, but it only works with `sendImmediately` set to `false`; otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail.\n\nBearer authentication is supported, and is activated when the `bearer` value is available. The value may be either a `String` or a `Function` returning a `String`. Using a function to supply the bearer token is particularly useful if used in conjuction with `defaults` to allow a single function to supply the last known token at the time or sending a request or to compute one on the fly.\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n  , oauth =\n    { callback: 'http://mysite.com/callback/'\n    , consumer_key: CONSUMER_KEY\n    , consumer_secret: CONSUMER_SECRET\n    }\n  , url = 'https://api.twitter.com/oauth/request_token'\n  ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n  // Ideally, you would take the body in the response\n  // and construct a URL that a user clicks on (like a sign in button).\n  // The verifier is only available in the response after a user has\n  // verified with twitter that they are authorizing your app.\n  var access_token = qs.parse(body)\n    , oauth =\n      { consumer_key: CONSUMER_KEY\n      , consumer_secret: CONSUMER_SECRET\n      , token: access_token.oauth_token\n      , verifier: access_token.oauth_verifier\n      }\n    , url = 'https://api.twitter.com/oauth/access_token'\n    ;\n  request.post({url:url, oauth:oauth}, function (e, r, body) {\n    var perm_token = qs.parse(body)\n      , oauth =\n        { consumer_key: CONSUMER_KEY\n        , consumer_secret: CONSUMER_SECRET\n        , token: perm_token.oauth_token\n        , token_secret: perm_token.oauth_token_secret\n        }\n      , url = 'https://api.twitter.com/1.1/users/show.json?'\n      , params =\n        { screen_name: perm_token.screen_name\n        , user_id: perm_token.user_id\n        }\n      ;\n    url += qs.stringify(params)\n    request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n      console.log(user)\n    })\n  })\n})\n```\n\n### Custom HTTP Headers\n\nHTTP Headers, such as `User-Agent`, can be set in the `options` object.\nIn the example below, we call the github API to find out the number\nof stars and forks for the request repository. This requires a\ncustom `User-Agent` header as well as https.\n\n```javascript\nvar request = require('request');\n\nvar options = {\n\turl: 'https://api.github.com/repos/mikeal/request',\n\theaders: {\n\t\t'User-Agent': 'request'\n\t}\n};\n\nfunction callback(error, response, body) {\n\tif (!error && response.statusCode == 200) {\n\t\tvar info = JSON.parse(body);\n\t\tconsole.log(info.stargazers_count + \" Stars\");\n\t\tconsole.log(info.forks_count + \" Forks\");\n\t}\n}\n\nrequest(options, callback);\n```\n\n### request(options, callback)\n\nThe first argument can be either a `url` or an `options` object. The only required option is `uri`; all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from `url.parse()`\n* `qs` - object containing querystring values to be appended to the `uri`\n* `method` - http method (default: `\"GET\"`)\n* `headers` - http headers (default: `{}`)\n* `body` - entity body for PATCH, POST and PUT requests. Must be a `Buffer` or `String`.\n* `form` - when passed an object, this sets `body` to a querystring representation of value, and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no options, a `FormData` instance is returned (and is piped to request).\n* `auth` - A hash containing values `user` || `username`, `pass` || `password`, and `sendImmediately` (optional).  See documentation above.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.  Additionally, parses the response body as JSON.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects (default: `true`)\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects (default: `false`)\n* `maxRedirects` - the maximum number of redirects to follow (default: `10`)\n* `encoding` - Encoding to be used on `setEncoding` of response data. If `null`, the `body` is returned as a `Buffer`.\n* `pool` - A hash object containing the agents for these requests. If omitted, the request will use the global pool (which is set to node's default `maxSockets`)\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\n* `proxy` - An HTTP proxy to be used. Supports proxy Auth with Basic Auth, identical to support for the `url` parameter (by embedding the auth info in the `uri`)\n* `oauth` - Options for OAuth HMAC-SHA1 signing. See documentation above.\n* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).\n* `strictSSL` - If `true`, requires SSL certificates be valid. **Note:** to use your own certificate authority, you need to specify an agent that was created with that CA as an option.\n* `jar` - If `true`, remember cookies for future use (or define your custom cookie jar; see examples section)\n* `aws` - `object` containing AWS signing information. Should have the properties `key`, `secret`. Also requires the property `bucket`, unless you’re specifying your `bucket` as part of the path, or the request doesn’t use a bucket (i.e. GET Services)\n* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.\n* `localAddress` - Local interface to bind for network connections.\n\n\nThe callback argument gets 3 arguments: \n\n1. An `error` when applicable (usually from [`http.ClientRequest`](http://nodejs.org/api/http.html#http_class_http_clientrequest) object)\n2. An [`http.IncomingMessage`](http://nodejs.org/api/http.html#http_http_incomingmessage) object\n3. The third is the `response` body (`String` or `Buffer`, or JSON object if the `json` option is supplied)\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options)\n\nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as `request()`, but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.patch\n\nSame as `request()`, but defaults to `method: \"PATCH\"`.\n\n```javascript\nrequest.patch(url)\n```\n\n### request.post\n\nSame as `request()`, but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as `request()`, but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nSame as `request()` (for uniformity).\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n  var request = require('request')\n    , rand = Math.floor(Math.random()*100000000).toString()\n    ;\n  request(\n    { method: 'PUT'\n    , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n    , multipart:\n      [ { 'content-type': 'application/json'\n        ,  body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n        }\n      , { body: 'I am an attachment' }\n      ]\n    }\n  , function (error, response, body) {\n      if(response.statusCode == 201){\n        console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n      } else {\n        console.log('error: '+ response.statusCode)\n        console.log(body)\n      }\n    }\n  )\n```\n\nCookies are disabled by default (else, they would be used in subsequent requests). To enable cookies, set `jar` to `true` (either in `defaults` or `options`).\n\n```javascript\nvar request = request.defaults({jar: true})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\n\nTo use a custom cookie jar (instead of `request`’s global cookie jar), set `jar` to an instance of `request.jar()` (either in `defaults` or `options`)\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\n\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.setCookie(cookie, uri);\nrequest({url: 'http://www.google.com', jar: j}, function () {\n  request('http://images.google.com')\n})\n```\n",
-  "readmeFilename": "README.md",
-  "homepage": "https://github.com/mikeal/request",
-  "_id": "request@2.36.0",
-  "_shasum": "28c6c04262c7b9ffdd21b9255374517ee6d943f5",
-  "_from": "request@2",
-  "_resolved": "https://registry.npmjs.org/request/-/request-2.36.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/request.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/request.js
deleted file mode 100644
index 0110cb2c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/request.js
+++ /dev/null
@@ -1,1362 +0,0 @@
-var optional = require('./lib/optional')
-  , http = require('http')
-  , https = optional('https')
-  , tls = optional('tls')
-  , url = require('url')
-  , util = require('util')
-  , stream = require('stream')
-  , qs = require('qs')
-  , querystring = require('querystring')
-  , crypto = require('crypto')
-
-  , oauth = optional('oauth-sign')
-  , hawk = optional('hawk')
-  , aws = optional('aws-sign2')
-  , httpSignature = optional('http-signature')
-  , uuid = require('node-uuid')
-  , mime = require('mime')
-  , tunnel = optional('tunnel-agent')
-  , _safeStringify = require('json-stringify-safe')
-
-  , ForeverAgent = require('forever-agent')
-  , FormData = optional('form-data')
-
-  , cookies = require('./lib/cookies')
-  , globalCookieJar = cookies.jar()
-
-  , copy = require('./lib/copy')
-  , debug = require('./lib/debug')
-  , getSafe = require('./lib/getSafe')
-  , net = require('net')
-  ;
-
-function safeStringify (obj) {
-  var ret
-  try { ret = JSON.stringify(obj) }
-  catch (e) { ret = _safeStringify(obj) }
-  return ret
-}
-
-var globalPool = {}
-var isUrl = /^https?:|^unix:/
-
-
-// Hacky fix for pre-0.4.4 https
-if (https && !https.Agent) {
-  https.Agent = function (options) {
-    http.Agent.call(this, options)
-  }
-  util.inherits(https.Agent, http.Agent)
-  https.Agent.prototype._getConnection = function (host, port, cb) {
-    var s = tls.connect(port, host, this.options, function () {
-      // do other checks here?
-      if (cb) cb()
-    })
-    return s
-  }
-}
-
-function isReadStream (rs) {
-  return rs.readable && rs.path && rs.mode;
-}
-
-function toBase64 (str) {
-  return (new Buffer(str || "", "ascii")).toString("base64")
-}
-
-function md5 (str) {
-  return crypto.createHash('md5').update(str).digest('hex')
-}
-
-function Request (options) {
-  stream.Stream.call(this)
-  this.readable = true
-  this.writable = true
-
-  if (typeof options === 'string') {
-    options = {uri:options}
-  }
-
-  var reserved = Object.keys(Request.prototype)
-  for (var i in options) {
-    if (reserved.indexOf(i) === -1) {
-      this[i] = options[i]
-    } else {
-      if (typeof options[i] === 'function') {
-        delete options[i]
-      }
-    }
-  }
-
-  if (options.method) {
-    this.explicitMethod = true
-  }
-
-  this.canTunnel = options.tunnel !== false && tunnel;
-
-  this.init(options)
-}
-util.inherits(Request, stream.Stream)
-Request.prototype.init = function (options) {
-  // init() contains all the code to setup the request object.
-  // the actual outgoing request is not started until start() is called
-  // this function is called from both the constructor and on redirect.
-  var self = this
-  if (!options) options = {}
-
-  if (!self.method) self.method = options.method || 'GET'
-  self.localAddress = options.localAddress
-
-  debug(options)
-  if (!self.pool && self.pool !== false) self.pool = globalPool
-  self.dests = self.dests || []
-  self.__isRequestRequest = true
-
-  // Protect against double callback
-  if (!self._callback && self.callback) {
-    self._callback = self.callback
-    self.callback = function () {
-      if (self._callbackCalled) return // Print a warning maybe?
-      self._callbackCalled = true
-      self._callback.apply(self, arguments)
-    }
-    self.on('error', self.callback.bind())
-    self.on('complete', self.callback.bind(self, null))
-  }
-
-  if (self.url && !self.uri) {
-    // People use this property instead all the time so why not just support it.
-    self.uri = self.url
-    delete self.url
-  }
-
-  if (!self.uri) {
-    // this will throw if unhandled but is handleable when in a redirect
-    return self.emit('error', new Error("options.uri is a required argument"))
-  } else {
-    if (typeof self.uri == "string") self.uri = url.parse(self.uri)
-  }
-
-  if (self.strictSSL === false) {
-    self.rejectUnauthorized = false
-  }
-
-  if (self.proxy) {
-    if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy)
-
-    // do the HTTP CONNECT dance using koichik/node-tunnel
-    if (http.globalAgent && self.uri.protocol === "https:" && self.canTunnel) {
-      var tunnelFn = self.proxy.protocol === "http:"
-                   ? tunnel.httpsOverHttp : tunnel.httpsOverHttps
-
-      var tunnelOptions = { proxy: { host: self.proxy.hostname
-                                   , port: +self.proxy.port
-                                   , proxyAuth: self.proxy.auth
-                                   , headers: { Host: self.uri.hostname + ':' +
-                                        (self.uri.port || self.uri.protocol === 'https:' ? 443 : 80) }}
-                          , rejectUnauthorized: self.rejectUnauthorized
-                          , ca: this.ca }
-
-      self.agent = tunnelFn(tunnelOptions)
-      self.tunnel = true
-    }
-  }
-
-  if (!self.uri.pathname) {self.uri.pathname = '/'}
-
-  if (!self.uri.host && !self.protocol=='unix:') {
-    // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar
-    // Detect and reject it as soon as possible
-    var faultyUri = url.format(self.uri)
-    var message = 'Invalid URI "' + faultyUri + '"'
-    if (Object.keys(options).length === 0) {
-      // No option ? This can be the sign of a redirect
-      // As this is a case where the user cannot do anything (they didn't call request directly with this URL)
-      // they should be warned that it can be caused by a redirection (can save some hair)
-      message += '. This can be caused by a crappy redirection.'
-    }
-    self.emit('error', new Error(message))
-    return // This error was fatal
-  }
-
-  self._redirectsFollowed = self._redirectsFollowed || 0
-  self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10
-  self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true
-  self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false
-  if (self.followRedirect || self.followAllRedirects)
-    self.redirects = self.redirects || []
-
-  self.headers = self.headers ? copy(self.headers) : {}
-
-  self.setHost = false
-  if (!self.hasHeader('host')) {
-    self.setHeader('host', self.uri.hostname)
-    if (self.uri.port) {
-      if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') &&
-           !(self.uri.port === 443 && self.uri.protocol === 'https:') )
-      self.setHeader('host', self.getHeader('host') + (':'+self.uri.port) )
-    }
-    self.setHost = true
-  }
-
-  self.jar(self._jar || options.jar)
-
-  if (!self.uri.port) {
-    if (self.uri.protocol == 'http:') {self.uri.port = 80}
-    else if (self.uri.protocol == 'https:') {self.uri.port = 443}
-  }
-
-  if (self.proxy && !self.tunnel) {
-    self.port = self.proxy.port
-    self.host = self.proxy.hostname
-  } else {
-    self.port = self.uri.port
-    self.host = self.uri.hostname
-  }
-
-  self.clientErrorHandler = function (error) {
-    if (self._aborted) return
-    if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET'
-        && self.agent.addRequestNoreuse) {
-      self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) }
-      self.start()
-      self.req.end()
-      return
-    }
-    if (self.timeout && self.timeoutTimer) {
-      clearTimeout(self.timeoutTimer)
-      self.timeoutTimer = null
-    }
-    self.emit('error', error)
-  }
-
-  self._parserErrorHandler = function (error) {
-    if (this.res) {
-      if (this.res.request) {
-        this.res.request.emit('error', error)
-      } else {
-        this.res.emit('error', error)
-      }
-    } else {
-      this._httpMessage.emit('error', error)
-    }
-  }
-
-  self._buildRequest = function(){
-    var self = this;
-
-    if (options.form) {
-      self.form(options.form)
-    }
-
-    if (options.qs) self.qs(options.qs)
-
-    if (self.uri.path) {
-      self.path = self.uri.path
-    } else {
-      self.path = self.uri.pathname + (self.uri.search || "")
-    }
-
-    if (self.path.length === 0) self.path = '/'
-
-
-    // Auth must happen last in case signing is dependent on other headers
-    if (options.oauth) {
-      self.oauth(options.oauth)
-    }
-
-    if (options.aws) {
-      self.aws(options.aws)
-    }
-
-    if (options.hawk) {
-      self.hawk(options.hawk)
-    }
-
-    if (options.httpSignature) {
-      self.httpSignature(options.httpSignature)
-    }
-
-    if (options.auth) {
-      if (Object.prototype.hasOwnProperty.call(options.auth, 'username')) options.auth.user = options.auth.username
-      if (Object.prototype.hasOwnProperty.call(options.auth, 'password')) options.auth.pass = options.auth.password
-
-      self.auth(
-        options.auth.user,
-        options.auth.pass,
-        options.auth.sendImmediately,
-        options.auth.bearer
-      )
-    }
-
-    if (self.uri.auth && !self.hasHeader('authorization')) {
-      var authPieces = self.uri.auth.split(':').map(function(item){ return querystring.unescape(item) })
-      self.auth(authPieces[0], authPieces.slice(1).join(':'), true)
-    }
-    if (self.proxy && self.proxy.auth && !self.hasHeader('proxy-authorization') && !self.tunnel) {
-      self.setHeader('proxy-authorization', "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return querystring.unescape(item)}).join(':')))
-    }
-
-
-    if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path)
-
-    if (options.json) {
-      self.json(options.json)
-    } else if (options.multipart) {
-      self.boundary = uuid()
-      self.multipart(options.multipart)
-    }
-
-    if (self.body) {
-      var length = 0
-      if (!Buffer.isBuffer(self.body)) {
-        if (Array.isArray(self.body)) {
-          for (var i = 0; i < self.body.length; i++) {
-            length += self.body[i].length
-          }
-        } else {
-          self.body = new Buffer(self.body)
-          length = self.body.length
-        }
-      } else {
-        length = self.body.length
-      }
-      if (length) {
-        if (!self.hasHeader('content-length')) self.setHeader('content-length', length)
-      } else {
-        throw new Error('Argument error, options.body.')
-      }
-    }
-
-    var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol
-      , defaultModules = {'http:':http, 'https:':https, 'unix:':http}
-      , httpModules = self.httpModules || {}
-      ;
-    self.httpModule = httpModules[protocol] || defaultModules[protocol]
-
-    if (!self.httpModule) return this.emit('error', new Error("Invalid protocol: " + protocol))
-
-    if (options.ca) self.ca = options.ca
-
-    if (!self.agent) {
-      if (options.agentOptions) self.agentOptions = options.agentOptions
-
-      if (options.agentClass) {
-        self.agentClass = options.agentClass
-      } else if (options.forever) {
-        self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL
-      } else {
-        self.agentClass = self.httpModule.Agent
-      }
-    }
-
-    if (self.pool === false) {
-      self.agent = false
-    } else {
-      self.agent = self.agent || self.getAgent()
-      if (self.maxSockets) {
-        // Don't use our pooling if node has the refactored client
-        self.agent.maxSockets = self.maxSockets
-      }
-      if (self.pool.maxSockets) {
-        // Don't use our pooling if node has the refactored client
-        self.agent.maxSockets = self.pool.maxSockets
-      }
-    }
-
-    self.on('pipe', function (src) {
-      if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.")
-      self.src = src
-      if (isReadStream(src)) {
-        if (!self.hasHeader('content-type')) self.setHeader('content-type', mime.lookup(src.path))
-      } else {
-        if (src.headers) {
-          for (var i in src.headers) {
-            if (!self.hasHeader(i)) {
-              self.setHeader(i, src.headers[i])
-            }
-          }
-        }
-        if (self._json && !self.hasHeader('content-type'))
-          self.setHeader('content-type', 'application/json')
-        if (src.method && !self.explicitMethod) {
-          self.method = src.method
-        }
-      }
-
-      // self.on('pipe', function () {
-      //   console.error("You have already piped to this stream. Pipeing twice is likely to break the request.")
-      // })
-    })
-
-    process.nextTick(function () {
-      if (self._aborted) return
-
-      if (self._form) {
-        self.setHeaders(self._form.getHeaders())
-        try {
-          var length = self._form.getLengthSync()
-          self.setHeader('content-length', length)
-        } catch(e){}
-        self._form.pipe(self)
-      }
-      if (self.body) {
-        if (Array.isArray(self.body)) {
-          self.body.forEach(function (part) {
-            self.write(part)
-          })
-        } else {
-          self.write(self.body)
-        }
-        self.end()
-      } else if (self.requestBodyStream) {
-        console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.")
-        self.requestBodyStream.pipe(self)
-      } else if (!self.src) {
-        if (self.method !== 'GET' && typeof self.method !== 'undefined') {
-          self.setHeader('content-length', 0)
-        }
-        self.end()
-      }
-      self.ntick = true
-    })
-
-  } // End _buildRequest
-
-  self._handleUnixSocketURI = function(self){
-    // Parse URI and extract a socket path (tested as a valid socket using net.connect), and a http style path suffix
-    // Thus http requests can be made to a socket using the uri unix://tmp/my.socket/urlpath
-    // and a request for '/urlpath' will be sent to the unix socket at /tmp/my.socket
-
-    self.unixsocket = true;
-
-    var full_path = self.uri.href.replace(self.uri.protocol+'/', '');
-
-    var lookup = full_path.split('/');
-    var error_connecting = true;
-
-    var lookup_table = {};
-    do { lookup_table[lookup.join('/')]={} } while(lookup.pop())
-    for (r in lookup_table){
-      try_next(r);
-    }
-
-    function try_next(table_row){
-      var client = net.connect( table_row );
-      client.path = table_row
-      client.on('error', function(){ lookup_table[this.path].error_connecting=true; this.end(); });
-      client.on('connect', function(){ lookup_table[this.path].error_connecting=false; this.end(); });
-      table_row.client = client;
-    }
-
-    wait_for_socket_response();
-
-    response_counter = 0;
-
-    function wait_for_socket_response(){
-      var detach;
-      if('undefined' == typeof setImmediate ) detach = process.nextTick
-      else detach = setImmediate;
-      detach(function(){
-        // counter to prevent infinite blocking waiting for an open socket to be found.
-        response_counter++;
-        var trying = false;
-        for (r in lookup_table){
-          //console.log(r, lookup_table[r], lookup_table[r].error_connecting)
-          if('undefined' == typeof lookup_table[r].error_connecting)
-            trying = true;
-        }
-        if(trying && response_counter<1000)
-          wait_for_socket_response()
-        else
-          set_socket_properties();
-      })
-    }
-
-    function set_socket_properties(){
-      var host;
-      for (r in lookup_table){
-        if(lookup_table[r].error_connecting === false){
-          host = r
-        }
-      }
-      if(!host){
-        self.emit('error', new Error("Failed to connect to any socket in "+full_path))
-      }
-      var path = full_path.replace(host, '')
-
-      self.socketPath = host
-      self.uri.pathname = path
-      self.uri.href = path
-      self.uri.path = path
-      self.host = ''
-      self.hostname = ''
-      delete self.host
-      delete self.hostname
-      self._buildRequest();
-    }
-  }
-
-  // Intercept UNIX protocol requests to change properties to match socket
-  if(/^unix:/.test(self.uri.protocol)){
-    self._handleUnixSocketURI(self);
-  } else {
-    self._buildRequest();
-  }
-
-}
-
-// Must call this when following a redirect from https to http or vice versa
-// Attempts to keep everything as identical as possible, but update the
-// httpModule, Tunneling agent, and/or Forever Agent in use.
-Request.prototype._updateProtocol = function () {
-  var self = this
-  var protocol = self.uri.protocol
-
-  if (protocol === 'https:') {
-    // previously was doing http, now doing https
-    // if it's https, then we might need to tunnel now.
-    if (self.proxy && self.canTunnel) {
-      self.tunnel = true
-      var tunnelFn = self.proxy.protocol === 'http:'
-                   ? tunnel.httpsOverHttp : tunnel.httpsOverHttps
-      var tunnelOptions = { proxy: { host: self.proxy.hostname
-                                   , port: +self.proxy.port
-                                   , proxyAuth: self.proxy.auth }
-                          , rejectUnauthorized: self.rejectUnauthorized
-                          , ca: self.ca }
-      self.agent = tunnelFn(tunnelOptions)
-      return
-    }
-
-    self.httpModule = https
-    switch (self.agentClass) {
-      case ForeverAgent:
-        self.agentClass = ForeverAgent.SSL
-        break
-      case http.Agent:
-        self.agentClass = https.Agent
-        break
-      default:
-        // nothing we can do.  Just hope for the best.
-        return
-    }
-
-    // if there's an agent, we need to get a new one.
-    if (self.agent) self.agent = self.getAgent()
-
-  } else {
-    // previously was doing https, now doing http
-    // stop any tunneling.
-    if (self.tunnel) self.tunnel = false
-    self.httpModule = http
-    switch (self.agentClass) {
-      case ForeverAgent.SSL:
-        self.agentClass = ForeverAgent
-        break
-      case https.Agent:
-        self.agentClass = http.Agent
-        break
-      default:
-        // nothing we can do.  just hope for the best
-        return
-    }
-
-    // if there's an agent, then get a new one.
-    if (self.agent) {
-      self.agent = null
-      self.agent = self.getAgent()
-    }
-  }
-}
-
-Request.prototype.getAgent = function () {
-  var Agent = this.agentClass
-  var options = {}
-  if (this.agentOptions) {
-    for (var i in this.agentOptions) {
-      options[i] = this.agentOptions[i]
-    }
-  }
-  if (this.ca) options.ca = this.ca
-  if (this.ciphers) options.ciphers = this.ciphers
-  if (this.secureProtocol) options.secureProtocol = this.secureProtocol
-  if (this.secureOptions) options.secureOptions = this.secureOptions
-  if (typeof this.rejectUnauthorized !== 'undefined') options.rejectUnauthorized = this.rejectUnauthorized
-
-  if (this.cert && this.key) {
-    options.key = this.key
-    options.cert = this.cert
-  }
-
-  var poolKey = ''
-
-  // different types of agents are in different pools
-  if (Agent !== this.httpModule.Agent) {
-    poolKey += Agent.name
-  }
-
-  if (!this.httpModule.globalAgent) {
-    // node 0.4.x
-    options.host = this.host
-    options.port = this.port
-    if (poolKey) poolKey += ':'
-    poolKey += this.host + ':' + this.port
-  }
-
-  // ca option is only relevant if proxy or destination are https
-  var proxy = this.proxy
-  if (typeof proxy === 'string') proxy = url.parse(proxy)
-  var isHttps = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:'
-  if (isHttps) {
-    if (options.ca) {
-      if (poolKey) poolKey += ':'
-      poolKey += options.ca
-    }
-
-    if (typeof options.rejectUnauthorized !== 'undefined') {
-      if (poolKey) poolKey += ':'
-      poolKey += options.rejectUnauthorized
-    }
-
-    if (options.cert)
-      poolKey += options.cert.toString('ascii') + options.key.toString('ascii')
-
-    if (options.ciphers) {
-      if (poolKey) poolKey += ':'
-      poolKey += options.ciphers
-    }
-
-    if (options.secureProtocol) {
-      if (poolKey) poolKey += ':'
-      poolKey += options.secureProtocol
-    }
-  }
-
-  if (this.pool === globalPool && !poolKey && Object.keys(options).length === 0 && this.httpModule.globalAgent) {
-    // not doing anything special.  Use the globalAgent
-    return this.httpModule.globalAgent
-  }
-
-  // we're using a stored agent.  Make sure it's protocol-specific
-  poolKey = this.uri.protocol + poolKey
-
-  // already generated an agent for this setting
-  if (this.pool[poolKey]) return this.pool[poolKey]
-
-  return this.pool[poolKey] = new Agent(options)
-}
-
-Request.prototype.start = function () {
-  // start() is called once we are ready to send the outgoing HTTP request.
-  // this is usually called on the first write(), end() or on nextTick()
-  var self = this
-
-  if (self._aborted) return
-
-  self._started = true
-  self.method = self.method || 'GET'
-  self.href = self.uri.href
-
-  if (self.src && self.src.stat && self.src.stat.size && !self.hasHeader('content-length')) {
-    self.setHeader('content-length', self.src.stat.size)
-  }
-  if (self._aws) {
-    self.aws(self._aws, true)
-  }
-
-  // We have a method named auth, which is completely different from the http.request
-  // auth option.  If we don't remove it, we're gonna have a bad time.
-  var reqOptions = copy(self)
-  delete reqOptions.auth
-
-  debug('make request', self.uri.href)
-  self.req = self.httpModule.request(reqOptions, self.onResponse.bind(self))
-
-  if (self.timeout && !self.timeoutTimer) {
-    self.timeoutTimer = setTimeout(function () {
-      self.req.abort()
-      var e = new Error("ETIMEDOUT")
-      e.code = "ETIMEDOUT"
-      self.emit("error", e)
-    }, self.timeout)
-
-    // Set additional timeout on socket - in case if remote
-    // server freeze after sending headers
-    if (self.req.setTimeout) { // only works on node 0.6+
-      self.req.setTimeout(self.timeout, function () {
-        if (self.req) {
-          self.req.abort()
-          var e = new Error("ESOCKETTIMEDOUT")
-          e.code = "ESOCKETTIMEDOUT"
-          self.emit("error", e)
-        }
-      })
-    }
-  }
-
-  self.req.on('error', self.clientErrorHandler)
-  self.req.on('drain', function() {
-    self.emit('drain')
-  })
-  self.on('end', function() {
-    if ( self.req.connection ) self.req.connection.removeListener('error', self._parserErrorHandler)
-  })
-  self.emit('request', self.req)
-}
-Request.prototype.onResponse = function (response) {
-  var self = this
-  debug('onResponse', self.uri.href, response.statusCode, response.headers)
-  response.on('end', function() {
-    debug('response end', self.uri.href, response.statusCode, response.headers)
-  });
-
-  if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) {
-    response.connection.once('error', self._parserErrorHandler)
-  }
-  if (self._aborted) {
-    debug('aborted', self.uri.href)
-    response.resume()
-    return
-  }
-  if (self._paused) response.pause()
-  else response.resume()
-
-  self.response = response
-  response.request = self
-  response.toJSON = toJSON
-
-  // XXX This is different on 0.10, because SSL is strict by default
-  if (self.httpModule === https &&
-      self.strictSSL &&
-      !response.client.authorized) {
-    debug('strict ssl error', self.uri.href)
-    var sslErr = response.client.authorizationError
-    self.emit('error', new Error('SSL Error: '+ sslErr))
-    return
-  }
-
-  if (self.setHost && self.hasHeader('host')) delete self.headers[self.hasHeader('host')]
-  if (self.timeout && self.timeoutTimer) {
-    clearTimeout(self.timeoutTimer)
-    self.timeoutTimer = null
-  }
-
-  var targetCookieJar = (self._jar && self._jar.setCookie)?self._jar:globalCookieJar;
-  var addCookie = function (cookie) {
-    //set the cookie if it's domain in the href's domain.
-    try {
-      targetCookieJar.setCookie(cookie, self.uri.href, {ignoreError: true});
-    } catch (e) {
-      self.emit('error', e);
-    }
-  }
-
-  if (hasHeader('set-cookie', response.headers) && (!self._disableCookies)) {
-    var headerName = hasHeader('set-cookie', response.headers)
-    if (Array.isArray(response.headers[headerName])) response.headers[headerName].forEach(addCookie)
-    else addCookie(response.headers[headerName])
-  }
-
-  var redirectTo = null
-  if (response.statusCode >= 300 && response.statusCode < 400 && hasHeader('location', response.headers)) {
-    var location = response.headers[hasHeader('location', response.headers)]
-    debug('redirect', location)
-
-    if (self.followAllRedirects) {
-      redirectTo = location
-    } else if (self.followRedirect) {
-      switch (self.method) {
-        case 'PATCH':
-        case 'PUT':
-        case 'POST':
-        case 'DELETE':
-          // Do not follow redirects
-          break
-        default:
-          redirectTo = location
-          break
-      }
-    }
-  } else if (response.statusCode == 401 && self._hasAuth && !self._sentAuth) {
-    var authHeader = response.headers[hasHeader('www-authenticate', response.headers)]
-    var authVerb = authHeader && authHeader.split(' ')[0].toLowerCase()
-    debug('reauth', authVerb)
-
-    switch (authVerb) {
-      case 'basic':
-        self.auth(self._user, self._pass, true)
-        redirectTo = self.uri
-        break
-
-      case 'bearer':
-        self.auth(null, null, true, self._bearer)
-        redirectTo = self.uri
-        break
-
-      case 'digest':
-        // TODO: More complete implementation of RFC 2617.
-        //   - check challenge.algorithm
-        //   - support algorithm="MD5-sess"
-        //   - handle challenge.domain
-        //   - support qop="auth-int" only
-        //   - handle Authentication-Info (not necessarily?)
-        //   - check challenge.stale (not necessarily?)
-        //   - increase nc (not necessarily?)
-        // For reference:
-        // http://tools.ietf.org/html/rfc2617#section-3
-        // https://github.com/bagder/curl/blob/master/lib/http_digest.c
-
-        var challenge = {}
-        var re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi
-        for (;;) {
-          var match = re.exec(authHeader)
-          if (!match) break
-          challenge[match[1]] = match[2] || match[3];
-        }
-
-        var ha1 = md5(self._user + ':' + challenge.realm + ':' + self._pass)
-        var ha2 = md5(self.method + ':' + self.uri.path)
-        var qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth'
-        var nc = qop && '00000001'
-        var cnonce = qop && uuid().replace(/-/g, '')
-        var digestResponse = qop ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2) : md5(ha1 + ':' + challenge.nonce + ':' + ha2)
-        var authValues = {
-          username: self._user,
-          realm: challenge.realm,
-          nonce: challenge.nonce,
-          uri: self.uri.path,
-          qop: qop,
-          response: digestResponse,
-          nc: nc,
-          cnonce: cnonce,
-          algorithm: challenge.algorithm,
-          opaque: challenge.opaque
-        }
-
-        authHeader = []
-        for (var k in authValues) {
-          if (!authValues[k]) {
-            //ignore
-          } else if (k === 'qop' || k === 'nc' || k === 'algorithm') {
-            authHeader.push(k + '=' + authValues[k])
-          } else {
-            authHeader.push(k + '="' + authValues[k] + '"')
-          }
-        }
-        authHeader = 'Digest ' + authHeader.join(', ')
-        self.setHeader('authorization', authHeader)
-        self._sentAuth = true
-
-        redirectTo = self.uri
-        break
-    }
-  }
-
-  if (redirectTo) {
-    debug('redirect to', redirectTo)
-
-    // ignore any potential response body.  it cannot possibly be useful
-    // to us at this point.
-    if (self._paused) response.resume()
-
-    if (self._redirectsFollowed >= self.maxRedirects) {
-      self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop "+self.uri.href))
-      return
-    }
-    self._redirectsFollowed += 1
-
-    if (!isUrl.test(redirectTo)) {
-      redirectTo = url.resolve(self.uri.href, redirectTo)
-    }
-
-    var uriPrev = self.uri
-    self.uri = url.parse(redirectTo)
-
-    // handle the case where we change protocol from https to http or vice versa
-    if (self.uri.protocol !== uriPrev.protocol) {
-      self._updateProtocol()
-    }
-
-    self.redirects.push(
-      { statusCode : response.statusCode
-      , redirectUri: redirectTo
-      }
-    )
-    if (self.followAllRedirects && response.statusCode != 401 && response.statusCode != 307) self.method = 'GET'
-    // self.method = 'GET' // Force all redirects to use GET || commented out fixes #215
-    delete self.src
-    delete self.req
-    delete self.agent
-    delete self._started
-    if (response.statusCode != 401 && response.statusCode != 307) {
-      // Remove parameters from the previous response, unless this is the second request
-      // for a server that requires digest authentication.
-      delete self.body
-      delete self._form
-      if (self.headers) {
-        if (self.hasHeader('host')) delete self.headers[self.hasHeader('host')]
-        if (self.hasHeader('content-type')) delete self.headers[self.hasHeader('content-type')]
-        if (self.hasHeader('content-length')) delete self.headers[self.hasHeader('content-length')]
-      }
-    }
-
-    self.emit('redirect');
-
-    self.init()
-    return // Ignore the rest of the response
-  } else {
-    self._redirectsFollowed = self._redirectsFollowed || 0
-    // Be a good stream and emit end when the response is finished.
-    // Hack to emit end on close because of a core bug that never fires end
-    response.on('close', function () {
-      if (!self._ended) self.response.emit('end')
-    })
-
-    if (self.encoding) {
-      if (self.dests.length !== 0) {
-        console.error("Ignoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.")
-      } else {
-        response.setEncoding(self.encoding)
-      }
-    }
-
-    self.emit('response', response)
-
-    self.dests.forEach(function (dest) {
-      self.pipeDest(dest)
-    })
-
-    response.on("data", function (chunk) {
-      self._destdata = true
-      self.emit("data", chunk)
-    })
-    response.on("end", function (chunk) {
-      self._ended = true
-      self.emit("end", chunk)
-    })
-    response.on("close", function () {self.emit("close")})
-
-    if (self.callback) {
-      var buffer = []
-      var bodyLen = 0
-      self.on("data", function (chunk) {
-        buffer.push(chunk)
-        bodyLen += chunk.length
-      })
-      self.on("end", function () {
-        debug('end event', self.uri.href)
-        if (self._aborted) {
-          debug('aborted', self.uri.href)
-          return
-        }
-
-        if (buffer.length && Buffer.isBuffer(buffer[0])) {
-          debug('has body', self.uri.href, bodyLen)
-          var body = new Buffer(bodyLen)
-          var i = 0
-          buffer.forEach(function (chunk) {
-            chunk.copy(body, i, 0, chunk.length)
-            i += chunk.length
-          })
-          if (self.encoding === null) {
-            response.body = body
-          } else {
-            response.body = body.toString(self.encoding)
-          }
-        } else if (buffer.length) {
-          // The UTF8 BOM [0xEF,0xBB,0xBF] is converted to [0xFE,0xFF] in the JS UTC16/UCS2 representation.
-          // Strip this value out when the encoding is set to 'utf8', as upstream consumers won't expect it and it breaks JSON.parse().
-          if (self.encoding === 'utf8' && buffer[0].length > 0 && buffer[0][0] === "\uFEFF") {
-            buffer[0] = buffer[0].substring(1)
-          }
-          response.body = buffer.join('')
-        }
-
-        if (self._json) {
-          try {
-            response.body = JSON.parse(response.body)
-          } catch (e) {}
-        }
-        debug('emitting complete', self.uri.href)
-        if(response.body == undefined && !self._json) {
-          response.body = "";
-        }
-        self.emit('complete', response, response.body)
-      })
-    }
-    //if no callback
-    else{
-      self.on("end", function () {
-        if (self._aborted) {
-          debug('aborted', self.uri.href)
-          return
-        }
-        self.emit('complete', response);
-      });
-    }
-  }
-  debug('finish init function', self.uri.href)
-}
-
-Request.prototype.abort = function () {
-  this._aborted = true
-
-  if (this.req) {
-    this.req.abort()
-  }
-  else if (this.response) {
-    this.response.abort()
-  }
-
-  this.emit("abort")
-}
-
-Request.prototype.pipeDest = function (dest) {
-  var response = this.response
-  // Called after the response is received
-  if (dest.headers && !dest.headersSent) {
-    if (hasHeader('content-type', response.headers)) {
-      var ctname = hasHeader('content-type', response.headers)
-      if (dest.setHeader) dest.setHeader(ctname, response.headers[ctname])
-      else dest.headers[ctname] = response.headers[ctname]
-    }
-
-    if (hasHeader('content-length', response.headers)) {
-      var clname = hasHeader('content-length', response.headers)
-      if (dest.setHeader) dest.setHeader(clname, response.headers[clname])
-      else dest.headers[clname] = response.headers[clname]
-    }
-  }
-  if (dest.setHeader && !dest.headersSent) {
-    for (var i in response.headers) {
-      dest.setHeader(i, response.headers[i])
-    }
-    dest.statusCode = response.statusCode
-  }
-  if (this.pipefilter) this.pipefilter(response, dest)
-}
-
-// Composable API
-Request.prototype.setHeader = function (name, value, clobber) {
-  if (clobber === undefined) clobber = true
-  if (clobber || !this.hasHeader(name)) this.headers[name] = value
-  else this.headers[this.hasHeader(name)] += ',' + value
-  return this
-}
-Request.prototype.setHeaders = function (headers) {
-  for (var i in headers) {this.setHeader(i, headers[i])}
-  return this
-}
-Request.prototype.hasHeader = function (header, headers) {
-  var headers = Object.keys(headers || this.headers)
-    , lheaders = headers.map(function (h) {return h.toLowerCase()})
-    ;
-  header = header.toLowerCase()
-  for (var i=0;i<lheaders.length;i++) {
-    if (lheaders[i] === header) return headers[i]
-  }
-  return false
-}
-
-var hasHeader = Request.prototype.hasHeader
-
-Request.prototype.qs = function (q, clobber) {
-  var base
-  if (!clobber && this.uri.query) base = qs.parse(this.uri.query)
-  else base = {}
-
-  for (var i in q) {
-    base[i] = q[i]
-  }
-
-  if (qs.stringify(base) === ''){
-    return this
-  }
-
-  this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base))
-  this.url = this.uri
-  this.path = this.uri.path
-
-  return this
-}
-Request.prototype.form = function (form) {
-  if (form) {
-    this.setHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8')
-    this.body = qs.stringify(form).toString('utf8')
-    return this
-  }
-  // create form-data object
-  this._form = new FormData()
-  return this._form
-}
-Request.prototype.multipart = function (multipart) {
-  var self = this
-  self.body = []
-
-  if (!self.hasHeader('content-type')) {
-    self.setHeader('content-type', 'multipart/related; boundary=' + self.boundary)
-  } else {
-    var headerName = self.hasHeader('content-type');
-    self.setHeader(headerName, self.headers[headerName].split(';')[0] + '; boundary=' + self.boundary)
-  }
-
-  if (!multipart.forEach) throw new Error('Argument error, options.multipart.')
-
-  if (self.preambleCRLF) {
-    self.body.push(new Buffer('\r\n'))
-  }
-
-  multipart.forEach(function (part) {
-    var body = part.body
-    if(body == null) throw Error('Body attribute missing in multipart.')
-    delete part.body
-    var preamble = '--' + self.boundary + '\r\n'
-    Object.keys(part).forEach(function (key) {
-      preamble += key + ': ' + part[key] + '\r\n'
-    })
-    preamble += '\r\n'
-    self.body.push(new Buffer(preamble))
-    self.body.push(new Buffer(body))
-    self.body.push(new Buffer('\r\n'))
-  })
-  self.body.push(new Buffer('--' + self.boundary + '--'))
-  return self
-}
-Request.prototype.json = function (val) {
-  var self = this
-
-  if (!self.hasHeader('accept')) self.setHeader('accept', 'application/json')
-
-  this._json = true
-  if (typeof val === 'boolean') {
-    if (typeof this.body === 'object') {
-      this.body = safeStringify(this.body)
-      if (!self.hasHeader('content-type'))
-        self.setHeader('content-type', 'application/json')
-    }
-  } else {
-    this.body = safeStringify(val)
-    if (!self.hasHeader('content-type'))
-      self.setHeader('content-type', 'application/json')
-  }
-
-  return this
-}
-Request.prototype.getHeader = function (name, headers) {
-  var result, re, match
-  if (!headers) headers = this.headers
-  Object.keys(headers).forEach(function (key) {
-    if (key.length !== name.length) return
-    re = new RegExp(name, 'i')
-    match = key.match(re)
-    if (match) result = headers[key]
-  })
-  return result
-}
-var getHeader = Request.prototype.getHeader
-
-Request.prototype.auth = function (user, pass, sendImmediately, bearer) {
-  if (bearer !== undefined) {
-    this._bearer = bearer
-    this._hasAuth = true
-    if (sendImmediately || typeof sendImmediately == 'undefined') {
-      if (typeof bearer === 'function') {
-        bearer = bearer()
-      }
-      this.setHeader('authorization', 'Bearer ' + bearer)
-      this._sentAuth = true
-    }
-    return this
-  }
-  if (typeof user !== 'string' || (pass !== undefined && typeof pass !== 'string')) {
-    throw new Error('auth() received invalid user or password')
-  }
-  this._user = user
-  this._pass = pass
-  this._hasAuth = true
-  var header = typeof pass !== 'undefined' ? user + ':' + pass : user
-  if (sendImmediately || typeof sendImmediately == 'undefined') {
-    this.setHeader('authorization', 'Basic ' + toBase64(header))
-    this._sentAuth = true
-  }
-  return this
-}
-Request.prototype.aws = function (opts, now) {
-  if (!now) {
-    this._aws = opts
-    return this
-  }
-  var date = new Date()
-  this.setHeader('date', date.toUTCString())
-  var auth =
-    { key: opts.key
-    , secret: opts.secret
-    , verb: this.method.toUpperCase()
-    , date: date
-    , contentType: this.getHeader('content-type') || ''
-    , md5: this.getHeader('content-md5') || ''
-    , amazonHeaders: aws.canonicalizeHeaders(this.headers)
-    }
-  if (opts.bucket && this.path) {
-    auth.resource = '/' + opts.bucket + this.path
-  } else if (opts.bucket && !this.path) {
-    auth.resource = '/' + opts.bucket
-  } else if (!opts.bucket && this.path) {
-    auth.resource = this.path
-  } else if (!opts.bucket && !this.path) {
-    auth.resource = '/'
-  }
-  auth.resource = aws.canonicalizeResource(auth.resource)
-  this.setHeader('authorization', aws.authorization(auth))
-
-  return this
-}
-Request.prototype.httpSignature = function (opts) {
-  var req = this
-  httpSignature.signRequest({
-    getHeader: function(header) {
-      return getHeader(header, req.headers)
-    },
-    setHeader: function(header, value) {
-      req.setHeader(header, value)
-    },
-    method: this.method,
-    path: this.path
-  }, opts)
-  debug('httpSignature authorization', this.getHeader('authorization'))
-
-  return this
-}
-
-Request.prototype.hawk = function (opts) {
-  this.setHeader('Authorization', hawk.client.header(this.uri, this.method, opts).field)
-}
-
-Request.prototype.oauth = function (_oauth) {
-  var form
-  if (this.hasHeader('content-type') &&
-      this.getHeader('content-type').slice(0, 'application/x-www-form-urlencoded'.length) ===
-        'application/x-www-form-urlencoded'
-     ) {
-    form = qs.parse(this.body)
-  }
-  if (this.uri.query) {
-    form = qs.parse(this.uri.query)
-  }
-  if (!form) form = {}
-  var oa = {}
-  for (var i in form) oa[i] = form[i]
-  for (var i in _oauth) oa['oauth_'+i] = _oauth[i]
-  if (!oa.oauth_version) oa.oauth_version = '1.0'
-  if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( Date.now() / 1000 ).toString()
-  if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '')
-
-  oa.oauth_signature_method = 'HMAC-SHA1'
-
-  var consumer_secret = oa.oauth_consumer_secret
-  delete oa.oauth_consumer_secret
-  var token_secret = oa.oauth_token_secret
-  delete oa.oauth_token_secret
-  var timestamp = oa.oauth_timestamp
-
-  var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname
-  var signature = oauth.hmacsign(this.method, baseurl, oa, consumer_secret, token_secret)
-
-  // oa.oauth_signature = signature
-  for (var i in form) {
-    if ( i.slice(0, 'oauth_') in _oauth) {
-      // skip
-    } else {
-      delete oa['oauth_'+i]
-      if (i !== 'x_auth_mode') delete oa[i]
-    }
-  }
-  oa.oauth_timestamp = timestamp
-  var authHeader = 'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+oauth.rfc3986(oa[i])+'"'}).join(',')
-  authHeader += ',oauth_signature="' + oauth.rfc3986(signature) + '"'
-  this.setHeader('Authorization', authHeader)
-  return this
-}
-Request.prototype.jar = function (jar) {
-  var cookies
-
-  if (this._redirectsFollowed === 0) {
-    this.originalCookieHeader = this.getHeader('cookie')
-  }
-
-  if (!jar) {
-    // disable cookies
-    cookies = false
-    this._disableCookies = true
-  } else {
-    var targetCookieJar = (jar && jar.getCookieString)?jar:globalCookieJar;
-    var urihref = this.uri.href
-    //fetch cookie in the Specified host
-    if (targetCookieJar) {
-      cookies = targetCookieJar.getCookieString(urihref);
-    }
-  }
-
-  //if need cookie and cookie is not empty
-  if (cookies && cookies.length) {
-    if (this.originalCookieHeader) {
-      // Don't overwrite existing Cookie header
-      this.setHeader('cookie', this.originalCookieHeader + '; ' + cookies)
-    } else {
-      this.setHeader('cookie', cookies)
-    }
-  }
-  this._jar = jar
-  return this
-}
-
-
-// Stream API
-Request.prototype.pipe = function (dest, opts) {
-  if (this.response) {
-    if (this._destdata) {
-      throw new Error("You cannot pipe after data has been emitted from the response.")
-    } else if (this._ended) {
-      throw new Error("You cannot pipe after the response has been ended.")
-    } else {
-      stream.Stream.prototype.pipe.call(this, dest, opts)
-      this.pipeDest(dest)
-      return dest
-    }
-  } else {
-    this.dests.push(dest)
-    stream.Stream.prototype.pipe.call(this, dest, opts)
-    return dest
-  }
-}
-Request.prototype.write = function () {
-  if (!this._started) this.start()
-  return this.req.write.apply(this.req, arguments)
-}
-Request.prototype.end = function (chunk) {
-  if (chunk) this.write(chunk)
-  if (!this._started) this.start()
-  this.req.end()
-}
-Request.prototype.pause = function () {
-  if (!this.response) this._paused = true
-  else this.response.pause.apply(this.response, arguments)
-}
-Request.prototype.resume = function () {
-  if (!this.response) this._paused = false
-  else this.response.resume.apply(this.response, arguments)
-}
-Request.prototype.destroy = function () {
-  if (!this._ended) this.end()
-  else if (this.response) this.response.destroy()
-}
-
-function toJSON () {
-  return getSafe(this, '__' + (((1+Math.random())*0x10000)|0).toString(16))
-}
-
-Request.prototype.toJSON = toJSON
-
-
-module.exports = Request
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/AUTHORS b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/AUTHORS
deleted file mode 100644
index 247b7543..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/AUTHORS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Authors sorted by whether or not they're me.
-Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)
-Wayne Larsen <wayne@larsen.st> (http://github.com/wvl)
-ritch <skawful@gmail.com>
-Marcel Laverdet
-Yosef Dinerstein <yosefd@microsoft.com>
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/LICENSE
deleted file mode 100644
index 05a40109..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
-All rights reserved.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/README.md
deleted file mode 100644
index cd123b65..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-`rm -rf` for node.
-
-Install with `npm install rimraf`, or just drop rimraf.js somewhere.
-
-## API
-
-`rimraf(f, callback)`
-
-The callback will be called with an error if there is one.  Certain
-errors are handled for you:
-
-* Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of
-  `opts.maxBusyTries` times before giving up.
-* `ENOENT` - If the file doesn't exist, rimraf will return
-  successfully, since your desired outcome is already the case.
-
-## rimraf.sync
-
-It can remove stuff synchronously, too.  But that's not so good.  Use
-the async API.  It's better.
-
-## CLI
-
-If installed with `npm install rimraf -g` it can be used as a global
-command `rimraf <path>` which is useful for cross platform support.
-
-## mkdirp
-
-If you need to create a directory recursively, check out
-[mkdirp](https://github.com/substack/node-mkdirp).
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/bin.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/bin.js
deleted file mode 100755
index 29bfa8a6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/bin.js
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env node
-
-var rimraf = require('./')
-
-var help = false
-var dashdash = false
-var args = process.argv.slice(2).filter(function(arg) {
-  if (dashdash)
-    return !!arg
-  else if (arg === '--')
-    dashdash = true
-  else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/))
-    help = true
-  else
-    return !!arg
-});
-
-if (help || args.length === 0) {
-  // If they didn't ask for help, then this is not a "success"
-  var log = help ? console.log : console.error
-  log('Usage: rimraf <path>')
-  log('')
-  log('  Deletes all files and folders at "path" recursively.')
-  log('')
-  log('Options:')
-  log('')
-  log('  -h, --help    Display this usage info')
-  process.exit(help ? 0 : 1)
-} else {
-  args.forEach(function(arg) {
-    rimraf.sync(arg)
-  })
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/package.json
deleted file mode 100644
index c55827da..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/package.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
-  "name": "rimraf",
-  "version": "2.2.8",
-  "main": "rimraf.js",
-  "description": "A deep deletion module for node (like `rm -rf`)",
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "license": {
-    "type": "MIT",
-    "url": "https://github.com/isaacs/rimraf/raw/master/LICENSE"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/rimraf.git"
-  },
-  "scripts": {
-    "test": "cd test && bash run.sh"
-  },
-  "bin": {
-    "rimraf": "./bin.js"
-  },
-  "contributors": [
-    {
-      "name": "Isaac Z. Schlueter",
-      "email": "i@izs.me",
-      "url": "http://blog.izs.me"
-    },
-    {
-      "name": "Wayne Larsen",
-      "email": "wayne@larsen.st",
-      "url": "http://github.com/wvl"
-    },
-    {
-      "name": "ritch",
-      "email": "skawful@gmail.com"
-    },
-    {
-      "name": "Marcel Laverdet"
-    },
-    {
-      "name": "Yosef Dinerstein",
-      "email": "yosefd@microsoft.com"
-    }
-  ],
-  "readme": "`rm -rf` for node.\n\nInstall with `npm install rimraf`, or just drop rimraf.js somewhere.\n\n## API\n\n`rimraf(f, callback)`\n\nThe callback will be called with an error if there is one.  Certain\nerrors are handled for you:\n\n* Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of\n  `opts.maxBusyTries` times before giving up.\n* `ENOENT` - If the file doesn't exist, rimraf will return\n  successfully, since your desired outcome is already the case.\n\n## rimraf.sync\n\nIt can remove stuff synchronously, too.  But that's not so good.  Use\nthe async API.  It's better.\n\n## CLI\n\nIf installed with `npm install rimraf -g` it can be used as a global\ncommand `rimraf <path>` which is useful for cross platform support.\n\n## mkdirp\n\nIf you need to create a directory recursively, check out\n[mkdirp](https://github.com/substack/node-mkdirp).\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/rimraf/issues"
-  },
-  "homepage": "https://github.com/isaacs/rimraf",
-  "_id": "rimraf@2.2.8",
-  "_shasum": "e439be2aaee327321952730f99a8929e4fc50582",
-  "_from": "rimraf@~2.2.5",
-  "_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/rimraf.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/rimraf.js
deleted file mode 100644
index eb96c46a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/rimraf.js
+++ /dev/null
@@ -1,248 +0,0 @@
-module.exports = rimraf
-rimraf.sync = rimrafSync
-
-var assert = require("assert")
-var path = require("path")
-var fs = require("fs")
-
-// for EMFILE handling
-var timeout = 0
-exports.EMFILE_MAX = 1000
-exports.BUSYTRIES_MAX = 3
-
-var isWindows = (process.platform === "win32")
-
-function defaults (options) {
-  var methods = [
-    'unlink',
-    'chmod',
-    'stat',
-    'rmdir',
-    'readdir'
-  ]
-  methods.forEach(function(m) {
-    options[m] = options[m] || fs[m]
-    m = m + 'Sync'
-    options[m] = options[m] || fs[m]
-  })
-}
-
-function rimraf (p, options, cb) {
-  if (typeof options === 'function') {
-    cb = options
-    options = {}
-  }
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-
-  defaults(options)
-
-  if (!cb) throw new Error("No callback passed to rimraf()")
-
-  var busyTries = 0
-  rimraf_(p, options, function CB (er) {
-    if (er) {
-      if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY") &&
-          busyTries < exports.BUSYTRIES_MAX) {
-        busyTries ++
-        var time = busyTries * 100
-        // try again, with the same exact callback as this one.
-        return setTimeout(function () {
-          rimraf_(p, options, CB)
-        }, time)
-      }
-
-      // this one won't happen if graceful-fs is used.
-      if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) {
-        return setTimeout(function () {
-          rimraf_(p, options, CB)
-        }, timeout ++)
-      }
-
-      // already gone
-      if (er.code === "ENOENT") er = null
-    }
-
-    timeout = 0
-    cb(er)
-  })
-}
-
-// Two possible strategies.
-// 1. Assume it's a file.  unlink it, then do the dir stuff on EPERM or EISDIR
-// 2. Assume it's a directory.  readdir, then do the file stuff on ENOTDIR
-//
-// Both result in an extra syscall when you guess wrong.  However, there
-// are likely far more normal files in the world than directories.  This
-// is based on the assumption that a the average number of files per
-// directory is >= 1.
-//
-// If anyone ever complains about this, then I guess the strategy could
-// be made configurable somehow.  But until then, YAGNI.
-function rimraf_ (p, options, cb) {
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-
-  options.unlink(p, function (er) {
-    if (er) {
-      if (er.code === "ENOENT")
-        return cb(null)
-      if (er.code === "EPERM")
-        return (isWindows)
-          ? fixWinEPERM(p, options, er, cb)
-          : rmdir(p, options, er, cb)
-      if (er.code === "EISDIR")
-        return rmdir(p, options, er, cb)
-    }
-    return cb(er)
-  })
-}
-
-function fixWinEPERM (p, options, er, cb) {
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-  if (er)
-    assert(er instanceof Error)
-
-  options.chmod(p, 666, function (er2) {
-    if (er2)
-      cb(er2.code === "ENOENT" ? null : er)
-    else
-      options.stat(p, function(er3, stats) {
-        if (er3)
-          cb(er3.code === "ENOENT" ? null : er)
-        else if (stats.isDirectory())
-          rmdir(p, options, er, cb)
-        else
-          options.unlink(p, cb)
-      })
-  })
-}
-
-function fixWinEPERMSync (p, options, er) {
-  assert(p)
-  assert(options)
-  if (er)
-    assert(er instanceof Error)
-
-  try {
-    options.chmodSync(p, 666)
-  } catch (er2) {
-    if (er2.code === "ENOENT")
-      return
-    else
-      throw er
-  }
-
-  try {
-    var stats = options.statSync(p)
-  } catch (er3) {
-    if (er3.code === "ENOENT")
-      return
-    else
-      throw er
-  }
-
-  if (stats.isDirectory())
-    rmdirSync(p, options, er)
-  else
-    options.unlinkSync(p)
-}
-
-function rmdir (p, options, originalEr, cb) {
-  assert(p)
-  assert(options)
-  if (originalEr)
-    assert(originalEr instanceof Error)
-  assert(typeof cb === 'function')
-
-  // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
-  // if we guessed wrong, and it's not a directory, then
-  // raise the original error.
-  options.rmdir(p, function (er) {
-    if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))
-      rmkids(p, options, cb)
-    else if (er && er.code === "ENOTDIR")
-      cb(originalEr)
-    else
-      cb(er)
-  })
-}
-
-function rmkids(p, options, cb) {
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-
-  options.readdir(p, function (er, files) {
-    if (er)
-      return cb(er)
-    var n = files.length
-    if (n === 0)
-      return options.rmdir(p, cb)
-    var errState
-    files.forEach(function (f) {
-      rimraf(path.join(p, f), options, function (er) {
-        if (errState)
-          return
-        if (er)
-          return cb(errState = er)
-        if (--n === 0)
-          options.rmdir(p, cb)
-      })
-    })
-  })
-}
-
-// this looks simpler, and is strictly *faster*, but will
-// tie up the JavaScript thread and fail on excessively
-// deep directory trees.
-function rimrafSync (p, options) {
-  options = options || {}
-  defaults(options)
-
-  assert(p)
-  assert(options)
-
-  try {
-    options.unlinkSync(p)
-  } catch (er) {
-    if (er.code === "ENOENT")
-      return
-    if (er.code === "EPERM")
-      return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
-    if (er.code !== "EISDIR")
-      throw er
-    rmdirSync(p, options, er)
-  }
-}
-
-function rmdirSync (p, options, originalEr) {
-  assert(p)
-  assert(options)
-  if (originalEr)
-    assert(originalEr instanceof Error)
-
-  try {
-    options.rmdirSync(p)
-  } catch (er) {
-    if (er.code === "ENOENT")
-      return
-    if (er.code === "ENOTDIR")
-      throw originalEr
-    if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")
-      rmkidsSync(p, options)
-  }
-}
-
-function rmkidsSync (p, options) {
-  assert(p)
-  assert(options)
-  options.readdirSync(p).forEach(function (f) {
-    rimrafSync(path.join(p, f), options)
-  })
-  options.rmdirSync(p, options)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/run.sh b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/run.sh
deleted file mode 100644
index 653ff9b7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/run.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-set -e
-code=0
-for i in test-*.js; do
-  echo -n $i ...
-  bash setup.sh
-  node $i
-  if [ -d target ]; then
-    echo "fail"
-    code=1
-  else
-    echo "pass"
-  fi
-done
-rm -rf target
-exit $code
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/setup.sh b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/setup.sh
deleted file mode 100644
index 2602e631..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/setup.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-
-set -e
-
-files=10
-folders=2
-depth=4
-target="$PWD/target"
-
-rm -rf target
-
-fill () {
-  local depth=$1
-  local files=$2
-  local folders=$3
-  local target=$4
-
-  if ! [ -d $target ]; then
-    mkdir -p $target
-  fi
-
-  local f
-
-  f=$files
-  while [ $f -gt 0 ]; do
-    touch "$target/f-$depth-$f"
-    let f--
-  done
-
-  let depth--
-
-  if [ $depth -le 0 ]; then
-    return 0
-  fi
-
-  f=$folders
-  while [ $f -gt 0 ]; do
-    mkdir "$target/folder-$depth-$f"
-    fill $depth $files $folders "$target/d-$depth-$f"
-    let f--
-  done
-}
-
-fill $depth $files $folders $target
-
-# sanity assert
-[ -d $target ]
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-async.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-async.js
deleted file mode 100644
index 9c2e0b7b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-async.js
+++ /dev/null
@@ -1,5 +0,0 @@
-var rimraf = require("../rimraf")
-  , path = require("path")
-rimraf(path.join(__dirname, "target"), function (er) {
-  if (er) throw er
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-sync.js
deleted file mode 100644
index eb71f104..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/rimraf/test/test-sync.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var rimraf = require("../rimraf")
-  , path = require("path")
-rimraf.sync(path.join(__dirname, "target"))
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/.npmignore
deleted file mode 100644
index 7300fbc7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-# nada
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/Makefile b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/Makefile
deleted file mode 100644
index 5717ccf4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-files =  semver.browser.js \
-         semver.min.js \
-				 semver.browser.js.gz \
-				 semver.min.js.gz
-
-all: $(files)
-
-clean:
-	rm -f $(files)
-
-semver.browser.js: head.js semver.js foot.js
-	( cat head.js; \
-		cat semver.js | \
-			egrep -v '^ *\/\* nomin \*\/' | \
-			perl -pi -e 's/debug\([^\)]+\)//g'; \
-		cat foot.js ) > semver.browser.js
-
-semver.min.js: semver.browser.js
-	uglifyjs -m <semver.browser.js >semver.min.js
-
-%.gz: %
-	gzip --stdout -9 <$< >$@
-
-.PHONY: all clean
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/README.md
deleted file mode 100644
index 4e95b846..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/README.md
+++ /dev/null
@@ -1,158 +0,0 @@
-semver(1) -- The semantic versioner for npm
-===========================================
-
-## Usage
-
-    $ npm install semver
-
-    semver.valid('1.2.3') // '1.2.3'
-    semver.valid('a.b.c') // null
-    semver.clean('  =v1.2.3   ') // '1.2.3'
-    semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
-    semver.gt('1.2.3', '9.8.7') // false
-    semver.lt('1.2.3', '9.8.7') // true
-
-As a command-line utility:
-
-    $ semver -h
-
-    Usage: semver <version> [<version> [...]] [-r <range> | -i <inc> | -d <dec>]
-    Test if version(s) satisfy the supplied range(s), and sort them.
-
-    Multiple versions or ranges may be supplied, unless increment
-    or decrement options are specified.  In that case, only a single
-    version may be used, and it is incremented by the specified level
-
-    Program exits successfully if any valid version satisfies
-    all supplied ranges, and prints all satisfying versions.
-
-    If no versions are valid, or ranges are not satisfied,
-    then exits failure.
-
-    Versions are printed in ascending order, so supplying
-    multiple versions to the utility will just sort them.
-
-## Versions
-
-A "version" is described by the `v2.0.0` specification found at
-<http://semver.org/>.
-
-A leading `"="` or `"v"` character is stripped off and ignored.
-
-## Ranges
-
-The following range styles are supported:
-
-* `1.2.3` A specific version.  When nothing else will do.  Must be a full
-  version number, with major, minor, and patch versions specified.
-  Note that build metadata is still ignored, so `1.2.3+build2012` will
-  satisfy this range.
-* `>1.2.3` Greater than a specific version.
-* `<1.2.3` Less than a specific version.  If there is no prerelease
-  tag on the version range, then no prerelease version will be allowed
-  either, even though these are technically "less than".
-* `>=1.2.3` Greater than or equal to.  Note that prerelease versions
-  are NOT equal to their "normal" equivalents, so `1.2.3-beta` will
-  not satisfy this range, but `2.3.0-beta` will.
-* `<=1.2.3` Less than or equal to.  In this case, prerelease versions
-  ARE allowed, so `1.2.3-beta` would satisfy.
-* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
-* `~1.2.3` := `>=1.2.3-0 <1.3.0-0`  "Reasonably close to `1.2.3`".  When
-  using tilde operators, prerelease versions are supported as well,
-  but a prerelease of the next significant digit will NOT be
-  satisfactory, so `1.3.0-beta` will not satisfy `~1.2.3`.
-* `^1.2.3` := `>=1.2.3-0 <2.0.0-0`  "Compatible with `1.2.3`".  When
-  using caret operators, anything from the specified version (including
-  prerelease) will be supported up to, but not including, the next
-  major version (or its prereleases). `1.5.1` will satisfy `^1.2.3`,
-  while `1.2.2` and `2.0.0-beta` will not.
-* `^0.1.3` := `>=0.1.3-0 <0.2.0-0` "Compatible with `0.1.3`". `0.x.x` versions are
-  special: the first non-zero component indicates potentially breaking changes,
-  meaning the caret operator matches any version with the same first non-zero
-  component starting at the specified version.
-* `^0.0.2` := `=0.0.2` "Only the version `0.0.2` is considered compatible"
-* `~1.2` := `>=1.2.0-0 <1.3.0-0` "Any version starting with `1.2`"
-* `^1.2` := `>=1.2.0-0 <2.0.0-0` "Any version compatible with `1.2`"
-* `1.2.x` := `>=1.2.0-0 <1.3.0-0` "Any version starting with `1.2`"
-* `1.2.*` Same as `1.2.x`.
-* `1.2` Same as `1.2.x`.
-* `~1` := `>=1.0.0-0 <2.0.0-0` "Any version starting with `1`"
-* `^1` := `>=1.0.0-0 <2.0.0-0` "Any version compatible with `1`"
-* `1.x` := `>=1.0.0-0 <2.0.0-0` "Any version starting with `1`"
-* `1.*` Same as `1.x`.
-* `1` Same as `1.x`.
-* `*` Any version whatsoever.
-* `x` Same as `*`.
-* `""` (just an empty string) Same as `*`.
-
-
-Ranges can be joined with either a space (which implies "and") or a
-`||` (which implies "or").
-
-## Functions
-
-All methods and classes take a final `loose` boolean argument that, if
-true, will be more forgiving about not-quite-valid semver strings.
-The resulting output will always be 100% strict, of course.
-
-Strict-mode Comparators and Ranges will be strict about the SemVer
-strings that they parse.
-
-* `valid(v)`: Return the parsed version, or null if it's not valid.
-* `inc(v, release)`: Return the version incremented by the release
-  type (`major`,   `premajor`, `minor`, `preminor`, `patch`,
-  `prepatch`, or `prerelease`), or null if it's not valid
-  * `premajor` in one call will bump the version up to the next major
-    version and down to a prerelease of that major version.
-    `preminor`, and `prepatch` work the same way.
-  * If called from a non-prerelease version, the `prerelease` will work the
-    same as `prepatch`. It increments the patch version, then makes a
-    prerelease. If the input version is already a prerelease it simply
-    increments it.
-
-### Comparison
-
-* `gt(v1, v2)`: `v1 > v2`
-* `gte(v1, v2)`: `v1 >= v2`
-* `lt(v1, v2)`: `v1 < v2`
-* `lte(v1, v2)`: `v1 <= v2`
-* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
-  even if they're not the exact same string.  You already know how to
-  compare strings.
-* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
-* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
-  the corresponding function above.  `"==="` and `"!=="` do simple
-  string comparison, but are included for completeness.  Throws if an
-  invalid comparison string is provided.
-* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
-  `v2` is greater.  Sorts in ascending order if passed to `Array.sort()`.
-* `rcompare(v1, v2)`: The reverse of compare.  Sorts an array of versions
-  in descending order when passed to `Array.sort()`.
-
-
-### Ranges
-
-* `validRange(range)`: Return the valid range or null if it's not valid
-* `satisfies(version, range)`: Return true if the version satisfies the
-  range.
-* `maxSatisfying(versions, range)`: Return the highest version in the list
-  that satisfies the range, or `null` if none of them do.
-* `gtr(version, range)`: Return `true` if version is greater than all the
-  versions possible in the range.
-* `ltr(version, range)`: Return `true` if version is less than all the
-  versions possible in the range.
-* `outside(version, range, hilo)`: Return true if the version is outside
-  the bounds of the range in either the high or low direction.  The
-  `hilo` argument must be either the string `'>'` or `'<'`.  (This is
-  the function called by `gtr` and `ltr`.)
-
-Note that, since ranges may be non-contiguous, a version might not be
-greater than a range, less than a range, *or* satisfy a range!  For
-example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
-until `2.0.0`, so the version `1.2.10` would not be greater than the
-range (because `2.0.1` satisfies, which is higher), nor less than the
-range (since `1.2.8` satisfies, which is lower), and it also does not
-satisfy the range.
-
-If you want to know if a version satisfies or does not satisfy a
-range, use the `satisfies(version, range)` function.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/bin/semver b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/bin/semver
deleted file mode 100755
index 84842063..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/bin/semver
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env node
-// Standalone semver comparison program.
-// Exits successfully and prints matching version(s) if
-// any supplied version is valid and passes all tests.
-
-var argv = process.argv.slice(2)
-  , versions = []
-  , range = []
-  , gt = []
-  , lt = []
-  , eq = []
-  , inc = null
-  , version = require("../package.json").version
-  , loose = false
-  , semver = require("../semver")
-  , reverse = false
-
-main()
-
-function main () {
-  if (!argv.length) return help()
-  while (argv.length) {
-    var a = argv.shift()
-    var i = a.indexOf('=')
-    if (i !== -1) {
-      a = a.slice(0, i)
-      argv.unshift(a.slice(i + 1))
-    }
-    switch (a) {
-      case "-rv": case "-rev": case "--rev": case "--reverse":
-        reverse = true
-        break
-      case "-l": case "--loose":
-        loose = true
-        break
-      case "-v": case "--version":
-        versions.push(argv.shift())
-        break
-      case "-i": case "--inc": case "--increment":
-        switch (argv[0]) {
-          case "major": case "minor": case "patch": case "prerelease":
-          case "premajor": case "preminor": case "prepatch":
-            inc = argv.shift()
-            break
-          default:
-            inc = "patch"
-            break
-        }
-        break
-      case "-r": case "--range":
-        range.push(argv.shift())
-        break
-      case "-h": case "--help": case "-?":
-        return help()
-      default:
-        versions.push(a)
-        break
-    }
-  }
-
-  versions = versions.filter(function (v) {
-    return semver.valid(v, loose)
-  })
-  if (!versions.length) return fail()
-  if (inc && (versions.length !== 1 || range.length))
-    return failInc()
-
-  for (var i = 0, l = range.length; i < l ; i ++) {
-    versions = versions.filter(function (v) {
-      return semver.satisfies(v, range[i], loose)
-    })
-    if (!versions.length) return fail()
-  }
-  return success(versions)
-}
-
-function failInc () {
-  console.error("--inc can only be used on a single version with no range")
-  fail()
-}
-
-function fail () { process.exit(1) }
-
-function success () {
-  var compare = reverse ? "rcompare" : "compare"
-  versions.sort(function (a, b) {
-    return semver[compare](a, b, loose)
-  }).map(function (v) {
-    return semver.clean(v, loose)
-  }).map(function (v) {
-    return inc ? semver.inc(v, inc, loose) : v
-  }).forEach(function (v,i,_) { console.log(v) })
-}
-
-function help () {
-  console.log(["SemVer " + version
-              ,""
-              ,"A JavaScript implementation of the http://semver.org/ specification"
-              ,"Copyright Isaac Z. Schlueter"
-              ,""
-              ,"Usage: semver [options] <version> [<version> [...]]"
-              ,"Prints valid versions sorted by SemVer precedence"
-              ,""
-              ,"Options:"
-              ,"-r --range <range>"
-              ,"        Print versions that match the specified range."
-              ,""
-              ,"-i --increment [<level>]"
-              ,"        Increment a version by the specified level.  Level can"
-              ,"        be one of: major, minor, patch, or prerelease"
-              ,"        Default level is 'patch'."
-              ,"        Only one version may be specified."
-              ,""
-              ,"-l --loose"
-              ,"        Interpret versions and ranges loosely"
-              ,""
-              ,"Program exits successfully if any valid version satisfies"
-              ,"all supplied ranges, and prints all satisfying versions."
-              ,""
-              ,"If no satisfying versions are found, then exits failure."
-              ,""
-              ,"Versions are printed in ascending order, so supplying"
-              ,"multiple versions to the utility will just sort them."
-              ].join("\n"))
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/foot.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/foot.js
deleted file mode 100644
index 8f83c20f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/foot.js
+++ /dev/null
@@ -1,6 +0,0 @@
-
-})(
-  typeof exports === 'object' ? exports :
-  typeof define === 'function' && define.amd ? {} :
-  semver = {}
-);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/head.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/head.js
deleted file mode 100644
index 65368651..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/head.js
+++ /dev/null
@@ -1,2 +0,0 @@
-;(function(exports) {
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/package.json
deleted file mode 100644
index 8128a40e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "name": "semver",
-  "version": "2.3.0",
-  "description": "The semantic version parser used by npm.",
-  "main": "semver.js",
-  "browser": "semver.browser.js",
-  "min": "semver.min.js",
-  "scripts": {
-    "test": "tap test/*.js",
-    "prepublish": "make"
-  },
-  "devDependencies": {
-    "tap": "0.x >=0.0.4",
-    "uglify-js": "~2.3.6"
-  },
-  "license": "BSD",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-semver.git"
-  },
-  "bin": {
-    "semver": "./bin/semver"
-  },
-  "readme": "semver(1) -- The semantic versioner for npm\n===========================================\n\n## Usage\n\n    $ npm install semver\n\n    semver.valid('1.2.3') // '1.2.3'\n    semver.valid('a.b.c') // null\n    semver.clean('  =v1.2.3   ') // '1.2.3'\n    semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true\n    semver.gt('1.2.3', '9.8.7') // false\n    semver.lt('1.2.3', '9.8.7') // true\n\nAs a command-line utility:\n\n    $ semver -h\n\n    Usage: semver <version> [<version> [...]] [-r <range> | -i <inc> | -d <dec>]\n    Test if version(s) satisfy the supplied range(s), and sort them.\n\n    Multiple versions or ranges may be supplied, unless increment\n    or decrement options are specified.  In that case, only a single\n    version may be used, and it is incremented by the specified level\n\n    Program exits successfully if any valid version satisfies\n    all supplied ranges, and prints all satisfying versions.\n\n    If no versions are valid, or ranges are not satisfied,\n    then exits failure.\n\n    Versions are printed in ascending order, so supplying\n    multiple versions to the utility will just sort them.\n\n## Versions\n\nA \"version\" is described by the `v2.0.0` specification found at\n<http://semver.org/>.\n\nA leading `\"=\"` or `\"v\"` character is stripped off and ignored.\n\n## Ranges\n\nThe following range styles are supported:\n\n* `1.2.3` A specific version.  When nothing else will do.  Must be a full\n  version number, with major, minor, and patch versions specified.\n  Note that build metadata is still ignored, so `1.2.3+build2012` will\n  satisfy this range.\n* `>1.2.3` Greater than a specific version.\n* `<1.2.3` Less than a specific version.  If there is no prerelease\n  tag on the version range, then no prerelease version will be allowed\n  either, even though these are technically \"less than\".\n* `>=1.2.3` Greater than or equal to.  Note that prerelease versions\n  are NOT equal to their \"normal\" equivalents, so `1.2.3-beta` will\n  not satisfy this range, but `2.3.0-beta` will.\n* `<=1.2.3` Less than or equal to.  In this case, prerelease versions\n  ARE allowed, so `1.2.3-beta` would satisfy.\n* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`\n* `~1.2.3` := `>=1.2.3-0 <1.3.0-0`  \"Reasonably close to `1.2.3`\".  When\n  using tilde operators, prerelease versions are supported as well,\n  but a prerelease of the next significant digit will NOT be\n  satisfactory, so `1.3.0-beta` will not satisfy `~1.2.3`.\n* `^1.2.3` := `>=1.2.3-0 <2.0.0-0`  \"Compatible with `1.2.3`\".  When\n  using caret operators, anything from the specified version (including\n  prerelease) will be supported up to, but not including, the next\n  major version (or its prereleases). `1.5.1` will satisfy `^1.2.3`,\n  while `1.2.2` and `2.0.0-beta` will not.\n* `^0.1.3` := `>=0.1.3-0 <0.2.0-0` \"Compatible with `0.1.3`\". `0.x.x` versions are\n  special: the first non-zero component indicates potentially breaking changes,\n  meaning the caret operator matches any version with the same first non-zero\n  component starting at the specified version.\n* `^0.0.2` := `=0.0.2` \"Only the version `0.0.2` is considered compatible\"\n* `~1.2` := `>=1.2.0-0 <1.3.0-0` \"Any version starting with `1.2`\"\n* `^1.2` := `>=1.2.0-0 <2.0.0-0` \"Any version compatible with `1.2`\"\n* `1.2.x` := `>=1.2.0-0 <1.3.0-0` \"Any version starting with `1.2`\"\n* `1.2.*` Same as `1.2.x`.\n* `1.2` Same as `1.2.x`.\n* `~1` := `>=1.0.0-0 <2.0.0-0` \"Any version starting with `1`\"\n* `^1` := `>=1.0.0-0 <2.0.0-0` \"Any version compatible with `1`\"\n* `1.x` := `>=1.0.0-0 <2.0.0-0` \"Any version starting with `1`\"\n* `1.*` Same as `1.x`.\n* `1` Same as `1.x`.\n* `*` Any version whatsoever.\n* `x` Same as `*`.\n* `\"\"` (just an empty string) Same as `*`.\n\n\nRanges can be joined with either a space (which implies \"and\") or a\n`||` (which implies \"or\").\n\n## Functions\n\nAll methods and classes take a final `loose` boolean argument that, if\ntrue, will be more forgiving about not-quite-valid semver strings.\nThe resulting output will always be 100% strict, of course.\n\nStrict-mode Comparators and Ranges will be strict about the SemVer\nstrings that they parse.\n\n* `valid(v)`: Return the parsed version, or null if it's not valid.\n* `inc(v, release)`: Return the version incremented by the release\n  type (`major`,   `premajor`, `minor`, `preminor`, `patch`,\n  `prepatch`, or `prerelease`), or null if it's not valid\n  * `premajor` in one call will bump the version up to the next major\n    version and down to a prerelease of that major version.\n    `preminor`, and `prepatch` work the same way.\n  * If called from a non-prerelease version, the `prerelease` will work the\n    same as `prepatch`. It increments the patch version, then makes a\n    prerelease. If the input version is already a prerelease it simply\n    increments it.\n\n### Comparison\n\n* `gt(v1, v2)`: `v1 > v2`\n* `gte(v1, v2)`: `v1 >= v2`\n* `lt(v1, v2)`: `v1 < v2`\n* `lte(v1, v2)`: `v1 <= v2`\n* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,\n  even if they're not the exact same string.  You already know how to\n  compare strings.\n* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.\n* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call\n  the corresponding function above.  `\"===\"` and `\"!==\"` do simple\n  string comparison, but are included for completeness.  Throws if an\n  invalid comparison string is provided.\n* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if\n  `v2` is greater.  Sorts in ascending order if passed to `Array.sort()`.\n* `rcompare(v1, v2)`: The reverse of compare.  Sorts an array of versions\n  in descending order when passed to `Array.sort()`.\n\n\n### Ranges\n\n* `validRange(range)`: Return the valid range or null if it's not valid\n* `satisfies(version, range)`: Return true if the version satisfies the\n  range.\n* `maxSatisfying(versions, range)`: Return the highest version in the list\n  that satisfies the range, or `null` if none of them do.\n* `gtr(version, range)`: Return `true` if version is greater than all the\n  versions possible in the range.\n* `ltr(version, range)`: Return `true` if version is less than all the\n  versions possible in the range.\n* `outside(version, range, hilo)`: Return true if the version is outside\n  the bounds of the range in either the high or low direction.  The\n  `hilo` argument must be either the string `'>'` or `'<'`.  (This is\n  the function called by `gtr` and `ltr`.)\n\nNote that, since ranges may be non-contiguous, a version might not be\ngreater than a range, less than a range, *or* satisfy a range!  For\nexample, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`\nuntil `2.0.0`, so the version `1.2.10` would not be greater than the\nrange (because `2.0.1` satisfies, which is higher), nor less than the\nrange (since `1.2.8` satisfies, which is lower), and it also does not\nsatisfy the range.\n\nIf you want to know if a version satisfies or does not satisfy a\nrange, use the `satisfies(version, range)` function.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/node-semver/issues"
-  },
-  "homepage": "https://github.com/isaacs/node-semver",
-  "_id": "semver@2.3.0",
-  "_shasum": "d31b2903ebe2a1806c05b8e763916a7183108a15",
-  "_from": "semver@~2.3.0",
-  "_resolved": "https://registry.npmjs.org/semver/-/semver-2.3.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.browser.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.browser.js
deleted file mode 100644
index 0f414c3d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.browser.js
+++ /dev/null
@@ -1,1039 +0,0 @@
-;(function(exports) {
-
-// export the class if we are in a Node-like system.
-if (typeof module === 'object' && module.exports === exports)
-  exports = module.exports = SemVer;
-
-// The debug function is excluded entirely from the minified version.
-
-// Note: this is the semver.org version of the spec that it implements
-// Not necessarily the package version of this code.
-exports.SEMVER_SPEC_VERSION = '2.0.0';
-
-// The actual regexps go on exports.re
-var re = exports.re = [];
-var src = exports.src = [];
-var R = 0;
-
-// The following Regular Expressions can be used for tokenizing,
-// validating, and parsing SemVer version strings.
-
-// ## Numeric Identifier
-// A single `0`, or a non-zero digit followed by zero or more digits.
-
-var NUMERICIDENTIFIER = R++;
-src[NUMERICIDENTIFIER] = '0|[1-9]\\d*';
-var NUMERICIDENTIFIERLOOSE = R++;
-src[NUMERICIDENTIFIERLOOSE] = '[0-9]+';
-
-
-// ## Non-numeric Identifier
-// Zero or more digits, followed by a letter or hyphen, and then zero or
-// more letters, digits, or hyphens.
-
-var NONNUMERICIDENTIFIER = R++;
-src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*';
-
-
-// ## Main Version
-// Three dot-separated numeric identifiers.
-
-var MAINVERSION = R++;
-src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
-                   '(' + src[NUMERICIDENTIFIER] + ')\\.' +
-                   '(' + src[NUMERICIDENTIFIER] + ')';
-
-var MAINVERSIONLOOSE = R++;
-src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
-                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
-                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')';
-
-// ## Pre-release Version Identifier
-// A numeric identifier, or a non-numeric identifier.
-
-var PRERELEASEIDENTIFIER = R++;
-src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
-                            '|' + src[NONNUMERICIDENTIFIER] + ')';
-
-var PRERELEASEIDENTIFIERLOOSE = R++;
-src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
-                                 '|' + src[NONNUMERICIDENTIFIER] + ')';
-
-
-// ## Pre-release Version
-// Hyphen, followed by one or more dot-separated pre-release version
-// identifiers.
-
-var PRERELEASE = R++;
-src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
-                  '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))';
-
-var PRERELEASELOOSE = R++;
-src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
-                       '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))';
-
-// ## Build Metadata Identifier
-// Any combination of digits, letters, or hyphens.
-
-var BUILDIDENTIFIER = R++;
-src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';
-
-// ## Build Metadata
-// Plus sign, followed by one or more period-separated build metadata
-// identifiers.
-
-var BUILD = R++;
-src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
-             '(?:\\.' + src[BUILDIDENTIFIER] + ')*))';
-
-
-// ## Full Version String
-// A main version, followed optionally by a pre-release version and
-// build metadata.
-
-// Note that the only major, minor, patch, and pre-release sections of
-// the version string are capturing groups.  The build metadata is not a
-// capturing group, because it should not ever be used in version
-// comparison.
-
-var FULL = R++;
-var FULLPLAIN = 'v?' + src[MAINVERSION] +
-                src[PRERELEASE] + '?' +
-                src[BUILD] + '?';
-
-src[FULL] = '^' + FULLPLAIN + '$';
-
-// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
-// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
-// common in the npm registry.
-var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
-                 src[PRERELEASELOOSE] + '?' +
-                 src[BUILD] + '?';
-
-var LOOSE = R++;
-src[LOOSE] = '^' + LOOSEPLAIN + '$';
-
-var GTLT = R++;
-src[GTLT] = '((?:<|>)?=?)';
-
-// Something like "2.*" or "1.2.x".
-// Note that "x.x" is a valid xRange identifer, meaning "any version"
-// Only the first item is strictly required.
-var XRANGEIDENTIFIERLOOSE = R++;
-src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*';
-var XRANGEIDENTIFIER = R++;
-src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*';
-
-var XRANGEPLAIN = R++;
-src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
-                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
-                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
-                   '(?:(' + src[PRERELEASE] + ')' +
-                   ')?)?)?';
-
-var XRANGEPLAINLOOSE = R++;
-src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
-                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
-                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
-                        '(?:(' + src[PRERELEASELOOSE] + ')' +
-                        ')?)?)?';
-
-// >=2.x, for example, means >=2.0.0-0
-// <1.x would be the same as "<1.0.0-0", though.
-var XRANGE = R++;
-src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$';
-var XRANGELOOSE = R++;
-src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$';
-
-// Tilde ranges.
-// Meaning is "reasonably at or greater than"
-var LONETILDE = R++;
-src[LONETILDE] = '(?:~>?)';
-
-var TILDETRIM = R++;
-src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+';
-re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g');
-var tildeTrimReplace = '$1~';
-
-var TILDE = R++;
-src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$';
-var TILDELOOSE = R++;
-src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$';
-
-// Caret ranges.
-// Meaning is "at least and backwards compatible with"
-var LONECARET = R++;
-src[LONECARET] = '(?:\\^)';
-
-var CARETTRIM = R++;
-src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+';
-re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g');
-var caretTrimReplace = '$1^';
-
-var CARET = R++;
-src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$';
-var CARETLOOSE = R++;
-src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$';
-
-// A simple gt/lt/eq thing, or just "" to indicate "any version"
-var COMPARATORLOOSE = R++;
-src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$';
-var COMPARATOR = R++;
-src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$';
-
-
-// An expression to strip any whitespace between the gtlt and the thing
-// it modifies, so that `> 1.2.3` ==> `>1.2.3`
-var COMPARATORTRIM = R++;
-src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
-                      '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')';
-
-// this one has to use the /g flag
-re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g');
-var comparatorTrimReplace = '$1$2$3';
-
-
-// Something like `1.2.3 - 1.2.4`
-// Note that these all use the loose form, because they'll be
-// checked against either the strict or loose comparator form
-// later.
-var HYPHENRANGE = R++;
-src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
-                   '\\s+-\\s+' +
-                   '(' + src[XRANGEPLAIN] + ')' +
-                   '\\s*$';
-
-var HYPHENRANGELOOSE = R++;
-src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
-                        '\\s+-\\s+' +
-                        '(' + src[XRANGEPLAINLOOSE] + ')' +
-                        '\\s*$';
-
-// Star ranges basically just allow anything at all.
-var STAR = R++;
-src[STAR] = '(<|>)?=?\\s*\\*';
-
-// Compile to actual regexp objects.
-// All are flag-free, unless they were created above with a flag.
-for (var i = 0; i < R; i++) {
-  ;
-  if (!re[i])
-    re[i] = new RegExp(src[i]);
-}
-
-exports.parse = parse;
-function parse(version, loose) {
-  var r = loose ? re[LOOSE] : re[FULL];
-  return (r.test(version)) ? new SemVer(version, loose) : null;
-}
-
-exports.valid = valid;
-function valid(version, loose) {
-  var v = parse(version, loose);
-  return v ? v.version : null;
-}
-
-
-exports.clean = clean;
-function clean(version, loose) {
-  var s = parse(version, loose);
-  return s ? s.version : null;
-}
-
-exports.SemVer = SemVer;
-
-function SemVer(version, loose) {
-  if (version instanceof SemVer) {
-    if (version.loose === loose)
-      return version;
-    else
-      version = version.version;
-  } else if (typeof version !== 'string') {
-    throw new TypeError('Invalid Version: ' + version);
-  }
-
-  if (!(this instanceof SemVer))
-    return new SemVer(version, loose);
-
-  ;
-  this.loose = loose;
-  var m = version.trim().match(loose ? re[LOOSE] : re[FULL]);
-
-  if (!m)
-    throw new TypeError('Invalid Version: ' + version);
-
-  this.raw = version;
-
-  // these are actually numbers
-  this.major = +m[1];
-  this.minor = +m[2];
-  this.patch = +m[3];
-
-  // numberify any prerelease numeric ids
-  if (!m[4])
-    this.prerelease = [];
-  else
-    this.prerelease = m[4].split('.').map(function(id) {
-      return (/^[0-9]+$/.test(id)) ? +id : id;
-    });
-
-  this.build = m[5] ? m[5].split('.') : [];
-  this.format();
-}
-
-SemVer.prototype.format = function() {
-  this.version = this.major + '.' + this.minor + '.' + this.patch;
-  if (this.prerelease.length)
-    this.version += '-' + this.prerelease.join('.');
-  return this.version;
-};
-
-SemVer.prototype.inspect = function() {
-  return '<SemVer "' + this + '">';
-};
-
-SemVer.prototype.toString = function() {
-  return this.version;
-};
-
-SemVer.prototype.compare = function(other) {
-  ;
-  if (!(other instanceof SemVer))
-    other = new SemVer(other, this.loose);
-
-  return this.compareMain(other) || this.comparePre(other);
-};
-
-SemVer.prototype.compareMain = function(other) {
-  if (!(other instanceof SemVer))
-    other = new SemVer(other, this.loose);
-
-  return compareIdentifiers(this.major, other.major) ||
-         compareIdentifiers(this.minor, other.minor) ||
-         compareIdentifiers(this.patch, other.patch);
-};
-
-SemVer.prototype.comparePre = function(other) {
-  if (!(other instanceof SemVer))
-    other = new SemVer(other, this.loose);
-
-  // NOT having a prerelease is > having one
-  if (this.prerelease.length && !other.prerelease.length)
-    return -1;
-  else if (!this.prerelease.length && other.prerelease.length)
-    return 1;
-  else if (!this.prerelease.length && !other.prerelease.length)
-    return 0;
-
-  var i = 0;
-  do {
-    var a = this.prerelease[i];
-    var b = other.prerelease[i];
-    ;
-    if (a === undefined && b === undefined)
-      return 0;
-    else if (b === undefined)
-      return 1;
-    else if (a === undefined)
-      return -1;
-    else if (a === b)
-      continue;
-    else
-      return compareIdentifiers(a, b);
-  } while (++i);
-};
-
-// preminor will bump the version up to the next minor release, and immediately
-// down to pre-release. premajor and prepatch work the same way.
-SemVer.prototype.inc = function(release) {
-  switch (release) {
-    case 'premajor':
-      this.inc('major');
-      this.inc('pre');
-      break;
-    case 'preminor':
-      this.inc('minor');
-      this.inc('pre');
-      break;
-    case 'prepatch':
-      this.inc('patch');
-      this.inc('pre');
-      break;
-    // If the input is a non-prerelease version, this acts the same as
-    // prepatch.
-    case 'prerelease':
-      if (this.prerelease.length === 0)
-        this.inc('patch');
-      this.inc('pre');
-      break;
-    case 'major':
-      this.major++;
-      this.minor = -1;
-    case 'minor':
-      this.minor++;
-      this.patch = 0;
-      this.prerelease = [];
-      break;
-    case 'patch':
-      // If this is not a pre-release version, it will increment the patch.
-      // If it is a pre-release it will bump up to the same patch version.
-      // 1.2.0-5 patches to 1.2.0
-      // 1.2.0 patches to 1.2.1
-      if (this.prerelease.length === 0)
-        this.patch++;
-      this.prerelease = [];
-      break;
-    // This probably shouldn't be used publically.
-    // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
-    case 'pre':
-      if (this.prerelease.length === 0)
-        this.prerelease = [0];
-      else {
-        var i = this.prerelease.length;
-        while (--i >= 0) {
-          if (typeof this.prerelease[i] === 'number') {
-            this.prerelease[i]++;
-            i = -2;
-          }
-        }
-        if (i === -1) // didn't increment anything
-          this.prerelease.push(0);
-      }
-      break;
-
-    default:
-      throw new Error('invalid increment argument: ' + release);
-  }
-  this.format();
-  return this;
-};
-
-exports.inc = inc;
-function inc(version, release, loose) {
-  try {
-    return new SemVer(version, loose).inc(release).version;
-  } catch (er) {
-    return null;
-  }
-}
-
-exports.compareIdentifiers = compareIdentifiers;
-
-var numeric = /^[0-9]+$/;
-function compareIdentifiers(a, b) {
-  var anum = numeric.test(a);
-  var bnum = numeric.test(b);
-
-  if (anum && bnum) {
-    a = +a;
-    b = +b;
-  }
-
-  return (anum && !bnum) ? -1 :
-         (bnum && !anum) ? 1 :
-         a < b ? -1 :
-         a > b ? 1 :
-         0;
-}
-
-exports.rcompareIdentifiers = rcompareIdentifiers;
-function rcompareIdentifiers(a, b) {
-  return compareIdentifiers(b, a);
-}
-
-exports.compare = compare;
-function compare(a, b, loose) {
-  return new SemVer(a, loose).compare(b);
-}
-
-exports.compareLoose = compareLoose;
-function compareLoose(a, b) {
-  return compare(a, b, true);
-}
-
-exports.rcompare = rcompare;
-function rcompare(a, b, loose) {
-  return compare(b, a, loose);
-}
-
-exports.sort = sort;
-function sort(list, loose) {
-  return list.sort(function(a, b) {
-    return exports.compare(a, b, loose);
-  });
-}
-
-exports.rsort = rsort;
-function rsort(list, loose) {
-  return list.sort(function(a, b) {
-    return exports.rcompare(a, b, loose);
-  });
-}
-
-exports.gt = gt;
-function gt(a, b, loose) {
-  return compare(a, b, loose) > 0;
-}
-
-exports.lt = lt;
-function lt(a, b, loose) {
-  return compare(a, b, loose) < 0;
-}
-
-exports.eq = eq;
-function eq(a, b, loose) {
-  return compare(a, b, loose) === 0;
-}
-
-exports.neq = neq;
-function neq(a, b, loose) {
-  return compare(a, b, loose) !== 0;
-}
-
-exports.gte = gte;
-function gte(a, b, loose) {
-  return compare(a, b, loose) >= 0;
-}
-
-exports.lte = lte;
-function lte(a, b, loose) {
-  return compare(a, b, loose) <= 0;
-}
-
-exports.cmp = cmp;
-function cmp(a, op, b, loose) {
-  var ret;
-  switch (op) {
-    case '===': ret = a === b; break;
-    case '!==': ret = a !== b; break;
-    case '': case '=': case '==': ret = eq(a, b, loose); break;
-    case '!=': ret = neq(a, b, loose); break;
-    case '>': ret = gt(a, b, loose); break;
-    case '>=': ret = gte(a, b, loose); break;
-    case '<': ret = lt(a, b, loose); break;
-    case '<=': ret = lte(a, b, loose); break;
-    default: throw new TypeError('Invalid operator: ' + op);
-  }
-  return ret;
-}
-
-exports.Comparator = Comparator;
-function Comparator(comp, loose) {
-  if (comp instanceof Comparator) {
-    if (comp.loose === loose)
-      return comp;
-    else
-      comp = comp.value;
-  }
-
-  if (!(this instanceof Comparator))
-    return new Comparator(comp, loose);
-
-  ;
-  this.loose = loose;
-  this.parse(comp);
-
-  if (this.semver === ANY)
-    this.value = '';
-  else
-    this.value = this.operator + this.semver.version;
-}
-
-var ANY = {};
-Comparator.prototype.parse = function(comp) {
-  var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
-  var m = comp.match(r);
-
-  if (!m)
-    throw new TypeError('Invalid comparator: ' + comp);
-
-  this.operator = m[1];
-  // if it literally is just '>' or '' then allow anything.
-  if (!m[2])
-    this.semver = ANY;
-  else {
-    this.semver = new SemVer(m[2], this.loose);
-
-    // <1.2.3-rc DOES allow 1.2.3-beta (has prerelease)
-    // >=1.2.3 DOES NOT allow 1.2.3-beta
-    // <=1.2.3 DOES allow 1.2.3-beta
-    // However, <1.2.3 does NOT allow 1.2.3-beta,
-    // even though `1.2.3-beta < 1.2.3`
-    // The assumption is that the 1.2.3 version has something you
-    // *don't* want, so we push the prerelease down to the minimum.
-    if (this.operator === '<' && !this.semver.prerelease.length) {
-      this.semver.prerelease = ['0'];
-      this.semver.format();
-    }
-  }
-};
-
-Comparator.prototype.inspect = function() {
-  return '<SemVer Comparator "' + this + '">';
-};
-
-Comparator.prototype.toString = function() {
-  return this.value;
-};
-
-Comparator.prototype.test = function(version) {
-  ;
-  return (this.semver === ANY) ? true :
-         cmp(version, this.operator, this.semver, this.loose);
-};
-
-
-exports.Range = Range;
-function Range(range, loose) {
-  if ((range instanceof Range) && range.loose === loose)
-    return range;
-
-  if (!(this instanceof Range))
-    return new Range(range, loose);
-
-  this.loose = loose;
-
-  // First, split based on boolean or ||
-  this.raw = range;
-  this.set = range.split(/\s*\|\|\s*/).map(function(range) {
-    return this.parseRange(range.trim());
-  }, this).filter(function(c) {
-    // throw out any that are not relevant for whatever reason
-    return c.length;
-  });
-
-  if (!this.set.length) {
-    throw new TypeError('Invalid SemVer Range: ' + range);
-  }
-
-  this.format();
-}
-
-Range.prototype.inspect = function() {
-  return '<SemVer Range "' + this.range + '">';
-};
-
-Range.prototype.format = function() {
-  this.range = this.set.map(function(comps) {
-    return comps.join(' ').trim();
-  }).join('||').trim();
-  return this.range;
-};
-
-Range.prototype.toString = function() {
-  return this.range;
-};
-
-Range.prototype.parseRange = function(range) {
-  var loose = this.loose;
-  range = range.trim();
-  ;
-  // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
-  var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];
-  range = range.replace(hr, hyphenReplace);
-  ;
-  // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
-  range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);
-  ;
-
-  // `~ 1.2.3` => `~1.2.3`
-  range = range.replace(re[TILDETRIM], tildeTrimReplace);
-
-  // `^ 1.2.3` => `^1.2.3`
-  range = range.replace(re[CARETTRIM], caretTrimReplace);
-
-  // normalize spaces
-  range = range.split(/\s+/).join(' ');
-
-  // At this point, the range is completely trimmed and
-  // ready to be split into comparators.
-
-  var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
-  var set = range.split(' ').map(function(comp) {
-    return parseComparator(comp, loose);
-  }).join(' ').split(/\s+/);
-  if (this.loose) {
-    // in loose mode, throw out any that are not valid comparators
-    set = set.filter(function(comp) {
-      return !!comp.match(compRe);
-    });
-  }
-  set = set.map(function(comp) {
-    return new Comparator(comp, loose);
-  });
-
-  return set;
-};
-
-// Mostly just for testing and legacy API reasons
-exports.toComparators = toComparators;
-function toComparators(range, loose) {
-  return new Range(range, loose).set.map(function(comp) {
-    return comp.map(function(c) {
-      return c.value;
-    }).join(' ').trim().split(' ');
-  });
-}
-
-// comprised of xranges, tildes, stars, and gtlt's at this point.
-// already replaced the hyphen ranges
-// turn into a set of JUST comparators.
-function parseComparator(comp, loose) {
-  ;
-  comp = replaceCarets(comp, loose);
-  ;
-  comp = replaceTildes(comp, loose);
-  ;
-  comp = replaceXRanges(comp, loose);
-  ;
-  comp = replaceStars(comp, loose);
-  ;
-  return comp;
-}
-
-function isX(id) {
-  return !id || id.toLowerCase() === 'x' || id === '*';
-}
-
-// ~, ~> --> * (any, kinda silly)
-// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
-// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
-// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
-// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
-// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
-function replaceTildes(comp, loose) {
-  return comp.trim().split(/\s+/).map(function(comp) {
-    return replaceTilde(comp, loose);
-  }).join(' ');
-}
-
-function replaceTilde(comp, loose) {
-  var r = loose ? re[TILDELOOSE] : re[TILDE];
-  return comp.replace(r, function(_, M, m, p, pr) {
-    ;
-    var ret;
-
-    if (isX(M))
-      ret = '';
-    else if (isX(m))
-      ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
-    else if (isX(p))
-      // ~1.2 == >=1.2.0- <1.3.0-
-      ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
-    else if (pr) {
-      ;
-      if (pr.charAt(0) !== '-')
-        pr = '-' + pr;
-      ret = '>=' + M + '.' + m + '.' + p + pr +
-            ' <' + M + '.' + (+m + 1) + '.0-0';
-    } else
-      // ~1.2.3 == >=1.2.3-0 <1.3.0-0
-      ret = '>=' + M + '.' + m + '.' + p + '-0' +
-            ' <' + M + '.' + (+m + 1) + '.0-0';
-
-    ;
-    return ret;
-  });
-}
-
-// ^ --> * (any, kinda silly)
-// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
-// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
-// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
-// ^1.2.3 --> >=1.2.3 <2.0.0
-// ^1.2.0 --> >=1.2.0 <2.0.0
-function replaceCarets(comp, loose) {
-  return comp.trim().split(/\s+/).map(function(comp) {
-    return replaceCaret(comp, loose);
-  }).join(' ');
-}
-
-function replaceCaret(comp, loose) {
-  var r = loose ? re[CARETLOOSE] : re[CARET];
-  return comp.replace(r, function(_, M, m, p, pr) {
-    ;
-    var ret;
-
-    if (isX(M))
-      ret = '';
-    else if (isX(m))
-      ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
-    else if (isX(p)) {
-      if (M === '0')
-        ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
-      else
-        ret = '>=' + M + '.' + m + '.0-0 <' + (+M + 1) + '.0.0-0';
-    } else if (pr) {
-      ;
-      if (pr.charAt(0) !== '-')
-        pr = '-' + pr;
-      if (M === '0') {
-        if (m === '0')
-          ret = '=' + M + '.' + m + '.' + p + pr;
-        else
-          ret = '>=' + M + '.' + m + '.' + p + pr +
-                ' <' + M + '.' + (+m + 1) + '.0-0';
-      } else
-        ret = '>=' + M + '.' + m + '.' + p + pr +
-              ' <' + (+M + 1) + '.0.0-0';
-    } else {
-      if (M === '0') {
-        if (m === '0')
-          ret = '=' + M + '.' + m + '.' + p;
-        else
-          ret = '>=' + M + '.' + m + '.' + p + '-0' +
-                ' <' + M + '.' + (+m + 1) + '.0-0';
-      } else
-        ret = '>=' + M + '.' + m + '.' + p + '-0' +
-              ' <' + (+M + 1) + '.0.0-0';
-    }
-
-    ;
-    return ret;
-  });
-}
-
-function replaceXRanges(comp, loose) {
-  ;
-  return comp.split(/\s+/).map(function(comp) {
-    return replaceXRange(comp, loose);
-  }).join(' ');
-}
-
-function replaceXRange(comp, loose) {
-  comp = comp.trim();
-  var r = loose ? re[XRANGELOOSE] : re[XRANGE];
-  return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
-    ;
-    var xM = isX(M);
-    var xm = xM || isX(m);
-    var xp = xm || isX(p);
-    var anyX = xp;
-
-    if (gtlt === '=' && anyX)
-      gtlt = '';
-
-    if (gtlt && anyX) {
-      // replace X with 0, and then append the -0 min-prerelease
-      if (xM)
-        M = 0;
-      if (xm)
-        m = 0;
-      if (xp)
-        p = 0;
-
-      if (gtlt === '>') {
-        // >1 => >=2.0.0-0
-        // >1.2 => >=1.3.0-0
-        // >1.2.3 => >= 1.2.4-0
-        gtlt = '>=';
-        if (xM) {
-          // no change
-        } else if (xm) {
-          M = +M + 1;
-          m = 0;
-          p = 0;
-        } else if (xp) {
-          m = +m + 1;
-          p = 0;
-        }
-      }
-
-
-      ret = gtlt + M + '.' + m + '.' + p + '-0';
-    } else if (xM) {
-      // allow any
-      ret = '*';
-    } else if (xm) {
-      // append '-0' onto the version, otherwise
-      // '1.x.x' matches '2.0.0-beta', since the tag
-      // *lowers* the version value
-      ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
-    } else if (xp) {
-      ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
-    }
-
-    ;
-
-    return ret;
-  });
-}
-
-// Because * is AND-ed with everything else in the comparator,
-// and '' means "any version", just remove the *s entirely.
-function replaceStars(comp, loose) {
-  ;
-  // Looseness is ignored here.  star is always as loose as it gets!
-  return comp.trim().replace(re[STAR], '');
-}
-
-// This function is passed to string.replace(re[HYPHENRANGE])
-// M, m, patch, prerelease, build
-// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5
-// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do
-// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0
-function hyphenReplace($0,
-                       from, fM, fm, fp, fpr, fb,
-                       to, tM, tm, tp, tpr, tb) {
-
-  if (isX(fM))
-    from = '';
-  else if (isX(fm))
-    from = '>=' + fM + '.0.0-0';
-  else if (isX(fp))
-    from = '>=' + fM + '.' + fm + '.0-0';
-  else
-    from = '>=' + from;
-
-  if (isX(tM))
-    to = '';
-  else if (isX(tm))
-    to = '<' + (+tM + 1) + '.0.0-0';
-  else if (isX(tp))
-    to = '<' + tM + '.' + (+tm + 1) + '.0-0';
-  else if (tpr)
-    to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;
-  else
-    to = '<=' + to;
-
-  return (from + ' ' + to).trim();
-}
-
-
-// if ANY of the sets match ALL of its comparators, then pass
-Range.prototype.test = function(version) {
-  if (!version)
-    return false;
-  for (var i = 0; i < this.set.length; i++) {
-    if (testSet(this.set[i], version))
-      return true;
-  }
-  return false;
-};
-
-function testSet(set, version) {
-  for (var i = 0; i < set.length; i++) {
-    if (!set[i].test(version))
-      return false;
-  }
-  return true;
-}
-
-exports.satisfies = satisfies;
-function satisfies(version, range, loose) {
-  try {
-    range = new Range(range, loose);
-  } catch (er) {
-    return false;
-  }
-  return range.test(version);
-}
-
-exports.maxSatisfying = maxSatisfying;
-function maxSatisfying(versions, range, loose) {
-  return versions.filter(function(version) {
-    return satisfies(version, range, loose);
-  }).sort(function(a, b) {
-    return rcompare(a, b, loose);
-  })[0] || null;
-}
-
-exports.validRange = validRange;
-function validRange(range, loose) {
-  try {
-    // Return '*' instead of '' so that truthiness works.
-    // This will throw if it's invalid anyway
-    return new Range(range, loose).range || '*';
-  } catch (er) {
-    return null;
-  }
-}
-
-// Determine if version is less than all the versions possible in the range
-exports.ltr = ltr;
-function ltr(version, range, loose) {
-  return outside(version, range, '<', loose);
-}
-
-// Determine if version is greater than all the versions possible in the range.
-exports.gtr = gtr;
-function gtr(version, range, loose) {
-  return outside(version, range, '>', loose);
-}
-
-exports.outside = outside;
-function outside(version, range, hilo, loose) {
-  version = new SemVer(version, loose);
-  range = new Range(range, loose);
-
-  var gtfn, ltefn, ltfn, comp, ecomp;
-  switch (hilo) {
-    case '>':
-      gtfn = gt;
-      ltefn = lte;
-      ltfn = lt;
-      comp = '>';
-      ecomp = '>=';
-      break;
-    case '<':
-      gtfn = lt;
-      ltefn = gte;
-      ltfn = gt;
-      comp = '<';
-      ecomp = '<=';
-      break;
-    default:
-      throw new TypeError('Must provide a hilo val of "<" or ">"');
-  }
-
-  // If it satisifes the range it is not outside
-  if (satisfies(version, range, loose)) {
-    return false;
-  }
-
-  // From now on, variable terms are as if we're in "gtr" mode.
-  // but note that everything is flipped for the "ltr" function.
-
-  for (var i = 0; i < range.set.length; ++i) {
-    var comparators = range.set[i];
-
-    var high = null;
-    var low = null;
-
-    comparators.forEach(function(comparator) {
-      high = high || comparator;
-      low = low || comparator;
-      if (gtfn(comparator.semver, high.semver, loose)) {
-        high = comparator;
-      } else if (ltfn(comparator.semver, low.semver, loose)) {
-        low = comparator;
-      }
-    });
-
-    // If the edge version comparator has a operator then our version
-    // isn't outside it
-    if (high.operator === comp || high.operator === ecomp) {
-      return false;
-    }
-
-    // If the lowest version comparator has an operator and our version
-    // is less than it then it isn't higher than the range
-    if ((!low.operator || low.operator === comp) &&
-        ltefn(version, low.semver)) {
-      return false;
-    } else if (low.operator === ecomp && ltfn(version, low.semver)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// Use the define() function if we're in AMD land
-if (typeof define === 'function' && define.amd)
-  define(exports);
-
-})(
-  typeof exports === 'object' ? exports :
-  typeof define === 'function' && define.amd ? {} :
-  semver = {}
-);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.browser.js.gz b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.browser.js.gz
deleted file mode 100644
index 2b07bae519b5715db7703a41dfad904df1b8b236..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 7180
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

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.js
deleted file mode 100644
index a7385b41..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.js
+++ /dev/null
@@ -1,1043 +0,0 @@
-// export the class if we are in a Node-like system.
-if (typeof module === 'object' && module.exports === exports)
-  exports = module.exports = SemVer;
-
-// The debug function is excluded entirely from the minified version.
-/* nomin */ var debug;
-/* nomin */ if (typeof process === 'object' &&
-    /* nomin */ process.env &&
-    /* nomin */ process.env.NODE_DEBUG &&
-    /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG))
-  /* nomin */ debug = function() {
-    /* nomin */ var args = Array.prototype.slice.call(arguments, 0);
-    /* nomin */ args.unshift('SEMVER');
-    /* nomin */ console.log.apply(console, args);
-    /* nomin */ };
-/* nomin */ else
-  /* nomin */ debug = function() {};
-
-// Note: this is the semver.org version of the spec that it implements
-// Not necessarily the package version of this code.
-exports.SEMVER_SPEC_VERSION = '2.0.0';
-
-// The actual regexps go on exports.re
-var re = exports.re = [];
-var src = exports.src = [];
-var R = 0;
-
-// The following Regular Expressions can be used for tokenizing,
-// validating, and parsing SemVer version strings.
-
-// ## Numeric Identifier
-// A single `0`, or a non-zero digit followed by zero or more digits.
-
-var NUMERICIDENTIFIER = R++;
-src[NUMERICIDENTIFIER] = '0|[1-9]\\d*';
-var NUMERICIDENTIFIERLOOSE = R++;
-src[NUMERICIDENTIFIERLOOSE] = '[0-9]+';
-
-
-// ## Non-numeric Identifier
-// Zero or more digits, followed by a letter or hyphen, and then zero or
-// more letters, digits, or hyphens.
-
-var NONNUMERICIDENTIFIER = R++;
-src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*';
-
-
-// ## Main Version
-// Three dot-separated numeric identifiers.
-
-var MAINVERSION = R++;
-src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
-                   '(' + src[NUMERICIDENTIFIER] + ')\\.' +
-                   '(' + src[NUMERICIDENTIFIER] + ')';
-
-var MAINVERSIONLOOSE = R++;
-src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
-                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
-                        '(' + src[NUMERICIDENTIFIERLOOSE] + ')';
-
-// ## Pre-release Version Identifier
-// A numeric identifier, or a non-numeric identifier.
-
-var PRERELEASEIDENTIFIER = R++;
-src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
-                            '|' + src[NONNUMERICIDENTIFIER] + ')';
-
-var PRERELEASEIDENTIFIERLOOSE = R++;
-src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
-                                 '|' + src[NONNUMERICIDENTIFIER] + ')';
-
-
-// ## Pre-release Version
-// Hyphen, followed by one or more dot-separated pre-release version
-// identifiers.
-
-var PRERELEASE = R++;
-src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
-                  '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))';
-
-var PRERELEASELOOSE = R++;
-src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
-                       '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))';
-
-// ## Build Metadata Identifier
-// Any combination of digits, letters, or hyphens.
-
-var BUILDIDENTIFIER = R++;
-src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';
-
-// ## Build Metadata
-// Plus sign, followed by one or more period-separated build metadata
-// identifiers.
-
-var BUILD = R++;
-src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
-             '(?:\\.' + src[BUILDIDENTIFIER] + ')*))';
-
-
-// ## Full Version String
-// A main version, followed optionally by a pre-release version and
-// build metadata.
-
-// Note that the only major, minor, patch, and pre-release sections of
-// the version string are capturing groups.  The build metadata is not a
-// capturing group, because it should not ever be used in version
-// comparison.
-
-var FULL = R++;
-var FULLPLAIN = 'v?' + src[MAINVERSION] +
-                src[PRERELEASE] + '?' +
-                src[BUILD] + '?';
-
-src[FULL] = '^' + FULLPLAIN + '$';
-
-// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
-// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
-// common in the npm registry.
-var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
-                 src[PRERELEASELOOSE] + '?' +
-                 src[BUILD] + '?';
-
-var LOOSE = R++;
-src[LOOSE] = '^' + LOOSEPLAIN + '$';
-
-var GTLT = R++;
-src[GTLT] = '((?:<|>)?=?)';
-
-// Something like "2.*" or "1.2.x".
-// Note that "x.x" is a valid xRange identifer, meaning "any version"
-// Only the first item is strictly required.
-var XRANGEIDENTIFIERLOOSE = R++;
-src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*';
-var XRANGEIDENTIFIER = R++;
-src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*';
-
-var XRANGEPLAIN = R++;
-src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
-                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
-                   '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
-                   '(?:(' + src[PRERELEASE] + ')' +
-                   ')?)?)?';
-
-var XRANGEPLAINLOOSE = R++;
-src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
-                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
-                        '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
-                        '(?:(' + src[PRERELEASELOOSE] + ')' +
-                        ')?)?)?';
-
-// >=2.x, for example, means >=2.0.0-0
-// <1.x would be the same as "<1.0.0-0", though.
-var XRANGE = R++;
-src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$';
-var XRANGELOOSE = R++;
-src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$';
-
-// Tilde ranges.
-// Meaning is "reasonably at or greater than"
-var LONETILDE = R++;
-src[LONETILDE] = '(?:~>?)';
-
-var TILDETRIM = R++;
-src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+';
-re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g');
-var tildeTrimReplace = '$1~';
-
-var TILDE = R++;
-src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$';
-var TILDELOOSE = R++;
-src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$';
-
-// Caret ranges.
-// Meaning is "at least and backwards compatible with"
-var LONECARET = R++;
-src[LONECARET] = '(?:\\^)';
-
-var CARETTRIM = R++;
-src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+';
-re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g');
-var caretTrimReplace = '$1^';
-
-var CARET = R++;
-src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$';
-var CARETLOOSE = R++;
-src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$';
-
-// A simple gt/lt/eq thing, or just "" to indicate "any version"
-var COMPARATORLOOSE = R++;
-src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$';
-var COMPARATOR = R++;
-src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$';
-
-
-// An expression to strip any whitespace between the gtlt and the thing
-// it modifies, so that `> 1.2.3` ==> `>1.2.3`
-var COMPARATORTRIM = R++;
-src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
-                      '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')';
-
-// this one has to use the /g flag
-re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g');
-var comparatorTrimReplace = '$1$2$3';
-
-
-// Something like `1.2.3 - 1.2.4`
-// Note that these all use the loose form, because they'll be
-// checked against either the strict or loose comparator form
-// later.
-var HYPHENRANGE = R++;
-src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
-                   '\\s+-\\s+' +
-                   '(' + src[XRANGEPLAIN] + ')' +
-                   '\\s*$';
-
-var HYPHENRANGELOOSE = R++;
-src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
-                        '\\s+-\\s+' +
-                        '(' + src[XRANGEPLAINLOOSE] + ')' +
-                        '\\s*$';
-
-// Star ranges basically just allow anything at all.
-var STAR = R++;
-src[STAR] = '(<|>)?=?\\s*\\*';
-
-// Compile to actual regexp objects.
-// All are flag-free, unless they were created above with a flag.
-for (var i = 0; i < R; i++) {
-  debug(i, src[i]);
-  if (!re[i])
-    re[i] = new RegExp(src[i]);
-}
-
-exports.parse = parse;
-function parse(version, loose) {
-  var r = loose ? re[LOOSE] : re[FULL];
-  return (r.test(version)) ? new SemVer(version, loose) : null;
-}
-
-exports.valid = valid;
-function valid(version, loose) {
-  var v = parse(version, loose);
-  return v ? v.version : null;
-}
-
-
-exports.clean = clean;
-function clean(version, loose) {
-  var s = parse(version, loose);
-  return s ? s.version : null;
-}
-
-exports.SemVer = SemVer;
-
-function SemVer(version, loose) {
-  if (version instanceof SemVer) {
-    if (version.loose === loose)
-      return version;
-    else
-      version = version.version;
-  } else if (typeof version !== 'string') {
-    throw new TypeError('Invalid Version: ' + version);
-  }
-
-  if (!(this instanceof SemVer))
-    return new SemVer(version, loose);
-
-  debug('SemVer', version, loose);
-  this.loose = loose;
-  var m = version.trim().match(loose ? re[LOOSE] : re[FULL]);
-
-  if (!m)
-    throw new TypeError('Invalid Version: ' + version);
-
-  this.raw = version;
-
-  // these are actually numbers
-  this.major = +m[1];
-  this.minor = +m[2];
-  this.patch = +m[3];
-
-  // numberify any prerelease numeric ids
-  if (!m[4])
-    this.prerelease = [];
-  else
-    this.prerelease = m[4].split('.').map(function(id) {
-      return (/^[0-9]+$/.test(id)) ? +id : id;
-    });
-
-  this.build = m[5] ? m[5].split('.') : [];
-  this.format();
-}
-
-SemVer.prototype.format = function() {
-  this.version = this.major + '.' + this.minor + '.' + this.patch;
-  if (this.prerelease.length)
-    this.version += '-' + this.prerelease.join('.');
-  return this.version;
-};
-
-SemVer.prototype.inspect = function() {
-  return '<SemVer "' + this + '">';
-};
-
-SemVer.prototype.toString = function() {
-  return this.version;
-};
-
-SemVer.prototype.compare = function(other) {
-  debug('SemVer.compare', this.version, this.loose, other);
-  if (!(other instanceof SemVer))
-    other = new SemVer(other, this.loose);
-
-  return this.compareMain(other) || this.comparePre(other);
-};
-
-SemVer.prototype.compareMain = function(other) {
-  if (!(other instanceof SemVer))
-    other = new SemVer(other, this.loose);
-
-  return compareIdentifiers(this.major, other.major) ||
-         compareIdentifiers(this.minor, other.minor) ||
-         compareIdentifiers(this.patch, other.patch);
-};
-
-SemVer.prototype.comparePre = function(other) {
-  if (!(other instanceof SemVer))
-    other = new SemVer(other, this.loose);
-
-  // NOT having a prerelease is > having one
-  if (this.prerelease.length && !other.prerelease.length)
-    return -1;
-  else if (!this.prerelease.length && other.prerelease.length)
-    return 1;
-  else if (!this.prerelease.length && !other.prerelease.length)
-    return 0;
-
-  var i = 0;
-  do {
-    var a = this.prerelease[i];
-    var b = other.prerelease[i];
-    debug('prerelease compare', i, a, b);
-    if (a === undefined && b === undefined)
-      return 0;
-    else if (b === undefined)
-      return 1;
-    else if (a === undefined)
-      return -1;
-    else if (a === b)
-      continue;
-    else
-      return compareIdentifiers(a, b);
-  } while (++i);
-};
-
-// preminor will bump the version up to the next minor release, and immediately
-// down to pre-release. premajor and prepatch work the same way.
-SemVer.prototype.inc = function(release) {
-  switch (release) {
-    case 'premajor':
-      this.inc('major');
-      this.inc('pre');
-      break;
-    case 'preminor':
-      this.inc('minor');
-      this.inc('pre');
-      break;
-    case 'prepatch':
-      this.inc('patch');
-      this.inc('pre');
-      break;
-    // If the input is a non-prerelease version, this acts the same as
-    // prepatch.
-    case 'prerelease':
-      if (this.prerelease.length === 0)
-        this.inc('patch');
-      this.inc('pre');
-      break;
-    case 'major':
-      this.major++;
-      this.minor = -1;
-    case 'minor':
-      this.minor++;
-      this.patch = 0;
-      this.prerelease = [];
-      break;
-    case 'patch':
-      // If this is not a pre-release version, it will increment the patch.
-      // If it is a pre-release it will bump up to the same patch version.
-      // 1.2.0-5 patches to 1.2.0
-      // 1.2.0 patches to 1.2.1
-      if (this.prerelease.length === 0)
-        this.patch++;
-      this.prerelease = [];
-      break;
-    // This probably shouldn't be used publically.
-    // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
-    case 'pre':
-      if (this.prerelease.length === 0)
-        this.prerelease = [0];
-      else {
-        var i = this.prerelease.length;
-        while (--i >= 0) {
-          if (typeof this.prerelease[i] === 'number') {
-            this.prerelease[i]++;
-            i = -2;
-          }
-        }
-        if (i === -1) // didn't increment anything
-          this.prerelease.push(0);
-      }
-      break;
-
-    default:
-      throw new Error('invalid increment argument: ' + release);
-  }
-  this.format();
-  return this;
-};
-
-exports.inc = inc;
-function inc(version, release, loose) {
-  try {
-    return new SemVer(version, loose).inc(release).version;
-  } catch (er) {
-    return null;
-  }
-}
-
-exports.compareIdentifiers = compareIdentifiers;
-
-var numeric = /^[0-9]+$/;
-function compareIdentifiers(a, b) {
-  var anum = numeric.test(a);
-  var bnum = numeric.test(b);
-
-  if (anum && bnum) {
-    a = +a;
-    b = +b;
-  }
-
-  return (anum && !bnum) ? -1 :
-         (bnum && !anum) ? 1 :
-         a < b ? -1 :
-         a > b ? 1 :
-         0;
-}
-
-exports.rcompareIdentifiers = rcompareIdentifiers;
-function rcompareIdentifiers(a, b) {
-  return compareIdentifiers(b, a);
-}
-
-exports.compare = compare;
-function compare(a, b, loose) {
-  return new SemVer(a, loose).compare(b);
-}
-
-exports.compareLoose = compareLoose;
-function compareLoose(a, b) {
-  return compare(a, b, true);
-}
-
-exports.rcompare = rcompare;
-function rcompare(a, b, loose) {
-  return compare(b, a, loose);
-}
-
-exports.sort = sort;
-function sort(list, loose) {
-  return list.sort(function(a, b) {
-    return exports.compare(a, b, loose);
-  });
-}
-
-exports.rsort = rsort;
-function rsort(list, loose) {
-  return list.sort(function(a, b) {
-    return exports.rcompare(a, b, loose);
-  });
-}
-
-exports.gt = gt;
-function gt(a, b, loose) {
-  return compare(a, b, loose) > 0;
-}
-
-exports.lt = lt;
-function lt(a, b, loose) {
-  return compare(a, b, loose) < 0;
-}
-
-exports.eq = eq;
-function eq(a, b, loose) {
-  return compare(a, b, loose) === 0;
-}
-
-exports.neq = neq;
-function neq(a, b, loose) {
-  return compare(a, b, loose) !== 0;
-}
-
-exports.gte = gte;
-function gte(a, b, loose) {
-  return compare(a, b, loose) >= 0;
-}
-
-exports.lte = lte;
-function lte(a, b, loose) {
-  return compare(a, b, loose) <= 0;
-}
-
-exports.cmp = cmp;
-function cmp(a, op, b, loose) {
-  var ret;
-  switch (op) {
-    case '===': ret = a === b; break;
-    case '!==': ret = a !== b; break;
-    case '': case '=': case '==': ret = eq(a, b, loose); break;
-    case '!=': ret = neq(a, b, loose); break;
-    case '>': ret = gt(a, b, loose); break;
-    case '>=': ret = gte(a, b, loose); break;
-    case '<': ret = lt(a, b, loose); break;
-    case '<=': ret = lte(a, b, loose); break;
-    default: throw new TypeError('Invalid operator: ' + op);
-  }
-  return ret;
-}
-
-exports.Comparator = Comparator;
-function Comparator(comp, loose) {
-  if (comp instanceof Comparator) {
-    if (comp.loose === loose)
-      return comp;
-    else
-      comp = comp.value;
-  }
-
-  if (!(this instanceof Comparator))
-    return new Comparator(comp, loose);
-
-  debug('comparator', comp, loose);
-  this.loose = loose;
-  this.parse(comp);
-
-  if (this.semver === ANY)
-    this.value = '';
-  else
-    this.value = this.operator + this.semver.version;
-}
-
-var ANY = {};
-Comparator.prototype.parse = function(comp) {
-  var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
-  var m = comp.match(r);
-
-  if (!m)
-    throw new TypeError('Invalid comparator: ' + comp);
-
-  this.operator = m[1];
-  // if it literally is just '>' or '' then allow anything.
-  if (!m[2])
-    this.semver = ANY;
-  else {
-    this.semver = new SemVer(m[2], this.loose);
-
-    // <1.2.3-rc DOES allow 1.2.3-beta (has prerelease)
-    // >=1.2.3 DOES NOT allow 1.2.3-beta
-    // <=1.2.3 DOES allow 1.2.3-beta
-    // However, <1.2.3 does NOT allow 1.2.3-beta,
-    // even though `1.2.3-beta < 1.2.3`
-    // The assumption is that the 1.2.3 version has something you
-    // *don't* want, so we push the prerelease down to the minimum.
-    if (this.operator === '<' && !this.semver.prerelease.length) {
-      this.semver.prerelease = ['0'];
-      this.semver.format();
-    }
-  }
-};
-
-Comparator.prototype.inspect = function() {
-  return '<SemVer Comparator "' + this + '">';
-};
-
-Comparator.prototype.toString = function() {
-  return this.value;
-};
-
-Comparator.prototype.test = function(version) {
-  debug('Comparator.test', version, this.loose);
-  return (this.semver === ANY) ? true :
-         cmp(version, this.operator, this.semver, this.loose);
-};
-
-
-exports.Range = Range;
-function Range(range, loose) {
-  if ((range instanceof Range) && range.loose === loose)
-    return range;
-
-  if (!(this instanceof Range))
-    return new Range(range, loose);
-
-  this.loose = loose;
-
-  // First, split based on boolean or ||
-  this.raw = range;
-  this.set = range.split(/\s*\|\|\s*/).map(function(range) {
-    return this.parseRange(range.trim());
-  }, this).filter(function(c) {
-    // throw out any that are not relevant for whatever reason
-    return c.length;
-  });
-
-  if (!this.set.length) {
-    throw new TypeError('Invalid SemVer Range: ' + range);
-  }
-
-  this.format();
-}
-
-Range.prototype.inspect = function() {
-  return '<SemVer Range "' + this.range + '">';
-};
-
-Range.prototype.format = function() {
-  this.range = this.set.map(function(comps) {
-    return comps.join(' ').trim();
-  }).join('||').trim();
-  return this.range;
-};
-
-Range.prototype.toString = function() {
-  return this.range;
-};
-
-Range.prototype.parseRange = function(range) {
-  var loose = this.loose;
-  range = range.trim();
-  debug('range', range, loose);
-  // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
-  var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];
-  range = range.replace(hr, hyphenReplace);
-  debug('hyphen replace', range);
-  // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
-  range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);
-  debug('comparator trim', range, re[COMPARATORTRIM]);
-
-  // `~ 1.2.3` => `~1.2.3`
-  range = range.replace(re[TILDETRIM], tildeTrimReplace);
-
-  // `^ 1.2.3` => `^1.2.3`
-  range = range.replace(re[CARETTRIM], caretTrimReplace);
-
-  // normalize spaces
-  range = range.split(/\s+/).join(' ');
-
-  // At this point, the range is completely trimmed and
-  // ready to be split into comparators.
-
-  var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
-  var set = range.split(' ').map(function(comp) {
-    return parseComparator(comp, loose);
-  }).join(' ').split(/\s+/);
-  if (this.loose) {
-    // in loose mode, throw out any that are not valid comparators
-    set = set.filter(function(comp) {
-      return !!comp.match(compRe);
-    });
-  }
-  set = set.map(function(comp) {
-    return new Comparator(comp, loose);
-  });
-
-  return set;
-};
-
-// Mostly just for testing and legacy API reasons
-exports.toComparators = toComparators;
-function toComparators(range, loose) {
-  return new Range(range, loose).set.map(function(comp) {
-    return comp.map(function(c) {
-      return c.value;
-    }).join(' ').trim().split(' ');
-  });
-}
-
-// comprised of xranges, tildes, stars, and gtlt's at this point.
-// already replaced the hyphen ranges
-// turn into a set of JUST comparators.
-function parseComparator(comp, loose) {
-  debug('comp', comp);
-  comp = replaceCarets(comp, loose);
-  debug('caret', comp);
-  comp = replaceTildes(comp, loose);
-  debug('tildes', comp);
-  comp = replaceXRanges(comp, loose);
-  debug('xrange', comp);
-  comp = replaceStars(comp, loose);
-  debug('stars', comp);
-  return comp;
-}
-
-function isX(id) {
-  return !id || id.toLowerCase() === 'x' || id === '*';
-}
-
-// ~, ~> --> * (any, kinda silly)
-// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
-// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
-// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
-// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
-// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
-function replaceTildes(comp, loose) {
-  return comp.trim().split(/\s+/).map(function(comp) {
-    return replaceTilde(comp, loose);
-  }).join(' ');
-}
-
-function replaceTilde(comp, loose) {
-  var r = loose ? re[TILDELOOSE] : re[TILDE];
-  return comp.replace(r, function(_, M, m, p, pr) {
-    debug('tilde', comp, _, M, m, p, pr);
-    var ret;
-
-    if (isX(M))
-      ret = '';
-    else if (isX(m))
-      ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
-    else if (isX(p))
-      // ~1.2 == >=1.2.0- <1.3.0-
-      ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
-    else if (pr) {
-      debug('replaceTilde pr', pr);
-      if (pr.charAt(0) !== '-')
-        pr = '-' + pr;
-      ret = '>=' + M + '.' + m + '.' + p + pr +
-            ' <' + M + '.' + (+m + 1) + '.0-0';
-    } else
-      // ~1.2.3 == >=1.2.3-0 <1.3.0-0
-      ret = '>=' + M + '.' + m + '.' + p + '-0' +
-            ' <' + M + '.' + (+m + 1) + '.0-0';
-
-    debug('tilde return', ret);
-    return ret;
-  });
-}
-
-// ^ --> * (any, kinda silly)
-// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
-// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
-// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
-// ^1.2.3 --> >=1.2.3 <2.0.0
-// ^1.2.0 --> >=1.2.0 <2.0.0
-function replaceCarets(comp, loose) {
-  return comp.trim().split(/\s+/).map(function(comp) {
-    return replaceCaret(comp, loose);
-  }).join(' ');
-}
-
-function replaceCaret(comp, loose) {
-  var r = loose ? re[CARETLOOSE] : re[CARET];
-  return comp.replace(r, function(_, M, m, p, pr) {
-    debug('caret', comp, _, M, m, p, pr);
-    var ret;
-
-    if (isX(M))
-      ret = '';
-    else if (isX(m))
-      ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
-    else if (isX(p)) {
-      if (M === '0')
-        ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
-      else
-        ret = '>=' + M + '.' + m + '.0-0 <' + (+M + 1) + '.0.0-0';
-    } else if (pr) {
-      debug('replaceCaret pr', pr);
-      if (pr.charAt(0) !== '-')
-        pr = '-' + pr;
-      if (M === '0') {
-        if (m === '0')
-          ret = '=' + M + '.' + m + '.' + p + pr;
-        else
-          ret = '>=' + M + '.' + m + '.' + p + pr +
-                ' <' + M + '.' + (+m + 1) + '.0-0';
-      } else
-        ret = '>=' + M + '.' + m + '.' + p + pr +
-              ' <' + (+M + 1) + '.0.0-0';
-    } else {
-      if (M === '0') {
-        if (m === '0')
-          ret = '=' + M + '.' + m + '.' + p;
-        else
-          ret = '>=' + M + '.' + m + '.' + p + '-0' +
-                ' <' + M + '.' + (+m + 1) + '.0-0';
-      } else
-        ret = '>=' + M + '.' + m + '.' + p + '-0' +
-              ' <' + (+M + 1) + '.0.0-0';
-    }
-
-    debug('caret return', ret);
-    return ret;
-  });
-}
-
-function replaceXRanges(comp, loose) {
-  debug('replaceXRanges', comp, loose);
-  return comp.split(/\s+/).map(function(comp) {
-    return replaceXRange(comp, loose);
-  }).join(' ');
-}
-
-function replaceXRange(comp, loose) {
-  comp = comp.trim();
-  var r = loose ? re[XRANGELOOSE] : re[XRANGE];
-  return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
-    debug('xRange', comp, ret, gtlt, M, m, p, pr);
-    var xM = isX(M);
-    var xm = xM || isX(m);
-    var xp = xm || isX(p);
-    var anyX = xp;
-
-    if (gtlt === '=' && anyX)
-      gtlt = '';
-
-    if (gtlt && anyX) {
-      // replace X with 0, and then append the -0 min-prerelease
-      if (xM)
-        M = 0;
-      if (xm)
-        m = 0;
-      if (xp)
-        p = 0;
-
-      if (gtlt === '>') {
-        // >1 => >=2.0.0-0
-        // >1.2 => >=1.3.0-0
-        // >1.2.3 => >= 1.2.4-0
-        gtlt = '>=';
-        if (xM) {
-          // no change
-        } else if (xm) {
-          M = +M + 1;
-          m = 0;
-          p = 0;
-        } else if (xp) {
-          m = +m + 1;
-          p = 0;
-        }
-      }
-
-
-      ret = gtlt + M + '.' + m + '.' + p + '-0';
-    } else if (xM) {
-      // allow any
-      ret = '*';
-    } else if (xm) {
-      // append '-0' onto the version, otherwise
-      // '1.x.x' matches '2.0.0-beta', since the tag
-      // *lowers* the version value
-      ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
-    } else if (xp) {
-      ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
-    }
-
-    debug('xRange return', ret);
-
-    return ret;
-  });
-}
-
-// Because * is AND-ed with everything else in the comparator,
-// and '' means "any version", just remove the *s entirely.
-function replaceStars(comp, loose) {
-  debug('replaceStars', comp, loose);
-  // Looseness is ignored here.  star is always as loose as it gets!
-  return comp.trim().replace(re[STAR], '');
-}
-
-// This function is passed to string.replace(re[HYPHENRANGE])
-// M, m, patch, prerelease, build
-// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5
-// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do
-// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0
-function hyphenReplace($0,
-                       from, fM, fm, fp, fpr, fb,
-                       to, tM, tm, tp, tpr, tb) {
-
-  if (isX(fM))
-    from = '';
-  else if (isX(fm))
-    from = '>=' + fM + '.0.0-0';
-  else if (isX(fp))
-    from = '>=' + fM + '.' + fm + '.0-0';
-  else
-    from = '>=' + from;
-
-  if (isX(tM))
-    to = '';
-  else if (isX(tm))
-    to = '<' + (+tM + 1) + '.0.0-0';
-  else if (isX(tp))
-    to = '<' + tM + '.' + (+tm + 1) + '.0-0';
-  else if (tpr)
-    to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;
-  else
-    to = '<=' + to;
-
-  return (from + ' ' + to).trim();
-}
-
-
-// if ANY of the sets match ALL of its comparators, then pass
-Range.prototype.test = function(version) {
-  if (!version)
-    return false;
-  for (var i = 0; i < this.set.length; i++) {
-    if (testSet(this.set[i], version))
-      return true;
-  }
-  return false;
-};
-
-function testSet(set, version) {
-  for (var i = 0; i < set.length; i++) {
-    if (!set[i].test(version))
-      return false;
-  }
-  return true;
-}
-
-exports.satisfies = satisfies;
-function satisfies(version, range, loose) {
-  try {
-    range = new Range(range, loose);
-  } catch (er) {
-    return false;
-  }
-  return range.test(version);
-}
-
-exports.maxSatisfying = maxSatisfying;
-function maxSatisfying(versions, range, loose) {
-  return versions.filter(function(version) {
-    return satisfies(version, range, loose);
-  }).sort(function(a, b) {
-    return rcompare(a, b, loose);
-  })[0] || null;
-}
-
-exports.validRange = validRange;
-function validRange(range, loose) {
-  try {
-    // Return '*' instead of '' so that truthiness works.
-    // This will throw if it's invalid anyway
-    return new Range(range, loose).range || '*';
-  } catch (er) {
-    return null;
-  }
-}
-
-// Determine if version is less than all the versions possible in the range
-exports.ltr = ltr;
-function ltr(version, range, loose) {
-  return outside(version, range, '<', loose);
-}
-
-// Determine if version is greater than all the versions possible in the range.
-exports.gtr = gtr;
-function gtr(version, range, loose) {
-  return outside(version, range, '>', loose);
-}
-
-exports.outside = outside;
-function outside(version, range, hilo, loose) {
-  version = new SemVer(version, loose);
-  range = new Range(range, loose);
-
-  var gtfn, ltefn, ltfn, comp, ecomp;
-  switch (hilo) {
-    case '>':
-      gtfn = gt;
-      ltefn = lte;
-      ltfn = lt;
-      comp = '>';
-      ecomp = '>=';
-      break;
-    case '<':
-      gtfn = lt;
-      ltefn = gte;
-      ltfn = gt;
-      comp = '<';
-      ecomp = '<=';
-      break;
-    default:
-      throw new TypeError('Must provide a hilo val of "<" or ">"');
-  }
-
-  // If it satisifes the range it is not outside
-  if (satisfies(version, range, loose)) {
-    return false;
-  }
-
-  // From now on, variable terms are as if we're in "gtr" mode.
-  // but note that everything is flipped for the "ltr" function.
-
-  for (var i = 0; i < range.set.length; ++i) {
-    var comparators = range.set[i];
-
-    var high = null;
-    var low = null;
-
-    comparators.forEach(function(comparator) {
-      high = high || comparator;
-      low = low || comparator;
-      if (gtfn(comparator.semver, high.semver, loose)) {
-        high = comparator;
-      } else if (ltfn(comparator.semver, low.semver, loose)) {
-        low = comparator;
-      }
-    });
-
-    // If the edge version comparator has a operator then our version
-    // isn't outside it
-    if (high.operator === comp || high.operator === ecomp) {
-      return false;
-    }
-
-    // If the lowest version comparator has an operator and our version
-    // is less than it then it isn't higher than the range
-    if ((!low.operator || low.operator === comp) &&
-        ltefn(version, low.semver)) {
-      return false;
-    } else if (low.operator === ecomp && ltfn(version, low.semver)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// Use the define() function if we're in AMD land
-if (typeof define === 'function' && define.amd)
-  define(exports);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.min.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.min.js
deleted file mode 100644
index 66e13b86..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(e){if(typeof module==="object"&&module.exports===e)e=module.exports=H;e.SEMVER_SPEC_VERSION="2.0.0";var r=e.re=[];var t=e.src=[];var n=0;var i=n++;t[i]="0|[1-9]\\d*";var s=n++;t[s]="[0-9]+";var a=n++;t[a]="\\d*[a-zA-Z-][a-zA-Z0-9-]*";var o=n++;t[o]="("+t[i]+")\\."+"("+t[i]+")\\."+"("+t[i]+")";var f=n++;t[f]="("+t[s]+")\\."+"("+t[s]+")\\."+"("+t[s]+")";var u=n++;t[u]="(?:"+t[i]+"|"+t[a]+")";var c=n++;t[c]="(?:"+t[s]+"|"+t[a]+")";var l=n++;t[l]="(?:-("+t[u]+"(?:\\."+t[u]+")*))";var p=n++;t[p]="(?:-?("+t[c]+"(?:\\."+t[c]+")*))";var h=n++;t[h]="[0-9A-Za-z-]+";var v=n++;t[v]="(?:\\+("+t[h]+"(?:\\."+t[h]+")*))";var m=n++;var g="v?"+t[o]+t[l]+"?"+t[v]+"?";t[m]="^"+g+"$";var w="[v=\\s]*"+t[f]+t[p]+"?"+t[v]+"?";var d=n++;t[d]="^"+w+"$";var y=n++;t[y]="((?:<|>)?=?)";var b=n++;t[b]=t[s]+"|x|X|\\*";var $=n++;t[$]=t[i]+"|x|X|\\*";var j=n++;t[j]="[v=\\s]*("+t[$]+")"+"(?:\\.("+t[$]+")"+"(?:\\.("+t[$]+")"+"(?:("+t[l]+")"+")?)?)?";var k=n++;t[k]="[v=\\s]*("+t[b]+")"+"(?:\\.("+t[b]+")"+"(?:\\.("+t[b]+")"+"(?:("+t[p]+")"+")?)?)?";var E=n++;t[E]="^"+t[y]+"\\s*"+t[j]+"$";var x=n++;t[x]="^"+t[y]+"\\s*"+t[k]+"$";var R=n++;t[R]="(?:~>?)";var S=n++;t[S]="(\\s*)"+t[R]+"\\s+";r[S]=new RegExp(t[S],"g");var V="$1~";var I=n++;t[I]="^"+t[R]+t[j]+"$";var T=n++;t[T]="^"+t[R]+t[k]+"$";var A=n++;t[A]="(?:\\^)";var C=n++;t[C]="(\\s*)"+t[A]+"\\s+";r[C]=new RegExp(t[C],"g");var M="$1^";var z=n++;t[z]="^"+t[A]+t[j]+"$";var P=n++;t[P]="^"+t[A]+t[k]+"$";var Z=n++;t[Z]="^"+t[y]+"\\s*("+w+")$|^$";var q=n++;t[q]="^"+t[y]+"\\s*("+g+")$|^$";var L=n++;t[L]="(\\s*)"+t[y]+"\\s*("+w+"|"+t[j]+")";r[L]=new RegExp(t[L],"g");var X="$1$2$3";var _=n++;t[_]="^\\s*("+t[j]+")"+"\\s+-\\s+"+"("+t[j]+")"+"\\s*$";var N=n++;t[N]="^\\s*("+t[k]+")"+"\\s+-\\s+"+"("+t[k]+")"+"\\s*$";var O=n++;t[O]="(<|>)?=?\\s*\\*";for(var B=0;B<n;B++){if(!r[B])r[B]=new RegExp(t[B])}e.parse=D;function D(e,t){var n=t?r[d]:r[m];return n.test(e)?new H(e,t):null}e.valid=F;function F(e,r){var t=D(e,r);return t?t.version:null}e.clean=G;function G(e,r){var t=D(e,r);return t?t.version:null}e.SemVer=H;function H(e,t){if(e instanceof H){if(e.loose===t)return e;else e=e.version}else if(typeof e!=="string"){throw new TypeError("Invalid Version: "+e)}if(!(this instanceof H))return new H(e,t);this.loose=t;var n=e.trim().match(t?r[d]:r[m]);if(!n)throw new TypeError("Invalid Version: "+e);this.raw=e;this.major=+n[1];this.minor=+n[2];this.patch=+n[3];if(!n[4])this.prerelease=[];else this.prerelease=n[4].split(".").map(function(e){return/^[0-9]+$/.test(e)?+e:e});this.build=n[5]?n[5].split("."):[];this.format()}H.prototype.format=function(){this.version=this.major+"."+this.minor+"."+this.patch;if(this.prerelease.length)this.version+="-"+this.prerelease.join(".");return this.version};H.prototype.inspect=function(){return'<SemVer "'+this+'">'};H.prototype.toString=function(){return this.version};H.prototype.compare=function(e){if(!(e instanceof H))e=new H(e,this.loose);return this.compareMain(e)||this.comparePre(e)};H.prototype.compareMain=function(e){if(!(e instanceof H))e=new H(e,this.loose);return Q(this.major,e.major)||Q(this.minor,e.minor)||Q(this.patch,e.patch)};H.prototype.comparePre=function(e){if(!(e instanceof H))e=new H(e,this.loose);if(this.prerelease.length&&!e.prerelease.length)return-1;else if(!this.prerelease.length&&e.prerelease.length)return 1;else if(!this.prerelease.length&&!e.prerelease.length)return 0;var r=0;do{var t=this.prerelease[r];var n=e.prerelease[r];if(t===undefined&&n===undefined)return 0;else if(n===undefined)return 1;else if(t===undefined)return-1;else if(t===n)continue;else return Q(t,n)}while(++r)};H.prototype.inc=function(e){switch(e){case"premajor":this.inc("major");this.inc("pre");break;case"preminor":this.inc("minor");this.inc("pre");break;case"prepatch":this.inc("patch");this.inc("pre");break;case"prerelease":if(this.prerelease.length===0)this.inc("patch");this.inc("pre");break;case"major":this.major++;this.minor=-1;case"minor":this.minor++;this.patch=0;this.prerelease=[];break;case"patch":if(this.prerelease.length===0)this.patch++;this.prerelease=[];break;case"pre":if(this.prerelease.length===0)this.prerelease=[0];else{var r=this.prerelease.length;while(--r>=0){if(typeof this.prerelease[r]==="number"){this.prerelease[r]++;r=-2}}if(r===-1)this.prerelease.push(0)}break;default:throw new Error("invalid increment argument: "+e)}this.format();return this};e.inc=J;function J(e,r,t){try{return new H(e,t).inc(r).version}catch(n){return null}}e.compareIdentifiers=Q;var K=/^[0-9]+$/;function Q(e,r){var t=K.test(e);var n=K.test(r);if(t&&n){e=+e;r=+r}return t&&!n?-1:n&&!t?1:e<r?-1:e>r?1:0}e.rcompareIdentifiers=U;function U(e,r){return Q(r,e)}e.compare=W;function W(e,r,t){return new H(e,t).compare(r)}e.compareLoose=Y;function Y(e,r){return W(e,r,true)}e.rcompare=er;function er(e,r,t){return W(r,e,t)}e.sort=rr;function rr(r,t){return r.sort(function(r,n){return e.compare(r,n,t)})}e.rsort=tr;function tr(r,t){return r.sort(function(r,n){return e.rcompare(r,n,t)})}e.gt=nr;function nr(e,r,t){return W(e,r,t)>0}e.lt=ir;function ir(e,r,t){return W(e,r,t)<0}e.eq=sr;function sr(e,r,t){return W(e,r,t)===0}e.neq=ar;function ar(e,r,t){return W(e,r,t)!==0}e.gte=or;function or(e,r,t){return W(e,r,t)>=0}e.lte=fr;function fr(e,r,t){return W(e,r,t)<=0}e.cmp=ur;function ur(e,r,t,n){var i;switch(r){case"===":i=e===t;break;case"!==":i=e!==t;break;case"":case"=":case"==":i=sr(e,t,n);break;case"!=":i=ar(e,t,n);break;case">":i=nr(e,t,n);break;case">=":i=or(e,t,n);break;case"<":i=ir(e,t,n);break;case"<=":i=fr(e,t,n);break;default:throw new TypeError("Invalid operator: "+r)}return i}e.Comparator=cr;function cr(e,r){if(e instanceof cr){if(e.loose===r)return e;else e=e.value}if(!(this instanceof cr))return new cr(e,r);this.loose=r;this.parse(e);if(this.semver===lr)this.value="";else this.value=this.operator+this.semver.version}var lr={};cr.prototype.parse=function(e){var t=this.loose?r[Z]:r[q];var n=e.match(t);if(!n)throw new TypeError("Invalid comparator: "+e);this.operator=n[1];if(!n[2])this.semver=lr;else{this.semver=new H(n[2],this.loose);if(this.operator==="<"&&!this.semver.prerelease.length){this.semver.prerelease=["0"];this.semver.format()}}};cr.prototype.inspect=function(){return'<SemVer Comparator "'+this+'">'};cr.prototype.toString=function(){return this.value};cr.prototype.test=function(e){return this.semver===lr?true:ur(e,this.operator,this.semver,this.loose)};e.Range=pr;function pr(e,r){if(e instanceof pr&&e.loose===r)return e;if(!(this instanceof pr))return new pr(e,r);this.loose=r;this.raw=e;this.set=e.split(/\s*\|\|\s*/).map(function(e){return this.parseRange(e.trim())},this).filter(function(e){return e.length});if(!this.set.length){throw new TypeError("Invalid SemVer Range: "+e)}this.format()}pr.prototype.inspect=function(){return'<SemVer Range "'+this.range+'">'};pr.prototype.format=function(){this.range=this.set.map(function(e){return e.join(" ").trim()}).join("||").trim();return this.range};pr.prototype.toString=function(){return this.range};pr.prototype.parseRange=function(e){var t=this.loose;e=e.trim();var n=t?r[N]:r[_];e=e.replace(n,kr);e=e.replace(r[L],X);e=e.replace(r[S],V);e=e.replace(r[C],M);e=e.split(/\s+/).join(" ");var i=t?r[Z]:r[q];var s=e.split(" ").map(function(e){return vr(e,t)}).join(" ").split(/\s+/);if(this.loose){s=s.filter(function(e){return!!e.match(i)})}s=s.map(function(e){return new cr(e,t)});return s};e.toComparators=hr;function hr(e,r){return new pr(e,r).set.map(function(e){return e.map(function(e){return e.value}).join(" ").trim().split(" ")})}function vr(e,r){e=dr(e,r);e=gr(e,r);e=br(e,r);e=jr(e,r);return e}function mr(e){return!e||e.toLowerCase()==="x"||e==="*"}function gr(e,r){return e.trim().split(/\s+/).map(function(e){return wr(e,r)}).join(" ")}function wr(e,t){var n=t?r[T]:r[I];return e.replace(n,function(e,r,t,n,i){var s;if(mr(r))s="";else if(mr(t))s=">="+r+".0.0-0 <"+(+r+1)+".0.0-0";else if(mr(n))s=">="+r+"."+t+".0-0 <"+r+"."+(+t+1)+".0-0";else if(i){if(i.charAt(0)!=="-")i="-"+i;s=">="+r+"."+t+"."+n+i+" <"+r+"."+(+t+1)+".0-0"}else s=">="+r+"."+t+"."+n+"-0"+" <"+r+"."+(+t+1)+".0-0";return s})}function dr(e,r){return e.trim().split(/\s+/).map(function(e){return yr(e,r)}).join(" ")}function yr(e,t){var n=t?r[P]:r[z];return e.replace(n,function(e,r,t,n,i){var s;if(mr(r))s="";else if(mr(t))s=">="+r+".0.0-0 <"+(+r+1)+".0.0-0";else if(mr(n)){if(r==="0")s=">="+r+"."+t+".0-0 <"+r+"."+(+t+1)+".0-0";else s=">="+r+"."+t+".0-0 <"+(+r+1)+".0.0-0"}else if(i){if(i.charAt(0)!=="-")i="-"+i;if(r==="0"){if(t==="0")s="="+r+"."+t+"."+n+i;else s=">="+r+"."+t+"."+n+i+" <"+r+"."+(+t+1)+".0-0"}else s=">="+r+"."+t+"."+n+i+" <"+(+r+1)+".0.0-0"}else{if(r==="0"){if(t==="0")s="="+r+"."+t+"."+n;else s=">="+r+"."+t+"."+n+"-0"+" <"+r+"."+(+t+1)+".0-0"}else s=">="+r+"."+t+"."+n+"-0"+" <"+(+r+1)+".0.0-0"}return s})}function br(e,r){return e.split(/\s+/).map(function(e){return $r(e,r)}).join(" ")}function $r(e,t){e=e.trim();var n=t?r[x]:r[E];return e.replace(n,function(e,r,t,n,i,s){var a=mr(t);var o=a||mr(n);var f=o||mr(i);var u=f;if(r==="="&&u)r="";if(r&&u){if(a)t=0;if(o)n=0;if(f)i=0;if(r===">"){r=">=";if(a){}else if(o){t=+t+1;n=0;i=0}else if(f){n=+n+1;i=0}}e=r+t+"."+n+"."+i+"-0"}else if(a){e="*"}else if(o){e=">="+t+".0.0-0 <"+(+t+1)+".0.0-0"}else if(f){e=">="+t+"."+n+".0-0 <"+t+"."+(+n+1)+".0-0"}return e})}function jr(e,t){return e.trim().replace(r[O],"")}function kr(e,r,t,n,i,s,a,o,f,u,c,l,p){if(mr(t))r="";else if(mr(n))r=">="+t+".0.0-0";else if(mr(i))r=">="+t+"."+n+".0-0";else r=">="+r;if(mr(f))o="";else if(mr(u))o="<"+(+f+1)+".0.0-0";else if(mr(c))o="<"+f+"."+(+u+1)+".0-0";else if(l)o="<="+f+"."+u+"."+c+"-"+l;else o="<="+o;return(r+" "+o).trim()}pr.prototype.test=function(e){if(!e)return false;for(var r=0;r<this.set.length;r++){if(Er(this.set[r],e))return true}return false};function Er(e,r){for(var t=0;t<e.length;t++){if(!e[t].test(r))return false}return true}e.satisfies=xr;function xr(e,r,t){try{r=new pr(r,t)}catch(n){return false}return r.test(e)}e.maxSatisfying=Rr;function Rr(e,r,t){return e.filter(function(e){return xr(e,r,t)}).sort(function(e,r){return er(e,r,t)})[0]||null}e.validRange=Sr;function Sr(e,r){try{return new pr(e,r).range||"*"}catch(t){return null}}e.ltr=Vr;function Vr(e,r,t){return Tr(e,r,"<",t)}e.gtr=Ir;function Ir(e,r,t){return Tr(e,r,">",t)}e.outside=Tr;function Tr(e,r,t,n){e=new H(e,n);r=new pr(r,n);var i,s,a,o,f;switch(t){case">":i=nr;s=fr;a=ir;o=">";f=">=";break;case"<":i=ir;s=or;a=nr;o="<";f="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(xr(e,r,n)){return false}for(var u=0;u<r.set.length;++u){var c=r.set[u];var l=null;var p=null;c.forEach(function(e){l=l||e;p=p||e;if(i(e.semver,l.semver,n)){l=e}else if(a(e.semver,p.semver,n)){p=e}});if(l.operator===o||l.operator===f){return false}if((!p.operator||p.operator===o)&&s(e,p.semver)){return false}else if(p.operator===f&&a(e,p.semver)){return false}}return true}if(typeof define==="function"&&define.amd)define(e)})(typeof exports==="object"?exports:typeof define==="function"&&define.amd?{}:semver={});
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.min.js.gz b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/semver.min.js.gz
deleted file mode 100644
index cc05248ffdd4fed33b71a141344ac657f11a44fc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3295
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

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/amd.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/amd.js
deleted file mode 100644
index a6041341..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/amd.js
+++ /dev/null
@@ -1,15 +0,0 @@
-var tap = require('tap');
-var test = tap.test;
-
-test('amd', function(t) {
-  global.define = define;
-  define.amd = true;
-  var defined = null;
-  function define(stuff) {
-    defined = stuff;
-  }
-  var fromRequire = require('../');
-  t.ok(defined, 'amd function called');
-  t.equal(fromRequire, defined, 'amd stuff same as require stuff');
-  t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/gtr.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/gtr.js
deleted file mode 100644
index cb6199ef..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/gtr.js
+++ /dev/null
@@ -1,173 +0,0 @@
-var tap = require('tap');
-var test = tap.test;
-var semver = require('../semver.js');
-var gtr = semver.gtr;
-
-test('\ngtr tests', function(t) {
-  // [range, version, loose]
-  // Version should be greater than range
-  [
-    ['~1.2.2', '1.3.0'],
-    ['~0.6.1-1', '0.7.1-1'],
-    ['1.0.0 - 2.0.0', '2.0.1'],
-    ['1.0.0', '1.0.1-beta1'],
-    ['1.0.0', '2.0.0'],
-    ['<=2.0.0', '2.1.1'],
-    ['<=2.0.0', '3.2.9'],
-    ['<2.0.0', '2.0.0'],
-    ['0.1.20 || 1.2.4', '1.2.5'],
-    ['2.x.x', '3.0.0'],
-    ['1.2.x', '1.3.0'],
-    ['1.2.x || 2.x', '3.0.0'],
-    ['2.*.*', '5.0.1'],
-    ['1.2.*', '1.3.3'],
-    ['1.2.* || 2.*', '4.0.0'],
-    ['2', '3.0.0'],
-    ['2.3', '2.4.2'],
-    ['~2.4', '2.5.0'], // >=2.4.0 <2.5.0
-    ['~2.4', '2.5.5'],
-    ['~>3.2.1', '3.3.0'], // >=3.2.1 <3.3.0
-    ['~1', '2.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '2.2.4'],
-    ['~> 1', '3.2.3'],
-    ['~1.0', '1.1.2'], // >=1.0.0 <1.1.0
-    ['~ 1.0', '1.1.0'],
-    ['<1.2', '1.2.0'],
-    ['< 1.2', '1.2.1'],
-    ['1', '2.0.0beta', true],
-    ['~v0.5.4-pre', '0.6.0'],
-    ['~v0.5.4-pre', '0.6.1-pre'],
-    ['=0.7.x', '0.8.0'],
-    ['=0.7.x', '0.8.0-asdf'],
-    ['<=0.7.x', '0.7.0'],
-    ['~1.2.2', '1.3.0'],
-    ['1.0.0 - 2.0.0', '2.2.3'],
-    ['1.0.0', '1.0.1'],
-    ['<=2.0.0', '3.0.0'],
-    ['<=2.0.0', '2.9999.9999'],
-    ['<=2.0.0', '2.2.9'],
-    ['<2.0.0', '2.9999.9999'],
-    ['<2.0.0', '2.2.9'],
-    ['2.x.x', '3.1.3'],
-    ['1.2.x', '1.3.3'],
-    ['1.2.x || 2.x', '3.1.3'],
-    ['2.*.*', '3.1.3'],
-    ['1.2.*', '1.3.3'],
-    ['1.2.* || 2.*', '3.1.3'],
-    ['2', '3.1.2'],
-    ['2.3', '2.4.1'],
-    ['~2.4', '2.5.0'], // >=2.4.0 <2.5.0
-    ['~>3.2.1', '3.3.2'], // >=3.2.1 <3.3.0
-    ['~1', '2.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '2.2.3'],
-    ['~1.0', '1.1.0'], // >=1.0.0 <1.1.0
-    ['<1', '1.0.0'],
-    ['1', '2.0.0beta', true],
-    ['<1', '1.0.0beta', true],
-    ['< 1', '1.0.0beta', true],
-    ['=0.7.x', '0.8.2'],
-    ['<=0.7.x', '0.7.2']
-  ].forEach(function(tuple) {
-    var range = tuple[0];
-    var version = tuple[1];
-    var loose = tuple[2] || false;
-    var msg = 'gtr(' + version + ', ' + range + ', ' + loose + ')';
-    t.ok(gtr(version, range, loose), msg);
-  });
-  t.end();
-});
-
-test('\nnegative gtr tests', function(t) {
-  // [range, version, loose]
-  // Version should NOT be greater than range
-  [
-    ['~0.6.1-1', '0.6.1-1'],
-    ['1.0.0 - 2.0.0', '1.2.3'],
-    ['1.0.0 - 2.0.0', '0.9.9'],
-    ['1.0.0', '1.0.0'],
-    ['>=*', '0.2.4'],
-    ['', '1.0.0', true],
-    ['*', '1.2.3'],
-    ['*', 'v1.2.3-foo'],
-    ['>=1.0.0', '1.0.0'],
-    ['>=1.0.0', '1.0.1'],
-    ['>=1.0.0', '1.1.0'],
-    ['>1.0.0', '1.0.1'],
-    ['>1.0.0', '1.1.0'],
-    ['<=2.0.0', '2.0.0'],
-    ['<=2.0.0', '1.9999.9999'],
-    ['<=2.0.0', '0.2.9'],
-    ['<2.0.0', '1.9999.9999'],
-    ['<2.0.0', '0.2.9'],
-    ['>= 1.0.0', '1.0.0'],
-    ['>=  1.0.0', '1.0.1'],
-    ['>=   1.0.0', '1.1.0'],
-    ['> 1.0.0', '1.0.1'],
-    ['>  1.0.0', '1.1.0'],
-    ['<=   2.0.0', '2.0.0'],
-    ['<= 2.0.0', '1.9999.9999'],
-    ['<=  2.0.0', '0.2.9'],
-    ['<    2.0.0', '1.9999.9999'],
-    ['<\t2.0.0', '0.2.9'],
-    ['>=0.1.97', 'v0.1.97'],
-    ['>=0.1.97', '0.1.97'],
-    ['0.1.20 || 1.2.4', '1.2.4'],
-    ['0.1.20 || >1.2.4', '1.2.4'],
-    ['0.1.20 || 1.2.4', '1.2.3'],
-    ['0.1.20 || 1.2.4', '0.1.20'],
-    ['>=0.2.3 || <0.0.1', '0.0.0'],
-    ['>=0.2.3 || <0.0.1', '0.2.3'],
-    ['>=0.2.3 || <0.0.1', '0.2.4'],
-    ['||', '1.3.4'],
-    ['2.x.x', '2.1.3'],
-    ['1.2.x', '1.2.3'],
-    ['1.2.x || 2.x', '2.1.3'],
-    ['1.2.x || 2.x', '1.2.3'],
-    ['x', '1.2.3'],
-    ['2.*.*', '2.1.3'],
-    ['1.2.*', '1.2.3'],
-    ['1.2.* || 2.*', '2.1.3'],
-    ['1.2.* || 2.*', '1.2.3'],
-    ['1.2.* || 2.*', '1.2.3'],
-    ['*', '1.2.3'],
-    ['2', '2.1.2'],
-    ['2.3', '2.3.1'],
-    ['~2.4', '2.4.0'], // >=2.4.0 <2.5.0
-    ['~2.4', '2.4.5'],
-    ['~>3.2.1', '3.2.2'], // >=3.2.1 <3.3.0
-    ['~1', '1.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '1.2.3'],
-    ['~> 1', '1.2.3'],
-    ['~1.0', '1.0.2'], // >=1.0.0 <1.1.0
-    ['~ 1.0', '1.0.2'],
-    ['>=1', '1.0.0'],
-    ['>= 1', '1.0.0'],
-    ['<1.2', '1.1.1'],
-    ['< 1.2', '1.1.1'],
-    ['1', '1.0.0beta', true],
-    ['~v0.5.4-pre', '0.5.5'],
-    ['~v0.5.4-pre', '0.5.4'],
-    ['=0.7.x', '0.7.2'],
-    ['>=0.7.x', '0.7.2'],
-    ['=0.7.x', '0.7.0-asdf'],
-    ['>=0.7.x', '0.7.0-asdf'],
-    ['<=0.7.x', '0.6.2'],
-    ['>0.2.3 >0.2.4 <=0.2.5', '0.2.5'],
-    ['>=0.2.3 <=0.2.4', '0.2.4'],
-    ['1.0.0 - 2.0.0', '2.0.0'],
-    ['^1', '0.0.0-0'],
-    ['^3.0.0', '2.0.0'],
-    ['^1.0.0 || ~2.0.1', '2.0.0'],
-    ['^0.1.0 || ~3.0.1 || 5.0.0', '3.2.0'],
-    ['^0.1.0 || ~3.0.1 || 5.0.0', '1.0.0beta', true],
-    ['^0.1.0 || ~3.0.1 || 5.0.0', '5.0.0-0', true],
-    ['^0.1.0 || ~3.0.1 || >4 <=5.0.0', '3.5.0']
-  ].forEach(function(tuple) {
-    var range = tuple[0];
-    var version = tuple[1];
-    var loose = tuple[2] || false;
-    var msg = '!gtr(' + version + ', ' + range + ', ' + loose + ')';
-    t.notOk(gtr(version, range, loose), msg);
-  });
-  t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/index.js
deleted file mode 100644
index 6285b693..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/index.js
+++ /dev/null
@@ -1,584 +0,0 @@
-var tap = require('tap');
-var test = tap.test;
-var semver = require('../semver.js');
-var eq = semver.eq;
-var gt = semver.gt;
-var lt = semver.lt;
-var neq = semver.neq;
-var cmp = semver.cmp;
-var gte = semver.gte;
-var lte = semver.lte;
-var satisfies = semver.satisfies;
-var validRange = semver.validRange;
-var inc = semver.inc;
-var replaceStars = semver.replaceStars;
-var toComparators = semver.toComparators;
-var SemVer = semver.SemVer;
-var Range = semver.Range;
-
-test('\ncomparison tests', function(t) {
-  // [version1, version2]
-  // version1 should be greater than version2
-  [['0.0.0', '0.0.0-foo'],
-    ['0.0.1', '0.0.0'],
-    ['1.0.0', '0.9.9'],
-    ['0.10.0', '0.9.0'],
-    ['0.99.0', '0.10.0'],
-    ['2.0.0', '1.2.3'],
-    ['v0.0.0', '0.0.0-foo', true],
-    ['v0.0.1', '0.0.0', true],
-    ['v1.0.0', '0.9.9', true],
-    ['v0.10.0', '0.9.0', true],
-    ['v0.99.0', '0.10.0', true],
-    ['v2.0.0', '1.2.3', true],
-    ['0.0.0', 'v0.0.0-foo', true],
-    ['0.0.1', 'v0.0.0', true],
-    ['1.0.0', 'v0.9.9', true],
-    ['0.10.0', 'v0.9.0', true],
-    ['0.99.0', 'v0.10.0', true],
-    ['2.0.0', 'v1.2.3', true],
-    ['1.2.3', '1.2.3-asdf'],
-    ['1.2.3', '1.2.3-4'],
-    ['1.2.3', '1.2.3-4-foo'],
-    ['1.2.3-5-foo', '1.2.3-5'],
-    ['1.2.3-5', '1.2.3-4'],
-    ['1.2.3-5-foo', '1.2.3-5-Foo'],
-    ['3.0.0', '2.7.2+asdf'],
-    ['1.2.3-a.10', '1.2.3-a.5'],
-    ['1.2.3-a.b', '1.2.3-a.5'],
-    ['1.2.3-a.b', '1.2.3-a'],
-    ['1.2.3-a.b.c.10.d.5', '1.2.3-a.b.c.5.d.100']
-  ].forEach(function(v) {
-    var v0 = v[0];
-    var v1 = v[1];
-    var loose = v[2];
-    t.ok(gt(v0, v1, loose), "gt('" + v0 + "', '" + v1 + "')");
-    t.ok(lt(v1, v0, loose), "lt('" + v1 + "', '" + v0 + "')");
-    t.ok(!gt(v1, v0, loose), "!gt('" + v1 + "', '" + v0 + "')");
-    t.ok(!lt(v0, v1, loose), "!lt('" + v0 + "', '" + v1 + "')");
-    t.ok(eq(v0, v0, loose), "eq('" + v0 + "', '" + v0 + "')");
-    t.ok(eq(v1, v1, loose), "eq('" + v1 + "', '" + v1 + "')");
-    t.ok(neq(v0, v1, loose), "neq('" + v0 + "', '" + v1 + "')");
-    t.ok(cmp(v1, '==', v1, loose), "cmp('" + v1 + "' == '" + v1 + "')");
-    t.ok(cmp(v0, '>=', v1, loose), "cmp('" + v0 + "' >= '" + v1 + "')");
-    t.ok(cmp(v1, '<=', v0, loose), "cmp('" + v1 + "' <= '" + v0 + "')");
-    t.ok(cmp(v0, '!=', v1, loose), "cmp('" + v0 + "' != '" + v1 + "')");
-  });
-  t.end();
-});
-
-test('\nequality tests', function(t) {
-  // [version1, version2]
-  // version1 should be equivalent to version2
-  [['1.2.3', 'v1.2.3', true],
-    ['1.2.3', '=1.2.3', true],
-    ['1.2.3', 'v 1.2.3', true],
-    ['1.2.3', '= 1.2.3', true],
-    ['1.2.3', ' v1.2.3', true],
-    ['1.2.3', ' =1.2.3', true],
-    ['1.2.3', ' v 1.2.3', true],
-    ['1.2.3', ' = 1.2.3', true],
-    ['1.2.3-0', 'v1.2.3-0', true],
-    ['1.2.3-0', '=1.2.3-0', true],
-    ['1.2.3-0', 'v 1.2.3-0', true],
-    ['1.2.3-0', '= 1.2.3-0', true],
-    ['1.2.3-0', ' v1.2.3-0', true],
-    ['1.2.3-0', ' =1.2.3-0', true],
-    ['1.2.3-0', ' v 1.2.3-0', true],
-    ['1.2.3-0', ' = 1.2.3-0', true],
-    ['1.2.3-1', 'v1.2.3-1', true],
-    ['1.2.3-1', '=1.2.3-1', true],
-    ['1.2.3-1', 'v 1.2.3-1', true],
-    ['1.2.3-1', '= 1.2.3-1', true],
-    ['1.2.3-1', ' v1.2.3-1', true],
-    ['1.2.3-1', ' =1.2.3-1', true],
-    ['1.2.3-1', ' v 1.2.3-1', true],
-    ['1.2.3-1', ' = 1.2.3-1', true],
-    ['1.2.3-beta', 'v1.2.3-beta', true],
-    ['1.2.3-beta', '=1.2.3-beta', true],
-    ['1.2.3-beta', 'v 1.2.3-beta', true],
-    ['1.2.3-beta', '= 1.2.3-beta', true],
-    ['1.2.3-beta', ' v1.2.3-beta', true],
-    ['1.2.3-beta', ' =1.2.3-beta', true],
-    ['1.2.3-beta', ' v 1.2.3-beta', true],
-    ['1.2.3-beta', ' = 1.2.3-beta', true],
-    ['1.2.3-beta+build', ' = 1.2.3-beta+otherbuild', true],
-    ['1.2.3+build', ' = 1.2.3+otherbuild', true],
-    ['1.2.3-beta+build', '1.2.3-beta+otherbuild'],
-    ['1.2.3+build', '1.2.3+otherbuild'],
-    ['  v1.2.3+build', '1.2.3+otherbuild']
-  ].forEach(function(v) {
-    var v0 = v[0];
-    var v1 = v[1];
-    var loose = v[2];
-    t.ok(eq(v0, v1, loose), "eq('" + v0 + "', '" + v1 + "')");
-    t.ok(!neq(v0, v1, loose), "!neq('" + v0 + "', '" + v1 + "')");
-    t.ok(cmp(v0, '==', v1, loose), 'cmp(' + v0 + '==' + v1 + ')');
-    t.ok(!cmp(v0, '!=', v1, loose), '!cmp(' + v0 + '!=' + v1 + ')');
-    t.ok(!cmp(v0, '===', v1, loose), '!cmp(' + v0 + '===' + v1 + ')');
-    t.ok(cmp(v0, '!==', v1, loose), 'cmp(' + v0 + '!==' + v1 + ')');
-    t.ok(!gt(v0, v1, loose), "!gt('" + v0 + "', '" + v1 + "')");
-    t.ok(gte(v0, v1, loose), "gte('" + v0 + "', '" + v1 + "')");
-    t.ok(!lt(v0, v1, loose), "!lt('" + v0 + "', '" + v1 + "')");
-    t.ok(lte(v0, v1, loose), "lte('" + v0 + "', '" + v1 + "')");
-  });
-  t.end();
-});
-
-
-test('\nrange tests', function(t) {
-  // [range, version]
-  // version should be included by range
-  [['1.0.0 - 2.0.0', '1.2.3'],
-    ['1.0.0', '1.0.0'],
-    ['>=*', '0.2.4'],
-    ['', '1.0.0'],
-    ['*', '1.2.3'],
-    ['*', 'v1.2.3-foo', true],
-    ['>=1.0.0', '1.0.0'],
-    ['>=1.0.0', '1.0.1'],
-    ['>=1.0.0', '1.1.0'],
-    ['>1.0.0', '1.0.1'],
-    ['>1.0.0', '1.1.0'],
-    ['<=2.0.0', '2.0.0'],
-    ['<=2.0.0', '1.9999.9999'],
-    ['<=2.0.0', '0.2.9'],
-    ['<2.0.0', '1.9999.9999'],
-    ['<2.0.0', '0.2.9'],
-    ['>= 1.0.0', '1.0.0'],
-    ['>=  1.0.0', '1.0.1'],
-    ['>=   1.0.0', '1.1.0'],
-    ['> 1.0.0', '1.0.1'],
-    ['>  1.0.0', '1.1.0'],
-    ['<=   2.0.0', '2.0.0'],
-    ['<= 2.0.0', '1.9999.9999'],
-    ['<=  2.0.0', '0.2.9'],
-    ['<    2.0.0', '1.9999.9999'],
-    ['<\t2.0.0', '0.2.9'],
-    ['>=0.1.97', 'v0.1.97', true],
-    ['>=0.1.97', '0.1.97'],
-    ['0.1.20 || 1.2.4', '1.2.4'],
-    ['>=0.2.3 || <0.0.1', '0.0.0'],
-    ['>=0.2.3 || <0.0.1', '0.2.3'],
-    ['>=0.2.3 || <0.0.1', '0.2.4'],
-    ['||', '1.3.4'],
-    ['2.x.x', '2.1.3'],
-    ['1.2.x', '1.2.3'],
-    ['1.2.x || 2.x', '2.1.3'],
-    ['1.2.x || 2.x', '1.2.3'],
-    ['x', '1.2.3'],
-    ['2.*.*', '2.1.3'],
-    ['1.2.*', '1.2.3'],
-    ['1.2.* || 2.*', '2.1.3'],
-    ['1.2.* || 2.*', '1.2.3'],
-    ['*', '1.2.3'],
-    ['2', '2.1.2'],
-    ['2.3', '2.3.1'],
-    ['~2.4', '2.4.0'], // >=2.4.0 <2.5.0
-    ['~2.4', '2.4.5'],
-    ['~>3.2.1', '3.2.2'], // >=3.2.1 <3.3.0,
-    ['~1', '1.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '1.2.3'],
-    ['~> 1', '1.2.3'],
-    ['~1.0', '1.0.2'], // >=1.0.0 <1.1.0,
-    ['~ 1.0', '1.0.2'],
-    ['~ 1.0.3', '1.0.12'],
-    ['>=1', '1.0.0'],
-    ['>= 1', '1.0.0'],
-    ['<1.2', '1.1.1'],
-    ['< 1.2', '1.1.1'],
-    ['1', '1.0.0beta', true],
-    ['~v0.5.4-pre', '0.5.5'],
-    ['~v0.5.4-pre', '0.5.4'],
-    ['=0.7.x', '0.7.2'],
-    ['>=0.7.x', '0.7.2'],
-    ['=0.7.x', '0.7.0-asdf'],
-    ['>=0.7.x', '0.7.0-asdf'],
-    ['<=0.7.x', '0.6.2'],
-    ['~1.2.1 >=1.2.3', '1.2.3'],
-    ['~1.2.1 =1.2.3', '1.2.3'],
-    ['~1.2.1 1.2.3', '1.2.3'],
-    ['~1.2.1 >=1.2.3 1.2.3', '1.2.3'],
-    ['~1.2.1 1.2.3 >=1.2.3', '1.2.3'],
-    ['~1.2.1 1.2.3', '1.2.3'],
-    ['>=1.2.1 1.2.3', '1.2.3'],
-    ['1.2.3 >=1.2.1', '1.2.3'],
-    ['>=1.2.3 >=1.2.1', '1.2.3'],
-    ['>=1.2.1 >=1.2.3', '1.2.3'],
-    ['<=1.2.3', '1.2.3-beta'],
-    ['>1.2', '1.3.0-beta'],
-    ['>=1.2', '1.2.8'],
-    ['^1.2.3', '1.8.1'],
-    ['^1.2.3', '1.2.3-beta'],
-    ['^0.1.2', '0.1.2'],
-    ['^0.1', '0.1.2'],
-    ['^1.2', '1.4.2'],
-    ['^1.2 ^1', '1.4.2'],
-    ['^1.2', '1.2.0-pre'],
-    ['^1.2.3', '1.2.3-pre']
-  ].forEach(function(v) {
-    var range = v[0];
-    var ver = v[1];
-    var loose = v[2];
-    t.ok(satisfies(ver, range, loose), range + ' satisfied by ' + ver);
-  });
-  t.end();
-});
-
-test('\nnegative range tests', function(t) {
-  // [range, version]
-  // version should not be included by range
-  [['1.0.0 - 2.0.0', '2.2.3'],
-    ['1.0.0', '1.0.1'],
-    ['>=1.0.0', '0.0.0'],
-    ['>=1.0.0', '0.0.1'],
-    ['>=1.0.0', '0.1.0'],
-    ['>1.0.0', '0.0.1'],
-    ['>1.0.0', '0.1.0'],
-    ['<=2.0.0', '3.0.0'],
-    ['<=2.0.0', '2.9999.9999'],
-    ['<=2.0.0', '2.2.9'],
-    ['<2.0.0', '2.9999.9999'],
-    ['<2.0.0', '2.2.9'],
-    ['>=0.1.97', 'v0.1.93', true],
-    ['>=0.1.97', '0.1.93'],
-    ['0.1.20 || 1.2.4', '1.2.3'],
-    ['>=0.2.3 || <0.0.1', '0.0.3'],
-    ['>=0.2.3 || <0.0.1', '0.2.2'],
-    ['2.x.x', '1.1.3'],
-    ['2.x.x', '3.1.3'],
-    ['1.2.x', '1.3.3'],
-    ['1.2.x || 2.x', '3.1.3'],
-    ['1.2.x || 2.x', '1.1.3'],
-    ['2.*.*', '1.1.3'],
-    ['2.*.*', '3.1.3'],
-    ['1.2.*', '1.3.3'],
-    ['1.2.* || 2.*', '3.1.3'],
-    ['1.2.* || 2.*', '1.1.3'],
-    ['2', '1.1.2'],
-    ['2.3', '2.4.1'],
-    ['~2.4', '2.5.0'], // >=2.4.0 <2.5.0
-    ['~2.4', '2.3.9'],
-    ['~>3.2.1', '3.3.2'], // >=3.2.1 <3.3.0
-    ['~>3.2.1', '3.2.0'], // >=3.2.1 <3.3.0
-    ['~1', '0.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '2.2.3'],
-    ['~1.0', '1.1.0'], // >=1.0.0 <1.1.0
-    ['<1', '1.0.0'],
-    ['>=1.2', '1.1.1'],
-    ['1', '2.0.0beta', true],
-    ['~v0.5.4-beta', '0.5.4-alpha'],
-    ['<1', '1.0.0beta', true],
-    ['< 1', '1.0.0beta', true],
-    ['=0.7.x', '0.8.2'],
-    ['>=0.7.x', '0.6.2'],
-    ['<=0.7.x', '0.7.2'],
-    ['<1.2.3', '1.2.3-beta'],
-    ['=1.2.3', '1.2.3-beta'],
-    ['>1.2', '1.2.8'],
-    ['^1.2.3', '2.0.0-alpha'],
-    ['^1.2.3', '1.2.2'],
-    ['^1.2', '1.1.9'],
-    // invalid ranges never satisfied!
-    ['blerg', '1.2.3'],
-    ['git+https://user:password0123@github.com/foo', '123.0.0', true],
-    ['^1.2.3', '2.0.0-pre']
-  ].forEach(function(v) {
-    var range = v[0];
-    var ver = v[1];
-    var loose = v[2];
-    var found = satisfies(ver, range, loose);
-    t.ok(!found, ver + ' not satisfied by ' + range);
-  });
-  t.end();
-});
-
-test('\nincrement versions test', function(t) {
-  // [version, inc, result]
-  // inc(version, inc) -> result
-  [['1.2.3', 'major', '2.0.0'],
-    ['1.2.3', 'minor', '1.3.0'],
-    ['1.2.3', 'patch', '1.2.4'],
-    ['1.2.3tag', 'major', '2.0.0', true],
-    ['1.2.3-tag', 'major', '2.0.0'],
-    ['1.2.3', 'fake', null],
-    ['1.2.0-0', 'patch', '1.2.0'],
-    ['fake', 'major', null],
-    ['1.2.3-4', 'major', '2.0.0'],
-    ['1.2.3-4', 'minor', '1.3.0'],
-    ['1.2.3-4', 'patch', '1.2.3'],
-    ['1.2.3-alpha.0.beta', 'major', '2.0.0'],
-    ['1.2.3-alpha.0.beta', 'minor', '1.3.0'],
-    ['1.2.3-alpha.0.beta', 'patch', '1.2.3'],
-    ['1.2.4', 'prerelease', '1.2.5-0'],
-    ['1.2.3-0', 'prerelease', '1.2.3-1'],
-    ['1.2.3-alpha.0', 'prerelease', '1.2.3-alpha.1'],
-    ['1.2.3-alpha.1', 'prerelease', '1.2.3-alpha.2'],
-    ['1.2.3-alpha.2', 'prerelease', '1.2.3-alpha.3'],
-    ['1.2.3-alpha.0.beta', 'prerelease', '1.2.3-alpha.1.beta'],
-    ['1.2.3-alpha.1.beta', 'prerelease', '1.2.3-alpha.2.beta'],
-    ['1.2.3-alpha.2.beta', 'prerelease', '1.2.3-alpha.3.beta'],
-    ['1.2.3-alpha.10.0.beta', 'prerelease', '1.2.3-alpha.10.1.beta'],
-    ['1.2.3-alpha.10.1.beta', 'prerelease', '1.2.3-alpha.10.2.beta'],
-    ['1.2.3-alpha.10.2.beta', 'prerelease', '1.2.3-alpha.10.3.beta'],
-    ['1.2.3-alpha.10.beta.0', 'prerelease', '1.2.3-alpha.10.beta.1'],
-    ['1.2.3-alpha.10.beta.1', 'prerelease', '1.2.3-alpha.10.beta.2'],
-    ['1.2.3-alpha.10.beta.2', 'prerelease', '1.2.3-alpha.10.beta.3'],
-    ['1.2.3-alpha.9.beta', 'prerelease', '1.2.3-alpha.10.beta'],
-    ['1.2.3-alpha.10.beta', 'prerelease', '1.2.3-alpha.11.beta'],
-    ['1.2.3-alpha.11.beta', 'prerelease', '1.2.3-alpha.12.beta'],
-    ['1.2.0', 'preminor', '1.3.0-0'],
-    ['1.2.0', 'premajor', '2.0.0-0'],
-    ['1.2.0', 'preminor', '1.3.0-0'],
-    ['1.2.0', 'premajor', '2.0.0-0']
-
-
-  ].forEach(function(v) {
-    var pre = v[0];
-    var what = v[1];
-    var wanted = v[2];
-    var loose = v[3];
-    var found = inc(pre, what, loose);
-    t.equal(found, wanted, 'inc(' + pre + ', ' + what + ') === ' + wanted);
-  });
-
-  t.end();
-});
-
-test('\nvalid range test', function(t) {
-  // [range, result]
-  // validRange(range) -> result
-  // translate ranges into their canonical form
-  [['1.0.0 - 2.0.0', '>=1.0.0 <=2.0.0'],
-    ['1.0.0', '1.0.0'],
-    ['>=*', '>=0.0.0-0'],
-    ['', '*'],
-    ['*', '*'],
-    ['*', '*'],
-    ['>=1.0.0', '>=1.0.0'],
-    ['>1.0.0', '>1.0.0'],
-    ['<=2.0.0', '<=2.0.0'],
-    ['1', '>=1.0.0-0 <2.0.0-0'],
-    ['<=2.0.0', '<=2.0.0'],
-    ['<=2.0.0', '<=2.0.0'],
-    ['<2.0.0', '<2.0.0-0'],
-    ['<2.0.0', '<2.0.0-0'],
-    ['>= 1.0.0', '>=1.0.0'],
-    ['>=  1.0.0', '>=1.0.0'],
-    ['>=   1.0.0', '>=1.0.0'],
-    ['> 1.0.0', '>1.0.0'],
-    ['>  1.0.0', '>1.0.0'],
-    ['<=   2.0.0', '<=2.0.0'],
-    ['<= 2.0.0', '<=2.0.0'],
-    ['<=  2.0.0', '<=2.0.0'],
-    ['<    2.0.0', '<2.0.0-0'],
-    ['<	2.0.0', '<2.0.0-0'],
-    ['>=0.1.97', '>=0.1.97'],
-    ['>=0.1.97', '>=0.1.97'],
-    ['0.1.20 || 1.2.4', '0.1.20||1.2.4'],
-    ['>=0.2.3 || <0.0.1', '>=0.2.3||<0.0.1-0'],
-    ['>=0.2.3 || <0.0.1', '>=0.2.3||<0.0.1-0'],
-    ['>=0.2.3 || <0.0.1', '>=0.2.3||<0.0.1-0'],
-    ['||', '||'],
-    ['2.x.x', '>=2.0.0-0 <3.0.0-0'],
-    ['1.2.x', '>=1.2.0-0 <1.3.0-0'],
-    ['1.2.x || 2.x', '>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0'],
-    ['1.2.x || 2.x', '>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0'],
-    ['x', '*'],
-    ['2.*.*', '>=2.0.0-0 <3.0.0-0'],
-    ['1.2.*', '>=1.2.0-0 <1.3.0-0'],
-    ['1.2.* || 2.*', '>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0'],
-    ['*', '*'],
-    ['2', '>=2.0.0-0 <3.0.0-0'],
-    ['2.3', '>=2.3.0-0 <2.4.0-0'],
-    ['~2.4', '>=2.4.0-0 <2.5.0-0'],
-    ['~2.4', '>=2.4.0-0 <2.5.0-0'],
-    ['~>3.2.1', '>=3.2.1-0 <3.3.0-0'],
-    ['~1', '>=1.0.0-0 <2.0.0-0'],
-    ['~>1', '>=1.0.0-0 <2.0.0-0'],
-    ['~> 1', '>=1.0.0-0 <2.0.0-0'],
-    ['~1.0', '>=1.0.0-0 <1.1.0-0'],
-    ['~ 1.0', '>=1.0.0-0 <1.1.0-0'],
-    ['^0', '>=0.0.0-0 <1.0.0-0'],
-    ['^ 1', '>=1.0.0-0 <2.0.0-0'],
-    ['^0.1', '>=0.1.0-0 <0.2.0-0'],
-    ['^1.0', '>=1.0.0-0 <2.0.0-0'],
-    ['^1.2', '>=1.2.0-0 <2.0.0-0'],
-    ['^0.0.1', '=0.0.1'],
-    ['^0.0.1-beta', '=0.0.1-beta'],
-    ['^0.1.2', '>=0.1.2-0 <0.2.0-0'],
-    ['^1.2.3', '>=1.2.3-0 <2.0.0-0'],
-    ['^1.2.3-beta.4', '>=1.2.3-beta.4 <2.0.0-0'],
-    ['<1', '<1.0.0-0'],
-    ['< 1', '<1.0.0-0'],
-    ['>=1', '>=1.0.0-0'],
-    ['>= 1', '>=1.0.0-0'],
-    ['<1.2', '<1.2.0-0'],
-    ['< 1.2', '<1.2.0-0'],
-    ['1', '>=1.0.0-0 <2.0.0-0'],
-    ['>01.02.03', '>1.2.3', true],
-    ['>01.02.03', null],
-    ['~1.2.3beta', '>=1.2.3-beta <1.3.0-0', true],
-    ['~1.2.3beta', null],
-    ['^ 1.2 ^ 1', '>=1.2.0-0 <2.0.0-0 >=1.0.0-0 <2.0.0-0']
-  ].forEach(function(v) {
-    var pre = v[0];
-    var wanted = v[1];
-    var loose = v[2];
-    var found = validRange(pre, loose);
-
-    t.equal(found, wanted, 'validRange(' + pre + ') === ' + wanted);
-  });
-
-  t.end();
-});
-
-test('\ncomparators test', function(t) {
-  // [range, comparators]
-  // turn range into a set of individual comparators
-  [['1.0.0 - 2.0.0', [['>=1.0.0', '<=2.0.0']]],
-    ['1.0.0', [['1.0.0']]],
-    ['>=*', [['>=0.0.0-0']]],
-    ['', [['']]],
-    ['*', [['']]],
-    ['*', [['']]],
-    ['>=1.0.0', [['>=1.0.0']]],
-    ['>=1.0.0', [['>=1.0.0']]],
-    ['>=1.0.0', [['>=1.0.0']]],
-    ['>1.0.0', [['>1.0.0']]],
-    ['>1.0.0', [['>1.0.0']]],
-    ['<=2.0.0', [['<=2.0.0']]],
-    ['1', [['>=1.0.0-0', '<2.0.0-0']]],
-    ['<=2.0.0', [['<=2.0.0']]],
-    ['<=2.0.0', [['<=2.0.0']]],
-    ['<2.0.0', [['<2.0.0-0']]],
-    ['<2.0.0', [['<2.0.0-0']]],
-    ['>= 1.0.0', [['>=1.0.0']]],
-    ['>=  1.0.0', [['>=1.0.0']]],
-    ['>=   1.0.0', [['>=1.0.0']]],
-    ['> 1.0.0', [['>1.0.0']]],
-    ['>  1.0.0', [['>1.0.0']]],
-    ['<=   2.0.0', [['<=2.0.0']]],
-    ['<= 2.0.0', [['<=2.0.0']]],
-    ['<=  2.0.0', [['<=2.0.0']]],
-    ['<    2.0.0', [['<2.0.0-0']]],
-    ['<\t2.0.0', [['<2.0.0-0']]],
-    ['>=0.1.97', [['>=0.1.97']]],
-    ['>=0.1.97', [['>=0.1.97']]],
-    ['0.1.20 || 1.2.4', [['0.1.20'], ['1.2.4']]],
-    ['>=0.2.3 || <0.0.1', [['>=0.2.3'], ['<0.0.1-0']]],
-    ['>=0.2.3 || <0.0.1', [['>=0.2.3'], ['<0.0.1-0']]],
-    ['>=0.2.3 || <0.0.1', [['>=0.2.3'], ['<0.0.1-0']]],
-    ['||', [[''], ['']]],
-    ['2.x.x', [['>=2.0.0-0', '<3.0.0-0']]],
-    ['1.2.x', [['>=1.2.0-0', '<1.3.0-0']]],
-    ['1.2.x || 2.x', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
-    ['1.2.x || 2.x', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
-    ['x', [['']]],
-    ['2.*.*', [['>=2.0.0-0', '<3.0.0-0']]],
-    ['1.2.*', [['>=1.2.0-0', '<1.3.0-0']]],
-    ['1.2.* || 2.*', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
-    ['1.2.* || 2.*', [['>=1.2.0-0', '<1.3.0-0'], ['>=2.0.0-0', '<3.0.0-0']]],
-    ['*', [['']]],
-    ['2', [['>=2.0.0-0', '<3.0.0-0']]],
-    ['2.3', [['>=2.3.0-0', '<2.4.0-0']]],
-    ['~2.4', [['>=2.4.0-0', '<2.5.0-0']]],
-    ['~2.4', [['>=2.4.0-0', '<2.5.0-0']]],
-    ['~>3.2.1', [['>=3.2.1-0', '<3.3.0-0']]],
-    ['~1', [['>=1.0.0-0', '<2.0.0-0']]],
-    ['~>1', [['>=1.0.0-0', '<2.0.0-0']]],
-    ['~> 1', [['>=1.0.0-0', '<2.0.0-0']]],
-    ['~1.0', [['>=1.0.0-0', '<1.1.0-0']]],
-    ['~ 1.0', [['>=1.0.0-0', '<1.1.0-0']]],
-    ['~ 1.0.3', [['>=1.0.3-0', '<1.1.0-0']]],
-    ['~> 1.0.3', [['>=1.0.3-0', '<1.1.0-0']]],
-    ['<1', [['<1.0.0-0']]],
-    ['< 1', [['<1.0.0-0']]],
-    ['>=1', [['>=1.0.0-0']]],
-    ['>= 1', [['>=1.0.0-0']]],
-    ['<1.2', [['<1.2.0-0']]],
-    ['< 1.2', [['<1.2.0-0']]],
-    ['1', [['>=1.0.0-0', '<2.0.0-0']]],
-    ['1 2', [['>=1.0.0-0', '<2.0.0-0', '>=2.0.0-0', '<3.0.0-0']]],
-    ['1.2 - 3.4.5', [['>=1.2.0-0', '<=3.4.5']]],
-    ['1.2.3 - 3.4', [['>=1.2.3', '<3.5.0-0']]]
-  ].forEach(function(v) {
-    var pre = v[0];
-    var wanted = v[1];
-    var found = toComparators(v[0]);
-    var jw = JSON.stringify(wanted);
-    t.equivalent(found, wanted, 'toComparators(' + pre + ') === ' + jw);
-  });
-
-  t.end();
-});
-
-test('\ninvalid version numbers', function(t) {
-  ['1.2.3.4',
-   'NOT VALID',
-   1.2,
-   null,
-   'Infinity.NaN.Infinity'
-  ].forEach(function(v) {
-    t.throws(function() {
-      new SemVer(v);
-    }, {name:'TypeError', message:'Invalid Version: ' + v});
-  });
-
-  t.end();
-});
-
-test('\nstrict vs loose version numbers', function(t) {
-  [['=1.2.3', '1.2.3'],
-    ['01.02.03', '1.2.3'],
-    ['1.2.3-beta.01', '1.2.3-beta.1'],
-    ['   =1.2.3', '1.2.3'],
-    ['1.2.3foo', '1.2.3-foo']
-  ].forEach(function(v) {
-    var loose = v[0];
-    var strict = v[1];
-    t.throws(function() {
-      new SemVer(loose);
-    });
-    var lv = new SemVer(loose, true);
-    t.equal(lv.version, strict);
-    t.ok(eq(loose, strict, true));
-    t.throws(function() {
-      eq(loose, strict);
-    });
-    t.throws(function() {
-      new SemVer(strict).compare(loose);
-    });
-  });
-  t.end();
-});
-
-test('\nstrict vs loose ranges', function(t) {
-  [['>=01.02.03', '>=1.2.3'],
-    ['~1.02.03beta', '>=1.2.3-beta <1.3.0-0']
-  ].forEach(function(v) {
-    var loose = v[0];
-    var comps = v[1];
-    t.throws(function() {
-      new Range(loose);
-    });
-    t.equal(new Range(loose, true).range, comps);
-  });
-  t.end();
-});
-
-test('\nmax satisfying', function(t) {
-  [[['1.2.3', '1.2.4'], '1.2', '1.2.4'],
-    [['1.2.4', '1.2.3'], '1.2', '1.2.4'],
-    [['1.2.3', '1.2.4', '1.2.5', '1.2.6'], '~1.2.3', '1.2.6'],
-    [['1.1.0', '1.2.0', '1.2.1', '1.3.0', '2.0.0b1', '2.0.0b2', '2.0.0b3', '2.0.0', '2.1.0'], '~2.0.0', '2.0.0', true]
-  ].forEach(function(v) {
-    var versions = v[0];
-    var range = v[1];
-    var expect = v[2];
-    var loose = v[3];
-    var actual = semver.maxSatisfying(versions, range, loose);
-    t.equal(actual, expect);
-  });
-  t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/ltr.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/ltr.js
deleted file mode 100644
index a4f503a3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/ltr.js
+++ /dev/null
@@ -1,174 +0,0 @@
-var tap = require('tap');
-var test = tap.test;
-var semver = require('../semver.js');
-var ltr = semver.ltr;
-
-test('\nltr tests', function(t) {
-  // [range, version, loose]
-  // Version should be less than range
-  [
-    ['~1.2.2', '1.2.1'],
-    ['~0.6.1-1', '0.6.1-0'],
-    ['1.0.0 - 2.0.0', '0.0.1'],
-    ['1.0.0-beta.2', '1.0.0-beta.1'],
-    ['1.0.0', '0.0.0'],
-    ['>=2.0.0', '1.1.1'],
-    ['>=2.0.0', '1.2.9'],
-    ['>2.0.0', '2.0.0'],
-    ['0.1.20 || 1.2.4', '0.1.5'],
-    ['2.x.x', '1.0.0'],
-    ['1.2.x', '1.1.0'],
-    ['1.2.x || 2.x', '1.0.0'],
-    ['2.*.*', '1.0.1'],
-    ['1.2.*', '1.1.3'],
-    ['1.2.* || 2.*', '1.1.9999'],
-    ['2', '1.0.0'],
-    ['2.3', '2.2.2'],
-    ['~2.4', '2.3.0'], // >=2.4.0 <2.5.0
-    ['~2.4', '2.3.5'],
-    ['~>3.2.1', '3.2.0'], // >=3.2.1 <3.3.0
-    ['~1', '0.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '0.2.4'],
-    ['~> 1', '0.2.3'],
-    ['~1.0', '0.1.2'], // >=1.0.0 <1.1.0
-    ['~ 1.0', '0.1.0'],
-    ['>1.2', '1.2.0'],
-    ['> 1.2', '1.2.1'],
-    ['1', '0.0.0beta', true],
-    ['~v0.5.4-pre', '0.5.4-alpha'],
-    ['~v0.5.4-pre', '0.5.4-alpha'],
-    ['=0.7.x', '0.6.0'],
-    ['=0.7.x', '0.6.0-asdf'],
-    ['>=0.7.x', '0.6.0'],
-    ['~1.2.2', '1.2.1'],
-    ['1.0.0 - 2.0.0', '0.2.3'],
-    ['1.0.0', '0.0.1'],
-    ['>=2.0.0', '1.0.0'],
-    ['>=2.0.0', '1.9999.9999'],
-    ['>=2.0.0', '1.2.9'],
-    ['>2.0.0', '2.0.0'],
-    ['>2.0.0', '1.2.9'],
-    ['2.x.x', '1.1.3'],
-    ['1.2.x', '1.1.3'],
-    ['1.2.x || 2.x', '1.1.3'],
-    ['2.*.*', '1.1.3'],
-    ['1.2.*', '1.1.3'],
-    ['1.2.* || 2.*', '1.1.3'],
-    ['2', '1.9999.9999'],
-    ['2.3', '2.2.1'],
-    ['~2.4', '2.3.0'], // >=2.4.0 <2.5.0
-    ['~>3.2.1', '2.3.2'], // >=3.2.1 <3.3.0
-    ['~1', '0.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '0.2.3'],
-    ['~1.0', '0.0.0'], // >=1.0.0 <1.1.0
-    ['>1', '1.0.0'],
-    ['2', '1.0.0beta', true],
-    ['>1', '1.0.0beta', true],
-    ['> 1', '1.0.0beta', true],
-    ['=0.7.x', '0.6.2'],
-    ['>=0.7.x', '0.6.2']
-  ].forEach(function(tuple) {
-    var range = tuple[0];
-    var version = tuple[1];
-    var loose = tuple[2] || false;
-    var msg = 'ltr(' + version + ', ' + range + ', ' + loose + ')';
-    t.ok(ltr(version, range, loose), msg);
-  });
-  t.end();
-});
-
-test('\nnegative ltr tests', function(t) {
-  // [range, version, loose]
-  // Version should NOT be greater than range
-  [
-    ['~ 1.0', '1.1.0'],
-    ['~0.6.1-1', '0.6.1-1'],
-    ['1.0.0 - 2.0.0', '1.2.3'],
-    ['1.0.0 - 2.0.0', '2.9.9'],
-    ['1.0.0', '1.0.0'],
-    ['>=*', '0.2.4'],
-    ['', '1.0.0', true],
-    ['*', '1.2.3'],
-    ['*', 'v1.2.3-foo'],
-    ['>=1.0.0', '1.0.0'],
-    ['>=1.0.0', '1.0.1'],
-    ['>=1.0.0', '1.1.0'],
-    ['>1.0.0', '1.0.1'],
-    ['>1.0.0', '1.1.0'],
-    ['<=2.0.0', '2.0.0'],
-    ['<=2.0.0', '1.9999.9999'],
-    ['<=2.0.0', '0.2.9'],
-    ['<2.0.0', '1.9999.9999'],
-    ['<2.0.0', '0.2.9'],
-    ['>= 1.0.0', '1.0.0'],
-    ['>=  1.0.0', '1.0.1'],
-    ['>=   1.0.0', '1.1.0'],
-    ['> 1.0.0', '1.0.1'],
-    ['>  1.0.0', '1.1.0'],
-    ['<=   2.0.0', '2.0.0'],
-    ['<= 2.0.0', '1.9999.9999'],
-    ['<=  2.0.0', '0.2.9'],
-    ['<    2.0.0', '1.9999.9999'],
-    ['<\t2.0.0', '0.2.9'],
-    ['>=0.1.97', 'v0.1.97'],
-    ['>=0.1.97', '0.1.97'],
-    ['0.1.20 || 1.2.4', '1.2.4'],
-    ['0.1.20 || >1.2.4', '1.2.4'],
-    ['0.1.20 || 1.2.4', '1.2.3'],
-    ['0.1.20 || 1.2.4', '0.1.20'],
-    ['>=0.2.3 || <0.0.1', '0.0.0'],
-    ['>=0.2.3 || <0.0.1', '0.2.3'],
-    ['>=0.2.3 || <0.0.1', '0.2.4'],
-    ['||', '1.3.4'],
-    ['2.x.x', '2.1.3'],
-    ['1.2.x', '1.2.3'],
-    ['1.2.x || 2.x', '2.1.3'],
-    ['1.2.x || 2.x', '1.2.3'],
-    ['x', '1.2.3'],
-    ['2.*.*', '2.1.3'],
-    ['1.2.*', '1.2.3'],
-    ['1.2.* || 2.*', '2.1.3'],
-    ['1.2.* || 2.*', '1.2.3'],
-    ['1.2.* || 2.*', '1.2.3'],
-    ['*', '1.2.3'],
-    ['2', '2.1.2'],
-    ['2.3', '2.3.1'],
-    ['~2.4', '2.4.0'], // >=2.4.0 <2.5.0
-    ['~2.4', '2.4.5'],
-    ['~>3.2.1', '3.2.2'], // >=3.2.1 <3.3.0
-    ['~1', '1.2.3'], // >=1.0.0 <2.0.0
-    ['~>1', '1.2.3'],
-    ['~> 1', '1.2.3'],
-    ['~1.0', '1.0.2'], // >=1.0.0 <1.1.0
-    ['~ 1.0', '1.0.2'],
-    ['>=1', '1.0.0'],
-    ['>= 1', '1.0.0'],
-    ['<1.2', '1.1.1'],
-    ['< 1.2', '1.1.1'],
-    ['1', '1.0.0beta', true],
-    ['~v0.5.4-pre', '0.5.5'],
-    ['~v0.5.4-pre', '0.5.4'],
-    ['=0.7.x', '0.7.2'],
-    ['>=0.7.x', '0.7.2'],
-    ['=0.7.x', '0.7.0-asdf'],
-    ['>=0.7.x', '0.7.0-asdf'],
-    ['<=0.7.x', '0.6.2'],
-    ['>0.2.3 >0.2.4 <=0.2.5', '0.2.5'],
-    ['>=0.2.3 <=0.2.4', '0.2.4'],
-    ['1.0.0 - 2.0.0', '2.0.0'],
-    ['^1', '1.0.0-0'],
-    ['^3.0.0', '4.0.0'],
-    ['^1.0.0 || ~2.0.1', '2.0.0'],
-    ['^0.1.0 || ~3.0.1 || 5.0.0', '3.2.0'],
-    ['^0.1.0 || ~3.0.1 || 5.0.0', '1.0.0beta', true],
-    ['^0.1.0 || ~3.0.1 || 5.0.0', '5.0.0-0', true],
-    ['^0.1.0 || ~3.0.1 || >4 <=5.0.0', '3.5.0']
-  ].forEach(function(tuple) {
-    var range = tuple[0];
-    var version = tuple[1];
-    var loose = tuple[2] || false;
-    var msg = '!ltr(' + version + ', ' + range + ', ' + loose + ')';
-    t.notOk(ltr(version, range, loose), msg);
-  });
-  t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/no-module.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/no-module.js
deleted file mode 100644
index 96d1cd1f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/semver/test/no-module.js
+++ /dev/null
@@ -1,19 +0,0 @@
-var tap = require('tap');
-var test = tap.test;
-
-test('no module system', function(t) {
-  var fs = require('fs');
-  var vm = require('vm');
-  var head = fs.readFileSync(require.resolve('../head.js'), 'utf8');
-  var src = fs.readFileSync(require.resolve('../'), 'utf8');
-  var foot = fs.readFileSync(require.resolve('../foot.js'), 'utf8');
-  vm.runInThisContext(head + src + foot, 'semver.js');
-
-  // just some basic poking to see if it did some stuff
-  t.type(global.semver, 'object');
-  t.type(global.semver.SemVer, 'function');
-  t.type(global.semver.Range, 'function');
-  t.ok(global.semver.satisfies('1.2.3', '1.2'));
-  t.end();
-});
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.npmignore
deleted file mode 100644
index 080b47ee..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.npmignore
+++ /dev/null
@@ -1,14 +0,0 @@
-lib-cov
-*.seed
-*.log
-*.csv
-*.dat
-*.out
-*.pid
-
-pids
-logs
-results
-
-npm-debug.log
-node_modules
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.travis.yml
deleted file mode 100644
index 1d8a1a65..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/.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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/README.md
deleted file mode 100644
index 135424bb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Tar Pack
-
-Package and un-package modules of some sort (in tar/gz bundles).  This is mostly useful for package managers.  Note that it doesn't check for or touch `package.json` so it can be used even if that's not the way you store your package info.
-
-[![Build Status](https://travis-ci.org/ForbesLindesay/tar-pack.png?branch=master)](https://travis-ci.org/ForbesLindesay/tar-pack)
-[![Dependency Status](https://gemnasium.com/ForbesLindesay/tar-pack.png)](https://gemnasium.com/ForbesLindesay/tar-pack)
-[![NPM version](https://badge.fury.io/js/tar-pack.png)](http://badge.fury.io/js/tar-pack)
-
-## Installation
-
-    $ npm install tar-pack
-
-## API
-
-### pack(folder|packer, [options])
-
-Pack the folder at `folder` into a gzipped tarball and return the tgz as a stream.  Files ignored by `.gitignore` will not be in the package.
-
-You can optionally pass a `fstream.DirReader` directly, instead of folder.  For example, to create an npm package, do:
-
-```js
-pack(require("fstream-npm")(folder), [options])
-```
-
-Options:
-
- - `noProprietary` (defaults to `false`) Set this to `true` to prevent any proprietary attributes being added to the tarball.  These attributes are allowed by the spec, but may trip up some poorly written tarball parsers.
- - `ignoreFiles` (defaults to `['.gitignore']`) These files can specify files to be excluded from the package using the syntax of `.gitignore`.  This option is ignored if you parse a `fstream.DirReader` instead of a string for folder.
- - `filter` (defaults to `entry => true`) A function that takes an entry and returns `true` if it should be included in the package and `false` if it should not.  Entryies are of the form `{path, basename, dirname, type}` where (type is "Directory" or "File").  This function is ignored if you parse a `fstream.DirReader` instead of a string for folder.
-
-Example:
-
-```js
-var write = require('fs').createWriteStream
-var pack = require('tar-pack').pack
-pack(process.cwd())
-  .pipe(write(__dirname + '/package.tar.gz'))
-  .on('error', function (err) {
-    console.error(err.stack)
-  })
-  .on('close', function () {
-    console.log('done')
-  })
-```
-
-### unpack(folder, [options,] cb)
-
-Return a stream that unpacks a tarball into a folder at `folder`.  N.B. the output folder will be removed first if it already exists.
-
-The callback is called with an optional error and, as its second argument, a string which is one of:
-
- - `'directory'`, indicating that the extracted package was a directory (either `.tar.gz` or `.tar`)
- - `'file'`, incating that the extracted package was just a single file (extracted to `defaultName`, see options)
-
-Basic Options:
-
- - `defaultName` (defaults to `index.js`) If the package is a single file, rather than a tarball, it will be "extracted" to this file name, set to `false` to disable.
-
-Advanced Options (you probably don't need any of these):
-
- - `gid` - (defaults to `null`) the `gid` to use when writing files
- - `uid` - (defaults to `null`) the `uid` to use when writing files
- - `dmode` - (defaults to `0777`) The mode to use when creating directories
- - `fmode` - (defaults to `0666`) The mode to use when creating files
- - `unsafe` - (defaults to `false`) (on non win32 OSes it overrides `gid` and `uid` with the current processes IDs)
-
-Example:
-
-```js
-var read = require('fs').createReadStream
-var unpack = require('tar-pack').unpack
-read(process.cwd() + '/package.tar.gz')
-  .pipe(unpack(__dirname + '/package/', function (err) {
-    if (err) console.error(err.stack)
-    else console.log('done')
-  }))
-```
-
-## License
-
-  BSD
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/index.js
deleted file mode 100644
index 23b95a90..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/index.js
+++ /dev/null
@@ -1,246 +0,0 @@
-"use strict"
-
-var debug = require('debug')('tar-pack')
-var uidNumber = require('uid-number')
-var rm = require('rimraf')
-var tar = require('tar')
-var once = require('once')
-var fstream = require('fstream')
-var packer = require('fstream-ignore')
-
-var PassThrough = require('stream').PassThrough || require('readable-stream').PassThrough
-var zlib = require('zlib')
-var path = require('path')
-var fs
-try {
-  fs = require('graceful-fs')
-} catch (ex) {
-  fs = require('fs')
-}
-
-var win32 = process.platform === 'win32'
-var myUid = process.getuid && process.getuid()
-var myGid = process.getgid && process.getgid()
-
-if (process.env.SUDO_UID && myUid === 0) {
-  if (!isNaN(process.env.SUDO_UID)) myUid = +process.env.SUDO_UID
-  if (!isNaN(process.env.SUDO_GID)) myGid = +process.env.SUDO_GID
-}
-
-exports.pack = pack
-exports.unpack = unpack
-
-function pack(folder, options) {
-  options = options || {}
-  if (typeof folder === 'string') {
-
-    var filter = options.filter || function (entry) { return true; }
-
-    folder = packer({
-      path: folder,
-      type: 'Directory',
-      isDirectory: true,
-      ignoreFiles: options.ignoreFiles || ['.gitignore'],
-      filter: function (entry) { // {path, basename, dirname, type} (type is "Directory" or "File")
-        var basename = entry.basename
-        // some files are *never* allowed under any circumstances
-        // these files should always be either temporary files or
-        // version control related files
-        if (basename === '.git' || basename === '.lock-wscript' || basename.match(/^\.wafpickle-[0-9]+$/) ||
-            basename === 'CVS' || basename === '.svn' || basename === '.hg' || basename.match(/^\..*\.swp$/) ||
-            basename === '.DS_Store' ||  basename.match(/^\._/)) {
-          return false
-        }
-        //custom excludes
-        return filter(entry)
-      }
-    })
-  }
-  // By default, npm includes some proprietary attributes in the
-  // package tarball.  This is sane, and allowed by the spec.
-  // However, npm *itself* excludes these from its own package,
-  // so that it can be more easily bootstrapped using old and
-  // non-compliant tar implementations.
-  var tarPack = tar.Pack({ noProprietary: options.noProprietary || false })
-  var gzip = zlib.Gzip()
-
-  folder
-    .on('error', function (er) {
-      if (er) debug('Error reading folder')
-      return gzip.emit('error', er)
-    })
-  tarPack
-    .on('error', function (er) {
-      if (er) debug('tar creation error')
-      gzip.emit('error', er)
-    })
-  return folder.pipe(tarPack).pipe(gzip)
-}
-
-function unpack(unpackTarget, options, cb) {
-  if (typeof options === 'function' && cb === undefined) cb = options, options = undefined
-
-  var tarball = new PassThrough()
-  if (typeof cb === 'function') {
-    cb = once(cb)
-    tarball.on('error', cb)
-    tarball.on('close', function () {
-      cb()
-    })
-  }
-
-  var parent = path.dirname(unpackTarget)
-  var base = path.basename(unpackTarget)
-
-  options = options || {}
-  var gid = options.gid || null
-  var uid = options.uid || null
-  var dMode = options.dmode || 0x0777 //npm.modes.exec
-  var fMode = options.fmode || 0x0666 //npm.modes.file
-  var defaultName = options.defaultName || (options.defaultName === false ? false : 'index.js')
-
-  // figure out who we're supposed to be, if we're not pretending
-  // to be a specific user.
-  if (options.unsafe && !win32) {
-    uid = myUid
-    gid = myGid
-  }
-
-  var pending = 2
-  uidNumber(uid, gid, function (er, uid, gid) {
-    if (er) {
-      tarball.emit('error', er)
-      return tarball.end()
-    }
-    if (0 === --pending) next()
-  })
-  rm(unpackTarget, function (er) {
-    if (er) {
-      tarball.emit('error', er)
-      return tarball.end()
-    }
-    if (0 === --pending) next()
-  })
-  function next() {
-    // gzip {tarball} --decompress --stdout \
-    //   | tar -mvxpf - --strip-components=1 -C {unpackTarget}
-    gunzTarPerm(tarball, unpackTarget, dMode, fMode, uid, gid, defaultName)
-  }
-  return tarball
-}
-
-
-function gunzTarPerm(tarball, target, dMode, fMode, uid, gid, defaultName) {
-  debug('modes %j', [dMode.toString(8), fMode.toString(8)])
-
-  function fixEntry(entry) {
-    debug('fixEntry %j', entry.path)
-    // never create things that are user-unreadable,
-    // or dirs that are user-un-listable. Only leads to headaches.
-    var originalMode = entry.mode = entry.mode || entry.props.mode
-    entry.mode = entry.mode | (entry.type === 'Directory' ? dMode : fMode)
-    entry.props.mode = entry.mode
-    if (originalMode !== entry.mode) {
-      debug('modified mode %j', [entry.path, originalMode, entry.mode])
-    }
-
-    // if there's a specific owner uid/gid that we want, then set that
-    if (!win32 &&  typeof uid === 'number' && typeof gid === 'number') {
-      entry.props.uid = entry.uid = uid
-      entry.props.gid = entry.gid = gid
-    }
-  }
-
-  var extractOpts = { type: 'Directory', path: target, strip: 1 }
-
-  if (!win32 && typeof uid === 'number' && typeof gid === 'number') {
-    extractOpts.uid = uid
-    extractOpts.gid = gid
-  }
-
-  extractOpts.filter = function () {
-    // symbolic links are not allowed in packages.
-    if (this.type.match(/^.*Link$/)) {
-      debug('excluding symbolic link: ' + this.path.substr(target.length + 1) + ' -> ' + this.linkpath)
-      return false
-    }
-    return true
-  }
-
-
-  type(tarball, function (err, type) {
-    if (err) return tarball.emit('error', err)
-    var strm = tarball
-    if (type === 'gzip') {
-      strm = strm.pipe(zlib.Unzip())
-      strm.on('error', function (er) {
-          if (er) debug('unzip error')
-          tarball.emit('error', er)
-        })
-      type = 'tar'
-    }
-    if (type === 'tar') {
-      strm
-        .pipe(tar.Extract(extractOpts))
-        .on('entry', fixEntry)
-        .on('error', function (er) {
-          if (er) debug('untar error')
-          tarball.emit('error', er)
-        })
-        .on('close', function () {
-          tarball.emit('close')
-        })
-      return
-    }
-    if (type === 'naked-file' && defaultName) {
-      var jsOpts = { path: path.resolve(target, defaultName) }
-
-      if (!win32 && typeof uid === 'number' && typeof gid === 'number') {
-        jsOpts.uid = uid
-        jsOpts.gid = gid
-      }
-
-      strm
-        .pipe(fstream.Writer(jsOpts))
-        .on('error', function (er) {
-          if (er) debug('copy error')
-          tarball.emit('error', er)
-        })
-        .on('close', function () {
-          tarball.emit('close')
-        })
-      return
-    }
-
-    return cb(new Error('Unrecognised package type'));
-  })
-}
-
-function type(stream, callback) {
-  stream.on('error', handle)
-  stream.on('data', parse)
-  function handle(err) {
-    stream.removeListener('data', parse)
-    stream.removeListener('error', handle)
-  }
-  function parse(chunk) {
-    // detect what it is.
-    // Then, depending on that, we'll figure out whether it's
-    // a single-file module, gzipped tarball, or naked tarball.
-
-    // gzipped files all start with 1f8b08
-    if (chunk[0] === 0x1F && chunk[1] === 0x8B && chunk[2] === 0x08) {
-      callback(null, 'gzip')
-    } else if (chunk.toString().match(/^package\/\u0000/)) {
-      // note, this will only pick up on tarballs with a root directory called package
-      callback(null, 'tar')
-    } else {
-      callback(null, 'naked-file')
-    }
-
-    // now un-hook, and re-emit the chunk
-    stream.removeListener('data', parse)
-    stream.removeListener('error', handle)
-    stream.unshift(chunk)
-  }
-}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/Readme.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/Readme.md
deleted file mode 100644
index c5a34e8b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/Readme.md
+++ /dev/null
@@ -1,115 +0,0 @@
-# debug
-
-  tiny node.js debugging utility modelled after node core's debugging technique.
-
-## Installation
-
-```
-$ npm install debug
-```
-
-## Usage
-
- With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.
- 
-Example _app.js_:
-
-```js
-var debug = require('debug')('http')
-  , http = require('http')
-  , name = 'My App';
-
-// fake app
-
-debug('booting %s', name);
-
-http.createServer(function(req, res){
-  debug(req.method + ' ' + req.url);
-  res.end('hello\n');
-}).listen(3000, function(){
-  debug('listening');
-});
-
-// fake worker of some kind
-
-require('./worker');
-```
-
-Example _worker.js_:
-
-```js
-var debug = require('debug')('worker');
-
-setInterval(function(){
-  debug('doing some work');
-}, 1000);
-```
-
- The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
-
-  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
-
-  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
-
-## Millisecond diff
-
-  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
-
-  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
-
-  When stderr is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
-  _(NOTE: Debug now uses stderr instead of stdout, so the correct shell command for this example is actually `DEBUG=* node example/worker 2> out &`)_
-  
-  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
-  
-## Conventions
-
- If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". 
-
-## Wildcards
-
-  The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
-
-  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:".
-
-## Browser support
-
- Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. 
-
-```js
-a = debug('worker:a');
-b = debug('worker:b');
-
-setInterval(function(){
-  a('doing some work');
-}, 1000);
-
-setInterval(function(){
-  a('doing some work');
-}, 1200);
-```
-
-## License 
-
-(The MIT License)
-
-Copyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/debug.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/debug.js
deleted file mode 100644
index 509dc0de..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/debug.js
+++ /dev/null
@@ -1,137 +0,0 @@
-
-/**
- * Expose `debug()` as the module.
- */
-
-module.exports = debug;
-
-/**
- * Create a debugger with the given `name`.
- *
- * @param {String} name
- * @return {Type}
- * @api public
- */
-
-function debug(name) {
-  if (!debug.enabled(name)) return function(){};
-
-  return function(fmt){
-    fmt = coerce(fmt);
-
-    var curr = new Date;
-    var ms = curr - (debug[name] || curr);
-    debug[name] = curr;
-
-    fmt = name
-      + ' '
-      + fmt
-      + ' +' + debug.humanize(ms);
-
-    // This hackery is required for IE8
-    // where `console.log` doesn't have 'apply'
-    window.console
-      && console.log
-      && Function.prototype.apply.call(console.log, console, arguments);
-  }
-}
-
-/**
- * The currently active debug mode names.
- */
-
-debug.names = [];
-debug.skips = [];
-
-/**
- * Enables a debug mode by name. This can include modes
- * separated by a colon and wildcards.
- *
- * @param {String} name
- * @api public
- */
-
-debug.enable = function(name) {
-  try {
-    localStorage.debug = name;
-  } catch(e){}
-
-  var split = (name || '').split(/[\s,]+/)
-    , len = split.length;
-
-  for (var i = 0; i < len; i++) {
-    name = split[i].replace('*', '.*?');
-    if (name[0] === '-') {
-      debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
-    }
-    else {
-      debug.names.push(new RegExp('^' + name + '$'));
-    }
-  }
-};
-
-/**
- * Disable debug output.
- *
- * @api public
- */
-
-debug.disable = function(){
-  debug.enable('');
-};
-
-/**
- * Humanize the given `ms`.
- *
- * @param {Number} m
- * @return {String}
- * @api private
- */
-
-debug.humanize = function(ms) {
-  var sec = 1000
-    , min = 60 * 1000
-    , hour = 60 * min;
-
-  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
-  if (ms >= min) return (ms / min).toFixed(1) + 'm';
-  if (ms >= sec) return (ms / sec | 0) + 's';
-  return ms + 'ms';
-};
-
-/**
- * Returns true if the given mode name is enabled, false otherwise.
- *
- * @param {String} name
- * @return {Boolean}
- * @api public
- */
-
-debug.enabled = function(name) {
-  for (var i = 0, len = debug.skips.length; i < len; i++) {
-    if (debug.skips[i].test(name)) {
-      return false;
-    }
-  }
-  for (var i = 0, len = debug.names.length; i < len; i++) {
-    if (debug.names[i].test(name)) {
-      return true;
-    }
-  }
-  return false;
-};
-
-/**
- * Coerce `val`.
- */
-
-function coerce(val) {
-  if (val instanceof Error) return val.stack || val.message;
-  return val;
-}
-
-// persist
-
-try {
-  if (window.localStorage) debug.enable(localStorage.debug);
-} catch(e){}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/index.js
deleted file mode 100644
index e02c13b7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-if ('undefined' == typeof window) {
-  module.exports = require('./lib/debug');
-} else {
-  module.exports = require('./debug');
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/lib/debug.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/lib/debug.js
deleted file mode 100644
index 3b0a9183..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/lib/debug.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- * Module dependencies.
- */
-
-var tty = require('tty');
-
-/**
- * Expose `debug()` as the module.
- */
-
-module.exports = debug;
-
-/**
- * Enabled debuggers.
- */
-
-var names = []
-  , skips = [];
-
-(process.env.DEBUG || '')
-  .split(/[\s,]+/)
-  .forEach(function(name){
-    name = name.replace('*', '.*?');
-    if (name[0] === '-') {
-      skips.push(new RegExp('^' + name.substr(1) + '$'));
-    } else {
-      names.push(new RegExp('^' + name + '$'));
-    }
-  });
-
-/**
- * Colors.
- */
-
-var colors = [6, 2, 3, 4, 5, 1];
-
-/**
- * Previous debug() call.
- */
-
-var prev = {};
-
-/**
- * Previously assigned color.
- */
-
-var prevColor = 0;
-
-/**
- * Is stdout a TTY? Colored output is disabled when `true`.
- */
-
-var isatty = tty.isatty(2);
-
-/**
- * Select a color.
- *
- * @return {Number}
- * @api private
- */
-
-function color() {
-  return colors[prevColor++ % colors.length];
-}
-
-/**
- * Humanize the given `ms`.
- *
- * @param {Number} m
- * @return {String}
- * @api private
- */
-
-function humanize(ms) {
-  var sec = 1000
-    , min = 60 * 1000
-    , hour = 60 * min;
-
-  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
-  if (ms >= min) return (ms / min).toFixed(1) + 'm';
-  if (ms >= sec) return (ms / sec | 0) + 's';
-  return ms + 'ms';
-}
-
-/**
- * Create a debugger with the given `name`.
- *
- * @param {String} name
- * @return {Type}
- * @api public
- */
-
-function debug(name) {
-  function disabled(){}
-  disabled.enabled = false;
-
-  var match = skips.some(function(re){
-    return re.test(name);
-  });
-
-  if (match) return disabled;
-
-  match = names.some(function(re){
-    return re.test(name);
-  });
-
-  if (!match) return disabled;
-  var c = color();
-
-  function colored(fmt) {
-    fmt = coerce(fmt);
-
-    var curr = new Date;
-    var ms = curr - (prev[name] || curr);
-    prev[name] = curr;
-
-    fmt = '  \u001b[9' + c + 'm' + name + ' '
-      + '\u001b[3' + c + 'm\u001b[90m'
-      + fmt + '\u001b[3' + c + 'm'
-      + ' +' + humanize(ms) + '\u001b[0m';
-
-    console.error.apply(this, arguments);
-  }
-
-  function plain(fmt) {
-    fmt = coerce(fmt);
-
-    fmt = new Date().toUTCString()
-      + ' ' + name + ' ' + fmt;
-    console.error.apply(this, arguments);
-  }
-
-  colored.enabled = plain.enabled = true;
-
-  return isatty || process.env.DEBUG_COLORS
-    ? colored
-    : plain;
-}
-
-/**
- * Coerce `val`.
- */
-
-function coerce(val) {
-  if (val instanceof Error) return val.stack || val.message;
-  return val;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/package.json
deleted file mode 100644
index dfd56f55..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/debug/package.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
-  "name": "debug",
-  "version": "0.7.4",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/visionmedia/debug.git"
-  },
-  "description": "small debugging utility",
-  "keywords": [
-    "debug",
-    "log",
-    "debugger"
-  ],
-  "author": {
-    "name": "TJ Holowaychuk",
-    "email": "tj@vision-media.ca"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "mocha": "*"
-  },
-  "main": "lib/debug.js",
-  "browser": "./debug.js",
-  "engines": {
-    "node": "*"
-  },
-  "files": [
-    "lib/debug.js",
-    "debug.js",
-    "index.js"
-  ],
-  "component": {
-    "scripts": {
-      "debug/index.js": "index.js",
-      "debug/debug.js": "debug.js"
-    }
-  },
-  "readme": "# debug\n\n  tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n  , http = require('http')\n  , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n  debug(req.method + ' ' + req.url);\n  res.end('hello\\n');\n}).listen(3000, function(){\n  debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n  debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n  When stderr is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n  _(NOTE: Debug now uses stderr instead of stdout, so the correct shell command for this example is actually `DEBUG=* node example/worker 2> out &`)_\n  \n  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n  \n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n  The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n  You can also exclude specific debuggers by prefixing them with a \"-\" character.  For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n  a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n  a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
-  "readmeFilename": "Readme.md",
-  "bugs": {
-    "url": "https://github.com/visionmedia/debug/issues"
-  },
-  "homepage": "https://github.com/visionmedia/debug",
-  "_id": "debug@0.7.4",
-  "_shasum": "06e1ea8082c2cb14e39806e22e2f6f757f92af39",
-  "_from": "debug@~0.7.2",
-  "_resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/.npmignore
deleted file mode 100644
index a843dc44..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-test/fixtures
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/README.md
deleted file mode 100644
index 31170fea..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# fstream-ignore
-
-A fstream DirReader that filters out files that match globs in `.ignore`
-files throughout the tree, like how git ignores files based on a
-`.gitignore` file.
-
-Here's an example:
-
-```javascript
-var Ignore = require("fstream-ignore")
-Ignore({ path: __dirname
-       , ignoreFiles: [".ignore", ".gitignore"]
-       })
-  .on("child", function (c) {
-    console.error(c.path.substr(c.root.path.length + 1))
-  })
-  .pipe(tar.Pack())
-  .pipe(fs.createWriteStream("foo.tar"))
-```
-
-This will tar up the files in __dirname into `foo.tar`, ignoring
-anything matched by the globs in any .iginore or .gitignore file.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/example/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/example/basic.js
deleted file mode 100644
index ff453428..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/example/basic.js
+++ /dev/null
@@ -1,13 +0,0 @@
-var Ignore = require("../")
-Ignore({ path: __dirname
-       , ignoreFiles: [".ignore", ".gitignore"]
-       })
-  .on("child", function (c) {
-    console.error(c.path.substr(c.root.path.length + 1))
-    c.on("ignoreFile", onIgnoreFile)
-  })
-  .on("ignoreFile", onIgnoreFile)
-
-function onIgnoreFile (e) {
-  console.error("adding ignore file", e.path)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/ignore.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/ignore.js
deleted file mode 100644
index 0728f7c8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/ignore.js
+++ /dev/null
@@ -1,275 +0,0 @@
-// Essentially, this is a fstream.DirReader class, but with a
-// bit of special logic to read the specified sort of ignore files,
-// and a filter that prevents it from picking up anything excluded
-// by those files.
-
-var Minimatch = require("minimatch").Minimatch
-, fstream = require("fstream")
-, DirReader = fstream.DirReader
-, inherits = require("inherits")
-, path = require("path")
-, fs = require("fs")
-
-module.exports = IgnoreReader
-
-inherits(IgnoreReader, DirReader)
-
-function IgnoreReader (props) {
-  if (!(this instanceof IgnoreReader)) {
-    return new IgnoreReader(props)
-  }
-
-  // must be a Directory type
-  if (typeof props === "string") {
-    props = { path: path.resolve(props) }
-  }
-
-  props.type = "Directory"
-  props.Directory = true
-
-  if (!props.ignoreFiles) props.ignoreFiles = [".ignore"]
-  this.ignoreFiles = props.ignoreFiles
-
-  this.ignoreRules = null
-
-  // ensure that .ignore files always show up at the top of the list
-  // that way, they can be read before proceeding to handle other
-  // entries in that same folder
-  if (props.sort) {
-    this._sort = props.sort === "alpha" ? alphasort : props.sort
-    props.sort = null
-  }
-
-  this.on("entries", function () {
-    // if there are any ignore files in the list, then
-    // pause and add them.
-    // then, filter the list based on our ignoreRules
-
-    var hasIg = this.entries.some(this.isIgnoreFile, this)
-
-    if (!hasIg) return this.filterEntries()
-
-    this.addIgnoreFiles()
-  })
-
-  // we filter entries before we know what they are.
-  // however, directories have to be re-tested against
-  // rules with a "/" appended, because "a/b/" will only
-  // match if "a/b" is a dir, and not otherwise.
-  this.on("_entryStat", function (entry, props) {
-    var t = entry.basename
-    if (!this.applyIgnores(entry.basename,
-                           entry.type === "Directory",
-                           entry)) {
-      entry.abort()
-    }
-  }.bind(this))
-
-  DirReader.call(this, props)
-}
-
-
-IgnoreReader.prototype.addIgnoreFiles = function () {
-  if (this._paused) {
-    this.once("resume", this.addIgnoreFiles)
-    return
-  }
-  if (this._ignoreFilesAdded) return
-  this._ignoreFilesAdded = true
-
-  var newIg = this.entries.filter(this.isIgnoreFile, this)
-  , count = newIg.length
-  , errState = null
-
-  if (!count) return
-
-  this.pause()
-
-  var then = function then (er) {
-    if (errState) return
-    if (er) return this.emit("error", errState = er)
-    if (-- count === 0) {
-      this.filterEntries()
-      this.resume()
-    }
-  }.bind(this)
-
-  newIg.forEach(function (ig) {
-    this.addIgnoreFile(ig, then)
-  }, this)
-}
-
-
-IgnoreReader.prototype.isIgnoreFile = function (e) {
-  return e !== "." &&
-         e !== ".." &&
-         -1 !== this.ignoreFiles.indexOf(e)
-}
-
-
-IgnoreReader.prototype.getChildProps = function (stat) {
-  var props = DirReader.prototype.getChildProps.call(this, stat)
-  props.ignoreFiles = this.ignoreFiles
-
-  // Directories have to be read as IgnoreReaders
-  // otherwise fstream.Reader will create a DirReader instead.
-  if (stat.isDirectory()) {
-    props.type = this.constructor
-  }
-  return props
-}
-
-
-IgnoreReader.prototype.addIgnoreFile = function (e, cb) {
-  // read the file, and then call addIgnoreRules
-  // if there's an error, then tell the cb about it.
-
-  var ig = path.resolve(this.path, e)
-  fs.readFile(ig, function (er, data) {
-    if (er) return cb(er)
-
-    this.emit("ignoreFile", e, data)
-    var rules = this.readRules(data, e)
-    this.addIgnoreRules(rules, e)
-    cb()
-  }.bind(this))
-}
-
-
-IgnoreReader.prototype.readRules = function (buf, e) {
-  return buf.toString().split(/\r?\n/)
-}
-
-
-// Override this to do fancier things, like read the
-// "files" array from a package.json file or something.
-IgnoreReader.prototype.addIgnoreRules = function (set, e) {
-  // filter out anything obvious
-  set = set.filter(function (s) {
-    s = s.trim()
-    return s && !s.match(/^#/)
-  })
-
-  // no rules to add!
-  if (!set.length) return
-
-  // now get a minimatch object for each one of these.
-  // Note that we need to allow dot files by default, and
-  // not switch the meaning of their exclusion
-  var mmopt = { matchBase: true, dot: true, flipNegate: true }
-  , mm = set.map(function (s) {
-    var m = new Minimatch(s, mmopt)
-    m.ignoreFile = e
-    return m
-  })
-
-  if (!this.ignoreRules) this.ignoreRules = []
-  this.ignoreRules.push.apply(this.ignoreRules, mm)
-}
-
-
-IgnoreReader.prototype.filterEntries = function () {
-  // this exclusion is at the point where we know the list of
-  // entries in the dir, but don't know what they are.  since
-  // some of them *might* be directories, we have to run the
-  // match in dir-mode as well, so that we'll pick up partials
-  // of files that will be included later.  Anything included
-  // at this point will be checked again later once we know
-  // what it is.
-  this.entries = this.entries.filter(function (entry) {
-    // at this point, we don't know if it's a dir or not.
-    return this.applyIgnores(entry) || this.applyIgnores(entry, true)
-  }, this)
-}
-
-
-IgnoreReader.prototype.applyIgnores = function (entry, partial, obj) {
-  var included = true
-
-  // this = /a/b/c
-  // entry = d
-  // parent /a/b sees c/d
-  if (this.parent && this.parent.applyIgnores) {
-    var pt = this.basename + "/" + entry
-    included = this.parent.applyIgnores(pt, partial)
-  }
-
-  // Negated Rules
-  // Since we're *ignoring* things here, negating means that a file
-  // is re-included, if it would have been excluded by a previous
-  // rule.  So, negated rules are only relevant if the file
-  // has been excluded.
-  //
-  // Similarly, if a file has been excluded, then there's no point
-  // trying it against rules that have already been applied
-  //
-  // We're using the "flipnegate" flag here, which tells minimatch
-  // to set the "negate" for our information, but still report
-  // whether the core pattern was a hit or a miss.
-
-  if (!this.ignoreRules) {
-    return included
-  }
-
-  this.ignoreRules.forEach(function (rule) {
-    // negation means inclusion
-    if (rule.negate && included ||
-        !rule.negate && !included) {
-      // unnecessary
-      return
-    }
-
-    // first, match against /foo/bar
-    var match = rule.match("/" + entry)
-
-    if (!match) {
-      // try with the leading / trimmed off the test
-      // eg: foo/bar instead of /foo/bar
-      match = rule.match(entry)
-    }
-
-    // if the entry is a directory, then it will match
-    // with a trailing slash. eg: /foo/bar/ or foo/bar/
-    if (!match && partial) {
-      match = rule.match("/" + entry + "/") ||
-              rule.match(entry + "/")
-    }
-
-    // When including a file with a negated rule, it's
-    // relevant if a directory partially matches, since
-    // it may then match a file within it.
-    // Eg, if you ignore /a, but !/a/b/c
-    if (!match && rule.negate && partial) {
-      match = rule.match("/" + entry, true) ||
-              rule.match(entry, true)
-    }
-
-    if (match) {
-      included = rule.negate
-    }
-  }, this)
-
-  return included
-}
-
-
-IgnoreReader.prototype.sort = function (a, b) {
-  var aig = this.ignoreFiles.indexOf(a) !== -1
-  , big = this.ignoreFiles.indexOf(b) !== -1
-
-  if (aig && !big) return -1
-  if (big && !aig) return 1
-  return this._sort(a, b)
-}
-
-IgnoreReader.prototype._sort = function (a, b) {
-  return 0
-}
-
-function alphasort (a, b) {
-  return a === b ? 0
-       : a.toLowerCase() > b.toLowerCase() ? 1
-       : a.toLowerCase() < b.toLowerCase() ? -1
-       : a > b ? 1
-       : -1
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/inherits.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/inherits.js
deleted file mode 100644
index 29f5e24f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/inherits.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('util').inherits
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/package.json
deleted file mode 100644
index 83ae772d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "inherits",
-  "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
-  "version": "2.0.1",
-  "keywords": [
-    "inheritance",
-    "class",
-    "klass",
-    "oop",
-    "object-oriented",
-    "inherits",
-    "browser",
-    "browserify"
-  ],
-  "main": "./inherits.js",
-  "browser": "./inherits_browser.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/inherits"
-  },
-  "license": "ISC",
-  "scripts": {
-    "test": "node test"
-  },
-  "readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n  superclass\n* new version overwrites current prototype while old one preserves any\n  existing fields on it\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/inherits/issues"
-  },
-  "homepage": "https://github.com/isaacs/inherits",
-  "_id": "inherits@2.0.1",
-  "_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
-  "_from": "inherits@~2.0.0",
-  "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/test.js
deleted file mode 100644
index fc53012d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/inherits/test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var inherits = require('./inherits.js')
-var assert = require('assert')
-
-function test(c) {
-  assert(c.constructor === Child)
-  assert(c.constructor.super_ === Parent)
-  assert(Object.getPrototypeOf(c) === Child.prototype)
-  assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype)
-  assert(c instanceof Child)
-  assert(c instanceof Parent)
-}
-
-function Child() {
-  Parent.call(this)
-  test(this)
-}
-
-function Parent() {}
-
-inherits(Child, Parent)
-
-var c = new Child
-test(c)
-
-console.log('ok')
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/.npmignore
deleted file mode 100644
index 3c3629e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/LICENSE
deleted file mode 100644
index 05a40109..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
-All rights reserved.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/README.md
deleted file mode 100644
index 978268e2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/README.md
+++ /dev/null
@@ -1,218 +0,0 @@
-# minimatch
-
-A minimal matching utility.
-
-[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)
-
-
-This is the matching library used internally by npm.
-
-Eventually, it will replace the C binding in node-glob.
-
-It works by converting glob expressions into JavaScript `RegExp`
-objects.
-
-## Usage
-
-```javascript
-var minimatch = require("minimatch")
-
-minimatch("bar.foo", "*.foo") // true!
-minimatch("bar.foo", "*.bar") // false!
-minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
-```
-
-## Features
-
-Supports these glob features:
-
-* Brace Expansion
-* Extended glob matching
-* "Globstar" `**` matching
-
-See:
-
-* `man sh`
-* `man bash`
-* `man 3 fnmatch`
-* `man 5 gitignore`
-
-## Minimatch Class
-
-Create a minimatch object by instanting the `minimatch.Minimatch` class.
-
-```javascript
-var Minimatch = require("minimatch").Minimatch
-var mm = new Minimatch(pattern, options)
-```
-
-### Properties
-
-* `pattern` The original pattern the minimatch object represents.
-* `options` The options supplied to the constructor.
-* `set` A 2-dimensional array of regexp or string expressions.
-  Each row in the
-  array corresponds to a brace-expanded pattern.  Each item in the row
-  corresponds to a single path-part.  For example, the pattern
-  `{a,b/c}/d` would expand to a set of patterns like:
-
-        [ [ a, d ]
-        , [ b, c, d ] ]
-
-    If a portion of the pattern doesn't have any "magic" in it
-    (that is, it's something like `"foo"` rather than `fo*o?`), then it
-    will be left as a string rather than converted to a regular
-    expression.
-
-* `regexp` Created by the `makeRe` method.  A single regular expression
-  expressing the entire pattern.  This is useful in cases where you wish
-  to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
-* `negate` True if the pattern is negated.
-* `comment` True if the pattern is a comment.
-* `empty` True if the pattern is `""`.
-
-### Methods
-
-* `makeRe` Generate the `regexp` member if necessary, and return it.
-  Will return `false` if the pattern is invalid.
-* `match(fname)` Return true if the filename matches the pattern, or
-  false otherwise.
-* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
-  filename, and match it against a single row in the `regExpSet`.  This
-  method is mainly for internal use, but is exposed so that it can be
-  used by a glob-walker that needs to avoid excessive filesystem calls.
-
-All other methods are internal, and will be called as necessary.
-
-## Functions
-
-The top-level exported function has a `cache` property, which is an LRU
-cache set to store 100 items.  So, calling these methods repeatedly
-with the same pattern and options will use the same Minimatch object,
-saving the cost of parsing it multiple times.
-
-### minimatch(path, pattern, options)
-
-Main export.  Tests a path against the pattern using the options.
-
-```javascript
-var isJS = minimatch(file, "*.js", { matchBase: true })
-```
-
-### minimatch.filter(pattern, options)
-
-Returns a function that tests its
-supplied argument, suitable for use with `Array.filter`.  Example:
-
-```javascript
-var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
-```
-
-### minimatch.match(list, pattern, options)
-
-Match against the list of
-files, in the style of fnmatch or glob.  If nothing is matched, and
-options.nonull is set, then return a list containing the pattern itself.
-
-```javascript
-var javascripts = minimatch.match(fileList, "*.js", {matchBase: true}))
-```
-
-### minimatch.makeRe(pattern, options)
-
-Make a regular expression object from the pattern.
-
-## Options
-
-All options are `false` by default.
-
-### debug
-
-Dump a ton of stuff to stderr.
-
-### nobrace
-
-Do not expand `{a,b}` and `{1..3}` brace sets.
-
-### noglobstar
-
-Disable `**` matching against multiple folder names.
-
-### dot
-
-Allow patterns to match filenames starting with a period, even if
-the pattern does not explicitly have a period in that spot.
-
-Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
-is set.
-
-### noext
-
-Disable "extglob" style patterns like `+(a|b)`.
-
-### nocase
-
-Perform a case-insensitive match.
-
-### nonull
-
-When a match is not found by `minimatch.match`, return a list containing
-the pattern itself.  When set, an empty list is returned if there are
-no matches.
-
-### matchBase
-
-If set, then patterns without slashes will be matched
-against the basename of the path if it contains slashes.  For example,
-`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
-
-### nocomment
-
-Suppress the behavior of treating `#` at the start of a pattern as a
-comment.
-
-### nonegate
-
-Suppress the behavior of treating a leading `!` character as negation.
-
-### flipNegate
-
-Returns from negate expressions the same as if they were not negated.
-(Ie, true on a hit, false on a miss.)
-
-
-## Comparisons to other fnmatch/glob implementations
-
-While strict compliance with the existing standards is a worthwhile
-goal, some discrepancies exist between minimatch and other
-implementations, and are intentional.
-
-If the pattern starts with a `!` character, then it is negated.  Set the
-`nonegate` flag to suppress this behavior, and treat leading `!`
-characters normally.  This is perhaps relevant if you wish to start the
-pattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`
-characters at the start of a pattern will negate the pattern multiple
-times.
-
-If a pattern starts with `#`, then it is treated as a comment, and
-will not match anything.  Use `\#` to match a literal `#` at the
-start of a line, or set the `nocomment` flag to suppress this behavior.
-
-The double-star character `**` is supported by default, unless the
-`noglobstar` flag is set.  This is supported in the manner of bsdglob
-and bash 4.1, where `**` only has special significance if it is the only
-thing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but
-`a/**b` will not.
-
-If an escaped pattern has no matches, and the `nonull` flag is set,
-then minimatch.match returns the pattern as-provided, rather than
-interpreting the character escapes.  For example,
-`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
-`"*a?"`.  This is akin to setting the `nullglob` option in bash, except
-that it does not resolve escaped pattern characters.
-
-If brace expansion is not disabled, then it is performed before any
-other interpretation of the glob pattern.  Thus, a pattern like
-`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
-**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
-checked for validity.  Since those two are valid, matching proceeds.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/minimatch.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/minimatch.js
deleted file mode 100644
index c633f89f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/minimatch.js
+++ /dev/null
@@ -1,1055 +0,0 @@
-;(function (require, exports, module, platform) {
-
-if (module) module.exports = minimatch
-else exports.minimatch = minimatch
-
-if (!require) {
-  require = function (id) {
-    switch (id) {
-      case "sigmund": return function sigmund (obj) {
-        return JSON.stringify(obj)
-      }
-      case "path": return { basename: function (f) {
-        f = f.split(/[\/\\]/)
-        var e = f.pop()
-        if (!e) e = f.pop()
-        return e
-      }}
-      case "lru-cache": return function LRUCache () {
-        // not quite an LRU, but still space-limited.
-        var cache = {}
-        var cnt = 0
-        this.set = function (k, v) {
-          cnt ++
-          if (cnt >= 100) cache = {}
-          cache[k] = v
-        }
-        this.get = function (k) { return cache[k] }
-      }
-    }
-  }
-}
-
-minimatch.Minimatch = Minimatch
-
-var LRU = require("lru-cache")
-  , cache = minimatch.cache = new LRU({max: 100})
-  , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
-  , sigmund = require("sigmund")
-
-var path = require("path")
-  // any single thing other than /
-  // don't need to escape / when using new RegExp()
-  , qmark = "[^/]"
-
-  // * => any number of characters
-  , star = qmark + "*?"
-
-  // ** when dots are allowed.  Anything goes, except .. and .
-  // not (^ or / followed by one or two dots followed by $ or /),
-  // followed by anything, any number of times.
-  , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?"
-
-  // not a ^ or / followed by a dot,
-  // followed by anything, any number of times.
-  , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?"
-
-  // characters that need to be escaped in RegExp.
-  , reSpecials = charSet("().*{}+?[]^$\\!")
-
-// "abc" -> { a:true, b:true, c:true }
-function charSet (s) {
-  return s.split("").reduce(function (set, c) {
-    set[c] = true
-    return set
-  }, {})
-}
-
-// normalizes slashes.
-var slashSplit = /\/+/
-
-minimatch.filter = filter
-function filter (pattern, options) {
-  options = options || {}
-  return function (p, i, list) {
-    return minimatch(p, pattern, options)
-  }
-}
-
-function ext (a, b) {
-  a = a || {}
-  b = b || {}
-  var t = {}
-  Object.keys(b).forEach(function (k) {
-    t[k] = b[k]
-  })
-  Object.keys(a).forEach(function (k) {
-    t[k] = a[k]
-  })
-  return t
-}
-
-minimatch.defaults = function (def) {
-  if (!def || !Object.keys(def).length) return minimatch
-
-  var orig = minimatch
-
-  var m = function minimatch (p, pattern, options) {
-    return orig.minimatch(p, pattern, ext(def, options))
-  }
-
-  m.Minimatch = function Minimatch (pattern, options) {
-    return new orig.Minimatch(pattern, ext(def, options))
-  }
-
-  return m
-}
-
-Minimatch.defaults = function (def) {
-  if (!def || !Object.keys(def).length) return Minimatch
-  return minimatch.defaults(def).Minimatch
-}
-
-
-function minimatch (p, pattern, options) {
-  if (typeof pattern !== "string") {
-    throw new TypeError("glob pattern string required")
-  }
-
-  if (!options) options = {}
-
-  // shortcut: comments match nothing.
-  if (!options.nocomment && pattern.charAt(0) === "#") {
-    return false
-  }
-
-  // "" only matches ""
-  if (pattern.trim() === "") return p === ""
-
-  return new Minimatch(pattern, options).match(p)
-}
-
-function Minimatch (pattern, options) {
-  if (!(this instanceof Minimatch)) {
-    return new Minimatch(pattern, options, cache)
-  }
-
-  if (typeof pattern !== "string") {
-    throw new TypeError("glob pattern string required")
-  }
-
-  if (!options) options = {}
-  pattern = pattern.trim()
-
-  // windows: need to use /, not \
-  // On other platforms, \ is a valid (albeit bad) filename char.
-  if (platform === "win32") {
-    pattern = pattern.split("\\").join("/")
-  }
-
-  // lru storage.
-  // these things aren't particularly big, but walking down the string
-  // and turning it into a regexp can get pretty costly.
-  var cacheKey = pattern + "\n" + sigmund(options)
-  var cached = minimatch.cache.get(cacheKey)
-  if (cached) return cached
-  minimatch.cache.set(cacheKey, this)
-
-  this.options = options
-  this.set = []
-  this.pattern = pattern
-  this.regexp = null
-  this.negate = false
-  this.comment = false
-  this.empty = false
-
-  // make the set of regexps etc.
-  this.make()
-}
-
-Minimatch.prototype.debug = function() {}
-
-Minimatch.prototype.make = make
-function make () {
-  // don't do it more than once.
-  if (this._made) return
-
-  var pattern = this.pattern
-  var options = this.options
-
-  // empty patterns and comments match nothing.
-  if (!options.nocomment && pattern.charAt(0) === "#") {
-    this.comment = true
-    return
-  }
-  if (!pattern) {
-    this.empty = true
-    return
-  }
-
-  // step 1: figure out negation, etc.
-  this.parseNegate()
-
-  // step 2: expand braces
-  var set = this.globSet = this.braceExpand()
-
-  if (options.debug) this.debug = console.error
-
-  this.debug(this.pattern, set)
-
-  // step 3: now we have a set, so turn each one into a series of path-portion
-  // matching patterns.
-  // These will be regexps, except in the case of "**", which is
-  // set to the GLOBSTAR object for globstar behavior,
-  // and will not contain any / characters
-  set = this.globParts = set.map(function (s) {
-    return s.split(slashSplit)
-  })
-
-  this.debug(this.pattern, set)
-
-  // glob --> regexps
-  set = set.map(function (s, si, set) {
-    return s.map(this.parse, this)
-  }, this)
-
-  this.debug(this.pattern, set)
-
-  // filter out everything that didn't compile properly.
-  set = set.filter(function (s) {
-    return -1 === s.indexOf(false)
-  })
-
-  this.debug(this.pattern, set)
-
-  this.set = set
-}
-
-Minimatch.prototype.parseNegate = parseNegate
-function parseNegate () {
-  var pattern = this.pattern
-    , negate = false
-    , options = this.options
-    , negateOffset = 0
-
-  if (options.nonegate) return
-
-  for ( var i = 0, l = pattern.length
-      ; i < l && pattern.charAt(i) === "!"
-      ; i ++) {
-    negate = !negate
-    negateOffset ++
-  }
-
-  if (negateOffset) this.pattern = pattern.substr(negateOffset)
-  this.negate = negate
-}
-
-// Brace expansion:
-// a{b,c}d -> abd acd
-// a{b,}c -> abc ac
-// a{0..3}d -> a0d a1d a2d a3d
-// a{b,c{d,e}f}g -> abg acdfg acefg
-// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
-//
-// Invalid sets are not expanded.
-// a{2..}b -> a{2..}b
-// a{b}c -> a{b}c
-minimatch.braceExpand = function (pattern, options) {
-  return new Minimatch(pattern, options).braceExpand()
-}
-
-Minimatch.prototype.braceExpand = braceExpand
-function braceExpand (pattern, options) {
-  options = options || this.options
-  pattern = typeof pattern === "undefined"
-    ? this.pattern : pattern
-
-  if (typeof pattern === "undefined") {
-    throw new Error("undefined pattern")
-  }
-
-  if (options.nobrace ||
-      !pattern.match(/\{.*\}/)) {
-    // shortcut. no need to expand.
-    return [pattern]
-  }
-
-  var escaping = false
-
-  // examples and comments refer to this crazy pattern:
-  // a{b,c{d,e},{f,g}h}x{y,z}
-  // expected:
-  // abxy
-  // abxz
-  // acdxy
-  // acdxz
-  // acexy
-  // acexz
-  // afhxy
-  // afhxz
-  // aghxy
-  // aghxz
-
-  // everything before the first \{ is just a prefix.
-  // So, we pluck that off, and work with the rest,
-  // and then prepend it to everything we find.
-  if (pattern.charAt(0) !== "{") {
-    this.debug(pattern)
-    var prefix = null
-    for (var i = 0, l = pattern.length; i < l; i ++) {
-      var c = pattern.charAt(i)
-      this.debug(i, c)
-      if (c === "\\") {
-        escaping = !escaping
-      } else if (c === "{" && !escaping) {
-        prefix = pattern.substr(0, i)
-        break
-      }
-    }
-
-    // actually no sets, all { were escaped.
-    if (prefix === null) {
-      this.debug("no sets")
-      return [pattern]
-    }
-
-   var tail = braceExpand.call(this, pattern.substr(i), options)
-    return tail.map(function (t) {
-      return prefix + t
-    })
-  }
-
-  // now we have something like:
-  // {b,c{d,e},{f,g}h}x{y,z}
-  // walk through the set, expanding each part, until
-  // the set ends.  then, we'll expand the suffix.
-  // If the set only has a single member, then'll put the {} back
-
-  // first, handle numeric sets, since they're easier
-  var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/)
-  if (numset) {
-    this.debug("numset", numset[1], numset[2])
-    var suf = braceExpand.call(this, pattern.substr(numset[0].length), options)
-      , start = +numset[1]
-      , end = +numset[2]
-      , inc = start > end ? -1 : 1
-      , set = []
-    for (var i = start; i != (end + inc); i += inc) {
-      // append all the suffixes
-      for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
-        set.push(i + suf[ii])
-      }
-    }
-    return set
-  }
-
-  // ok, walk through the set
-  // We hope, somewhat optimistically, that there
-  // will be a } at the end.
-  // If the closing brace isn't found, then the pattern is
-  // interpreted as braceExpand("\\" + pattern) so that
-  // the leading \{ will be interpreted literally.
-  var i = 1 // skip the \{
-    , depth = 1
-    , set = []
-    , member = ""
-    , sawEnd = false
-    , escaping = false
-
-  function addMember () {
-    set.push(member)
-    member = ""
-  }
-
-  this.debug("Entering for")
-  FOR: for (i = 1, l = pattern.length; i < l; i ++) {
-    var c = pattern.charAt(i)
-    this.debug("", i, c)
-
-    if (escaping) {
-      escaping = false
-      member += "\\" + c
-    } else {
-      switch (c) {
-        case "\\":
-          escaping = true
-          continue
-
-        case "{":
-          depth ++
-          member += "{"
-          continue
-
-        case "}":
-          depth --
-          // if this closes the actual set, then we're done
-          if (depth === 0) {
-            addMember()
-            // pluck off the close-brace
-            i ++
-            break FOR
-          } else {
-            member += c
-            continue
-          }
-
-        case ",":
-          if (depth === 1) {
-            addMember()
-          } else {
-            member += c
-          }
-          continue
-
-        default:
-          member += c
-          continue
-      } // switch
-    } // else
-  } // for
-
-  // now we've either finished the set, and the suffix is
-  // pattern.substr(i), or we have *not* closed the set,
-  // and need to escape the leading brace
-  if (depth !== 0) {
-    this.debug("didn't close", pattern)
-    return braceExpand.call(this, "\\" + pattern, options)
-  }
-
-  // x{y,z} -> ["xy", "xz"]
-  this.debug("set", set)
-  this.debug("suffix", pattern.substr(i))
-  var suf = braceExpand.call(this, pattern.substr(i), options)
-  // ["b", "c{d,e}","{f,g}h"] ->
-  //   [["b"], ["cd", "ce"], ["fh", "gh"]]
-  var addBraces = set.length === 1
-  this.debug("set pre-expanded", set)
-  set = set.map(function (p) {
-    return braceExpand.call(this, p, options)
-  }, this)
-  this.debug("set expanded", set)
-
-
-  // [["b"], ["cd", "ce"], ["fh", "gh"]] ->
-  //   ["b", "cd", "ce", "fh", "gh"]
-  set = set.reduce(function (l, r) {
-    return l.concat(r)
-  })
-
-  if (addBraces) {
-    set = set.map(function (s) {
-      return "{" + s + "}"
-    })
-  }
-
-  // now attach the suffixes.
-  var ret = []
-  for (var i = 0, l = set.length; i < l; i ++) {
-    for (var ii = 0, ll = suf.length; ii < ll; ii ++) {
-      ret.push(set[i] + suf[ii])
-    }
-  }
-  return ret
-}
-
-// parse a component of the expanded set.
-// At this point, no pattern may contain "/" in it
-// so we're going to return a 2d array, where each entry is the full
-// pattern, split on '/', and then turned into a regular expression.
-// A regexp is made at the end which joins each array with an
-// escaped /, and another full one which joins each regexp with |.
-//
-// Following the lead of Bash 4.1, note that "**" only has special meaning
-// when it is the *only* thing in a path portion.  Otherwise, any series
-// of * is equivalent to a single *.  Globstar behavior is enabled by
-// default, and can be disabled by setting options.noglobstar.
-Minimatch.prototype.parse = parse
-var SUBPARSE = {}
-function parse (pattern, isSub) {
-  var options = this.options
-
-  // shortcuts
-  if (!options.noglobstar && pattern === "**") return GLOBSTAR
-  if (pattern === "") return ""
-
-  var re = ""
-    , hasMagic = !!options.nocase
-    , escaping = false
-    // ? => one single character
-    , patternListStack = []
-    , plType
-    , stateChar
-    , inClass = false
-    , reClassStart = -1
-    , classStart = -1
-    // . and .. never match anything that doesn't start with .,
-    // even when options.dot is set.
-    , patternStart = pattern.charAt(0) === "." ? "" // anything
-      // not (start or / followed by . or .. followed by / or end)
-      : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))"
-      : "(?!\\.)"
-    , self = this
-
-  function clearStateChar () {
-    if (stateChar) {
-      // we had some state-tracking character
-      // that wasn't consumed by this pass.
-      switch (stateChar) {
-        case "*":
-          re += star
-          hasMagic = true
-          break
-        case "?":
-          re += qmark
-          hasMagic = true
-          break
-        default:
-          re += "\\"+stateChar
-          break
-      }
-      self.debug('clearStateChar %j %j', stateChar, re)
-      stateChar = false
-    }
-  }
-
-  for ( var i = 0, len = pattern.length, c
-      ; (i < len) && (c = pattern.charAt(i))
-      ; i ++ ) {
-
-    this.debug("%s\t%s %s %j", pattern, i, re, c)
-
-    // skip over any that are escaped.
-    if (escaping && reSpecials[c]) {
-      re += "\\" + c
-      escaping = false
-      continue
-    }
-
-    SWITCH: switch (c) {
-      case "/":
-        // completely not allowed, even escaped.
-        // Should already be path-split by now.
-        return false
-
-      case "\\":
-        clearStateChar()
-        escaping = true
-        continue
-
-      // the various stateChar values
-      // for the "extglob" stuff.
-      case "?":
-      case "*":
-      case "+":
-      case "@":
-      case "!":
-        this.debug("%s\t%s %s %j <-- stateChar", pattern, i, re, c)
-
-        // all of those are literals inside a class, except that
-        // the glob [!a] means [^a] in regexp
-        if (inClass) {
-          this.debug('  in class')
-          if (c === "!" && i === classStart + 1) c = "^"
-          re += c
-          continue
-        }
-
-        // if we already have a stateChar, then it means
-        // that there was something like ** or +? in there.
-        // Handle the stateChar, then proceed with this one.
-        self.debug('call clearStateChar %j', stateChar)
-        clearStateChar()
-        stateChar = c
-        // if extglob is disabled, then +(asdf|foo) isn't a thing.
-        // just clear the statechar *now*, rather than even diving into
-        // the patternList stuff.
-        if (options.noext) clearStateChar()
-        continue
-
-      case "(":
-        if (inClass) {
-          re += "("
-          continue
-        }
-
-        if (!stateChar) {
-          re += "\\("
-          continue
-        }
-
-        plType = stateChar
-        patternListStack.push({ type: plType
-                              , start: i - 1
-                              , reStart: re.length })
-        // negation is (?:(?!js)[^/]*)
-        re += stateChar === "!" ? "(?:(?!" : "(?:"
-        this.debug('plType %j %j', stateChar, re)
-        stateChar = false
-        continue
-
-      case ")":
-        if (inClass || !patternListStack.length) {
-          re += "\\)"
-          continue
-        }
-
-        clearStateChar()
-        hasMagic = true
-        re += ")"
-        plType = patternListStack.pop().type
-        // negation is (?:(?!js)[^/]*)
-        // The others are (?:<pattern>)<type>
-        switch (plType) {
-          case "!":
-            re += "[^/]*?)"
-            break
-          case "?":
-          case "+":
-          case "*": re += plType
-          case "@": break // the default anyway
-        }
-        continue
-
-      case "|":
-        if (inClass || !patternListStack.length || escaping) {
-          re += "\\|"
-          escaping = false
-          continue
-        }
-
-        clearStateChar()
-        re += "|"
-        continue
-
-      // these are mostly the same in regexp and glob
-      case "[":
-        // swallow any state-tracking char before the [
-        clearStateChar()
-
-        if (inClass) {
-          re += "\\" + c
-          continue
-        }
-
-        inClass = true
-        classStart = i
-        reClassStart = re.length
-        re += c
-        continue
-
-      case "]":
-        //  a right bracket shall lose its special
-        //  meaning and represent itself in
-        //  a bracket expression if it occurs
-        //  first in the list.  -- POSIX.2 2.8.3.2
-        if (i === classStart + 1 || !inClass) {
-          re += "\\" + c
-          escaping = false
-          continue
-        }
-
-        // finish up the class.
-        hasMagic = true
-        inClass = false
-        re += c
-        continue
-
-      default:
-        // swallow any state char that wasn't consumed
-        clearStateChar()
-
-        if (escaping) {
-          // no need
-          escaping = false
-        } else if (reSpecials[c]
-                   && !(c === "^" && inClass)) {
-          re += "\\"
-        }
-
-        re += c
-
-    } // switch
-  } // for
-
-
-  // handle the case where we left a class open.
-  // "[abc" is valid, equivalent to "\[abc"
-  if (inClass) {
-    // split where the last [ was, and escape it
-    // this is a huge pita.  We now have to re-walk
-    // the contents of the would-be class to re-translate
-    // any characters that were passed through as-is
-    var cs = pattern.substr(classStart + 1)
-      , sp = this.parse(cs, SUBPARSE)
-    re = re.substr(0, reClassStart) + "\\[" + sp[0]
-    hasMagic = hasMagic || sp[1]
-  }
-
-  // handle the case where we had a +( thing at the *end*
-  // of the pattern.
-  // each pattern list stack adds 3 chars, and we need to go through
-  // and escape any | chars that were passed through as-is for the regexp.
-  // Go through and escape them, taking care not to double-escape any
-  // | chars that were already escaped.
-  var pl
-  while (pl = patternListStack.pop()) {
-    var tail = re.slice(pl.reStart + 3)
-    // maybe some even number of \, then maybe 1 \, followed by a |
-    tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
-      if (!$2) {
-        // the | isn't already escaped, so escape it.
-        $2 = "\\"
-      }
-
-      // need to escape all those slashes *again*, without escaping the
-      // one that we need for escaping the | character.  As it works out,
-      // escaping an even number of slashes can be done by simply repeating
-      // it exactly after itself.  That's why this trick works.
-      //
-      // I am sorry that you have to see this.
-      return $1 + $1 + $2 + "|"
-    })
-
-    this.debug("tail=%j\n   %s", tail, tail)
-    var t = pl.type === "*" ? star
-          : pl.type === "?" ? qmark
-          : "\\" + pl.type
-
-    hasMagic = true
-    re = re.slice(0, pl.reStart)
-       + t + "\\("
-       + tail
-  }
-
-  // handle trailing things that only matter at the very end.
-  clearStateChar()
-  if (escaping) {
-    // trailing \\
-    re += "\\\\"
-  }
-
-  // only need to apply the nodot start if the re starts with
-  // something that could conceivably capture a dot
-  var addPatternStart = false
-  switch (re.charAt(0)) {
-    case ".":
-    case "[":
-    case "(": addPatternStart = true
-  }
-
-  // if the re is not "" at this point, then we need to make sure
-  // it doesn't match against an empty path part.
-  // Otherwise a/* will match a/, which it should not.
-  if (re !== "" && hasMagic) re = "(?=.)" + re
-
-  if (addPatternStart) re = patternStart + re
-
-  // parsing just a piece of a larger pattern.
-  if (isSub === SUBPARSE) {
-    return [ re, hasMagic ]
-  }
-
-  // skip the regexp for non-magical patterns
-  // unescape anything in it, though, so that it'll be
-  // an exact match against a file etc.
-  if (!hasMagic) {
-    return globUnescape(pattern)
-  }
-
-  var flags = options.nocase ? "i" : ""
-    , regExp = new RegExp("^" + re + "$", flags)
-
-  regExp._glob = pattern
-  regExp._src = re
-
-  return regExp
-}
-
-minimatch.makeRe = function (pattern, options) {
-  return new Minimatch(pattern, options || {}).makeRe()
-}
-
-Minimatch.prototype.makeRe = makeRe
-function makeRe () {
-  if (this.regexp || this.regexp === false) return this.regexp
-
-  // at this point, this.set is a 2d array of partial
-  // pattern strings, or "**".
-  //
-  // It's better to use .match().  This function shouldn't
-  // be used, really, but it's pretty convenient sometimes,
-  // when you just want to work with a regex.
-  var set = this.set
-
-  if (!set.length) return this.regexp = false
-  var options = this.options
-
-  var twoStar = options.noglobstar ? star
-      : options.dot ? twoStarDot
-      : twoStarNoDot
-    , flags = options.nocase ? "i" : ""
-
-  var re = set.map(function (pattern) {
-    return pattern.map(function (p) {
-      return (p === GLOBSTAR) ? twoStar
-           : (typeof p === "string") ? regExpEscape(p)
-           : p._src
-    }).join("\\\/")
-  }).join("|")
-
-  // must match entire pattern
-  // ending in a * or ** will make it less strict.
-  re = "^(?:" + re + ")$"
-
-  // can match anything, as long as it's not this.
-  if (this.negate) re = "^(?!" + re + ").*$"
-
-  try {
-    return this.regexp = new RegExp(re, flags)
-  } catch (ex) {
-    return this.regexp = false
-  }
-}
-
-minimatch.match = function (list, pattern, options) {
-  var mm = new Minimatch(pattern, options)
-  list = list.filter(function (f) {
-    return mm.match(f)
-  })
-  if (options.nonull && !list.length) {
-    list.push(pattern)
-  }
-  return list
-}
-
-Minimatch.prototype.match = match
-function match (f, partial) {
-  this.debug("match", f, this.pattern)
-  // short-circuit in the case of busted things.
-  // comments, etc.
-  if (this.comment) return false
-  if (this.empty) return f === ""
-
-  if (f === "/" && partial) return true
-
-  var options = this.options
-
-  // windows: need to use /, not \
-  // On other platforms, \ is a valid (albeit bad) filename char.
-  if (platform === "win32") {
-    f = f.split("\\").join("/")
-  }
-
-  // treat the test path as a set of pathparts.
-  f = f.split(slashSplit)
-  this.debug(this.pattern, "split", f)
-
-  // just ONE of the pattern sets in this.set needs to match
-  // in order for it to be valid.  If negating, then just one
-  // match means that we have failed.
-  // Either way, return on the first hit.
-
-  var set = this.set
-  this.debug(this.pattern, "set", set)
-
-  var splitFile = path.basename(f.join("/")).split("/")
-
-  for (var i = 0, l = set.length; i < l; i ++) {
-    var pattern = set[i], file = f
-    if (options.matchBase && pattern.length === 1) {
-      file = splitFile
-    }
-    var hit = this.matchOne(file, pattern, partial)
-    if (hit) {
-      if (options.flipNegate) return true
-      return !this.negate
-    }
-  }
-
-  // didn't get any hits.  this is success if it's a negative
-  // pattern, failure otherwise.
-  if (options.flipNegate) return false
-  return this.negate
-}
-
-// set partial to true to test if, for example,
-// "/a/b" matches the start of "/*/b/*/d"
-// Partial means, if you run out of file before you run
-// out of pattern, then that's fine, as long as all
-// the parts match.
-Minimatch.prototype.matchOne = function (file, pattern, partial) {
-  var options = this.options
-
-  this.debug("matchOne",
-              { "this": this
-              , file: file
-              , pattern: pattern })
-
-  this.debug("matchOne", file.length, pattern.length)
-
-  for ( var fi = 0
-          , pi = 0
-          , fl = file.length
-          , pl = pattern.length
-      ; (fi < fl) && (pi < pl)
-      ; fi ++, pi ++ ) {
-
-    this.debug("matchOne loop")
-    var p = pattern[pi]
-      , f = file[fi]
-
-    this.debug(pattern, p, f)
-
-    // should be impossible.
-    // some invalid regexp stuff in the set.
-    if (p === false) return false
-
-    if (p === GLOBSTAR) {
-      this.debug('GLOBSTAR', [pattern, p, f])
-
-      // "**"
-      // a/**/b/**/c would match the following:
-      // a/b/x/y/z/c
-      // a/x/y/z/b/c
-      // a/b/x/b/x/c
-      // a/b/c
-      // To do this, take the rest of the pattern after
-      // the **, and see if it would match the file remainder.
-      // If so, return success.
-      // If not, the ** "swallows" a segment, and try again.
-      // This is recursively awful.
-      //
-      // a/**/b/**/c matching a/b/x/y/z/c
-      // - a matches a
-      // - doublestar
-      //   - matchOne(b/x/y/z/c, b/**/c)
-      //     - b matches b
-      //     - doublestar
-      //       - matchOne(x/y/z/c, c) -> no
-      //       - matchOne(y/z/c, c) -> no
-      //       - matchOne(z/c, c) -> no
-      //       - matchOne(c, c) yes, hit
-      var fr = fi
-        , pr = pi + 1
-      if (pr === pl) {
-        this.debug('** at the end')
-        // a ** at the end will just swallow the rest.
-        // We have found a match.
-        // however, it will not swallow /.x, unless
-        // options.dot is set.
-        // . and .. are *never* matched by **, for explosively
-        // exponential reasons.
-        for ( ; fi < fl; fi ++) {
-          if (file[fi] === "." || file[fi] === ".." ||
-              (!options.dot && file[fi].charAt(0) === ".")) return false
-        }
-        return true
-      }
-
-      // ok, let's see if we can swallow whatever we can.
-      WHILE: while (fr < fl) {
-        var swallowee = file[fr]
-
-        this.debug('\nglobstar while',
-                    file, fr, pattern, pr, swallowee)
-
-        // XXX remove this slice.  Just pass the start index.
-        if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
-          this.debug('globstar found match!', fr, fl, swallowee)
-          // found a match.
-          return true
-        } else {
-          // can't swallow "." or ".." ever.
-          // can only swallow ".foo" when explicitly asked.
-          if (swallowee === "." || swallowee === ".." ||
-              (!options.dot && swallowee.charAt(0) === ".")) {
-            this.debug("dot detected!", file, fr, pattern, pr)
-            break WHILE
-          }
-
-          // ** swallows a segment, and continue.
-          this.debug('globstar swallow a segment, and continue')
-          fr ++
-        }
-      }
-      // no match was found.
-      // However, in partial mode, we can't say this is necessarily over.
-      // If there's more *pattern* left, then 
-      if (partial) {
-        // ran out of file
-        this.debug("\n>>> no match, partial?", file, fr, pattern, pr)
-        if (fr === fl) return true
-      }
-      return false
-    }
-
-    // something other than **
-    // non-magic patterns just have to match exactly
-    // patterns with magic have been turned into regexps.
-    var hit
-    if (typeof p === "string") {
-      if (options.nocase) {
-        hit = f.toLowerCase() === p.toLowerCase()
-      } else {
-        hit = f === p
-      }
-      this.debug("string match", p, f, hit)
-    } else {
-      hit = f.match(p)
-      this.debug("pattern match", p, f, hit)
-    }
-
-    if (!hit) return false
-  }
-
-  // Note: ending in / means that we'll get a final ""
-  // at the end of the pattern.  This can only match a
-  // corresponding "" at the end of the file.
-  // If the file ends in /, then it can only match a
-  // a pattern that ends in /, unless the pattern just
-  // doesn't have any more for it. But, a/b/ should *not*
-  // match "a/b/*", even though "" matches against the
-  // [^/]*? pattern, except in partial mode, where it might
-  // simply not be reached yet.
-  // However, a/b/ should still satisfy a/*
-
-  // now either we fell off the end of the pattern, or we're done.
-  if (fi === fl && pi === pl) {
-    // ran out of pattern and filename at the same time.
-    // an exact hit!
-    return true
-  } else if (fi === fl) {
-    // ran out of file, but still had pattern left.
-    // this is ok if we're doing the match as part of
-    // a glob fs traversal.
-    return partial
-  } else if (pi === pl) {
-    // ran out of pattern, still have file left.
-    // this is only acceptable if we're on the very last
-    // empty segment of a file with a trailing slash.
-    // a/* should match a/b/
-    var emptyFileEnd = (fi === fl - 1) && (file[fi] === "")
-    return emptyFileEnd
-  }
-
-  // should be unreachable.
-  throw new Error("wtf?")
-}
-
-
-// replace stuff like \* with *
-function globUnescape (s) {
-  return s.replace(/\\(.)/g, "$1")
-}
-
-
-function regExpEscape (s) {
-  return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
-}
-
-})( typeof require === "function" ? require : null,
-    this,
-    typeof module === "object" ? module : null,
-    typeof process === "object" ? process.platform : "win32"
-  )
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/.npmignore
deleted file mode 100644
index 07e6e472..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-/node_modules
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS
deleted file mode 100644
index 4a0bc503..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS
+++ /dev/null
@@ -1,14 +0,0 @@
-# Authors, sorted by whether or not they are me
-Isaac Z. Schlueter <i@izs.me>
-Brian Cottingham <spiffytech@gmail.com>
-Carlos Brito Lage <carlos@carloslage.net>
-Jesse Dailey <jesse.dailey@gmail.com>
-Kevin O'Hara <kevinohara80@gmail.com>
-Marco Rogers <marco.rogers@gmail.com>
-Mark Cavage <mcavage@gmail.com>
-Marko Mikulicic <marko.mikulicic@isti.cnr.it>
-Nathan Rajlich <nathan@tootallnate.net>
-Satheesh Natesan <snateshan@myspace-inc.com>
-Trent Mick <trentm@gmail.com>
-ashleybrener <ashley@starlogik.com>
-n4kz <n4kz@n4kz.com>
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/LICENSE
deleted file mode 100644
index 05a40109..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
-All rights reserved.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/README.md
deleted file mode 100644
index 03ee0f98..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/README.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# lru cache
-
-A cache object that deletes the least-recently-used items.
-
-## Usage:
-
-```javascript
-var LRU = require("lru-cache")
-  , options = { max: 500
-              , length: function (n) { return n * 2 }
-              , dispose: function (key, n) { n.close() }
-              , maxAge: 1000 * 60 * 60 }
-  , cache = LRU(options)
-  , otherCache = LRU(50) // sets just the max size
-
-cache.set("key", "value")
-cache.get("key") // "value"
-
-cache.reset()    // empty the cache
-```
-
-If you put more stuff in it, then items will fall out.
-
-If you try to put an oversized thing in it, then it'll fall out right
-away.
-
-## Options
-
-* `max` The maximum size of the cache, checked by applying the length
-  function to all values in the cache.  Not setting this is kind of
-  silly, since that's the whole purpose of this lib, but it defaults
-  to `Infinity`.
-* `maxAge` Maximum age in ms.  Items are not pro-actively pruned out
-  as they age, but if you try to get an item that is too old, it'll
-  drop it and return undefined instead of giving it to you.
-* `length` Function that is used to calculate the length of stored
-  items.  If you're storing strings or buffers, then you probably want
-  to do something like `function(n){return n.length}`.  The default is
-  `function(n){return 1}`, which is fine if you want to store `n`
-  like-sized things.
-* `dispose` Function that is called on items when they are dropped
-  from the cache.  This can be handy if you want to close file
-  descriptors or do other cleanup tasks when items are no longer
-  accessible.  Called with `key, value`.  It's called *before*
-  actually removing the item from the internal cache, so if you want
-  to immediately put it back in, you'll have to do that in a
-  `nextTick` or `setTimeout` callback or it won't do anything.
-* `stale` By default, if you set a `maxAge`, it'll only actually pull
-  stale items out of the cache when you `get(key)`.  (That is, it's
-  not pre-emptively doing a `setTimeout` or anything.)  If you set
-  `stale:true`, it'll return the stale value before deleting it.  If
-  you don't set this, then it'll return `undefined` when you try to
-  get a stale entry, as if it had already been deleted.
-
-## API
-
-* `set(key, value)`
-* `get(key) => value`
-
-    Both of these will update the "recently used"-ness of the key.
-    They do what you think.
-
-* `peek(key)`
-
-    Returns the key value (or `undefined` if not found) without
-    updating the "recently used"-ness of the key.
-
-    (If you find yourself using this a lot, you *might* be using the
-    wrong sort of data structure, but there are some use cases where
-    it's handy.)
-
-* `del(key)`
-
-    Deletes a key out of the cache.
-
-* `reset()`
-
-    Clear the cache entirely, throwing away all values.
-
-* `has(key)`
-
-    Check if a key is in the cache, without updating the recent-ness
-    or deleting it for being stale.
-
-* `forEach(function(value,key,cache), [thisp])`
-
-    Just like `Array.prototype.forEach`.  Iterates over all the keys
-    in the cache, in order of recent-ness.  (Ie, more recently used
-    items are iterated over first.)
-
-* `keys()`
-
-    Return an array of the keys in the cache.
-
-* `values()`
-
-    Return an array of the values in the cache.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js
deleted file mode 100644
index d1d13817..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js
+++ /dev/null
@@ -1,252 +0,0 @@
-;(function () { // closure for web browsers
-
-if (typeof module === 'object' && module.exports) {
-  module.exports = LRUCache
-} else {
-  // just set the global for non-node platforms.
-  this.LRUCache = LRUCache
-}
-
-function hOP (obj, key) {
-  return Object.prototype.hasOwnProperty.call(obj, key)
-}
-
-function naiveLength () { return 1 }
-
-function LRUCache (options) {
-  if (!(this instanceof LRUCache))
-    return new LRUCache(options)
-
-  if (typeof options === 'number')
-    options = { max: options }
-
-  if (!options)
-    options = {}
-
-  this._max = options.max
-  // Kind of weird to have a default max of Infinity, but oh well.
-  if (!this._max || !(typeof this._max === "number") || this._max <= 0 )
-    this._max = Infinity
-
-  this._lengthCalculator = options.length || naiveLength
-  if (typeof this._lengthCalculator !== "function")
-    this._lengthCalculator = naiveLength
-
-  this._allowStale = options.stale || false
-  this._maxAge = options.maxAge || null
-  this._dispose = options.dispose
-  this.reset()
-}
-
-// resize the cache when the max changes.
-Object.defineProperty(LRUCache.prototype, "max",
-  { set : function (mL) {
-      if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity
-      this._max = mL
-      if (this._length > this._max) trim(this)
-    }
-  , get : function () { return this._max }
-  , enumerable : true
-  })
-
-// resize the cache when the lengthCalculator changes.
-Object.defineProperty(LRUCache.prototype, "lengthCalculator",
-  { set : function (lC) {
-      if (typeof lC !== "function") {
-        this._lengthCalculator = naiveLength
-        this._length = this._itemCount
-        for (var key in this._cache) {
-          this._cache[key].length = 1
-        }
-      } else {
-        this._lengthCalculator = lC
-        this._length = 0
-        for (var key in this._cache) {
-          this._cache[key].length = this._lengthCalculator(this._cache[key].value)
-          this._length += this._cache[key].length
-        }
-      }
-
-      if (this._length > this._max) trim(this)
-    }
-  , get : function () { return this._lengthCalculator }
-  , enumerable : true
-  })
-
-Object.defineProperty(LRUCache.prototype, "length",
-  { get : function () { return this._length }
-  , enumerable : true
-  })
-
-
-Object.defineProperty(LRUCache.prototype, "itemCount",
-  { get : function () { return this._itemCount }
-  , enumerable : true
-  })
-
-LRUCache.prototype.forEach = function (fn, thisp) {
-  thisp = thisp || this
-  var i = 0;
-  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
-    i++
-    var hit = this._lruList[k]
-    if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
-      del(this, hit)
-      if (!this._allowStale) hit = undefined
-    }
-    if (hit) {
-      fn.call(thisp, hit.value, hit.key, this)
-    }
-  }
-}
-
-LRUCache.prototype.keys = function () {
-  var keys = new Array(this._itemCount)
-  var i = 0
-  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
-    var hit = this._lruList[k]
-    keys[i++] = hit.key
-  }
-  return keys
-}
-
-LRUCache.prototype.values = function () {
-  var values = new Array(this._itemCount)
-  var i = 0
-  for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) {
-    var hit = this._lruList[k]
-    values[i++] = hit.value
-  }
-  return values
-}
-
-LRUCache.prototype.reset = function () {
-  if (this._dispose && this._cache) {
-    for (var k in this._cache) {
-      this._dispose(k, this._cache[k].value)
-    }
-  }
-
-  this._cache = Object.create(null) // hash of items by key
-  this._lruList = Object.create(null) // list of items in order of use recency
-  this._mru = 0 // most recently used
-  this._lru = 0 // least recently used
-  this._length = 0 // number of items in the list
-  this._itemCount = 0
-}
-
-// Provided for debugging/dev purposes only. No promises whatsoever that
-// this API stays stable.
-LRUCache.prototype.dump = function () {
-  return this._cache
-}
-
-LRUCache.prototype.dumpLru = function () {
-  return this._lruList
-}
-
-LRUCache.prototype.set = function (key, value) {
-  if (hOP(this._cache, key)) {
-    // dispose of the old one before overwriting
-    if (this._dispose) this._dispose(key, this._cache[key].value)
-    if (this._maxAge) this._cache[key].now = Date.now()
-    this._cache[key].value = value
-    this.get(key)
-    return true
-  }
-
-  var len = this._lengthCalculator(value)
-  var age = this._maxAge ? Date.now() : 0
-  var hit = new Entry(key, value, this._mru++, len, age)
-
-  // oversized objects fall out of cache automatically.
-  if (hit.length > this._max) {
-    if (this._dispose) this._dispose(key, value)
-    return false
-  }
-
-  this._length += hit.length
-  this._lruList[hit.lu] = this._cache[key] = hit
-  this._itemCount ++
-
-  if (this._length > this._max) trim(this)
-  return true
-}
-
-LRUCache.prototype.has = function (key) {
-  if (!hOP(this._cache, key)) return false
-  var hit = this._cache[key]
-  if (this._maxAge && (Date.now() - hit.now > this._maxAge)) {
-    return false
-  }
-  return true
-}
-
-LRUCache.prototype.get = function (key) {
-  return get(this, key, true)
-}
-
-LRUCache.prototype.peek = function (key) {
-  return get(this, key, false)
-}
-
-LRUCache.prototype.pop = function () {
-  var hit = this._lruList[this._lru]
-  del(this, hit)
-  return hit || null
-}
-
-LRUCache.prototype.del = function (key) {
-  del(this, this._cache[key])
-}
-
-function get (self, key, doUse) {
-  var hit = self._cache[key]
-  if (hit) {
-    if (self._maxAge && (Date.now() - hit.now > self._maxAge)) {
-      del(self, hit)
-      if (!self._allowStale) hit = undefined
-    } else {
-      if (doUse) use(self, hit)
-    }
-    if (hit) hit = hit.value
-  }
-  return hit
-}
-
-function use (self, hit) {
-  shiftLU(self, hit)
-  hit.lu = self._mru ++
-  self._lruList[hit.lu] = hit
-}
-
-function trim (self) {
-  while (self._lru < self._mru && self._length > self._max)
-    del(self, self._lruList[self._lru])
-}
-
-function shiftLU (self, hit) {
-  delete self._lruList[ hit.lu ]
-  while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++
-}
-
-function del (self, hit) {
-  if (hit) {
-    if (self._dispose) self._dispose(hit.key, hit.value)
-    self._length -= hit.length
-    self._itemCount --
-    delete self._cache[ hit.key ]
-    shiftLU(self, hit)
-  }
-}
-
-// classy, since V8 prefers predictable objects.
-function Entry (key, value, lu, length, now) {
-  this.key = key
-  this.value = value
-  this.lu = lu
-  this.length = length
-  this.now = now
-}
-
-})()
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/package.json
deleted file mode 100644
index 9c45e47a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "lru-cache",
-  "description": "A cache object that deletes the least-recently-used items.",
-  "version": "2.5.0",
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me"
-  },
-  "scripts": {
-    "test": "tap test --gc"
-  },
-  "main": "lib/lru-cache.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-lru-cache.git"
-  },
-  "devDependencies": {
-    "tap": "",
-    "weak": ""
-  },
-  "license": {
-    "type": "MIT",
-    "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE"
-  },
-  "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n  , options = { max: 500\n              , length: function (n) { return n * 2 }\n              , dispose: function (key, n) { n.close() }\n              , maxAge: 1000 * 60 * 60 }\n  , cache = LRU(options)\n  , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset()    // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n  function to all values in the cache.  Not setting this is kind of\n  silly, since that's the whole purpose of this lib, but it defaults\n  to `Infinity`.\n* `maxAge` Maximum age in ms.  Items are not pro-actively pruned out\n  as they age, but if you try to get an item that is too old, it'll\n  drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n  items.  If you're storing strings or buffers, then you probably want\n  to do something like `function(n){return n.length}`.  The default is\n  `function(n){return 1}`, which is fine if you want to store `n`\n  like-sized things.\n* `dispose` Function that is called on items when they are dropped\n  from the cache.  This can be handy if you want to close file\n  descriptors or do other cleanup tasks when items are no longer\n  accessible.  Called with `key, value`.  It's called *before*\n  actually removing the item from the internal cache, so if you want\n  to immediately put it back in, you'll have to do that in a\n  `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n  stale items out of the cache when you `get(key)`.  (That is, it's\n  not pre-emptively doing a `setTimeout` or anything.)  If you set\n  `stale:true`, it'll return the stale value before deleting it.  If\n  you don't set this, then it'll return `undefined` when you try to\n  get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n    Both of these will update the \"recently used\"-ness of the key.\n    They do what you think.\n\n* `peek(key)`\n\n    Returns the key value (or `undefined` if not found) without\n    updating the \"recently used\"-ness of the key.\n\n    (If you find yourself using this a lot, you *might* be using the\n    wrong sort of data structure, but there are some use cases where\n    it's handy.)\n\n* `del(key)`\n\n    Deletes a key out of the cache.\n\n* `reset()`\n\n    Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n    Check if a key is in the cache, without updating the recent-ness\n    or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n    Just like `Array.prototype.forEach`.  Iterates over all the keys\n    in the cache, in order of recent-ness.  (Ie, more recently used\n    items are iterated over first.)\n\n* `keys()`\n\n    Return an array of the keys in the cache.\n\n* `values()`\n\n    Return an array of the values in the cache.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/node-lru-cache/issues"
-  },
-  "homepage": "https://github.com/isaacs/node-lru-cache",
-  "_id": "lru-cache@2.5.0",
-  "_shasum": "d82388ae9c960becbea0c73bb9eb79b6c6ce9aeb",
-  "_from": "lru-cache@2",
-  "_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/basic.js
deleted file mode 100644
index f72697c4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/basic.js
+++ /dev/null
@@ -1,369 +0,0 @@
-var test = require("tap").test
-  , LRU = require("../")
-
-test("basic", function (t) {
-  var cache = new LRU({max: 10})
-  cache.set("key", "value")
-  t.equal(cache.get("key"), "value")
-  t.equal(cache.get("nada"), undefined)
-  t.equal(cache.length, 1)
-  t.equal(cache.max, 10)
-  t.end()
-})
-
-test("least recently set", function (t) {
-  var cache = new LRU(2)
-  cache.set("a", "A")
-  cache.set("b", "B")
-  cache.set("c", "C")
-  t.equal(cache.get("c"), "C")
-  t.equal(cache.get("b"), "B")
-  t.equal(cache.get("a"), undefined)
-  t.end()
-})
-
-test("lru recently gotten", function (t) {
-  var cache = new LRU(2)
-  cache.set("a", "A")
-  cache.set("b", "B")
-  cache.get("a")
-  cache.set("c", "C")
-  t.equal(cache.get("c"), "C")
-  t.equal(cache.get("b"), undefined)
-  t.equal(cache.get("a"), "A")
-  t.end()
-})
-
-test("del", function (t) {
-  var cache = new LRU(2)
-  cache.set("a", "A")
-  cache.del("a")
-  t.equal(cache.get("a"), undefined)
-  t.end()
-})
-
-test("max", function (t) {
-  var cache = new LRU(3)
-
-  // test changing the max, verify that the LRU items get dropped.
-  cache.max = 100
-  for (var i = 0; i < 100; i ++) cache.set(i, i)
-  t.equal(cache.length, 100)
-  for (var i = 0; i < 100; i ++) {
-    t.equal(cache.get(i), i)
-  }
-  cache.max = 3
-  t.equal(cache.length, 3)
-  for (var i = 0; i < 97; i ++) {
-    t.equal(cache.get(i), undefined)
-  }
-  for (var i = 98; i < 100; i ++) {
-    t.equal(cache.get(i), i)
-  }
-
-  // now remove the max restriction, and try again.
-  cache.max = "hello"
-  for (var i = 0; i < 100; i ++) cache.set(i, i)
-  t.equal(cache.length, 100)
-  for (var i = 0; i < 100; i ++) {
-    t.equal(cache.get(i), i)
-  }
-  // should trigger an immediate resize
-  cache.max = 3
-  t.equal(cache.length, 3)
-  for (var i = 0; i < 97; i ++) {
-    t.equal(cache.get(i), undefined)
-  }
-  for (var i = 98; i < 100; i ++) {
-    t.equal(cache.get(i), i)
-  }
-  t.end()
-})
-
-test("reset", function (t) {
-  var cache = new LRU(10)
-  cache.set("a", "A")
-  cache.set("b", "B")
-  cache.reset()
-  t.equal(cache.length, 0)
-  t.equal(cache.max, 10)
-  t.equal(cache.get("a"), undefined)
-  t.equal(cache.get("b"), undefined)
-  t.end()
-})
-
-
-// Note: `<cache>.dump()` is a debugging tool only. No guarantees are made
-// about the format/layout of the response.
-test("dump", function (t) {
-  var cache = new LRU(10)
-  var d = cache.dump();
-  t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache")
-  cache.set("a", "A")
-  var d = cache.dump()  // { a: { key: "a", value: "A", lu: 0 } }
-  t.ok(d.a)
-  t.equal(d.a.key, "a")
-  t.equal(d.a.value, "A")
-  t.equal(d.a.lu, 0)
-
-  cache.set("b", "B")
-  cache.get("b")
-  d = cache.dump()
-  t.ok(d.b)
-  t.equal(d.b.key, "b")
-  t.equal(d.b.value, "B")
-  t.equal(d.b.lu, 2)
-
-  t.end()
-})
-
-
-test("basic with weighed length", function (t) {
-  var cache = new LRU({
-    max: 100,
-    length: function (item) { return item.size }
-  })
-  cache.set("key", {val: "value", size: 50})
-  t.equal(cache.get("key").val, "value")
-  t.equal(cache.get("nada"), undefined)
-  t.equal(cache.lengthCalculator(cache.get("key")), 50)
-  t.equal(cache.length, 50)
-  t.equal(cache.max, 100)
-  t.end()
-})
-
-
-test("weighed length item too large", function (t) {
-  var cache = new LRU({
-    max: 10,
-    length: function (item) { return item.size }
-  })
-  t.equal(cache.max, 10)
-
-  // should fall out immediately
-  cache.set("key", {val: "value", size: 50})
-
-  t.equal(cache.length, 0)
-  t.equal(cache.get("key"), undefined)
-  t.end()
-})
-
-test("least recently set with weighed length", function (t) {
-  var cache = new LRU({
-    max:8,
-    length: function (item) { return item.length }
-  })
-  cache.set("a", "A")
-  cache.set("b", "BB")
-  cache.set("c", "CCC")
-  cache.set("d", "DDDD")
-  t.equal(cache.get("d"), "DDDD")
-  t.equal(cache.get("c"), "CCC")
-  t.equal(cache.get("b"), undefined)
-  t.equal(cache.get("a"), undefined)
-  t.end()
-})
-
-test("lru recently gotten with weighed length", function (t) {
-  var cache = new LRU({
-    max: 8,
-    length: function (item) { return item.length }
-  })
-  cache.set("a", "A")
-  cache.set("b", "BB")
-  cache.set("c", "CCC")
-  cache.get("a")
-  cache.get("b")
-  cache.set("d", "DDDD")
-  t.equal(cache.get("c"), undefined)
-  t.equal(cache.get("d"), "DDDD")
-  t.equal(cache.get("b"), "BB")
-  t.equal(cache.get("a"), "A")
-  t.end()
-})
-
-test("set returns proper booleans", function(t) {
-  var cache = new LRU({
-    max: 5,
-    length: function (item) { return item.length }
-  })
-
-  t.equal(cache.set("a", "A"), true)
-
-  // should return false for max exceeded
-  t.equal(cache.set("b", "donuts"), false)
-
-  t.equal(cache.set("b", "B"), true)
-  t.equal(cache.set("c", "CCCC"), true)
-  t.end()
-})
-
-test("drop the old items", function(t) {
-  var cache = new LRU({
-    max: 5,
-    maxAge: 50
-  })
-
-  cache.set("a", "A")
-
-  setTimeout(function () {
-    cache.set("b", "b")
-    t.equal(cache.get("a"), "A")
-  }, 25)
-
-  setTimeout(function () {
-    cache.set("c", "C")
-    // timed out
-    t.notOk(cache.get("a"))
-  }, 60)
-
-  setTimeout(function () {
-    t.notOk(cache.get("b"))
-    t.equal(cache.get("c"), "C")
-  }, 90)
-
-  setTimeout(function () {
-    t.notOk(cache.get("c"))
-    t.end()
-  }, 155)
-})
-
-test("disposal function", function(t) {
-  var disposed = false
-  var cache = new LRU({
-    max: 1,
-    dispose: function (k, n) {
-      disposed = n
-    }
-  })
-
-  cache.set(1, 1)
-  cache.set(2, 2)
-  t.equal(disposed, 1)
-  cache.set(3, 3)
-  t.equal(disposed, 2)
-  cache.reset()
-  t.equal(disposed, 3)
-  t.end()
-})
-
-test("disposal function on too big of item", function(t) {
-  var disposed = false
-  var cache = new LRU({
-    max: 1,
-    length: function (k) {
-      return k.length
-    },
-    dispose: function (k, n) {
-      disposed = n
-    }
-  })
-  var obj = [ 1, 2 ]
-
-  t.equal(disposed, false)
-  cache.set("obj", obj)
-  t.equal(disposed, obj)
-  t.end()
-})
-
-test("has()", function(t) {
-  var cache = new LRU({
-    max: 1,
-    maxAge: 10
-  })
-
-  cache.set('foo', 'bar')
-  t.equal(cache.has('foo'), true)
-  cache.set('blu', 'baz')
-  t.equal(cache.has('foo'), false)
-  t.equal(cache.has('blu'), true)
-  setTimeout(function() {
-    t.equal(cache.has('blu'), false)
-    t.end()
-  }, 15)
-})
-
-test("stale", function(t) {
-  var cache = new LRU({
-    maxAge: 10,
-    stale: true
-  })
-
-  cache.set('foo', 'bar')
-  t.equal(cache.get('foo'), 'bar')
-  t.equal(cache.has('foo'), true)
-  setTimeout(function() {
-    t.equal(cache.has('foo'), false)
-    t.equal(cache.get('foo'), 'bar')
-    t.equal(cache.get('foo'), undefined)
-    t.end()
-  }, 15)
-})
-
-test("lru update via set", function(t) {
-  var cache = LRU({ max: 2 });
-
-  cache.set('foo', 1);
-  cache.set('bar', 2);
-  cache.del('bar');
-  cache.set('baz', 3);
-  cache.set('qux', 4);
-
-  t.equal(cache.get('foo'), undefined)
-  t.equal(cache.get('bar'), undefined)
-  t.equal(cache.get('baz'), 3)
-  t.equal(cache.get('qux'), 4)
-  t.end()
-})
-
-test("least recently set w/ peek", function (t) {
-  var cache = new LRU(2)
-  cache.set("a", "A")
-  cache.set("b", "B")
-  t.equal(cache.peek("a"), "A")
-  cache.set("c", "C")
-  t.equal(cache.get("c"), "C")
-  t.equal(cache.get("b"), "B")
-  t.equal(cache.get("a"), undefined)
-  t.end()
-})
-
-test("pop the least used item", function (t) {
-  var cache = new LRU(3)
-  , last
-
-  cache.set("a", "A")
-  cache.set("b", "B")
-  cache.set("c", "C")
-
-  t.equal(cache.length, 3)
-  t.equal(cache.max, 3)
-
-  // Ensure we pop a, c, b
-  cache.get("b", "B")
-
-  last = cache.pop()
-  t.equal(last.key, "a")
-  t.equal(last.value, "A")
-  t.equal(cache.length, 2)
-  t.equal(cache.max, 3)
-
-  last = cache.pop()
-  t.equal(last.key, "c")
-  t.equal(last.value, "C")
-  t.equal(cache.length, 1)
-  t.equal(cache.max, 3)
-
-  last = cache.pop()
-  t.equal(last.key, "b")
-  t.equal(last.value, "B")
-  t.equal(cache.length, 0)
-  t.equal(cache.max, 3)
-
-  last = cache.pop()
-  t.equal(last, null)
-  t.equal(cache.length, 0)
-  t.equal(cache.max, 3)
-
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/foreach.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/foreach.js
deleted file mode 100644
index eefb80d9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/foreach.js
+++ /dev/null
@@ -1,52 +0,0 @@
-var test = require('tap').test
-var LRU = require('../')
-
-test('forEach', function (t) {
-  var l = new LRU(5)
-  for (var i = 0; i < 10; i ++) {
-    l.set(i.toString(), i.toString(2))
-  }
-
-  var i = 9
-  l.forEach(function (val, key, cache) {
-    t.equal(cache, l)
-    t.equal(key, i.toString())
-    t.equal(val, i.toString(2))
-    i -= 1
-  })
-
-  // get in order of most recently used
-  l.get(6)
-  l.get(8)
-
-  var order = [ 8, 6, 9, 7, 5 ]
-  var i = 0
-
-  l.forEach(function (val, key, cache) {
-    var j = order[i ++]
-    t.equal(cache, l)
-    t.equal(key, j.toString())
-    t.equal(val, j.toString(2))
-  })
-
-  t.end()
-})
-
-test('keys() and values()', function (t) {
-  var l = new LRU(5)
-  for (var i = 0; i < 10; i ++) {
-    l.set(i.toString(), i.toString(2))
-  }
-
-  t.similar(l.keys(), ['9', '8', '7', '6', '5'])
-  t.similar(l.values(), ['1001', '1000', '111', '110', '101'])
-
-  // get in order of most recently used
-  l.get(6)
-  l.get(8)
-
-  t.similar(l.keys(), ['8', '6', '9', '7', '5'])
-  t.similar(l.values(), ['1000', '110', '1001', '111', '101'])
-
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js
deleted file mode 100644
index 7af45b02..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env node --expose_gc
-
-var weak = require('weak');
-var test = require('tap').test
-var LRU = require('../')
-var l = new LRU({ max: 10 })
-var refs = 0
-function X() {
-  refs ++
-  weak(this, deref)
-}
-
-function deref() {
-  refs --
-}
-
-test('no leaks', function (t) {
-  // fill up the cache
-  for (var i = 0; i < 100; i++) {
-    l.set(i, new X);
-    // throw some gets in there, too.
-    if (i % 2 === 0)
-      l.get(i / 2)
-  }
-
-  gc()
-
-  var start = process.memoryUsage()
-
-  // capture the memory
-  var startRefs = refs
-
-  // do it again, but more
-  for (var i = 0; i < 10000; i++) {
-    l.set(i, new X);
-    // throw some gets in there, too.
-    if (i % 2 === 0)
-      l.get(i / 2)
-  }
-
-  gc()
-
-  var end = process.memoryUsage()
-  t.equal(refs, startRefs, 'no leaky refs')
-
-  console.error('start: %j\n' +
-                'end:   %j', start, end);
-  t.pass();
-  t.end();
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/README.md
deleted file mode 100644
index 7e365129..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# sigmund
-
-Quick and dirty signatures for Objects.
-
-This is like a much faster `deepEquals` comparison, which returns a
-string key suitable for caches and the like.
-
-## Usage
-
-```javascript
-function doSomething (someObj) {
-  var key = sigmund(someObj, maxDepth) // max depth defaults to 10
-  var cached = cache.get(key)
-  if (cached) return cached)
-
-  var result = expensiveCalculation(someObj)
-  cache.set(key, result)
-  return result
-}
-```
-
-The resulting key will be as unique and reproducible as calling
-`JSON.stringify` or `util.inspect` on the object, but is much faster.
-In order to achieve this speed, some differences are glossed over.
-For example, the object `{0:'foo'}` will be treated identically to the
-array `['foo']`.
-
-Also, just as there is no way to summon the soul from the scribblings
-of a cocain-addled psychoanalyst, there is no way to revive the object
-from the signature string that sigmund gives you.  In fact, it's
-barely even readable.
-
-As with `sys.inspect` and `JSON.stringify`, larger objects will
-produce larger signature strings.
-
-Because sigmund is a bit less strict than the more thorough
-alternatives, the strings will be shorter, and also there is a
-slightly higher chance for collisions.  For example, these objects
-have the same signature:
-
-    var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}
-    var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}
-
-Like a good Freudian, sigmund is most effective when you already have
-some understanding of what you're looking for.  It can help you help
-yourself, but you must be willing to do some work as well.
-
-Cycles are handled, and cyclical objects are silently omitted (though
-the key is included in the signature output.)
-
-The second argument is the maximum depth, which defaults to 10,
-because that is the maximum object traversal depth covered by most
-insurance carriers.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/bench.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/bench.js
deleted file mode 100644
index 5acfd6d9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/bench.js
+++ /dev/null
@@ -1,283 +0,0 @@
-// different ways to id objects
-// use a req/res pair, since it's crazy deep and cyclical
-
-// sparseFE10 and sigmund are usually pretty close, which is to be expected,
-// since they are essentially the same algorithm, except that sigmund handles
-// regular expression objects properly.
-
-
-var http = require('http')
-var util = require('util')
-var sigmund = require('./sigmund.js')
-var sreq, sres, creq, cres, test
-
-http.createServer(function (q, s) {
-  sreq = q
-  sres = s
-  sres.end('ok')
-  this.close(function () { setTimeout(function () {
-    start()
-  }, 200) })
-}).listen(1337, function () {
-  creq = http.get({ port: 1337 })
-  creq.on('response', function (s) { cres = s })
-})
-
-function start () {
-  test = [sreq, sres, creq, cres]
-  // test = sreq
-  // sreq.sres = sres
-  // sreq.creq = creq
-  // sreq.cres = cres
-
-  for (var i in exports.compare) {
-    console.log(i)
-    var hash = exports.compare[i]()
-    console.log(hash)
-    console.log(hash.length)
-    console.log('')
-  }
-
-  require('bench').runMain()
-}
-
-function customWs (obj, md, d) {
-  d = d || 0
-  var to = typeof obj
-  if (to === 'undefined' || to === 'function' || to === null) return ''
-  if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '')
-
-  if (Array.isArray(obj)) {
-    return obj.map(function (i, _, __) {
-      return customWs(i, md, d + 1)
-    }).reduce(function (a, b) { return a + b }, '')
-  }
-
-  var keys = Object.keys(obj)
-  return keys.map(function (k, _, __) {
-    return k + ':' + customWs(obj[k], md, d + 1)
-  }).reduce(function (a, b) { return a + b }, '')
-}
-
-function custom (obj, md, d) {
-  d = d || 0
-  var to = typeof obj
-  if (to === 'undefined' || to === 'function' || to === null) return ''
-  if (d > md || !obj || to !== 'object') return '' + obj
-
-  if (Array.isArray(obj)) {
-    return obj.map(function (i, _, __) {
-      return custom(i, md, d + 1)
-    }).reduce(function (a, b) { return a + b }, '')
-  }
-
-  var keys = Object.keys(obj)
-  return keys.map(function (k, _, __) {
-    return k + ':' + custom(obj[k], md, d + 1)
-  }).reduce(function (a, b) { return a + b }, '')
-}
-
-function sparseFE2 (obj, maxDepth) {
-  var seen = []
-  var soFar = ''
-  function ch (v, depth) {
-    if (depth > maxDepth) return
-    if (typeof v === 'function' || typeof v === 'undefined') return
-    if (typeof v !== 'object' || !v) {
-      soFar += v
-      return
-    }
-    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
-    seen.push(v)
-    soFar += '{'
-    Object.keys(v).forEach(function (k, _, __) {
-      // pseudo-private values.  skip those.
-      if (k.charAt(0) === '_') return
-      var to = typeof v[k]
-      if (to === 'function' || to === 'undefined') return
-      soFar += k + ':'
-      ch(v[k], depth + 1)
-    })
-    soFar += '}'
-  }
-  ch(obj, 0)
-  return soFar
-}
-
-function sparseFE (obj, maxDepth) {
-  var seen = []
-  var soFar = ''
-  function ch (v, depth) {
-    if (depth > maxDepth) return
-    if (typeof v === 'function' || typeof v === 'undefined') return
-    if (typeof v !== 'object' || !v) {
-      soFar += v
-      return
-    }
-    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
-    seen.push(v)
-    soFar += '{'
-    Object.keys(v).forEach(function (k, _, __) {
-      // pseudo-private values.  skip those.
-      if (k.charAt(0) === '_') return
-      var to = typeof v[k]
-      if (to === 'function' || to === 'undefined') return
-      soFar += k
-      ch(v[k], depth + 1)
-    })
-  }
-  ch(obj, 0)
-  return soFar
-}
-
-function sparse (obj, maxDepth) {
-  var seen = []
-  var soFar = ''
-  function ch (v, depth) {
-    if (depth > maxDepth) return
-    if (typeof v === 'function' || typeof v === 'undefined') return
-    if (typeof v !== 'object' || !v) {
-      soFar += v
-      return
-    }
-    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
-    seen.push(v)
-    soFar += '{'
-    for (var k in v) {
-      // pseudo-private values.  skip those.
-      if (k.charAt(0) === '_') continue
-      var to = typeof v[k]
-      if (to === 'function' || to === 'undefined') continue
-      soFar += k
-      ch(v[k], depth + 1)
-    }
-  }
-  ch(obj, 0)
-  return soFar
-}
-
-function noCommas (obj, maxDepth) {
-  var seen = []
-  var soFar = ''
-  function ch (v, depth) {
-    if (depth > maxDepth) return
-    if (typeof v === 'function' || typeof v === 'undefined') return
-    if (typeof v !== 'object' || !v) {
-      soFar += v
-      return
-    }
-    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
-    seen.push(v)
-    soFar += '{'
-    for (var k in v) {
-      // pseudo-private values.  skip those.
-      if (k.charAt(0) === '_') continue
-      var to = typeof v[k]
-      if (to === 'function' || to === 'undefined') continue
-      soFar += k + ':'
-      ch(v[k], depth + 1)
-    }
-    soFar += '}'
-  }
-  ch(obj, 0)
-  return soFar
-}
-
-
-function flatten (obj, maxDepth) {
-  var seen = []
-  var soFar = ''
-  function ch (v, depth) {
-    if (depth > maxDepth) return
-    if (typeof v === 'function' || typeof v === 'undefined') return
-    if (typeof v !== 'object' || !v) {
-      soFar += v
-      return
-    }
-    if (seen.indexOf(v) !== -1 || depth === maxDepth) return
-    seen.push(v)
-    soFar += '{'
-    for (var k in v) {
-      // pseudo-private values.  skip those.
-      if (k.charAt(0) === '_') continue
-      var to = typeof v[k]
-      if (to === 'function' || to === 'undefined') continue
-      soFar += k + ':'
-      ch(v[k], depth + 1)
-      soFar += ','
-    }
-    soFar += '}'
-  }
-  ch(obj, 0)
-  return soFar
-}
-
-exports.compare =
-{
-  // 'custom 2': function () {
-  //   return custom(test, 2, 0)
-  // },
-  // 'customWs 2': function () {
-  //   return customWs(test, 2, 0)
-  // },
-  'JSON.stringify (guarded)': function () {
-    var seen = []
-    return JSON.stringify(test, function (k, v) {
-      if (typeof v !== 'object' || !v) return v
-      if (seen.indexOf(v) !== -1) return undefined
-      seen.push(v)
-      return v
-    })
-  },
-
-  'flatten 10': function () {
-    return flatten(test, 10)
-  },
-
-  // 'flattenFE 10': function () {
-  //   return flattenFE(test, 10)
-  // },
-
-  'noCommas 10': function () {
-    return noCommas(test, 10)
-  },
-
-  'sparse 10': function () {
-    return sparse(test, 10)
-  },
-
-  'sparseFE 10': function () {
-    return sparseFE(test, 10)
-  },
-
-  'sparseFE2 10': function () {
-    return sparseFE2(test, 10)
-  },
-
-  sigmund: function() {
-    return sigmund(test, 10)
-  },
-
-
-  // 'util.inspect 1': function () {
-  //   return util.inspect(test, false, 1, false)
-  // },
-  // 'util.inspect undefined': function () {
-  //   util.inspect(test)
-  // },
-  // 'util.inspect 2': function () {
-  //   util.inspect(test, false, 2, false)
-  // },
-  // 'util.inspect 3': function () {
-  //   util.inspect(test, false, 3, false)
-  // },
-  // 'util.inspect 4': function () {
-  //   util.inspect(test, false, 4, false)
-  // },
-  // 'util.inspect Infinity': function () {
-  //   util.inspect(test, false, Infinity, false)
-  // }
-}
-
-/** results
-**/
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/package.json
deleted file mode 100644
index d93de798..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/package.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-  "name": "sigmund",
-  "version": "1.0.0",
-  "description": "Quick and dirty signatures for Objects.",
-  "main": "sigmund.js",
-  "directories": {
-    "test": "test"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "tap": "~0.3.0"
-  },
-  "scripts": {
-    "test": "tap test/*.js",
-    "bench": "node bench.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/sigmund"
-  },
-  "keywords": [
-    "object",
-    "signature",
-    "key",
-    "data",
-    "psychoanalysis"
-  ],
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "license": "BSD",
-  "readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n  var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n  var cached = cache.get(key)\n  if (cached) return cached)\n\n  var result = expensiveCalculation(someObj)\n  cache.set(key, result)\n  return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you.  In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions.  For example, these objects\nhave the same signature:\n\n    var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n    var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for.  It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/sigmund/issues"
-  },
-  "homepage": "https://github.com/isaacs/sigmund",
-  "_id": "sigmund@1.0.0",
-  "_shasum": "66a2b3a749ae8b5fb89efd4fcc01dc94fbe02296",
-  "_from": "sigmund@~1.0.0",
-  "_resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/sigmund.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/sigmund.js
deleted file mode 100644
index 82c7ab8c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/sigmund.js
+++ /dev/null
@@ -1,39 +0,0 @@
-module.exports = sigmund
-function sigmund (subject, maxSessions) {
-    maxSessions = maxSessions || 10;
-    var notes = [];
-    var analysis = '';
-    var RE = RegExp;
-
-    function psychoAnalyze (subject, session) {
-        if (session > maxSessions) return;
-
-        if (typeof subject === 'function' ||
-            typeof subject === 'undefined') {
-            return;
-        }
-
-        if (typeof subject !== 'object' || !subject ||
-            (subject instanceof RE)) {
-            analysis += subject;
-            return;
-        }
-
-        if (notes.indexOf(subject) !== -1 || session === maxSessions) return;
-
-        notes.push(subject);
-        analysis += '{';
-        Object.keys(subject).forEach(function (issue, _, __) {
-            // pseudo-private values.  skip those.
-            if (issue.charAt(0) === '_') return;
-            var to = typeof subject[issue];
-            if (to === 'function' || to === 'undefined') return;
-            analysis += issue;
-            psychoAnalyze(subject[issue], session + 1);
-        });
-    }
-    psychoAnalyze(subject, 0);
-    return analysis;
-}
-
-// vim: set softtabstop=4 shiftwidth=4:
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/test/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/test/basic.js
deleted file mode 100644
index 50c53a13..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/node_modules/sigmund/test/basic.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var test = require('tap').test
-var sigmund = require('../sigmund.js')
-
-
-// occasionally there are duplicates
-// that's an acceptable edge-case.  JSON.stringify and util.inspect
-// have some collision potential as well, though less, and collision
-// detection is expensive.
-var hash = '{abc/def/g{0h1i2{jkl'
-var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}
-var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}
-
-var obj3 = JSON.parse(JSON.stringify(obj1))
-obj3.c = /def/
-obj3.g[2].cycle = obj3
-var cycleHash = '{abc/def/g{0h1i2{jklcycle'
-
-test('basic', function (t) {
-    t.equal(sigmund(obj1), hash)
-    t.equal(sigmund(obj2), hash)
-    t.equal(sigmund(obj3), cycleHash)
-    t.end()
-})
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/package.json
deleted file mode 100644
index 30f45ac6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/package.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me"
-  },
-  "name": "minimatch",
-  "description": "a glob matcher in javascript",
-  "version": "0.2.14",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/minimatch.git"
-  },
-  "main": "minimatch.js",
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "engines": {
-    "node": "*"
-  },
-  "dependencies": {
-    "lru-cache": "2",
-    "sigmund": "~1.0.0"
-  },
-  "devDependencies": {
-    "tap": ""
-  },
-  "license": {
-    "type": "MIT",
-    "url": "http://github.com/isaacs/minimatch/raw/master/LICENSE"
-  },
-  "readme": "# minimatch\n\nA minimal matching utility.\n\n[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)\n\n\nThis is the matching library used internally by npm.\n\nEventually, it will replace the C binding in node-glob.\n\nIt works by converting glob expressions into JavaScript `RegExp`\nobjects.\n\n## Usage\n\n```javascript\nvar minimatch = require(\"minimatch\")\n\nminimatch(\"bar.foo\", \"*.foo\") // true!\nminimatch(\"bar.foo\", \"*.bar\") // false!\nminimatch(\"bar.foo\", \"*.+(bar|foo)\", { debug: true }) // true, and noisy!\n```\n\n## Features\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n\n## Minimatch Class\n\nCreate a minimatch object by instanting the `minimatch.Minimatch` class.\n\n```javascript\nvar Minimatch = require(\"minimatch\").Minimatch\nvar mm = new Minimatch(pattern, options)\n```\n\n### Properties\n\n* `pattern` The original pattern the minimatch object represents.\n* `options` The options supplied to the constructor.\n* `set` A 2-dimensional array of regexp or string expressions.\n  Each row in the\n  array corresponds to a brace-expanded pattern.  Each item in the row\n  corresponds to a single path-part.  For example, the pattern\n  `{a,b/c}/d` would expand to a set of patterns like:\n\n        [ [ a, d ]\n        , [ b, c, d ] ]\n\n    If a portion of the pattern doesn't have any \"magic\" in it\n    (that is, it's something like `\"foo\"` rather than `fo*o?`), then it\n    will be left as a string rather than converted to a regular\n    expression.\n\n* `regexp` Created by the `makeRe` method.  A single regular expression\n  expressing the entire pattern.  This is useful in cases where you wish\n  to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.\n* `negate` True if the pattern is negated.\n* `comment` True if the pattern is a comment.\n* `empty` True if the pattern is `\"\"`.\n\n### Methods\n\n* `makeRe` Generate the `regexp` member if necessary, and return it.\n  Will return `false` if the pattern is invalid.\n* `match(fname)` Return true if the filename matches the pattern, or\n  false otherwise.\n* `matchOne(fileArray, patternArray, partial)` Take a `/`-split\n  filename, and match it against a single row in the `regExpSet`.  This\n  method is mainly for internal use, but is exposed so that it can be\n  used by a glob-walker that needs to avoid excessive filesystem calls.\n\nAll other methods are internal, and will be called as necessary.\n\n## Functions\n\nThe top-level exported function has a `cache` property, which is an LRU\ncache set to store 100 items.  So, calling these methods repeatedly\nwith the same pattern and options will use the same Minimatch object,\nsaving the cost of parsing it multiple times.\n\n### minimatch(path, pattern, options)\n\nMain export.  Tests a path against the pattern using the options.\n\n```javascript\nvar isJS = minimatch(file, \"*.js\", { matchBase: true })\n```\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`.  Example:\n\n```javascript\nvar javascripts = fileList.filter(minimatch.filter(\"*.js\", {matchBase: true}))\n```\n\n### minimatch.match(list, pattern, options)\n\nMatch against the list of\nfiles, in the style of fnmatch or glob.  If nothing is matched, and\noptions.nonull is set, then return a list containing the pattern itself.\n\n```javascript\nvar javascripts = minimatch.match(fileList, \"*.js\", {matchBase: true}))\n```\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object from the pattern.\n\n## Options\n\nAll options are `false` by default.\n\n### debug\n\nDump a ton of stuff to stderr.\n\n### nobrace\n\nDo not expand `{a,b}` and `{1..3}` brace sets.\n\n### noglobstar\n\nDisable `**` matching against multiple folder names.\n\n### dot\n\nAllow patterns to match filenames starting with a period, even if\nthe pattern does not explicitly have a period in that spot.\n\nNote that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`\nis set.\n\n### noext\n\nDisable \"extglob\" style patterns like `+(a|b)`.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### nonull\n\nWhen a match is not found by `minimatch.match`, return a list containing\nthe pattern itself.  When set, an empty list is returned if there are\nno matches.\n\n### matchBase\n\nIf set, then patterns without slashes will be matched\nagainst the basename of the path if it contains slashes.  For example,\n`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.\n\n### nocomment\n\nSuppress the behavior of treating `#` at the start of a pattern as a\ncomment.\n\n### nonegate\n\nSuppress the behavior of treating a leading `!` character as negation.\n\n### flipNegate\n\nReturns from negate expressions the same as if they were not negated.\n(Ie, true on a hit, false on a miss.)\n\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between minimatch and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated.  Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally.  This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything.  Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set.  This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not.\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen minimatch.match returns the pattern as-provided, rather than\ninterpreting the character escapes.  For example,\n`minimatch.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`.  This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern.  Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity.  Since those two are valid, matching proceeds.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/minimatch/issues"
-  },
-  "homepage": "https://github.com/isaacs/minimatch",
-  "_id": "minimatch@0.2.14",
-  "_shasum": "c74e780574f63c6f9a090e90efbe6ef53a6a756a",
-  "_from": "minimatch@~0.2.0",
-  "_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/basic.js
deleted file mode 100644
index ae7ac73c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/basic.js
+++ /dev/null
@@ -1,399 +0,0 @@
-// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test
-//
-// TODO: Some of these tests do very bad things with backslashes, and will
-// most likely fail badly on windows.  They should probably be skipped.
-
-var tap = require("tap")
-  , globalBefore = Object.keys(global)
-  , mm = require("../")
-  , files = [ "a", "b", "c", "d", "abc"
-            , "abd", "abe", "bb", "bcd"
-            , "ca", "cb", "dd", "de"
-            , "bdir/", "bdir/cfile"]
-  , next = files.concat([ "a-b", "aXb"
-                        , ".x", ".y" ])
-
-
-var patterns =
-  [ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test"
-  , ["a*", ["a", "abc", "abd", "abe"]]
-  , ["X*", ["X*"], {nonull: true}]
-
-  // allow null glob expansion
-  , ["X*", []]
-
-  // isaacs: Slightly different than bash/sh/ksh
-  // \\* is not un-escaped to literal "*" in a failed match,
-  // but it does make it get treated as a literal star
-  , ["\\*", ["\\*"], {nonull: true}]
-  , ["\\**", ["\\**"], {nonull: true}]
-  , ["\\*\\*", ["\\*\\*"], {nonull: true}]
-
-  , ["b*/", ["bdir/"]]
-  , ["c*", ["c", "ca", "cb"]]
-  , ["**", files]
-
-  , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}]
-  , ["s/\\..*//", ["s/\\..*//"], {nonull: true}]
-
-  , "legendary larry crashes bashes"
-  , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"
-    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}]
-  , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"
-    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}]
-
-  , "character classes"
-  , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]]
-  , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd",
-     "bdir/", "ca", "cb", "dd", "de"]]
-  , ["a*[^c]", ["abd", "abe"]]
-  , function () { files.push("a-b", "aXb") }
-  , ["a[X-]b", ["a-b", "aXb"]]
-  , function () { files.push(".x", ".y") }
-  , ["[^a-c]*", ["d", "dd", "de"]]
-  , function () { files.push("a*b/", "a*b/ooo") }
-  , ["a\\*b/*", ["a*b/ooo"]]
-  , ["a\\*?/*", ["a*b/ooo"]]
-  , ["*\\\\!*", [], {null: true}, ["echo !7"]]
-  , ["*\\!*", ["echo !7"], null, ["echo !7"]]
-  , ["*.\\*", ["r.*"], null, ["r.*"]]
-  , ["a[b]c", ["abc"]]
-  , ["a[\\b]c", ["abc"]]
-  , ["a?c", ["abc"]]
-  , ["a\\*c", [], {null: true}, ["abc"]]
-  , ["", [""], { null: true }, [""]]
-
-  , "http://www.opensource.apple.com/source/bash/bash-23/" +
-    "bash/tests/glob-test"
-  , function () { files.push("man/", "man/man1/", "man/man1/bash.1") }
-  , ["*/man*/bash.*", ["man/man1/bash.1"]]
-  , ["man/man1/bash.1", ["man/man1/bash.1"]]
-  , ["a***c", ["abc"], null, ["abc"]]
-  , ["a*****?c", ["abc"], null, ["abc"]]
-  , ["?*****??", ["abc"], null, ["abc"]]
-  , ["*****??", ["abc"], null, ["abc"]]
-  , ["?*****?c", ["abc"], null, ["abc"]]
-  , ["?***?****c", ["abc"], null, ["abc"]]
-  , ["?***?****?", ["abc"], null, ["abc"]]
-  , ["?***?****", ["abc"], null, ["abc"]]
-  , ["*******c", ["abc"], null, ["abc"]]
-  , ["*******?", ["abc"], null, ["abc"]]
-  , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-  , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-  , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-  , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-  , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-  , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-  , ["[-abc]", ["-"], null, ["-"]]
-  , ["[abc-]", ["-"], null, ["-"]]
-  , ["\\", ["\\"], null, ["\\"]]
-  , ["[\\\\]", ["\\"], null, ["\\"]]
-  , ["[[]", ["["], null, ["["]]
-  , ["[", ["["], null, ["["]]
-  , ["[*", ["[abc"], null, ["[abc"]]
-  , "a right bracket shall lose its special meaning and\n" +
-    "represent itself in a bracket expression if it occurs\n" +
-    "first in the list.  -- POSIX.2 2.8.3.2"
-  , ["[]]", ["]"], null, ["]"]]
-  , ["[]-]", ["]"], null, ["]"]]
-  , ["[a-\z]", ["p"], null, ["p"]]
-  , ["??**********?****?", [], { null: true }, ["abc"]]
-  , ["??**********?****c", [], { null: true }, ["abc"]]
-  , ["?************c****?****", [], { null: true }, ["abc"]]
-  , ["*c*?**", [], { null: true }, ["abc"]]
-  , ["a*****c*?**", [], { null: true }, ["abc"]]
-  , ["a********???*******", [], { null: true }, ["abc"]]
-  , ["[]", [], { null: true }, ["a"]]
-  , ["[abc", [], { null: true }, ["["]]
-
-  , "nocase tests"
-  , ["XYZ", ["xYz"], { nocase: true, null: true }
-    , ["xYz", "ABC", "IjK"]]
-  , ["ab*", ["ABC"], { nocase: true, null: true }
-    , ["xYz", "ABC", "IjK"]]
-  , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true }
-    , ["xYz", "ABC", "IjK"]]
-
-  // [ pattern, [matches], MM opts, files, TAP opts]
-  , "onestar/twostar"
-  , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]]
-  , ["{/?,*}", ["/a", "bb"], {null: true}
-    , ["/a", "/b/b", "/a/b/c", "bb"]]
-
-  , "dots should not match unless requested"
-  , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]]
-
-  // .. and . can only match patterns starting with .,
-  // even when options.dot is set.
-  , function () {
-      files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"]
-    }
-  , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}]
-  , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}]
-  , ["a/*/b", ["a/c/b"], {dot:false}]
-  , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}]
-
-
-  // this also tests that changing the options needs
-  // to change the cache key, even if the pattern is
-  // the same!
-  , ["**", ["a/b","a/.d",".a/.d"], { dot: true }
-    , [ ".a/.d", "a/.d", "a/b"]]
-
-  , "paren sets cannot contain slashes"
-  , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]]
-
-  // brace sets trump all else.
-  //
-  // invalid glob pattern.  fails on bash4 and bsdglob.
-  // however, in this implementation, it's easier just
-  // to do the intuitive thing, and let brace-expansion
-  // actually come before parsing any extglob patterns,
-  // like the documentation seems to say.
-  //
-  // XXX: if anyone complains about this, either fix it
-  // or tell them to grow up and stop complaining.
-  //
-  // bash/bsdglob says this:
-  // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]]
-  // but we do this instead:
-  , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]]
-
-  // test partial parsing in the presence of comment/negation chars
-  , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]]
-  , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]]
-
-  // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped.
-  , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g"
-    , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"]
-    , {}
-    , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]]
-
-
-  // crazy nested {,,} and *(||) tests.
-  , function () {
-      files = [ "a", "b", "c", "d"
-              , "ab", "ac", "ad"
-              , "bc", "cb"
-              , "bc,d", "c,db", "c,d"
-              , "d)", "(b|c", "*(b|c"
-              , "b|c", "b|cc", "cb|c"
-              , "x(a|b|c)", "x(a|c)"
-              , "(a|b|c)", "(a|c)"]
-    }
-  , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]]
-  , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]]
-  // a
-  // *(b|c)
-  // *(b|d)
-  , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]]
-  , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]]
-
-
-  // test various flag settings.
-  , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"]
-    , { noext: true } ]
-  , ["a?b", ["x/y/acb", "acb/"], {matchBase: true}
-    , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ]
-  , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]]
-
-
-  // begin channelling Boole and deMorgan...
-  , "negation tests"
-  , function () {
-      files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"]
-    }
-
-  // anything that is NOT a* matches.
-  , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]]
-
-  // anything that IS !a* matches.
-  , ["!a*", ["!ab", "!abc"], {nonegate: true}]
-
-  // anything that IS a* matches
-  , ["!!a*", ["a!b"]]
-
-  // anything that is NOT !a* matches
-  , ["!\\!a*", ["a!b", "d", "e", "\\!a"]]
-
-  // negation nestled within a pattern
-  , function () {
-      files = [ "foo.js"
-              , "foo.bar"
-              // can't match this one without negative lookbehind.
-              , "foo.js.js"
-              , "blar.js"
-              , "foo."
-              , "boo.js.boo" ]
-    }
-  , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ]
-
-  // https://github.com/isaacs/minimatch/issues/5
-  , function () {
-      files = [ 'a/b/.x/c'
-              , 'a/b/.x/c/d'
-              , 'a/b/.x/c/d/e'
-              , 'a/b/.x'
-              , 'a/b/.x/'
-              , 'a/.x/b'
-              , '.x'
-              , '.x/'
-              , '.x/a'
-              , '.x/a/b'
-              , 'a/.x/b/.x/c'
-              , '.x/.x' ]
-  }
-  , ["**/.x/**", [ '.x/'
-                 , '.x/a'
-                 , '.x/a/b'
-                 , 'a/.x/b'
-                 , 'a/b/.x/'
-                 , 'a/b/.x/c'
-                 , 'a/b/.x/c/d'
-                 , 'a/b/.x/c/d/e' ] ]
-
-  ]
-
-var regexps =
-  [ '/^(?:(?=.)a[^/]*?)$/',
-    '/^(?:(?=.)X[^/]*?)$/',
-    '/^(?:(?=.)X[^/]*?)$/',
-    '/^(?:\\*)$/',
-    '/^(?:(?=.)\\*[^/]*?)$/',
-    '/^(?:\\*\\*)$/',
-    '/^(?:(?=.)b[^/]*?\\/)$/',
-    '/^(?:(?=.)c[^/]*?)$/',
-    '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
-    '/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/',
-    '/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/',
-    '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/',
-    '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/',
-    '/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/',
-    '/^(?:(?=.)a[^/]*?[^c])$/',
-    '/^(?:(?=.)a[X-]b)$/',
-    '/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/',
-    '/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/',
-    '/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/',
-    '/^(?:(?=.)a[b]c)$/',
-    '/^(?:(?=.)a[b]c)$/',
-    '/^(?:(?=.)a[^/]c)$/',
-    '/^(?:a\\*c)$/',
-    'false',
-    '/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/',
-    '/^(?:man\\/man1\\/bash\\.1)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
-    '/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[-abc])$/',
-    '/^(?:(?!\\.)(?=.)[abc-])$/',
-    '/^(?:\\\\)$/',
-    '/^(?:(?!\\.)(?=.)[\\\\])$/',
-    '/^(?:(?!\\.)(?=.)[\\[])$/',
-    '/^(?:\\[)$/',
-    '/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[\\]])$/',
-    '/^(?:(?!\\.)(?=.)[\\]-])$/',
-    '/^(?:(?!\\.)(?=.)[a-z])$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/',
-    '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/',
-    '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/',
-    '/^(?:\\[\\])$/',
-    '/^(?:\\[abc)$/',
-    '/^(?:(?=.)XYZ)$/i',
-    '/^(?:(?=.)ab[^/]*?)$/i',
-    '/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i',
-    '/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/',
-    '/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/',
-    '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/',
-    '/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/',
-    '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
-    '/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/',
-    '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/',
-    '/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/',
-    '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
-    '/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/',
-    '/^(?:(?=.)\\[(?=.)#a[^/]*?)$/',
-    '/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/',
-    '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/',
-    '/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/',
-    '/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/',
-    '/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/',
-    '/^(?:(?=.)a[^/]b)$/',
-    '/^(?:(?=.)#[^/]*?)$/',
-    '/^(?!^(?:(?=.)a[^/]*?)$).*$/',
-    '/^(?:(?=.)\\!a[^/]*?)$/',
-    '/^(?:(?=.)a[^/]*?)$/',
-    '/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/',
-    '/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/',
-    '/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ]
-var re = 0;
-
-tap.test("basic tests", function (t) {
-  var start = Date.now()
-
-  // [ pattern, [matches], MM opts, files, TAP opts]
-  patterns.forEach(function (c) {
-    if (typeof c === "function") return c()
-    if (typeof c === "string") return t.comment(c)
-
-    var pattern = c[0]
-      , expect = c[1].sort(alpha)
-      , options = c[2] || {}
-      , f = c[3] || files
-      , tapOpts = c[4] || {}
-
-    // options.debug = true
-    var m = new mm.Minimatch(pattern, options)
-    var r = m.makeRe()
-    var expectRe = regexps[re++]
-    tapOpts.re = String(r) || JSON.stringify(r)
-    tapOpts.files = JSON.stringify(f)
-    tapOpts.pattern = pattern
-    tapOpts.set = m.set
-    tapOpts.negated = m.negate
-
-    var actual = mm.match(f, pattern, options)
-    actual.sort(alpha)
-
-    t.equivalent( actual, expect
-                , JSON.stringify(pattern) + " " + JSON.stringify(expect)
-                , tapOpts )
-
-    t.equal(tapOpts.re, expectRe, tapOpts)
-  })
-
-  t.comment("time=" + (Date.now() - start) + "ms")
-  t.end()
-})
-
-tap.test("global leak test", function (t) {
-  var globalAfter = Object.keys(global)
-  t.equivalent(globalAfter, globalBefore, "no new globals, please")
-  t.end()
-})
-
-function alpha (a, b) {
-  return a > b ? 1 : -1
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/brace-expand.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/brace-expand.js
deleted file mode 100644
index 7ee278a2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/brace-expand.js
+++ /dev/null
@@ -1,33 +0,0 @@
-var tap = require("tap")
-  , minimatch = require("../")
-
-tap.test("brace expansion", function (t) {
-  // [ pattern, [expanded] ]
-  ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}"
-      , [ "abxy"
-        , "abxz"
-        , "acdxy"
-        , "acdxz"
-        , "acexy"
-        , "acexz"
-        , "afhxy"
-        , "afhxz"
-        , "aghxy"
-        , "aghxz" ] ]
-    , [ "a{1..5}b"
-      , [ "a1b"
-        , "a2b"
-        , "a3b"
-        , "a4b"
-        , "a5b" ] ]
-    , [ "a{b}c", ["a{b}c"] ]
-  ].forEach(function (tc) {
-    var p = tc[0]
-      , expect = tc[1]
-    t.equivalent(minimatch.braceExpand(p), expect, p)
-  })
-  console.error("ending")
-  t.end()
-})
-
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/caching.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/caching.js
deleted file mode 100644
index 0fec4b0f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/caching.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var Minimatch = require("../minimatch.js").Minimatch
-var tap = require("tap")
-tap.test("cache test", function (t) {
-  var mm1 = new Minimatch("a?b")
-  var mm2 = new Minimatch("a?b")
-  t.equal(mm1, mm2, "should get the same object")
-  // the lru should drop it after 100 entries
-  for (var i = 0; i < 100; i ++) {
-    new Minimatch("a"+i)
-  }
-  mm2 = new Minimatch("a?b")
-  t.notEqual(mm1, mm2, "cache should have dropped")
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/defaults.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/defaults.js
deleted file mode 100644
index 25f1f601..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/defaults.js
+++ /dev/null
@@ -1,274 +0,0 @@
-// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test
-//
-// TODO: Some of these tests do very bad things with backslashes, and will
-// most likely fail badly on windows.  They should probably be skipped.
-
-var tap = require("tap")
-  , globalBefore = Object.keys(global)
-  , mm = require("../")
-  , files = [ "a", "b", "c", "d", "abc"
-            , "abd", "abe", "bb", "bcd"
-            , "ca", "cb", "dd", "de"
-            , "bdir/", "bdir/cfile"]
-  , next = files.concat([ "a-b", "aXb"
-                        , ".x", ".y" ])
-
-tap.test("basic tests", function (t) {
-  var start = Date.now()
-
-  // [ pattern, [matches], MM opts, files, TAP opts]
-  ; [ "http://www.bashcookbook.com/bashinfo" +
-      "/source/bash-1.14.7/tests/glob-test"
-    , ["a*", ["a", "abc", "abd", "abe"]]
-    , ["X*", ["X*"], {nonull: true}]
-
-    // allow null glob expansion
-    , ["X*", []]
-
-    // isaacs: Slightly different than bash/sh/ksh
-    // \\* is not un-escaped to literal "*" in a failed match,
-    // but it does make it get treated as a literal star
-    , ["\\*", ["\\*"], {nonull: true}]
-    , ["\\**", ["\\**"], {nonull: true}]
-    , ["\\*\\*", ["\\*\\*"], {nonull: true}]
-
-    , ["b*/", ["bdir/"]]
-    , ["c*", ["c", "ca", "cb"]]
-    , ["**", files]
-
-    , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}]
-    , ["s/\\..*//", ["s/\\..*//"], {nonull: true}]
-
-    , "legendary larry crashes bashes"
-    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"
-      , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}]
-    , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"
-      , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}]
-
-    , "character classes"
-    , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]]
-    , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd",
-       "bdir/", "ca", "cb", "dd", "de"]]
-    , ["a*[^c]", ["abd", "abe"]]
-    , function () { files.push("a-b", "aXb") }
-    , ["a[X-]b", ["a-b", "aXb"]]
-    , function () { files.push(".x", ".y") }
-    , ["[^a-c]*", ["d", "dd", "de"]]
-    , function () { files.push("a*b/", "a*b/ooo") }
-    , ["a\\*b/*", ["a*b/ooo"]]
-    , ["a\\*?/*", ["a*b/ooo"]]
-    , ["*\\\\!*", [], {null: true}, ["echo !7"]]
-    , ["*\\!*", ["echo !7"], null, ["echo !7"]]
-    , ["*.\\*", ["r.*"], null, ["r.*"]]
-    , ["a[b]c", ["abc"]]
-    , ["a[\\b]c", ["abc"]]
-    , ["a?c", ["abc"]]
-    , ["a\\*c", [], {null: true}, ["abc"]]
-    , ["", [""], { null: true }, [""]]
-
-    , "http://www.opensource.apple.com/source/bash/bash-23/" +
-      "bash/tests/glob-test"
-    , function () { files.push("man/", "man/man1/", "man/man1/bash.1") }
-    , ["*/man*/bash.*", ["man/man1/bash.1"]]
-    , ["man/man1/bash.1", ["man/man1/bash.1"]]
-    , ["a***c", ["abc"], null, ["abc"]]
-    , ["a*****?c", ["abc"], null, ["abc"]]
-    , ["?*****??", ["abc"], null, ["abc"]]
-    , ["*****??", ["abc"], null, ["abc"]]
-    , ["?*****?c", ["abc"], null, ["abc"]]
-    , ["?***?****c", ["abc"], null, ["abc"]]
-    , ["?***?****?", ["abc"], null, ["abc"]]
-    , ["?***?****", ["abc"], null, ["abc"]]
-    , ["*******c", ["abc"], null, ["abc"]]
-    , ["*******?", ["abc"], null, ["abc"]]
-    , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-    , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-    , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-    , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-    , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-    , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]]
-    , ["[-abc]", ["-"], null, ["-"]]
-    , ["[abc-]", ["-"], null, ["-"]]
-    , ["\\", ["\\"], null, ["\\"]]
-    , ["[\\\\]", ["\\"], null, ["\\"]]
-    , ["[[]", ["["], null, ["["]]
-    , ["[", ["["], null, ["["]]
-    , ["[*", ["[abc"], null, ["[abc"]]
-    , "a right bracket shall lose its special meaning and\n" +
-      "represent itself in a bracket expression if it occurs\n" +
-      "first in the list.  -- POSIX.2 2.8.3.2"
-    , ["[]]", ["]"], null, ["]"]]
-    , ["[]-]", ["]"], null, ["]"]]
-    , ["[a-\z]", ["p"], null, ["p"]]
-    , ["??**********?****?", [], { null: true }, ["abc"]]
-    , ["??**********?****c", [], { null: true }, ["abc"]]
-    , ["?************c****?****", [], { null: true }, ["abc"]]
-    , ["*c*?**", [], { null: true }, ["abc"]]
-    , ["a*****c*?**", [], { null: true }, ["abc"]]
-    , ["a********???*******", [], { null: true }, ["abc"]]
-    , ["[]", [], { null: true }, ["a"]]
-    , ["[abc", [], { null: true }, ["["]]
-
-    , "nocase tests"
-    , ["XYZ", ["xYz"], { nocase: true, null: true }
-      , ["xYz", "ABC", "IjK"]]
-    , ["ab*", ["ABC"], { nocase: true, null: true }
-      , ["xYz", "ABC", "IjK"]]
-    , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true }
-      , ["xYz", "ABC", "IjK"]]
-
-    // [ pattern, [matches], MM opts, files, TAP opts]
-    , "onestar/twostar"
-    , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]]
-    , ["{/?,*}", ["/a", "bb"], {null: true}
-      , ["/a", "/b/b", "/a/b/c", "bb"]]
-
-    , "dots should not match unless requested"
-    , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]]
-
-    // .. and . can only match patterns starting with .,
-    // even when options.dot is set.
-    , function () {
-        files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"]
-      }
-    , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}]
-    , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}]
-    , ["a/*/b", ["a/c/b"], {dot:false}]
-    , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}]
-
-
-    // this also tests that changing the options needs
-    // to change the cache key, even if the pattern is
-    // the same!
-    , ["**", ["a/b","a/.d",".a/.d"], { dot: true }
-      , [ ".a/.d", "a/.d", "a/b"]]
-
-    , "paren sets cannot contain slashes"
-    , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]]
-
-    // brace sets trump all else.
-    //
-    // invalid glob pattern.  fails on bash4 and bsdglob.
-    // however, in this implementation, it's easier just
-    // to do the intuitive thing, and let brace-expansion
-    // actually come before parsing any extglob patterns,
-    // like the documentation seems to say.
-    //
-    // XXX: if anyone complains about this, either fix it
-    // or tell them to grow up and stop complaining.
-    //
-    // bash/bsdglob says this:
-    // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]]
-    // but we do this instead:
-    , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]]
-
-    // test partial parsing in the presence of comment/negation chars
-    , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]]
-    , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]]
-
-    // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped.
-    , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g"
-      , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"]
-      , {}
-      , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]]
-
-
-    // crazy nested {,,} and *(||) tests.
-    , function () {
-        files = [ "a", "b", "c", "d"
-                , "ab", "ac", "ad"
-                , "bc", "cb"
-                , "bc,d", "c,db", "c,d"
-                , "d)", "(b|c", "*(b|c"
-                , "b|c", "b|cc", "cb|c"
-                , "x(a|b|c)", "x(a|c)"
-                , "(a|b|c)", "(a|c)"]
-      }
-    , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]]
-    , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]]
-    // a
-    // *(b|c)
-    // *(b|d)
-    , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]]
-    , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]]
-
-
-    // test various flag settings.
-    , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"]
-      , { noext: true } ]
-    , ["a?b", ["x/y/acb", "acb/"], {matchBase: true}
-      , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ]
-    , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]]
-
-
-    // begin channelling Boole and deMorgan...
-    , "negation tests"
-    , function () {
-        files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"]
-      }
-
-    // anything that is NOT a* matches.
-    , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]]
-
-    // anything that IS !a* matches.
-    , ["!a*", ["!ab", "!abc"], {nonegate: true}]
-
-    // anything that IS a* matches
-    , ["!!a*", ["a!b"]]
-
-    // anything that is NOT !a* matches
-    , ["!\\!a*", ["a!b", "d", "e", "\\!a"]]
-
-    // negation nestled within a pattern
-    , function () {
-        files = [ "foo.js"
-                , "foo.bar"
-                // can't match this one without negative lookbehind.
-                , "foo.js.js"
-                , "blar.js"
-                , "foo."
-                , "boo.js.boo" ]
-      }
-    , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ]
-
-    ].forEach(function (c) {
-      if (typeof c === "function") return c()
-      if (typeof c === "string") return t.comment(c)
-
-      var pattern = c[0]
-        , expect = c[1].sort(alpha)
-        , options = c[2] || {}
-        , f = c[3] || files
-        , tapOpts = c[4] || {}
-
-      // options.debug = true
-      var Class = mm.defaults(options).Minimatch
-      var m = new Class(pattern, {})
-      var r = m.makeRe()
-      tapOpts.re = String(r) || JSON.stringify(r)
-      tapOpts.files = JSON.stringify(f)
-      tapOpts.pattern = pattern
-      tapOpts.set = m.set
-      tapOpts.negated = m.negate
-
-      var actual = mm.match(f, pattern, options)
-      actual.sort(alpha)
-
-      t.equivalent( actual, expect
-                  , JSON.stringify(pattern) + " " + JSON.stringify(expect)
-                  , tapOpts )
-    })
-
-  t.comment("time=" + (Date.now() - start) + "ms")
-  t.end()
-})
-
-tap.test("global leak test", function (t) {
-  var globalAfter = Object.keys(global)
-  t.equivalent(globalAfter, globalBefore, "no new globals, please")
-  t.end()
-})
-
-function alpha (a, b) {
-  return a > b ? 1 : -1
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/extglob-ending-with-state-char.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/extglob-ending-with-state-char.js
deleted file mode 100644
index 6676e262..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/node_modules/minimatch/test/extglob-ending-with-state-char.js
+++ /dev/null
@@ -1,8 +0,0 @@
-var test = require('tap').test
-var minimatch = require('../')
-
-test('extglob ending with statechar', function(t) {
-  t.notOk(minimatch('ax', 'a?(b*)'))
-  t.ok(minimatch('ax', '?(a*|b)'))
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/package.json
deleted file mode 100644
index 09c8508f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/package.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "fstream-ignore",
-  "description": "A thing for ignoring files based on globs",
-  "version": "0.0.7",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/fstream-ignore.git"
-  },
-  "main": "ignore.js",
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "dependencies": {
-    "minimatch": "~0.2.0",
-    "fstream": "~0.1.17",
-    "inherits": "2"
-  },
-  "devDependencies": {
-    "tap": "",
-    "rimraf": "",
-    "mkdirp": ""
-  },
-  "license": "BSD",
-  "readme": "# fstream-ignore\n\nA fstream DirReader that filters out files that match globs in `.ignore`\nfiles throughout the tree, like how git ignores files based on a\n`.gitignore` file.\n\nHere's an example:\n\n```javascript\nvar Ignore = require(\"fstream-ignore\")\nIgnore({ path: __dirname\n       , ignoreFiles: [\".ignore\", \".gitignore\"]\n       })\n  .on(\"child\", function (c) {\n    console.error(c.path.substr(c.root.path.length + 1))\n  })\n  .pipe(tar.Pack())\n  .pipe(fs.createWriteStream(\"foo.tar\"))\n```\n\nThis will tar up the files in __dirname into `foo.tar`, ignoring\nanything matched by the globs in any .iginore or .gitignore file.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/fstream-ignore/issues"
-  },
-  "homepage": "https://github.com/isaacs/fstream-ignore",
-  "_id": "fstream-ignore@0.0.7",
-  "_shasum": "eea3033f0c3728139de7b57ab1b0d6d89c353c63",
-  "_from": "fstream-ignore@0.0.7",
-  "_resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-0.0.7.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.ignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.ignore
deleted file mode 100644
index 773679d4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.ignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.gitignore
-.*.swp
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.npmignore
deleted file mode 100644
index 1b26d0de..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-*/a
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/00-setup.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/00-setup.js
deleted file mode 100644
index 7d7e4a1b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/00-setup.js
+++ /dev/null
@@ -1,71 +0,0 @@
-// The test fixtures work like this:
-// These dirs are all created: {a,b,c}/{a,b,c}/{a,b,c}/
-// in each one, these files are created:
-// {.,}{a,b,c}{a,b,c}{a,b,c}
-//
-// So, there'll be a/b/c/abc, a/b/c/aba, etc., and dot-versions of each.
-//
-// Each test then writes their own ignore file rules for their purposes,
-// and is responsible for removing them afterwards.
-
-var mkdirp = require("mkdirp")
-var path = require("path")
-var i = 0
-var tap = require("tap")
-var fs = require("fs")
-var rimraf = require("rimraf")
-var fixtures = path.resolve(__dirname, "fixtures")
-
-var chars = ['a', 'b', 'c']
-var dirs = []
-
-for (var i = 0; i < 3; i ++) {
-  for (var j = 0; j < 3; j ++) {
-    for (var k = 0; k < 3; k ++) {
-      dirs.push(chars[i] + '/' + chars[j] + '/' + chars[k])
-    }
-  }
-}
-
-var files = []
-
-for (var i = 0; i < 3; i ++) {
-  for (var j = 0; j < 3; j ++) {
-    for (var k = 0; k < 3; k ++) {
-      files.push(chars[i] + chars[j] + chars[k])
-      files.push('.' + chars[i] + chars[j] + chars[k])
-    }
-  }
-}
-
-tap.test("remove fixtures", function (t) {
-  rimraf(path.resolve(__dirname, "fixtures"), function (er) {
-    t.ifError(er, "remove fixtures")
-    t.end()
-  })
-})
-
-tap.test("create fixtures", function (t) {
-  dirs.forEach(function (dir) {
-    dir = path.resolve(fixtures, dir)
-    t.test("mkdir "+dir, function (t) {
-      mkdirp(dir, function (er) {
-        t.ifError(er, "mkdir "+dir)
-        if (er) return t.end()
-
-        files.forEach(function (file) {
-          file = path.resolve(dir, file)
-          t.test("writeFile "+file, function (t) {
-            fs.writeFile(file, path.basename(file), function (er) {
-              t.ifError(er, "writing "+file)
-              t.end()
-            })
-          })
-        })
-        t.end()
-      })
-    })
-  })
-  t.end()
-})
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/basic.js
deleted file mode 100644
index 3718076e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/basic.js
+++ /dev/null
@@ -1,28 +0,0 @@
-var IgnoreFile = require("../")
-
-// set the ignores just for this test
-var c = require("./common.js")
-c.ignores({ "a/.basic-ignore": ["b/", "aca"] })
-
-// the files that we expect to not see
-var notAllowed =
-  [ /^\/a\/b\/.*/
-  , /^\/a\/.*\/aca$/ ]
-
-
-require("tap").test("basic ignore rules", function (t) {
-  t.pass("start")
-
-  IgnoreFile({ path: __dirname + "/fixtures"
-             , ignoreFiles: [".basic-ignore"] })
-    .on("ignoreFile", function (e) {
-      console.error("ignore file!", e)
-    })
-    .on("child", function (e) {
-      var p = e.path.substr(e.root.path.length)
-      notAllowed.forEach(function (na) {
-        t.dissimilar(p, na)
-      })
-    })
-    .on("close", t.end.bind(t))
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/common.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/common.js
deleted file mode 100644
index 0e6cd989..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/common.js
+++ /dev/null
@@ -1,40 +0,0 @@
-if (require.main === module) {
-  console.log("0..1")
-  console.log("ok 1 trivial pass")
-  return
-}
-
-var fs = require("fs")
-var path = require("path")
-var rimraf = require("rimraf")
-
-exports.ignores = ignores
-exports.writeIgnoreFile = writeIgnoreFile
-exports.writeIgnores = writeIgnores
-exports.clearIgnores = clearIgnores
-
-function writeIgnoreFile (file, rules) {
-  file = path.resolve(__dirname, "fixtures", file)
-  if (Array.isArray(rules)) {
-    rules = rules.join("\n")
-  }
-  fs.writeFileSync(file, rules)
-  console.error(file, rules)
-}
-
-function writeIgnores (set) {
-  Object.keys(set).forEach(function (f) {
-    writeIgnoreFile(f, set[f])
-  })
-}
-
-function clearIgnores (set) {
-  Object.keys(set).forEach(function (file) {
-    fs.unlinkSync(path.resolve(__dirname, "fixtures", file))
-  })
-}
-
-function ignores (set) {
-  writeIgnores(set)
-  process.on("exit", clearIgnores.bind(null, set))
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/ignore-most.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/ignore-most.js
deleted file mode 100644
index 43eec4b5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/ignore-most.js
+++ /dev/null
@@ -1,41 +0,0 @@
-// ignore most things
-var IgnoreFile = require("../")
-
-// set the ignores just for this test
-var c = require("./common.js")
-c.ignores({ ".ignore": ["*", "!a/b/c/.abc", "!/c/b/a/cba"] })
-
-// the only files we expect to see
-var expected =
-  [ "/a/b/c/.abc"
-  , "/a"
-  , "/a/b"
-  , "/a/b/c"
-  , "/c/b/a/cba"
-  , "/c"
-  , "/c/b"
-  , "/c/b/a" ]
-
-require("tap").test("basic ignore rules", function (t) {
-  t.pass("start")
-
-  IgnoreFile({ path: __dirname + "/fixtures"
-             , ignoreFiles: [".ignore"] })
-    .on("ignoreFile", function (e) {
-      console.error("ignore file!", e)
-    })
-    .on("child", function (e) {
-      var p = e.path.substr(e.root.path.length)
-      var i = expected.indexOf(p)
-      if (i === -1) {
-        t.fail("unexpected file found", {file: p})
-      } else {
-        t.pass(p)
-        expected.splice(i, 1)
-      }
-    })
-    .on("close", function () {
-      t.notOk(expected.length, "all expected files should be seen")
-      t.end()
-    })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/nested-ignores.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/nested-ignores.js
deleted file mode 100644
index a9ede59c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/nested-ignores.js
+++ /dev/null
@@ -1,51 +0,0 @@
-// ignore most things
-var IgnoreFile = require("../")
-
-// set the ignores just for this test
-var c = require("./common.js")
-c.ignores(
-  { ".ignore": ["*", "a", "c", "!a/b/c/.abc", "!/c/b/a/cba"]
-  , "a/.ignore": [ "!*", ".ignore" ] // unignore everything
-  , "a/a/.ignore": [ "*" ] // re-ignore everything
-  , "a/b/.ignore": [ "*", "!/c/.abc" ] // original unignore
-  , "a/c/.ignore": [ "*" ] // ignore everything again
-  , "c/b/a/.ignore": [ "!cba", "!.cba", "!/a{bc,cb}" ]
-  })
-
-// the only files we expect to see
-var expected =
-  [ "/a"
-  , "/a/a"
-  , "/a/b"
-  , "/a/b/c"
-  , "/a/b/c/.abc"
-  , "/a/c"
-  , "/c"
-  , "/c/b"
-  , "/c/b/a"
-  , "/c/b/a/cba"
-  , "/c/b/a/.cba"
-  , "/c/b/a/abc"
-  , "/c/b/a/acb" ]
-
-require("tap").test("basic ignore rules", function (t) {
-  t.pass("start")
-
-  IgnoreFile({ path: __dirname + "/fixtures"
-             , ignoreFiles: [".ignore"] })
-    .on("child", function (e) {
-      var p = e.path.substr(e.root.path.length)
-      var i = expected.indexOf(p)
-      if (i === -1) {
-        console.log("not ok "+p)
-        t.fail("unexpected file found", {found: p})
-      } else {
-        t.pass(p)
-        expected.splice(i, 1)
-      }
-    })
-    .on("close", function () {
-      t.deepEqual(expected, [], "all expected files should be seen")
-      t.end()
-    })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/unignore-child.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/unignore-child.js
deleted file mode 100644
index 5812354d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/unignore-child.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// ignore most things
-var IgnoreFile = require("../")
-
-// set the ignores just for this test
-var c = require("./common.js")
-c.ignores({ ".ignore": ["*", "a", "c", "!a/b/c/.abc", "!/c/b/a/cba"] })
-
-// the only files we expect to see
-var expected =
-  [ "/a/b/c/.abc"
-  , "/a"
-  , "/a/b"
-  , "/a/b/c"
-  , "/c/b/a/cba"
-  , "/c"
-  , "/c/b"
-  , "/c/b/a" ]
-
-require("tap").test("basic ignore rules", function (t) {
-  t.pass("start")
-
-  IgnoreFile({ path: __dirname + "/fixtures"
-             , ignoreFiles: [".ignore"] })
-    .on("child", function (e) {
-      var p = e.path.substr(e.root.path.length)
-      var i = expected.indexOf(p)
-      if (i === -1) {
-        t.fail("unexpected file found", {f: p})
-      } else {
-        t.pass(p)
-        expected.splice(i, 1)
-      }
-    })
-    .on("close", function () {
-      t.notOk(expected.length, "all expected files should be seen")
-      t.end()
-    })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/zz-cleanup.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/zz-cleanup.js
deleted file mode 100644
index 82f064a4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream-ignore/test/zz-cleanup.js
+++ /dev/null
@@ -1,10 +0,0 @@
-var tap = require("tap")
-, rimraf = require("rimraf")
-, path = require("path")
-
-tap.test("remove fixtures", function (t) {
-  rimraf(path.resolve(__dirname, "fixtures"), function (er) {
-    t.ifError(er, "remove fixtures")
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.npmignore
deleted file mode 100644
index 494272a8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.npmignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.*.swp
-node_modules/
-examples/deep-copy/
-examples/path/
-examples/filter-copy/
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.travis.yml
deleted file mode 100644
index 2d26206d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/.travis.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/README.md
deleted file mode 100644
index 9d8cb77e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/README.md
+++ /dev/null
@@ -1,76 +0,0 @@
-Like FS streams, but with stat on them, and supporting directories and
-symbolic links, as well as normal files.  Also, you can use this to set
-the stats on a file, even if you don't change its contents, or to create
-a symlink, etc.
-
-So, for example, you can "write" a directory, and it'll call `mkdir`.  You
-can specify a uid and gid, and it'll call `chown`.  You can specify a
-`mtime` and `atime`, and it'll call `utimes`.  You can call it a symlink
-and provide a `linkpath` and it'll call `symlink`.
-
-Note that it won't automatically resolve symbolic links.  So, if you
-call `fstream.Reader('/some/symlink')` then you'll get an object
-that stats and then ends immediately (since it has no data).  To follow
-symbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:
-true })`.
-
-There are various checks to make sure that the bytes emitted are the
-same as the intended size, if the size is set.
-
-## Examples
-
-```javascript
-fstream
-  .Writer({ path: "path/to/file"
-          , mode: 0755
-          , size: 6
-          })
-  .write("hello\n")
-  .end()
-```
-
-This will create the directories if they're missing, and then write
-`hello\n` into the file, chmod it to 0755, and assert that 6 bytes have
-been written when it's done.
-
-```javascript
-fstream
-  .Writer({ path: "path/to/file"
-          , mode: 0755
-          , size: 6
-          , flags: "a"
-          })
-  .write("hello\n")
-  .end()
-```
-
-You can pass flags in, if you want to append to a file.
-
-```javascript
-fstream
-  .Writer({ path: "path/to/symlink"
-          , linkpath: "./file"
-          , SymbolicLink: true
-          , mode: "0755" // octal strings supported
-          })
-  .end()
-```
-
-If isSymbolicLink is a function, it'll be called, and if it returns
-true, then it'll treat it as a symlink.  If it's not a function, then
-any truish value will make a symlink, or you can set `type:
-'SymbolicLink'`, which does the same thing.
-
-Note that the linkpath is relative to the symbolic link location, not
-the parent dir or cwd.
-
-```javascript
-fstream
-  .Reader("path/to/dir")
-  .pipe(fstream.Writer("path/to/other/dir"))
-```
-
-This will do like `cp -Rp path/to/dir path/to/other/dir`.  If the other
-dir exists and isn't a directory, then it'll emit an error.  It'll also
-set the uid, gid, mode, etc. to be identical.  In this way, it's more
-like `rsync -a` than simply a copy.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/filter-pipe.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/filter-pipe.js
deleted file mode 100644
index c6b55b3e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/filter-pipe.js
+++ /dev/null
@@ -1,131 +0,0 @@
-var fstream = require("../fstream.js")
-var path = require("path")
-
-var r = fstream.Reader({ path: path.dirname(__dirname)
-                       , filter: function () {
-                           return !this.basename.match(/^\./) &&
-                                  !this.basename.match(/^node_modules$/)
-                                  !this.basename.match(/^deep-copy$/)
-                                  !this.basename.match(/^filter-copy$/)
-                         }
-                       })
-
-// this writer will only write directories
-var w = fstream.Writer({ path: path.resolve(__dirname, "filter-copy")
-                       , type: "Directory"
-                       , filter: function () {
-                           return this.type === "Directory"
-                         }
-                       })
-
-var indent = ""
-var escape = {}
-
-r.on("entry", appears)
-r.on("ready", function () {
-  console.error("ready to begin!", r.path)
-})
-
-function appears (entry) {
-  console.error(indent + "a %s appears!", entry.type, entry.basename, typeof entry.basename)
-  if (foggy) {
-    console.error("FOGGY!")
-    var p = entry
-    do {
-      console.error(p.depth, p.path, p._paused)
-    } while (p = p.parent)
-
-    throw new Error("\033[mshould not have entries while foggy")
-  }
-  indent += "\t"
-  entry.on("data", missile(entry))
-  entry.on("end", runaway(entry))
-  entry.on("entry", appears)
-}
-
-var foggy
-function missile (entry) {
-  if (entry.type === "Directory") {
-    var ended = false
-    entry.once("end", function () { ended = true })
-    return function (c) {
-      // throw in some pathological pause()/resume() behavior
-      // just for extra fun.
-      process.nextTick(function () {
-        if (!foggy && !ended) { // && Math.random() < 0.3) {
-          console.error(indent +"%s casts a spell", entry.basename)
-          console.error("\na slowing fog comes over the battlefield...\n\033[32m")
-          entry.pause()
-          entry.once("resume", liftFog)
-          foggy = setTimeout(liftFog, 1000)
-
-          function liftFog (who) {
-            if (!foggy) return
-            if (who) {
-              console.error("%s breaks the spell!", who && who.path)
-            } else {
-              console.error("the spell expires!")
-            }
-            console.error("\033[mthe fog lifts!\n")
-            clearTimeout(foggy)
-            foggy = null
-            if (entry._paused) entry.resume()
-          }
-
-        }
-      })
-    }
-  }
-
-  return function (c) {
-    var e = Math.random() < 0.5
-    console.error(indent + "%s %s for %d damage!",
-                entry.basename,
-                e ? "is struck" : "fires a chunk",
-                c.length)
-  }
-}
-
-function runaway (entry) { return function () {
-  var e = Math.random() < 0.5
-  console.error(indent + "%s %s",
-                entry.basename,
-                e ? "turns to flee" : "is vanquished!")
-  indent = indent.slice(0, -1)
-}}
-
-
-w.on("entry", attacks)
-//w.on("ready", function () { attacks(w) })
-function attacks (entry) {
-  console.error(indent + "%s %s!", entry.basename,
-              entry.type === "Directory" ? "calls for backup" : "attacks")
-  entry.on("entry", attacks)
-}
-
-ended = false
-var i = 1
-r.on("end", function () {
-  if (foggy) clearTimeout(foggy)
-  console.error("\033[mIT'S OVER!!")
-  console.error("A WINNAR IS YOU!")
-
-  console.log("ok " + (i ++) + " A WINNAR IS YOU")
-  ended = true
-  // now go through and verify that everything in there is a dir.
-  var p = path.resolve(__dirname, "filter-copy")
-  var checker = fstream.Reader({ path: p })
-  checker.checker = true
-  checker.on("child", function (e) {
-    var ok = e.type === "Directory"
-    console.log((ok ? "" : "not ") + "ok " + (i ++) +
-                " should be a dir: " +
-                e.path.substr(checker.path.length + 1))
-  })
-})
-
-process.on("exit", function () {
-  console.log((ended ? "" : "not ") + "ok " + (i ++) + " ended")
-})
-
-r.pipe(w)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/pipe.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/pipe.js
deleted file mode 100644
index 648ec849..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/pipe.js
+++ /dev/null
@@ -1,115 +0,0 @@
-var fstream = require("../fstream.js")
-var path = require("path")
-
-var r = fstream.Reader({ path: path.dirname(__dirname)
-                       , filter: function () {
-                           return !this.basename.match(/^\./) &&
-                                  !this.basename.match(/^node_modules$/)
-                                  !this.basename.match(/^deep-copy$/)
-                         }
-                       })
-
-var w = fstream.Writer({ path: path.resolve(__dirname, "deep-copy")
-                       , type: "Directory"
-                       })
-
-var indent = ""
-var escape = {}
-
-r.on("entry", appears)
-r.on("ready", function () {
-  console.error("ready to begin!", r.path)
-})
-
-function appears (entry) {
-  console.error(indent + "a %s appears!", entry.type, entry.basename, typeof entry.basename, entry)
-  if (foggy) {
-    console.error("FOGGY!")
-    var p = entry
-    do {
-      console.error(p.depth, p.path, p._paused)
-    } while (p = p.parent)
-
-    throw new Error("\033[mshould not have entries while foggy")
-  }
-  indent += "\t"
-  entry.on("data", missile(entry))
-  entry.on("end", runaway(entry))
-  entry.on("entry", appears)
-}
-
-var foggy
-function missile (entry) {
-  if (entry.type === "Directory") {
-    var ended = false
-    entry.once("end", function () { ended = true })
-    return function (c) {
-      // throw in some pathological pause()/resume() behavior
-      // just for extra fun.
-      process.nextTick(function () {
-        if (!foggy && !ended) { // && Math.random() < 0.3) {
-          console.error(indent +"%s casts a spell", entry.basename)
-          console.error("\na slowing fog comes over the battlefield...\n\033[32m")
-          entry.pause()
-          entry.once("resume", liftFog)
-          foggy = setTimeout(liftFog, 10)
-
-          function liftFog (who) {
-            if (!foggy) return
-            if (who) {
-              console.error("%s breaks the spell!", who && who.path)
-            } else {
-              console.error("the spell expires!")
-            }
-            console.error("\033[mthe fog lifts!\n")
-            clearTimeout(foggy)
-            foggy = null
-            if (entry._paused) entry.resume()
-          }
-
-        }
-      })
-    }
-  }
-
-  return function (c) {
-    var e = Math.random() < 0.5
-    console.error(indent + "%s %s for %d damage!",
-                entry.basename,
-                e ? "is struck" : "fires a chunk",
-                c.length)
-  }
-}
-
-function runaway (entry) { return function () {
-  var e = Math.random() < 0.5
-  console.error(indent + "%s %s",
-                entry.basename,
-                e ? "turns to flee" : "is vanquished!")
-  indent = indent.slice(0, -1)
-}}
-
-
-w.on("entry", attacks)
-//w.on("ready", function () { attacks(w) })
-function attacks (entry) {
-  console.error(indent + "%s %s!", entry.basename,
-              entry.type === "Directory" ? "calls for backup" : "attacks")
-  entry.on("entry", attacks)
-}
-
-ended = false
-r.on("end", function () {
-  if (foggy) clearTimeout(foggy)
-  console.error("\033[mIT'S OVER!!")
-  console.error("A WINNAR IS YOU!")
-
-  console.log("ok 1 A WINNAR IS YOU")
-  ended = true
-})
-
-process.on("exit", function () {
-  console.log((ended ? "" : "not ") + "ok 2 ended")
-})
-
-r.pipe(w)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/reader.js
deleted file mode 100644
index 9aa1a953..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/reader.js
+++ /dev/null
@@ -1,54 +0,0 @@
-var fstream = require("../fstream.js")
-var tap = require("tap")
-var fs = require("fs")
-var path = require("path")
-var children = -1
-var dir = path.dirname(__dirname)
-
-var gotReady = false
-var ended = false
-
-tap.test("reader test", function (t) {
-
-  var r = fstream.Reader({ path: dir
-                         , filter: function () {
-                             // return this.parent === r
-                             return this.parent === r || this === r
-                           }
-                         })
-
-  r.on("ready", function () {
-    gotReady = true
-    children = fs.readdirSync(dir).length
-    console.error("Setting expected children to "+children)
-    t.equal(r.type, "Directory", "should be a directory")
-  })
-
-  r.on("entry", function (entry) {
-    children --
-    if (!gotReady) {
-      t.fail("children before ready!")
-    }
-    t.equal(entry.dirname, r.path, "basename is parent dir")
-  })
-
-  r.on("error", function (er) {
-    t.fail(er)
-    t.end()
-    process.exit(1)
-  })
-
-  r.on("end", function () {
-    t.equal(children, 0, "should have seen all children")
-    ended = true
-  })
-
-  var closed = false
-  r.on("close", function () {
-    t.ok(ended, "saw end before close")
-    t.notOk(closed, "close should only happen once")
-    closed = true
-    t.end()
-  })
-
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/symlink-write.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/symlink-write.js
deleted file mode 100644
index d7816d24..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/examples/symlink-write.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var fstream = require("../fstream.js")
-  , closed = false
-
-fstream
-  .Writer({ path: "path/to/symlink"
-          , linkpath: "./file"
-          , isSymbolicLink: true
-          , mode: "0755" // octal strings supported
-          })
-  .on("close", function () {
-    closed = true
-    var fs = require("fs")
-    var s = fs.lstatSync("path/to/symlink")
-    var isSym = s.isSymbolicLink()
-    console.log((isSym?"":"not ") +"ok 1 should be symlink")
-    var t = fs.readlinkSync("path/to/symlink")
-    var isTarget = t === "./file"
-    console.log((isTarget?"":"not ") +"ok 2 should link to ./file")
-  })
-  .end()
-
-process.on("exit", function () {
-  console.log((closed?"":"not ")+"ok 3 should be closed")
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/fstream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/fstream.js
deleted file mode 100644
index c66d26f5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/fstream.js
+++ /dev/null
@@ -1,31 +0,0 @@
-exports.Abstract = require("./lib/abstract.js")
-exports.Reader = require("./lib/reader.js")
-exports.Writer = require("./lib/writer.js")
-
-exports.File =
-  { Reader: require("./lib/file-reader.js")
-  , Writer: require("./lib/file-writer.js") }
-
-exports.Dir = 
-  { Reader : require("./lib/dir-reader.js")
-  , Writer : require("./lib/dir-writer.js") }
-
-exports.Link =
-  { Reader : require("./lib/link-reader.js")
-  , Writer : require("./lib/link-writer.js") }
-
-exports.Proxy =
-  { Reader : require("./lib/proxy-reader.js")
-  , Writer : require("./lib/proxy-writer.js") }
-
-exports.Reader.Dir = exports.DirReader = exports.Dir.Reader
-exports.Reader.File = exports.FileReader = exports.File.Reader
-exports.Reader.Link = exports.LinkReader = exports.Link.Reader
-exports.Reader.Proxy = exports.ProxyReader = exports.Proxy.Reader
-
-exports.Writer.Dir = exports.DirWriter = exports.Dir.Writer
-exports.Writer.File = exports.FileWriter = exports.File.Writer
-exports.Writer.Link = exports.LinkWriter = exports.Link.Writer
-exports.Writer.Proxy = exports.ProxyWriter = exports.Proxy.Writer
-
-exports.collect = require("./lib/collect.js")
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/abstract.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/abstract.js
deleted file mode 100644
index 11ef0e28..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/abstract.js
+++ /dev/null
@@ -1,85 +0,0 @@
-// the parent class for all fstreams.
-
-module.exports = Abstract
-
-var Stream = require("stream").Stream
-  , inherits = require("inherits")
-
-function Abstract () {
-  Stream.call(this)
-}
-
-inherits(Abstract, Stream)
-
-Abstract.prototype.on = function (ev, fn) {
-  if (ev === "ready" && this.ready) {
-    process.nextTick(fn.bind(this))
-  } else {
-    Stream.prototype.on.call(this, ev, fn)
-  }
-  return this
-}
-
-Abstract.prototype.abort = function () {
-  this._aborted = true
-  this.emit("abort")
-}
-
-Abstract.prototype.destroy = function () {}
-
-Abstract.prototype.warn = function (msg, code) {
-  var me = this
-    , er = decorate(msg, code, me)
-  if (!me.listeners("warn")) {
-    console.error("%s %s\n" +
-                  "path = %s\n" +
-                  "syscall = %s\n" +
-                  "fstream_type = %s\n" +
-                  "fstream_path = %s\n" +
-                  "fstream_unc_path = %s\n" +
-                  "fstream_class = %s\n" +
-                  "fstream_stack =\n%s\n",
-                  code || "UNKNOWN",
-                  er.stack,
-                  er.path,
-                  er.syscall,
-                  er.fstream_type,
-                  er.fstream_path,
-                  er.fstream_unc_path,
-                  er.fstream_class,
-                  er.fstream_stack.join("\n"))
-  } else {
-    me.emit("warn", er)
-  }
-}
-
-Abstract.prototype.info = function (msg, code) {
-  this.emit("info", msg, code)
-}
-
-Abstract.prototype.error = function (msg, code, th) {
-  var er = decorate(msg, code, this)
-  if (th) throw er
-  else this.emit("error", er)
-}
-
-function decorate (er, code, me) {
-  if (!(er instanceof Error)) er = new Error(er)
-  er.code = er.code || code
-  er.path = er.path || me.path
-  er.fstream_type = er.fstream_type || me.type
-  er.fstream_path = er.fstream_path || me.path
-  if (me._path !== me.path) {
-    er.fstream_unc_path = er.fstream_unc_path || me._path
-  }
-  if (me.linkpath) {
-    er.fstream_linkpath = er.fstream_linkpath || me.linkpath
-  }
-  er.fstream_class = er.fstream_class || me.constructor.name
-  er.fstream_stack = er.fstream_stack ||
-    new Error().stack.split(/\n/).slice(3).map(function (s) {
-      return s.replace(/^    at /, "")
-    })
-
-  return er
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/collect.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/collect.js
deleted file mode 100644
index a36f780e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/collect.js
+++ /dev/null
@@ -1,67 +0,0 @@
-module.exports = collect
-
-function collect (stream) {
-  if (stream._collected) return
-
-  stream._collected = true
-  stream.pause()
-
-  stream.on("data", save)
-  stream.on("end", save)
-  var buf = []
-  function save (b) {
-    if (typeof b === "string") b = new Buffer(b)
-    if (Buffer.isBuffer(b) && !b.length) return
-    buf.push(b)
-  }
-
-  stream.on("entry", saveEntry)
-  var entryBuffer = []
-  function saveEntry (e) {
-    collect(e)
-    entryBuffer.push(e)
-  }
-
-  stream.on("proxy", proxyPause)
-  function proxyPause (p) {
-    p.pause()
-  }
-
-
-  // replace the pipe method with a new version that will
-  // unlock the buffered stuff.  if you just call .pipe()
-  // without a destination, then it'll re-play the events.
-  stream.pipe = (function (orig) { return function (dest) {
-    // console.error(" === open the pipes", dest && dest.path)
-
-    // let the entries flow through one at a time.
-    // Once they're all done, then we can resume completely.
-    var e = 0
-    ;(function unblockEntry () {
-      var entry = entryBuffer[e++]
-      // console.error(" ==== unblock entry", entry && entry.path)
-      if (!entry) return resume()
-      entry.on("end", unblockEntry)
-      if (dest) dest.add(entry)
-      else stream.emit("entry", entry)
-    })()
-
-    function resume () {
-      stream.removeListener("entry", saveEntry)
-      stream.removeListener("data", save)
-      stream.removeListener("end", save)
-
-      stream.pipe = orig
-      if (dest) stream.pipe(dest)
-
-      buf.forEach(function (b) {
-        if (b) stream.emit("data", b)
-        else stream.emit("end")
-      })
-
-      stream.resume()
-    }
-
-    return dest
-  }})(stream.pipe)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-reader.js
deleted file mode 100644
index 346ac2b8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-reader.js
+++ /dev/null
@@ -1,251 +0,0 @@
-// A thing that emits "entry" events with Reader objects
-// Pausing it causes it to stop emitting entry events, and also
-// pauses the current entry if there is one.
-
-module.exports = DirReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , Reader = fstream.Reader
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , path = require("path")
-  , Reader = require("./reader.js")
-  , assert = require("assert").ok
-
-inherits(DirReader, Reader)
-
-function DirReader (props) {
-  var me = this
-  if (!(me instanceof DirReader)) throw new Error(
-    "DirReader must be called as constructor.")
-
-  // should already be established as a Directory type
-  if (props.type !== "Directory" || !props.Directory) {
-    throw new Error("Non-directory type "+ props.type)
-  }
-
-  me.entries = null
-  me._index = -1
-  me._paused = false
-  me._length = -1
-
-  if (props.sort) {
-    this.sort = props.sort
-  }
-
-  Reader.call(this, props)
-}
-
-DirReader.prototype._getEntries = function () {
-  var me = this
-
-  // race condition.  might pause() before calling _getEntries,
-  // and then resume, and try to get them a second time.
-  if (me._gotEntries) return
-  me._gotEntries = true
-
-  fs.readdir(me._path, function (er, entries) {
-    if (er) return me.error(er)
-
-    me.entries = entries
-
-    me.emit("entries", entries)
-    if (me._paused) me.once("resume", processEntries)
-    else processEntries()
-
-    function processEntries () {
-      me._length = me.entries.length
-      if (typeof me.sort === "function") {
-        me.entries = me.entries.sort(me.sort.bind(me))
-      }
-      me._read()
-    }
-  })
-}
-
-// start walking the dir, and emit an "entry" event for each one.
-DirReader.prototype._read = function () {
-  var me = this
-
-  if (!me.entries) return me._getEntries()
-
-  if (me._paused || me._currentEntry || me._aborted) {
-    // console.error("DR paused=%j, current=%j, aborted=%j", me._paused, !!me._currentEntry, me._aborted)
-    return
-  }
-
-  me._index ++
-  if (me._index >= me.entries.length) {
-    if (!me._ended) {
-      me._ended = true
-      me.emit("end")
-      me.emit("close")
-    }
-    return
-  }
-
-  // ok, handle this one, then.
-
-  // save creating a proxy, by stat'ing the thing now.
-  var p = path.resolve(me._path, me.entries[me._index])
-  assert(p !== me._path)
-  assert(me.entries[me._index])
-
-  // set this to prevent trying to _read() again in the stat time.
-  me._currentEntry = p
-  fs[ me.props.follow ? "stat" : "lstat" ](p, function (er, stat) {
-    if (er) return me.error(er)
-
-    var who = me._proxy || me
-
-    stat.path = p
-    stat.basename = path.basename(p)
-    stat.dirname = path.dirname(p)
-    var childProps = me.getChildProps.call(who, stat)
-    childProps.path = p
-    childProps.basename = path.basename(p)
-    childProps.dirname = path.dirname(p)
-
-    var entry = Reader(childProps, stat)
-
-    // console.error("DR Entry", p, stat.size)
-
-    me._currentEntry = entry
-
-    // "entry" events are for direct entries in a specific dir.
-    // "child" events are for any and all children at all levels.
-    // This nomenclature is not completely final.
-
-    entry.on("pause", function (who) {
-      if (!me._paused && !entry._disowned) {
-        me.pause(who)
-      }
-    })
-
-    entry.on("resume", function (who) {
-      if (me._paused && !entry._disowned) {
-        me.resume(who)
-      }
-    })
-
-    entry.on("stat", function (props) {
-      me.emit("_entryStat", entry, props)
-      if (entry._aborted) return
-      if (entry._paused) entry.once("resume", function () {
-        me.emit("entryStat", entry, props)
-      })
-      else me.emit("entryStat", entry, props)
-    })
-
-    entry.on("ready", function EMITCHILD () {
-      // console.error("DR emit child", entry._path)
-      if (me._paused) {
-        // console.error("  DR emit child - try again later")
-        // pause the child, and emit the "entry" event once we drain.
-        // console.error("DR pausing child entry")
-        entry.pause(me)
-        return me.once("resume", EMITCHILD)
-      }
-
-      // skip over sockets.  they can't be piped around properly,
-      // so there's really no sense even acknowledging them.
-      // if someone really wants to see them, they can listen to
-      // the "socket" events.
-      if (entry.type === "Socket") {
-        me.emit("socket", entry)
-      } else {
-        me.emitEntry(entry)
-      }
-    })
-
-    var ended = false
-    entry.on("close", onend)
-    entry.on("disown", onend)
-    function onend () {
-      if (ended) return
-      ended = true
-      me.emit("childEnd", entry)
-      me.emit("entryEnd", entry)
-      me._currentEntry = null
-      if (!me._paused) {
-        me._read()
-      }
-    }
-
-    // XXX Remove this.  Works in node as of 0.6.2 or so.
-    // Long filenames should not break stuff.
-    entry.on("error", function (er) {
-      if (entry._swallowErrors) {
-        me.warn(er)
-        entry.emit("end")
-        entry.emit("close")
-      } else {
-        me.emit("error", er)
-      }
-    })
-
-    // proxy up some events.
-    ; [ "child"
-      , "childEnd"
-      , "warn"
-      ].forEach(function (ev) {
-        entry.on(ev, me.emit.bind(me, ev))
-      })
-  })
-}
-
-DirReader.prototype.disown = function (entry) {
-  entry.emit("beforeDisown")
-  entry._disowned = true
-  entry.parent = entry.root = null
-  if (entry === this._currentEntry) {
-    this._currentEntry = null
-  }
-  entry.emit("disown")
-}
-
-DirReader.prototype.getChildProps = function (stat) {
-  return { depth: this.depth + 1
-         , root: this.root || this
-         , parent: this
-         , follow: this.follow
-         , filter: this.filter
-         , sort: this.props.sort
-         , hardlinks: this.props.hardlinks
-         }
-}
-
-DirReader.prototype.pause = function (who) {
-  var me = this
-  if (me._paused) return
-  who = who || me
-  me._paused = true
-  if (me._currentEntry && me._currentEntry.pause) {
-    me._currentEntry.pause(who)
-  }
-  me.emit("pause", who)
-}
-
-DirReader.prototype.resume = function (who) {
-  var me = this
-  if (!me._paused) return
-  who = who || me
-
-  me._paused = false
-  // console.error("DR Emit Resume", me._path)
-  me.emit("resume", who)
-  if (me._paused) {
-    // console.error("DR Re-paused", me._path)
-    return
-  }
-
-  if (me._currentEntry) {
-    if (me._currentEntry.resume) me._currentEntry.resume(who)
-  } else me._read()
-}
-
-DirReader.prototype.emitEntry = function (entry) {
-  this.emit("entry", entry)
-  this.emit("child", entry)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-writer.js
deleted file mode 100644
index 7073b883..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/dir-writer.js
+++ /dev/null
@@ -1,171 +0,0 @@
-// It is expected that, when .add() returns false, the consumer
-// of the DirWriter will pause until a "drain" event occurs. Note
-// that this is *almost always going to be the case*, unless the
-// thing being written is some sort of unsupported type, and thus
-// skipped over.
-
-module.exports = DirWriter
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , Writer = require("./writer.js")
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , path = require("path")
-  , collect = require("./collect.js")
-
-inherits(DirWriter, Writer)
-
-function DirWriter (props) {
-  var me = this
-  if (!(me instanceof DirWriter)) me.error(
-    "DirWriter must be called as constructor.", null, true)
-
-  // should already be established as a Directory type
-  if (props.type !== "Directory" || !props.Directory) {
-    me.error("Non-directory type "+ props.type + " " +
-                    JSON.stringify(props), null, true)
-  }
-
-  Writer.call(this, props)
-}
-
-DirWriter.prototype._create = function () {
-  var me = this
-  mkdir(me._path, Writer.dirmode, function (er) {
-    if (er) return me.error(er)
-    // ready to start getting entries!
-    me.ready = true
-    me.emit("ready")
-    me._process()
-  })
-}
-
-// a DirWriter has an add(entry) method, but its .write() doesn't
-// do anything.  Why a no-op rather than a throw?  Because this
-// leaves open the door for writing directory metadata for
-// gnu/solaris style dumpdirs.
-DirWriter.prototype.write = function () {
-  return true
-}
-
-DirWriter.prototype.end = function () {
-  this._ended = true
-  this._process()
-}
-
-DirWriter.prototype.add = function (entry) {
-  var me = this
-
-  // console.error("\tadd", entry._path, "->", me._path)
-  collect(entry)
-  if (!me.ready || me._currentEntry) {
-    me._buffer.push(entry)
-    return false
-  }
-
-  // create a new writer, and pipe the incoming entry into it.
-  if (me._ended) {
-    return me.error("add after end")
-  }
-
-  me._buffer.push(entry)
-  me._process()
-
-  return 0 === this._buffer.length
-}
-
-DirWriter.prototype._process = function () {
-  var me = this
-
-  // console.error("DW Process p=%j", me._processing, me.basename)
-
-  if (me._processing) return
-
-  var entry = me._buffer.shift()
-  if (!entry) {
-    // console.error("DW Drain")
-    me.emit("drain")
-    if (me._ended) me._finish()
-    return
-  }
-
-  me._processing = true
-  // console.error("DW Entry", entry._path)
-
-  me.emit("entry", entry)
-
-  // ok, add this entry
-  //
-  // don't allow recursive copying
-  var p = entry
-  do {
-    var pp = p._path || p.path
-    if (pp === me.root._path || pp === me._path ||
-        (pp && pp.indexOf(me._path) === 0)) {
-      // console.error("DW Exit (recursive)", entry.basename, me._path)
-      me._processing = false
-      if (entry._collected) entry.pipe()
-      return me._process()
-    }
-  } while (p = p.parent)
-
-  // console.error("DW not recursive")
-
-  // chop off the entry's root dir, replace with ours
-  var props = { parent: me
-              , root: me.root || me
-              , type: entry.type
-              , depth: me.depth + 1 }
-
-  var p = entry._path || entry.path || entry.props.path
-  if (entry.parent) {
-    p = p.substr(entry.parent._path.length + 1)
-  }
-  // get rid of any ../../ shenanigans
-  props.path = path.join(me.path, path.join("/", p))
-
-  // if i have a filter, the child should inherit it.
-  props.filter = me.filter
-
-  // all the rest of the stuff, copy over from the source.
-  Object.keys(entry.props).forEach(function (k) {
-    if (!props.hasOwnProperty(k)) {
-      props[k] = entry.props[k]
-    }
-  })
-
-  // not sure at this point what kind of writer this is.
-  var child = me._currentChild = new Writer(props)
-  child.on("ready", function () {
-    // console.error("DW Child Ready", child.type, child._path)
-    // console.error("  resuming", entry._path)
-    entry.pipe(child)
-    entry.resume()
-  })
-
-  // XXX Make this work in node.
-  // Long filenames should not break stuff.
-  child.on("error", function (er) {
-    if (child._swallowErrors) {
-      me.warn(er)
-      child.emit("end")
-      child.emit("close")
-    } else {
-      me.emit("error", er)
-    }
-  })
-
-  // we fire _end internally *after* end, so that we don't move on
-  // until any "end" listeners have had their chance to do stuff.
-  child.on("close", onend)
-  var ended = false
-  function onend () {
-    if (ended) return
-    ended = true
-    // console.error("* DW Child end", child.basename)
-    me._currentChild = null
-    me._processing = false
-    me._process()
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-reader.js
deleted file mode 100644
index b1f98618..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-reader.js
+++ /dev/null
@@ -1,147 +0,0 @@
-// Basically just a wrapper around an fs.ReadStream
-
-module.exports = FileReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , Reader = fstream.Reader
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , Reader = require("./reader.js")
-  , EOF = {EOF: true}
-  , CLOSE = {CLOSE: true}
-
-inherits(FileReader, Reader)
-
-function FileReader (props) {
-  // console.error("    FR create", props.path, props.size, new Error().stack)
-  var me = this
-  if (!(me instanceof FileReader)) throw new Error(
-    "FileReader must be called as constructor.")
-
-  // should already be established as a File type
-  // XXX Todo: preserve hardlinks by tracking dev+inode+nlink,
-  // with a HardLinkReader class.
-  if (!((props.type === "Link" && props.Link) ||
-        (props.type === "File" && props.File))) {
-    throw new Error("Non-file type "+ props.type)
-  }
-
-  me._buffer = []
-  me._bytesEmitted = 0
-  Reader.call(me, props)
-}
-
-FileReader.prototype._getStream = function () {
-  var me = this
-    , stream = me._stream = fs.createReadStream(me._path, me.props)
-
-  if (me.props.blksize) {
-    stream.bufferSize = me.props.blksize
-  }
-
-  stream.on("open", me.emit.bind(me, "open"))
-
-  stream.on("data", function (c) {
-    // console.error("\t\t%d %s", c.length, me.basename)
-    me._bytesEmitted += c.length
-    // no point saving empty chunks
-    if (!c.length) return
-    else if (me._paused || me._buffer.length) {
-      me._buffer.push(c)
-      me._read()
-    } else me.emit("data", c)
-  })
-
-  stream.on("end", function () {
-    if (me._paused || me._buffer.length) {
-      // console.error("FR Buffering End", me._path)
-      me._buffer.push(EOF)
-      me._read()
-    } else {
-      me.emit("end")
-    }
-
-    if (me._bytesEmitted !== me.props.size) {
-      me.error("Didn't get expected byte count\n"+
-               "expect: "+me.props.size + "\n" +
-               "actual: "+me._bytesEmitted)
-    }
-  })
-
-  stream.on("close", function () {
-    if (me._paused || me._buffer.length) {
-      // console.error("FR Buffering Close", me._path)
-      me._buffer.push(CLOSE)
-      me._read()
-    } else {
-      // console.error("FR close 1", me._path)
-      me.emit("close")
-    }
-  })
-
-  me._read()
-}
-
-FileReader.prototype._read = function () {
-  var me = this
-  // console.error("FR _read", me._path)
-  if (me._paused) {
-    // console.error("FR _read paused", me._path)
-    return
-  }
-
-  if (!me._stream) {
-    // console.error("FR _getStream calling", me._path)
-    return me._getStream()
-  }
-
-  // clear out the buffer, if there is one.
-  if (me._buffer.length) {
-    // console.error("FR _read has buffer", me._buffer.length, me._path)
-    var buf = me._buffer
-    for (var i = 0, l = buf.length; i < l; i ++) {
-      var c = buf[i]
-      if (c === EOF) {
-        // console.error("FR Read emitting buffered end", me._path)
-        me.emit("end")
-      } else if (c === CLOSE) {
-        // console.error("FR Read emitting buffered close", me._path)
-        me.emit("close")
-      } else {
-        // console.error("FR Read emitting buffered data", me._path)
-        me.emit("data", c)
-      }
-
-      if (me._paused) {
-        // console.error("FR Read Re-pausing at "+i, me._path)
-        me._buffer = buf.slice(i)
-        return
-      }
-    }
-    me._buffer.length = 0
-  }
-  // console.error("FR _read done")
-  // that's about all there is to it.
-}
-
-FileReader.prototype.pause = function (who) {
-  var me = this
-  // console.error("FR Pause", me._path)
-  if (me._paused) return
-  who = who || me
-  me._paused = true
-  if (me._stream) me._stream.pause()
-  me.emit("pause", who)
-}
-
-FileReader.prototype.resume = function (who) {
-  var me = this
-  // console.error("FR Resume", me._path)
-  if (!me._paused) return
-  who = who || me
-  me.emit("resume", who)
-  me._paused = false
-  if (me._stream) me._stream.resume()
-  me._read()
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-writer.js
deleted file mode 100644
index 68114625..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/file-writer.js
+++ /dev/null
@@ -1,100 +0,0 @@
-module.exports = FileWriter
-
-var fs = require("graceful-fs")
-  , mkdir = require("mkdirp")
-  , Writer = require("./writer.js")
-  , inherits = require("inherits")
-  , EOF = {}
-
-inherits(FileWriter, Writer)
-
-function FileWriter (props) {
-  var me = this
-  if (!(me instanceof FileWriter)) throw new Error(
-    "FileWriter must be called as constructor.")
-
-  // should already be established as a File type
-  if (props.type !== "File" || !props.File) {
-    throw new Error("Non-file type "+ props.type)
-  }
-
-  me._buffer = []
-  me._bytesWritten = 0
-
-  Writer.call(this, props)
-}
-
-FileWriter.prototype._create = function () {
-  var me = this
-  if (me._stream) return
-
-  var so = {}
-  if (me.props.flags) so.flags = me.props.flags
-  so.mode = Writer.filemode
-  if (me._old && me._old.blksize) so.bufferSize = me._old.blksize
-
-  me._stream = fs.createWriteStream(me._path, so)
-
-  me._stream.on("open", function (fd) {
-    // console.error("FW open", me._buffer, me._path)
-    me.ready = true
-    me._buffer.forEach(function (c) {
-      if (c === EOF) me._stream.end()
-      else me._stream.write(c)
-    })
-    me.emit("ready")
-    // give this a kick just in case it needs it.
-    me.emit("drain")
-  })
-
-  me._stream.on("drain", function () { me.emit("drain") })
-
-  me._stream.on("close", function () {
-    // console.error("\n\nFW Stream Close", me._path, me.size)
-    me._finish()
-  })
-}
-
-FileWriter.prototype.write = function (c) {
-  var me = this
-
-  me._bytesWritten += c.length
-
-  if (!me.ready) {
-    if (!Buffer.isBuffer(c) && typeof c !== 'string')
-      throw new Error('invalid write data')
-    me._buffer.push(c)
-    return false
-  }
-
-  var ret = me._stream.write(c)
-  // console.error("\t-- fw wrote, _stream says", ret, me._stream._queue.length)
-
-  // allow 2 buffered writes, because otherwise there's just too
-  // much stop and go bs.
-  return ret || (me._stream._queue && me._stream._queue.length <= 2)
-}
-
-FileWriter.prototype.end = function (c) {
-  var me = this
-
-  if (c) me.write(c)
-
-  if (!me.ready) {
-    me._buffer.push(EOF)
-    return false
-  }
-
-  return me._stream.end()
-}
-
-FileWriter.prototype._finish = function () {
-  var me = this
-  if (typeof me.size === "number" && me._bytesWritten != me.size) {
-    me.error(
-      "Did not get expected byte count.\n" +
-      "expect: " + me.size + "\n" +
-      "actual: " + me._bytesWritten)
-  }
-  Writer.prototype._finish.call(me)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/get-type.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/get-type.js
deleted file mode 100644
index cd65c41d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/get-type.js
+++ /dev/null
@@ -1,32 +0,0 @@
-module.exports = getType
-
-function getType (st) {
-  var types =
-      [ "Directory"
-      , "File"
-      , "SymbolicLink"
-      , "Link" // special for hardlinks from tarballs
-      , "BlockDevice"
-      , "CharacterDevice"
-      , "FIFO"
-      , "Socket" ]
-    , type
-
-  if (st.type && -1 !== types.indexOf(st.type)) {
-    st[st.type] = true
-    return st.type
-  }
-
-  for (var i = 0, l = types.length; i < l; i ++) {
-    type = types[i]
-    var is = st[type] || st["is" + type]
-    if (typeof is === "function") is = is.call(st)
-    if (is) {
-      st[type] = true
-      st.type = type
-      return type
-    }
-  }
-
-  return null
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-reader.js
deleted file mode 100644
index 7e7ab6ce..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-reader.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Basically just a wrapper around an fs.readlink
-//
-// XXX: Enhance this to support the Link type, by keeping
-// a lookup table of {<dev+inode>:<path>}, so that hardlinks
-// can be preserved in tarballs.
-
-module.exports = LinkReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , Reader = require("./reader.js")
-
-inherits(LinkReader, Reader)
-
-function LinkReader (props) {
-  var me = this
-  if (!(me instanceof LinkReader)) throw new Error(
-    "LinkReader must be called as constructor.")
-
-  if (!((props.type === "Link" && props.Link) ||
-        (props.type === "SymbolicLink" && props.SymbolicLink))) {
-    throw new Error("Non-link type "+ props.type)
-  }
-
-  Reader.call(me, props)
-}
-
-// When piping a LinkReader into a LinkWriter, we have to
-// already have the linkpath property set, so that has to
-// happen *before* the "ready" event, which means we need to
-// override the _stat method.
-LinkReader.prototype._stat = function (currentStat) {
-  var me = this
-  fs.readlink(me._path, function (er, linkpath) {
-    if (er) return me.error(er)
-    me.linkpath = me.props.linkpath = linkpath
-    me.emit("linkpath", linkpath)
-    Reader.prototype._stat.call(me, currentStat)
-  })
-}
-
-LinkReader.prototype._read = function () {
-  var me = this
-  if (me._paused) return
-  // basically just a no-op, since we got all the info we need
-  // from the _stat method
-  if (!me._ended) {
-    me.emit("end")
-    me.emit("close")
-    me._ended = true
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-writer.js
deleted file mode 100644
index 5c8f1e70..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/link-writer.js
+++ /dev/null
@@ -1,95 +0,0 @@
-
-module.exports = LinkWriter
-
-var fs = require("graceful-fs")
-  , Writer = require("./writer.js")
-  , inherits = require("inherits")
-  , path = require("path")
-  , rimraf = require("rimraf")
-
-inherits(LinkWriter, Writer)
-
-function LinkWriter (props) {
-  var me = this
-  if (!(me instanceof LinkWriter)) throw new Error(
-    "LinkWriter must be called as constructor.")
-
-  // should already be established as a Link type
-  if (!((props.type === "Link" && props.Link) ||
-        (props.type === "SymbolicLink" && props.SymbolicLink))) {
-    throw new Error("Non-link type "+ props.type)
-  }
-
-  if (props.linkpath === "") props.linkpath = "."
-  if (!props.linkpath) {
-    me.error("Need linkpath property to create " + props.type)
-  }
-
-  Writer.call(this, props)
-}
-
-LinkWriter.prototype._create = function () {
-  // console.error(" LW _create")
-  var me = this
-    , hard = me.type === "Link" || process.platform === "win32"
-    , link = hard ? "link" : "symlink"
-    , lp = hard ? path.resolve(me.dirname, me.linkpath) : me.linkpath
-
-  // can only change the link path by clobbering
-  // For hard links, let's just assume that's always the case, since
-  // there's no good way to read them if we don't already know.
-  if (hard) return clobber(me, lp, link)
-
-  fs.readlink(me._path, function (er, p) {
-    // only skip creation if it's exactly the same link
-    if (p && p === lp) return finish(me)
-    clobber(me, lp, link)
-  })
-}
-
-function clobber (me, lp, link) {
-  rimraf(me._path, function (er) {
-    if (er) return me.error(er)
-    create(me, lp, link)
-  })
-}
-
-function create (me, lp, link) {
-  fs[link](lp, me._path, function (er) {
-    // if this is a hard link, and we're in the process of writing out a
-    // directory, it's very possible that the thing we're linking to
-    // doesn't exist yet (especially if it was intended as a symlink),
-    // so swallow ENOENT errors here and just soldier in.
-    // Additionally, an EPERM or EACCES can happen on win32 if it's trying
-    // to make a link to a directory.  Again, just skip it.
-    // A better solution would be to have fs.symlink be supported on
-    // windows in some nice fashion.
-    if (er) {
-      if ((er.code === "ENOENT" ||
-           er.code === "EACCES" ||
-           er.code === "EPERM" ) && process.platform === "win32") {
-        me.ready = true
-        me.emit("ready")
-        me.emit("end")
-        me.emit("close")
-        me.end = me._finish = function () {}
-      } else return me.error(er)
-    }
-    finish(me)
-  })
-}
-
-function finish (me) {
-  me.ready = true
-  me.emit("ready")
-  if (me._ended && !me._finished) me._finish()
-}
-
-LinkWriter.prototype.end = function () {
-  // console.error("LW finish in end")
-  this._ended = true
-  if (this.ready) {
-    this._finished = true
-    this._finish()
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-reader.js
deleted file mode 100644
index a0ece34a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-reader.js
+++ /dev/null
@@ -1,93 +0,0 @@
-// A reader for when we don't yet know what kind of thing
-// the thing is.
-
-module.exports = ProxyReader
-
-var Reader = require("./reader.js")
-  , getType = require("./get-type.js")
-  , inherits = require("inherits")
-  , fs = require("graceful-fs")
-
-inherits(ProxyReader, Reader)
-
-function ProxyReader (props) {
-  var me = this
-  if (!(me instanceof ProxyReader)) throw new Error(
-    "ProxyReader must be called as constructor.")
-
-  me.props = props
-  me._buffer = []
-  me.ready = false
-
-  Reader.call(me, props)
-}
-
-ProxyReader.prototype._stat = function () {
-  var me = this
-    , props = me.props
-    // stat the thing to see what the proxy should be.
-    , stat = props.follow ? "stat" : "lstat"
-
-  fs[stat](props.path, function (er, current) {
-    var type
-    if (er || !current) {
-      type = "File"
-    } else {
-      type = getType(current)
-    }
-
-    props[type] = true
-    props.type = me.type = type
-
-    me._old = current
-    me._addProxy(Reader(props, current))
-  })
-}
-
-ProxyReader.prototype._addProxy = function (proxy) {
-  var me = this
-  if (me._proxyTarget) {
-    return me.error("proxy already set")
-  }
-
-  me._proxyTarget = proxy
-  proxy._proxy = me
-
-  ; [ "error"
-    , "data"
-    , "end"
-    , "close"
-    , "linkpath"
-    , "entry"
-    , "entryEnd"
-    , "child"
-    , "childEnd"
-    , "warn"
-    , "stat"
-    ].forEach(function (ev) {
-      // console.error("~~ proxy event", ev, me.path)
-      proxy.on(ev, me.emit.bind(me, ev))
-    })
-
-  me.emit("proxy", proxy)
-
-  proxy.on("ready", function () {
-    // console.error("~~ proxy is ready!", me.path)
-    me.ready = true
-    me.emit("ready")
-  })
-
-  var calls = me._buffer
-  me._buffer.length = 0
-  calls.forEach(function (c) {
-    proxy[c[0]].apply(proxy, c[1])
-  })
-}
-
-ProxyReader.prototype.pause = function () {
-  return this._proxyTarget ? this._proxyTarget.pause() : false
-}
-
-ProxyReader.prototype.resume = function () {
-  return this._proxyTarget ? this._proxyTarget.resume() : false
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-writer.js
deleted file mode 100644
index b0476633..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/proxy-writer.js
+++ /dev/null
@@ -1,109 +0,0 @@
-// A writer for when we don't know what kind of thing
-// the thing is.  That is, it's not explicitly set,
-// so we're going to make it whatever the thing already
-// is, or "File"
-//
-// Until then, collect all events.
-
-module.exports = ProxyWriter
-
-var Writer = require("./writer.js")
-  , getType = require("./get-type.js")
-  , inherits = require("inherits")
-  , collect = require("./collect.js")
-  , fs = require("fs")
-
-inherits(ProxyWriter, Writer)
-
-function ProxyWriter (props) {
-  var me = this
-  if (!(me instanceof ProxyWriter)) throw new Error(
-    "ProxyWriter must be called as constructor.")
-
-  me.props = props
-  me._needDrain = false
-
-  Writer.call(me, props)
-}
-
-ProxyWriter.prototype._stat = function () {
-  var me = this
-    , props = me.props
-    // stat the thing to see what the proxy should be.
-    , stat = props.follow ? "stat" : "lstat"
-
-  fs[stat](props.path, function (er, current) {
-    var type
-    if (er || !current) {
-      type = "File"
-    } else {
-      type = getType(current)
-    }
-
-    props[type] = true
-    props.type = me.type = type
-
-    me._old = current
-    me._addProxy(Writer(props, current))
-  })
-}
-
-ProxyWriter.prototype._addProxy = function (proxy) {
-  // console.error("~~ set proxy", this.path)
-  var me = this
-  if (me._proxy) {
-    return me.error("proxy already set")
-  }
-
-  me._proxy = proxy
-  ; [ "ready"
-    , "error"
-    , "close"
-    , "pipe"
-    , "drain"
-    , "warn"
-    ].forEach(function (ev) {
-      proxy.on(ev, me.emit.bind(me, ev))
-    })
-
-  me.emit("proxy", proxy)
-
-  var calls = me._buffer
-  calls.forEach(function (c) {
-    // console.error("~~ ~~ proxy buffered call", c[0], c[1])
-    proxy[c[0]].apply(proxy, c[1])
-  })
-  me._buffer.length = 0
-  if (me._needsDrain) me.emit("drain")
-}
-
-ProxyWriter.prototype.add = function (entry) {
-  // console.error("~~ proxy add")
-  collect(entry)
-
-  if (!this._proxy) {
-    this._buffer.push(["add", [entry]])
-    this._needDrain = true
-    return false
-  }
-  return this._proxy.add(entry)
-}
-
-ProxyWriter.prototype.write = function (c) {
-  // console.error("~~ proxy write")
-  if (!this._proxy) {
-    this._buffer.push(["write", [c]])
-    this._needDrain = true
-    return false
-  }
-  return this._proxy.write(c)
-}
-
-ProxyWriter.prototype.end = function (c) {
-  // console.error("~~ proxy end")
-  if (!this._proxy) {
-    this._buffer.push(["end", [c]])
-    return false
-  }
-  return this._proxy.end(c)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/reader.js
deleted file mode 100644
index eaf921cd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/reader.js
+++ /dev/null
@@ -1,260 +0,0 @@
-
-module.exports = Reader
-
-var fs = require("graceful-fs")
-  , Stream = require("stream").Stream
-  , inherits = require("inherits")
-  , path = require("path")
-  , getType = require("./get-type.js")
-  , hardLinks = Reader.hardLinks = {}
-  , Abstract = require("./abstract.js")
-
-// Must do this *before* loading the child classes
-inherits(Reader, Abstract)
-
-var DirReader = require("./dir-reader.js")
-  , FileReader = require("./file-reader.js")
-  , LinkReader = require("./link-reader.js")
-  , SocketReader = require("./socket-reader.js")
-  , ProxyReader = require("./proxy-reader.js")
-
-function Reader (props, currentStat) {
-  var me = this
-  if (!(me instanceof Reader)) return new Reader(props, currentStat)
-
-  if (typeof props === "string") {
-    props = { path: props }
-  }
-
-  if (!props.path) {
-    me.error("Must provide a path", null, true)
-  }
-
-  // polymorphism.
-  // call fstream.Reader(dir) to get a DirReader object, etc.
-  // Note that, unlike in the Writer case, ProxyReader is going
-  // to be the *normal* state of affairs, since we rarely know
-  // the type of a file prior to reading it.
-
-
-  var type
-    , ClassType
-
-  if (props.type && typeof props.type === "function") {
-    type = props.type
-    ClassType = type
-  } else {
-    type = getType(props)
-    ClassType = Reader
-  }
-
-  if (currentStat && !type) {
-    type = getType(currentStat)
-    props[type] = true
-    props.type = type
-  }
-
-  switch (type) {
-    case "Directory":
-      ClassType = DirReader
-      break
-
-    case "Link":
-      // XXX hard links are just files.
-      // However, it would be good to keep track of files' dev+inode
-      // and nlink values, and create a HardLinkReader that emits
-      // a linkpath value of the original copy, so that the tar
-      // writer can preserve them.
-      // ClassType = HardLinkReader
-      // break
-
-    case "File":
-      ClassType = FileReader
-      break
-
-    case "SymbolicLink":
-      ClassType = LinkReader
-      break
-
-    case "Socket":
-      ClassType = SocketReader
-      break
-
-    case null:
-      ClassType = ProxyReader
-      break
-  }
-
-  if (!(me instanceof ClassType)) {
-    return new ClassType(props)
-  }
-
-  Abstract.call(me)
-
-  me.readable = true
-  me.writable = false
-
-  me.type = type
-  me.props = props
-  me.depth = props.depth = props.depth || 0
-  me.parent = props.parent || null
-  me.root = props.root || (props.parent && props.parent.root) || me
-
-  me._path = me.path = path.resolve(props.path)
-  if (process.platform === "win32") {
-    me.path = me._path = me.path.replace(/\?/g, "_")
-    if (me._path.length >= 260) {
-      // how DOES one create files on the moon?
-      // if the path has spaces in it, then UNC will fail.
-      me._swallowErrors = true
-      //if (me._path.indexOf(" ") === -1) {
-        me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
-      //}
-    }
-  }
-  me.basename = props.basename = path.basename(me.path)
-  me.dirname = props.dirname = path.dirname(me.path)
-
-  // these have served their purpose, and are now just noisy clutter
-  props.parent = props.root = null
-
-  // console.error("\n\n\n%s setting size to", props.path, props.size)
-  me.size = props.size
-  me.filter = typeof props.filter === "function" ? props.filter : null
-  if (props.sort === "alpha") props.sort = alphasort
-
-  // start the ball rolling.
-  // this will stat the thing, and then call me._read()
-  // to start reading whatever it is.
-  // console.error("calling stat", props.path, currentStat)
-  me._stat(currentStat)
-}
-
-function alphasort (a, b) {
-  return a === b ? 0
-       : a.toLowerCase() > b.toLowerCase() ? 1
-       : a.toLowerCase() < b.toLowerCase() ? -1
-       : a > b ? 1
-       : -1
-}
-
-Reader.prototype._stat = function (currentStat) {
-  var me = this
-    , props = me.props
-    , stat = props.follow ? "stat" : "lstat"
-  // console.error("Reader._stat", me._path, currentStat)
-  if (currentStat) process.nextTick(statCb.bind(null, null, currentStat))
-  else fs[stat](me._path, statCb)
-
-
-  function statCb (er, props_) {
-    // console.error("Reader._stat, statCb", me._path, props_, props_.nlink)
-    if (er) return me.error(er)
-
-    Object.keys(props_).forEach(function (k) {
-      props[k] = props_[k]
-    })
-
-    // if it's not the expected size, then abort here.
-    if (undefined !== me.size && props.size !== me.size) {
-      return me.error("incorrect size")
-    }
-    me.size = props.size
-
-    var type = getType(props)
-    var handleHardlinks = props.hardlinks !== false
-    
-    // special little thing for handling hardlinks.
-    if (handleHardlinks && type !== "Directory" && props.nlink && props.nlink > 1) {
-      var k = props.dev + ":" + props.ino
-      // console.error("Reader has nlink", me._path, k)
-      if (hardLinks[k] === me._path || !hardLinks[k]) hardLinks[k] = me._path
-      else {
-        // switch into hardlink mode.
-        type = me.type = me.props.type = "Link"
-        me.Link = me.props.Link = true
-        me.linkpath = me.props.linkpath = hardLinks[k]
-        // console.error("Hardlink detected, switching mode", me._path, me.linkpath)
-        // Setting __proto__ would arguably be the "correct"
-        // approach here, but that just seems too wrong.
-        me._stat = me._read = LinkReader.prototype._read
-      }
-    }
-
-    if (me.type && me.type !== type) {
-      me.error("Unexpected type: " + type)
-    }
-
-    // if the filter doesn't pass, then just skip over this one.
-    // still have to emit end so that dir-walking can move on.
-    if (me.filter) {
-      var who = me._proxy || me
-      // special handling for ProxyReaders
-      if (!me.filter.call(who, who, props)) {
-        if (!me._disowned) {
-          me.abort()
-          me.emit("end")
-          me.emit("close")
-        }
-        return
-      }
-    }
-
-    // last chance to abort or disown before the flow starts!
-    var events = ["_stat", "stat", "ready"]
-    var e = 0
-    ;(function go () {
-      if (me._aborted) {
-        me.emit("end")
-        me.emit("close")
-        return
-      }
-
-      if (me._paused) {
-        me.once("resume", go)
-        return
-      }
-
-      var ev = events[e ++]
-      if (!ev) return me._read()
-      me.emit(ev, props)
-      go()
-    })()
-  }
-}
-
-Reader.prototype.pipe = function (dest, opts) {
-  var me = this
-  if (typeof dest.add === "function") {
-    // piping to a multi-compatible, and we've got directory entries.
-    me.on("entry", function (entry) {
-      var ret = dest.add(entry)
-      if (false === ret) {
-        me.pause()
-      }
-    })
-  }
-
-  // console.error("R Pipe apply Stream Pipe")
-  return Stream.prototype.pipe.apply(this, arguments)
-}
-
-Reader.prototype.pause = function (who) {
-  this._paused = true
-  who = who || this
-  this.emit("pause", who)
-  if (this._stream) this._stream.pause(who)
-}
-
-Reader.prototype.resume = function (who) {
-  this._paused = false
-  who = who || this
-  this.emit("resume", who)
-  if (this._stream) this._stream.resume(who)
-  this._read()
-}
-
-Reader.prototype._read = function () {
-  this.error("Cannot read unknown type: "+this.type)
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/socket-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/socket-reader.js
deleted file mode 100644
index e89c1731..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/socket-reader.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// Just get the stats, and then don't do anything.
-// You can't really "read" from a socket.  You "connect" to it.
-// Mostly, this is here so that reading a dir with a socket in it
-// doesn't blow up.
-
-module.exports = SocketReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , Reader = require("./reader.js")
-
-inherits(SocketReader, Reader)
-
-function SocketReader (props) {
-  var me = this
-  if (!(me instanceof SocketReader)) throw new Error(
-    "SocketReader must be called as constructor.")
-
-  if (!(props.type === "Socket" && props.Socket)) {
-    throw new Error("Non-socket type "+ props.type)
-  }
-
-  Reader.call(me, props)
-}
-
-SocketReader.prototype._read = function () {
-  var me = this
-  if (me._paused) return
-  // basically just a no-op, since we got all the info we have
-  // from the _stat method
-  if (!me._ended) {
-    me.emit("end")
-    me.emit("close")
-    me._ended = true
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/writer.js
deleted file mode 100644
index 5599fb22..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/lib/writer.js
+++ /dev/null
@@ -1,389 +0,0 @@
-
-module.exports = Writer
-
-var fs = require("graceful-fs")
-  , inherits = require("inherits")
-  , rimraf = require("rimraf")
-  , mkdir = require("mkdirp")
-  , path = require("path")
-  , umask = process.platform === "win32" ? 0 : process.umask()
-  , getType = require("./get-type.js")
-  , Abstract = require("./abstract.js")
-
-// Must do this *before* loading the child classes
-inherits(Writer, Abstract)
-
-Writer.dirmode = 0777 & (~umask)
-Writer.filemode = 0666 & (~umask)
-
-var DirWriter = require("./dir-writer.js")
-  , LinkWriter = require("./link-writer.js")
-  , FileWriter = require("./file-writer.js")
-  , ProxyWriter = require("./proxy-writer.js")
-
-// props is the desired state.  current is optionally the current stat,
-// provided here so that subclasses can avoid statting the target
-// more than necessary.
-function Writer (props, current) {
-  var me = this
-
-  if (typeof props === "string") {
-    props = { path: props }
-  }
-
-  if (!props.path) me.error("Must provide a path", null, true)
-
-  // polymorphism.
-  // call fstream.Writer(dir) to get a DirWriter object, etc.
-  var type = getType(props)
-    , ClassType = Writer
-
-  switch (type) {
-    case "Directory":
-      ClassType = DirWriter
-      break
-    case "File":
-      ClassType = FileWriter
-      break
-    case "Link":
-    case "SymbolicLink":
-      ClassType = LinkWriter
-      break
-    case null:
-      // Don't know yet what type to create, so we wrap in a proxy.
-      ClassType = ProxyWriter
-      break
-  }
-
-  if (!(me instanceof ClassType)) return new ClassType(props)
-
-  // now get down to business.
-
-  Abstract.call(me)
-
-  // props is what we want to set.
-  // set some convenience properties as well.
-  me.type = props.type
-  me.props = props
-  me.depth = props.depth || 0
-  me.clobber = false === props.clobber ? props.clobber : true
-  me.parent = props.parent || null
-  me.root = props.root || (props.parent && props.parent.root) || me
-
-  me._path = me.path = path.resolve(props.path)
-  if (process.platform === "win32") {
-    me.path = me._path = me.path.replace(/\?/g, "_")
-    if (me._path.length >= 260) {
-      me._swallowErrors = true
-      me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
-    }
-  }
-  me.basename = path.basename(props.path)
-  me.dirname = path.dirname(props.path)
-  me.linkpath = props.linkpath || null
-
-  props.parent = props.root = null
-
-  // console.error("\n\n\n%s setting size to", props.path, props.size)
-  me.size = props.size
-
-  if (typeof props.mode === "string") {
-    props.mode = parseInt(props.mode, 8)
-  }
-
-  me.readable = false
-  me.writable = true
-
-  // buffer until ready, or while handling another entry
-  me._buffer = []
-  me.ready = false
-
-  me.filter = typeof props.filter === "function" ? props.filter: null
-
-  // start the ball rolling.
-  // this checks what's there already, and then calls
-  // me._create() to call the impl-specific creation stuff.
-  me._stat(current)
-}
-
-// Calling this means that it's something we can't create.
-// Just assert that it's already there, otherwise raise a warning.
-Writer.prototype._create = function () {
-  var me = this
-  fs[me.props.follow ? "stat" : "lstat"](me._path, function (er, current) {
-    if (er) {
-      return me.warn("Cannot create " + me._path + "\n" +
-                     "Unsupported type: "+me.type, "ENOTSUP")
-    }
-    me._finish()
-  })
-}
-
-Writer.prototype._stat = function (current) {
-  var me = this
-    , props = me.props
-    , stat = props.follow ? "stat" : "lstat"
-    , who = me._proxy || me
-
-  if (current) statCb(null, current)
-  else fs[stat](me._path, statCb)
-
-  function statCb (er, current) {
-    if (me.filter && !me.filter.call(who, who, current)) {
-      me._aborted = true
-      me.emit("end")
-      me.emit("close")
-      return
-    }
-
-    // if it's not there, great.  We'll just create it.
-    // if it is there, then we'll need to change whatever differs
-    if (er || !current) {
-      return create(me)
-    }
-
-    me._old = current
-    var currentType = getType(current)
-
-    // if it's a type change, then we need to clobber or error.
-    // if it's not a type change, then let the impl take care of it.
-    if (currentType !== me.type) {
-      return rimraf(me._path, function (er) {
-        if (er) return me.error(er)
-        me._old = null
-        create(me)
-      })
-    }
-
-    // otherwise, just handle in the app-specific way
-    // this creates a fs.WriteStream, or mkdir's, or whatever
-    create(me)
-  }
-}
-
-function create (me) {
-  // console.error("W create", me._path, Writer.dirmode)
-
-  // XXX Need to clobber non-dirs that are in the way,
-  // unless { clobber: false } in the props.
-  mkdir(path.dirname(me._path), Writer.dirmode, function (er, made) {
-    // console.error("W created", path.dirname(me._path), er)
-    if (er) return me.error(er)
-
-    // later on, we have to set the mode and owner for these
-    me._madeDir = made
-    return me._create()
-  })
-}
-
-function endChmod (me, want, current, path, cb) {
-    var wantMode = want.mode
-      , chmod = want.follow || me.type !== "SymbolicLink"
-              ? "chmod" : "lchmod"
-
-  if (!fs[chmod]) return cb()
-  if (typeof wantMode !== "number") return cb()
-
-  var curMode = current.mode & 0777
-  wantMode = wantMode & 0777
-  if (wantMode === curMode) return cb()
-
-  fs[chmod](path, wantMode, cb)
-}
-
-
-function endChown (me, want, current, path, cb) {
-  // Don't even try it unless root.  Too easy to EPERM.
-  if (process.platform === "win32") return cb()
-  if (!process.getuid || !process.getuid() === 0) return cb()
-  if (typeof want.uid !== "number" &&
-      typeof want.gid !== "number" ) return cb()
-
-  if (current.uid === want.uid &&
-      current.gid === want.gid) return cb()
-
-  var chown = (me.props.follow || me.type !== "SymbolicLink")
-            ? "chown" : "lchown"
-  if (!fs[chown]) return cb()
-
-  if (typeof want.uid !== "number") want.uid = current.uid
-  if (typeof want.gid !== "number") want.gid = current.gid
-
-  fs[chown](path, want.uid, want.gid, cb)
-}
-
-function endUtimes (me, want, current, path, cb) {
-  if (!fs.utimes || process.platform === "win32") return cb()
-
-  var utimes = (want.follow || me.type !== "SymbolicLink")
-             ? "utimes" : "lutimes"
-
-  if (utimes === "lutimes" && !fs[utimes]) {
-    utimes = "utimes"
-  }
-
-  if (!fs[utimes]) return cb()
-
-  var curA = current.atime
-    , curM = current.mtime
-    , meA = want.atime
-    , meM = want.mtime
-
-  if (meA === undefined) meA = curA
-  if (meM === undefined) meM = curM
-
-  if (!isDate(meA)) meA = new Date(meA)
-  if (!isDate(meM)) meA = new Date(meM)
-
-  if (meA.getTime() === curA.getTime() &&
-      meM.getTime() === curM.getTime()) return cb()
-
-  fs[utimes](path, meA, meM, cb)
-}
-
-
-// XXX This function is beastly.  Break it up!
-Writer.prototype._finish = function () {
-  var me = this
-
-  // console.error(" W Finish", me._path, me.size)
-
-  // set up all the things.
-  // At this point, we're already done writing whatever we've gotta write,
-  // adding files to the dir, etc.
-  var todo = 0
-  var errState = null
-  var done = false
-
-  if (me._old) {
-    // the times will almost *certainly* have changed.
-    // adds the utimes syscall, but remove another stat.
-    me._old.atime = new Date(0)
-    me._old.mtime = new Date(0)
-    // console.error(" W Finish Stale Stat", me._path, me.size)
-    setProps(me._old)
-  } else {
-    var stat = me.props.follow ? "stat" : "lstat"
-    // console.error(" W Finish Stating", me._path, me.size)
-    fs[stat](me._path, function (er, current) {
-      // console.error(" W Finish Stated", me._path, me.size, current)
-      if (er) {
-        // if we're in the process of writing out a
-        // directory, it's very possible that the thing we're linking to
-        // doesn't exist yet (especially if it was intended as a symlink),
-        // so swallow ENOENT errors here and just soldier on.
-        if (er.code === "ENOENT" &&
-            (me.type === "Link" || me.type === "SymbolicLink") &&
-            process.platform === "win32") {
-          me.ready = true
-          me.emit("ready")
-          me.emit("end")
-          me.emit("close")
-          me.end = me._finish = function () {}
-          return
-        } else return me.error(er)
-      }
-      setProps(me._old = current)
-    })
-  }
-
-  return
-
-  function setProps (current) {
-    todo += 3
-    endChmod(me, me.props, current, me._path, next("chmod"))
-    endChown(me, me.props, current, me._path, next("chown"))
-    endUtimes(me, me.props, current, me._path, next("utimes"))
-  }
-
-  function next (what) {
-    return function (er) {
-      // console.error("   W Finish", what, todo)
-      if (errState) return
-      if (er) {
-        er.fstream_finish_call = what
-        return me.error(errState = er)
-      }
-      if (--todo > 0) return
-      if (done) return
-      done = true
-
-      // we may still need to set the mode/etc. on some parent dirs
-      // that were created previously.  delay end/close until then.
-      if (!me._madeDir) return end()
-      else endMadeDir(me, me._path, end)
-
-      function end (er) {
-        if (er) {
-          er.fstream_finish_call = "setupMadeDir"
-          return me.error(er)
-        }
-        // all the props have been set, so we're completely done.
-        me.emit("end")
-        me.emit("close")
-      }
-    }
-  }
-}
-
-function endMadeDir (me, p, cb) {
-  var made = me._madeDir
-  // everything *between* made and path.dirname(me._path)
-  // needs to be set up.  Note that this may just be one dir.
-  var d = path.dirname(p)
-
-  endMadeDir_(me, d, function (er) {
-    if (er) return cb(er)
-    if (d === made) {
-      return cb()
-    }
-    endMadeDir(me, d, cb)
-  })
-}
-
-function endMadeDir_ (me, p, cb) {
-  var dirProps = {}
-  Object.keys(me.props).forEach(function (k) {
-    dirProps[k] = me.props[k]
-
-    // only make non-readable dirs if explicitly requested.
-    if (k === "mode" && me.type !== "Directory") {
-      dirProps[k] = dirProps[k] | 0111
-    }
-  })
-
-  var todo = 3
-  , errState = null
-  fs.stat(p, function (er, current) {
-    if (er) return cb(errState = er)
-    endChmod(me, dirProps, current, p, next)
-    endChown(me, dirProps, current, p, next)
-    endUtimes(me, dirProps, current, p, next)
-  })
-
-  function next (er) {
-    if (errState) return
-    if (er) return cb(errState = er)
-    if (-- todo === 0) return cb()
-  }
-}
-
-Writer.prototype.pipe = function () {
-  this.error("Can't pipe from writable stream")
-}
-
-Writer.prototype.add = function () {
-  this.error("Cannot add to non-Directory type")
-}
-
-Writer.prototype.write = function () {
-  return true
-}
-
-function objectToString (d) {
-  return Object.prototype.toString.call(d)
-}
-
-function isDate(d) {
-  return typeof d === 'object' && objectToString(d) === '[object Date]';
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/README.md
deleted file mode 100644
index eb1a1093..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# graceful-fs
-
-graceful-fs functions as a drop-in replacement for the fs module,
-making various improvements.
-
-The improvements are meant to normalize behavior across different
-platforms and environments, and to make filesystem access more
-resilient to errors.
-
-## Improvements over fs module
-
-graceful-fs:
-
-* Queues up `open` and `readdir` calls, and retries them once
-  something closes if there is an EMFILE error from too many file
-  descriptors.
-* fixes `lchmod` for Node versions prior to 0.6.2.
-* implements `fs.lutimes` if possible. Otherwise it becomes a noop.
-* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or
-  `lchown` if the user isn't root.
-* makes `lchmod` and `lchown` become noops, if not available.
-* retries reading a file if `read` results in EAGAIN error.
-
-On Windows, it retries renaming a file for up to one second if `EACCESS`
-or `EPERM` error occurs, likely because antivirus software has locked
-the directory.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js
deleted file mode 100644
index c84db910..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js
+++ /dev/null
@@ -1,160 +0,0 @@
-// Monkey-patching the fs module.
-// It's ugly, but there is simply no other way to do this.
-var fs = module.exports = require('fs')
-
-var assert = require('assert')
-
-// fix up some busted stuff, mostly on windows and old nodes
-require('./polyfills.js')
-
-// The EMFILE enqueuing stuff
-
-var util = require('util')
-
-function noop () {}
-
-var debug = noop
-if (util.debuglog)
-  debug = util.debuglog('gfs')
-else if (/\bgfs\b/i.test(process.env.NODE_DEBUG || ''))
-  debug = function() {
-    var m = util.format.apply(util, arguments)
-    m = 'GFS: ' + m.split(/\n/).join('\nGFS: ')
-    console.error(m)
-  }
-
-if (/\bgfs\b/i.test(process.env.NODE_DEBUG || '')) {
-  process.on('exit', function() {
-    debug('fds', fds)
-    debug(queue)
-    assert.equal(queue.length, 0)
-  })
-}
-
-
-var originalOpen = fs.open
-fs.open = open
-
-function open(path, flags, mode, cb) {
-  if (typeof mode === "function") cb = mode, mode = null
-  if (typeof cb !== "function") cb = noop
-  new OpenReq(path, flags, mode, cb)
-}
-
-function OpenReq(path, flags, mode, cb) {
-  this.path = path
-  this.flags = flags
-  this.mode = mode
-  this.cb = cb
-  Req.call(this)
-}
-
-util.inherits(OpenReq, Req)
-
-OpenReq.prototype.process = function() {
-  originalOpen.call(fs, this.path, this.flags, this.mode, this.done)
-}
-
-var fds = {}
-OpenReq.prototype.done = function(er, fd) {
-  debug('open done', er, fd)
-  if (fd)
-    fds['fd' + fd] = this.path
-  Req.prototype.done.call(this, er, fd)
-}
-
-
-var originalReaddir = fs.readdir
-fs.readdir = readdir
-
-function readdir(path, cb) {
-  if (typeof cb !== "function") cb = noop
-  new ReaddirReq(path, cb)
-}
-
-function ReaddirReq(path, cb) {
-  this.path = path
-  this.cb = cb
-  Req.call(this)
-}
-
-util.inherits(ReaddirReq, Req)
-
-ReaddirReq.prototype.process = function() {
-  originalReaddir.call(fs, this.path, this.done)
-}
-
-ReaddirReq.prototype.done = function(er, files) {
-  if (files && files.sort)
-    files = files.sort()
-  Req.prototype.done.call(this, er, files)
-  onclose()
-}
-
-
-var originalClose = fs.close
-fs.close = close
-
-function close (fd, cb) {
-  debug('close', fd)
-  if (typeof cb !== "function") cb = noop
-  delete fds['fd' + fd]
-  originalClose.call(fs, fd, function(er) {
-    onclose()
-    cb(er)
-  })
-}
-
-
-var originalCloseSync = fs.closeSync
-fs.closeSync = closeSync
-
-function closeSync (fd) {
-  try {
-    return originalCloseSync(fd)
-  } finally {
-    onclose()
-  }
-}
-
-
-// Req class
-function Req () {
-  // start processing
-  this.done = this.done.bind(this)
-  this.failures = 0
-  this.process()
-}
-
-Req.prototype.done = function (er, result) {
-  var tryAgain = false
-  if (er) {
-    var code = er.code
-    var tryAgain = code === "EMFILE"
-    if (process.platform === "win32")
-      tryAgain = tryAgain || code === "OK"
-  }
-
-  if (tryAgain) {
-    this.failures ++
-    enqueue(this)
-  } else {
-    var cb = this.cb
-    cb(er, result)
-  }
-}
-
-var queue = []
-
-function enqueue(req) {
-  queue.push(req)
-  debug('enqueue %d %s', queue.length, req.constructor.name, req)
-}
-
-function onclose() {
-  var req = queue.shift()
-  if (req) {
-    debug('process', req.constructor.name, req)
-    req.process()
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/package.json
deleted file mode 100644
index 8b6a2fac..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/package.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me"
-  },
-  "name": "graceful-fs",
-  "description": "A drop-in replacement for fs, making various improvements.",
-  "version": "2.0.3",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-graceful-fs.git"
-  },
-  "main": "graceful-fs.js",
-  "engines": {
-    "node": ">=0.4.0"
-  },
-  "directories": {
-    "test": "test"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "keywords": [
-    "fs",
-    "module",
-    "reading",
-    "retry",
-    "retries",
-    "queue",
-    "error",
-    "errors",
-    "handling",
-    "EMFILE",
-    "EAGAIN",
-    "EINVAL",
-    "EPERM",
-    "EACCESS"
-  ],
-  "license": "BSD",
-  "readme": "# graceful-fs\n\ngraceful-fs functions as a drop-in replacement for the fs module,\nmaking various improvements.\n\nThe improvements are meant to normalize behavior across different\nplatforms and environments, and to make filesystem access more\nresilient to errors.\n\n## Improvements over fs module\n\ngraceful-fs:\n\n* Queues up `open` and `readdir` calls, and retries them once\n  something closes if there is an EMFILE error from too many file\n  descriptors.\n* fixes `lchmod` for Node versions prior to 0.6.2.\n* implements `fs.lutimes` if possible. Otherwise it becomes a noop.\n* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or\n  `lchown` if the user isn't root.\n* makes `lchmod` and `lchown` become noops, if not available.\n* retries reading a file if `read` results in EAGAIN error.\n\nOn Windows, it retries renaming a file for up to one second if `EACCESS`\nor `EPERM` error occurs, likely because antivirus software has locked\nthe directory.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/node-graceful-fs/issues"
-  },
-  "homepage": "https://github.com/isaacs/node-graceful-fs",
-  "_id": "graceful-fs@2.0.3",
-  "_shasum": "7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0",
-  "_from": "graceful-fs@~2.0.0",
-  "_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/polyfills.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/polyfills.js
deleted file mode 100644
index afc83b3f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/polyfills.js
+++ /dev/null
@@ -1,228 +0,0 @@
-var fs = require('fs')
-var constants = require('constants')
-
-var origCwd = process.cwd
-var cwd = null
-process.cwd = function() {
-  if (!cwd)
-    cwd = origCwd.call(process)
-  return cwd
-}
-var chdir = process.chdir
-process.chdir = function(d) {
-  cwd = null
-  chdir.call(process, d)
-}
-
-// (re-)implement some things that are known busted or missing.
-
-// lchmod, broken prior to 0.6.2
-// back-port the fix here.
-if (constants.hasOwnProperty('O_SYMLINK') &&
-    process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
-  fs.lchmod = function (path, mode, callback) {
-    callback = callback || noop
-    fs.open( path
-           , constants.O_WRONLY | constants.O_SYMLINK
-           , mode
-           , function (err, fd) {
-      if (err) {
-        callback(err)
-        return
-      }
-      // prefer to return the chmod error, if one occurs,
-      // but still try to close, and report closing errors if they occur.
-      fs.fchmod(fd, mode, function (err) {
-        fs.close(fd, function(err2) {
-          callback(err || err2)
-        })
-      })
-    })
-  }
-
-  fs.lchmodSync = function (path, mode) {
-    var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
-
-    // prefer to return the chmod error, if one occurs,
-    // but still try to close, and report closing errors if they occur.
-    var err, err2
-    try {
-      var ret = fs.fchmodSync(fd, mode)
-    } catch (er) {
-      err = er
-    }
-    try {
-      fs.closeSync(fd)
-    } catch (er) {
-      err2 = er
-    }
-    if (err || err2) throw (err || err2)
-    return ret
-  }
-}
-
-
-// lutimes implementation, or no-op
-if (!fs.lutimes) {
-  if (constants.hasOwnProperty("O_SYMLINK")) {
-    fs.lutimes = function (path, at, mt, cb) {
-      fs.open(path, constants.O_SYMLINK, function (er, fd) {
-        cb = cb || noop
-        if (er) return cb(er)
-        fs.futimes(fd, at, mt, function (er) {
-          fs.close(fd, function (er2) {
-            return cb(er || er2)
-          })
-        })
-      })
-    }
-
-    fs.lutimesSync = function (path, at, mt) {
-      var fd = fs.openSync(path, constants.O_SYMLINK)
-        , err
-        , err2
-        , ret
-
-      try {
-        var ret = fs.futimesSync(fd, at, mt)
-      } catch (er) {
-        err = er
-      }
-      try {
-        fs.closeSync(fd)
-      } catch (er) {
-        err2 = er
-      }
-      if (err || err2) throw (err || err2)
-      return ret
-    }
-
-  } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) {
-    // maybe utimensat will be bound soonish?
-    fs.lutimes = function (path, at, mt, cb) {
-      fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb)
-    }
-
-    fs.lutimesSync = function (path, at, mt) {
-      return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW)
-    }
-
-  } else {
-    fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
-    fs.lutimesSync = function () {}
-  }
-}
-
-
-// https://github.com/isaacs/node-graceful-fs/issues/4
-// Chown should not fail on einval or eperm if non-root.
-
-fs.chown = chownFix(fs.chown)
-fs.fchown = chownFix(fs.fchown)
-fs.lchown = chownFix(fs.lchown)
-
-fs.chownSync = chownFixSync(fs.chownSync)
-fs.fchownSync = chownFixSync(fs.fchownSync)
-fs.lchownSync = chownFixSync(fs.lchownSync)
-
-function chownFix (orig) {
-  if (!orig) return orig
-  return function (target, uid, gid, cb) {
-    return orig.call(fs, target, uid, gid, function (er, res) {
-      if (chownErOk(er)) er = null
-      cb(er, res)
-    })
-  }
-}
-
-function chownFixSync (orig) {
-  if (!orig) return orig
-  return function (target, uid, gid) {
-    try {
-      return orig.call(fs, target, uid, gid)
-    } catch (er) {
-      if (!chownErOk(er)) throw er
-    }
-  }
-}
-
-function chownErOk (er) {
-  // if there's no getuid, or if getuid() is something other than 0,
-  // and the error is EINVAL or EPERM, then just ignore it.
-  // This specific case is a silent failure in cp, install, tar,
-  // and most other unix tools that manage permissions.
-  // When running as root, or if other types of errors are encountered,
-  // then it's strict.
-  if (!er || (!process.getuid || process.getuid() !== 0)
-      && (er.code === "EINVAL" || er.code === "EPERM")) return true
-}
-
-
-// if lchmod/lchown do not exist, then make them no-ops
-if (!fs.lchmod) {
-  fs.lchmod = function (path, mode, cb) {
-    process.nextTick(cb)
-  }
-  fs.lchmodSync = function () {}
-}
-if (!fs.lchown) {
-  fs.lchown = function (path, uid, gid, cb) {
-    process.nextTick(cb)
-  }
-  fs.lchownSync = function () {}
-}
-
-
-
-// on Windows, A/V software can lock the directory, causing this
-// to fail with an EACCES or EPERM if the directory contains newly
-// created files.  Try again on failure, for up to 1 second.
-if (process.platform === "win32") {
-  var rename_ = fs.rename
-  fs.rename = function rename (from, to, cb) {
-    var start = Date.now()
-    rename_(from, to, function CB (er) {
-      if (er
-          && (er.code === "EACCES" || er.code === "EPERM")
-          && Date.now() - start < 1000) {
-        return rename_(from, to, CB)
-      }
-      cb(er)
-    })
-  }
-}
-
-
-// if read() returns EAGAIN, then just try it again.
-var read = fs.read
-fs.read = function (fd, buffer, offset, length, position, callback_) {
-  var callback
-  if (callback_ && typeof callback_ === 'function') {
-    var eagCounter = 0
-    callback = function (er, _, __) {
-      if (er && er.code === 'EAGAIN' && eagCounter < 10) {
-        eagCounter ++
-        return read.call(fs, fd, buffer, offset, length, position, callback)
-      }
-      callback_.apply(this, arguments)
-    }
-  }
-  return read.call(fs, fd, buffer, offset, length, position, callback)
-}
-
-var readSync = fs.readSync
-fs.readSync = function (fd, buffer, offset, length, position) {
-  var eagCounter = 0
-  while (true) {
-    try {
-      return readSync.call(fs, fd, buffer, offset, length, position)
-    } catch (er) {
-      if (er.code === 'EAGAIN' && eagCounter < 10) {
-        eagCounter ++
-        continue
-      }
-      throw er
-    }
-  }
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/open.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/open.js
deleted file mode 100644
index 104f36b0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/open.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var test = require('tap').test
-var fs = require('../graceful-fs.js')
-
-test('graceful fs is monkeypatched fs', function (t) {
-  t.equal(fs, require('fs'))
-  t.end()
-})
-
-test('open an existing file works', function (t) {
-  var fd = fs.openSync(__filename, 'r')
-  fs.closeSync(fd)
-  fs.open(__filename, 'r', function (er, fd) {
-    if (er) throw er
-    fs.close(fd, function (er) {
-      if (er) throw er
-      t.pass('works')
-      t.end()
-    })
-  })
-})
-
-test('open a non-existing file throws', function (t) {
-  var er
-  try {
-    var fd = fs.openSync('this file does not exist', 'r')
-  } catch (x) {
-    er = x
-  }
-  t.ok(er, 'should throw')
-  t.notOk(fd, 'should not get an fd')
-  t.equal(er.code, 'ENOENT')
-
-  fs.open('neither does this file', 'r', function (er, fd) {
-    t.ok(er, 'should throw')
-    t.notOk(fd, 'should not get an fd')
-    t.equal(er.code, 'ENOENT')
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js
deleted file mode 100644
index aeaedf1c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js
+++ /dev/null
@@ -1,21 +0,0 @@
-var test = require("tap").test
-var fs = require("fs")
-
-var readdir = fs.readdir
-fs.readdir = function(path, cb) {
-  process.nextTick(function() {
-    cb(null, ["b", "z", "a"])
-  })
-}
-
-var g = require("../")
-
-test("readdir reorder", function (t) {
-  g.readdir("whatevers", function (er, files) {
-    if (er)
-      throw er
-    console.error(files)
-    t.same(files, [ "a", "b", "z" ])
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/LICENSE
deleted file mode 100644
index dea3013d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/LICENSE
+++ /dev/null
@@ -1,16 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/README.md
deleted file mode 100644
index b1c56658..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-Browser-friendly inheritance fully compatible with standard node.js
-[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).
-
-This package exports standard `inherits` from node.js `util` module in
-node environment, but also provides alternative browser-friendly
-implementation through [browser
-field](https://gist.github.com/shtylman/4339901). Alternative
-implementation is a literal copy of standard one located in standalone
-module to avoid requiring of `util`. It also has a shim for old
-browsers with no `Object.create` support.
-
-While keeping you sure you are using standard `inherits`
-implementation in node.js environment, it allows bundlers such as
-[browserify](https://github.com/substack/node-browserify) to not
-include full `util` package to your client code if all you need is
-just `inherits` function. It worth, because browser shim for `util`
-package is large and `inherits` is often the single function you need
-from it.
-
-It's recommended to use this package instead of
-`require('util').inherits` for any code that has chances to be used
-not only in node.js but in browser too.
-
-## usage
-
-```js
-var inherits = require('inherits');
-// then use exactly as the standard one
-```
-
-## note on version ~1.0
-
-Version ~1.0 had completely different motivation and is not compatible
-neither with 2.0 nor with standard node.js `inherits`.
-
-If you are using version ~1.0 and planning to switch to ~2.0, be
-careful:
-
-* new version uses `super_` instead of `super` for referencing
-  superclass
-* new version overwrites current prototype while old one preserves any
-  existing fields on it
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits.js
deleted file mode 100644
index 29f5e24f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('util').inherits
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits_browser.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits_browser.js
deleted file mode 100644
index c1e78a75..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/inherits_browser.js
+++ /dev/null
@@ -1,23 +0,0 @@
-if (typeof Object.create === 'function') {
-  // implementation from standard node.js 'util' module
-  module.exports = function inherits(ctor, superCtor) {
-    ctor.super_ = superCtor
-    ctor.prototype = Object.create(superCtor.prototype, {
-      constructor: {
-        value: ctor,
-        enumerable: false,
-        writable: true,
-        configurable: true
-      }
-    });
-  };
-} else {
-  // old school shim for old browsers
-  module.exports = function inherits(ctor, superCtor) {
-    ctor.super_ = superCtor
-    var TempCtor = function () {}
-    TempCtor.prototype = superCtor.prototype
-    ctor.prototype = new TempCtor()
-    ctor.prototype.constructor = ctor
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/package.json
deleted file mode 100644
index 83ae772d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "inherits",
-  "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
-  "version": "2.0.1",
-  "keywords": [
-    "inheritance",
-    "class",
-    "klass",
-    "oop",
-    "object-oriented",
-    "inherits",
-    "browser",
-    "browserify"
-  ],
-  "main": "./inherits.js",
-  "browser": "./inherits_browser.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/inherits"
-  },
-  "license": "ISC",
-  "scripts": {
-    "test": "node test"
-  },
-  "readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n  superclass\n* new version overwrites current prototype while old one preserves any\n  existing fields on it\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/inherits/issues"
-  },
-  "homepage": "https://github.com/isaacs/inherits",
-  "_id": "inherits@2.0.1",
-  "_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
-  "_from": "inherits@~2.0.0",
-  "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/test.js
deleted file mode 100644
index fc53012d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/inherits/test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var inherits = require('./inherits.js')
-var assert = require('assert')
-
-function test(c) {
-  assert(c.constructor === Child)
-  assert(c.constructor.super_ === Parent)
-  assert(Object.getPrototypeOf(c) === Child.prototype)
-  assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype)
-  assert(c instanceof Child)
-  assert(c instanceof Parent)
-}
-
-function Child() {
-  Parent.call(this)
-  test(this)
-}
-
-function Parent() {}
-
-inherits(Child, Parent)
-
-var c = new Child
-test(c)
-
-console.log('ok')
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.npmignore
deleted file mode 100644
index 9303c347..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules/
-npm-debug.log
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.travis.yml
deleted file mode 100644
index 84fd7ca2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
-  - 0.8
-  - 0.9
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/LICENSE
deleted file mode 100644
index 432d1aeb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/examples/pow.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/examples/pow.js
deleted file mode 100644
index e6924212..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/examples/pow.js
+++ /dev/null
@@ -1,6 +0,0 @@
-var mkdirp = require('mkdirp');
-
-mkdirp('/tmp/foo/bar/baz', function (err) {
-    if (err) console.error(err)
-    else console.log('pow!')
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/index.js
deleted file mode 100644
index fda6de8a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/index.js
+++ /dev/null
@@ -1,82 +0,0 @@
-var path = require('path');
-var fs = require('fs');
-
-module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
-
-function mkdirP (p, mode, f, made) {
-    if (typeof mode === 'function' || mode === undefined) {
-        f = mode;
-        mode = 0777 & (~process.umask());
-    }
-    if (!made) made = null;
-
-    var cb = f || function () {};
-    if (typeof mode === 'string') mode = parseInt(mode, 8);
-    p = path.resolve(p);
-
-    fs.mkdir(p, mode, function (er) {
-        if (!er) {
-            made = made || p;
-            return cb(null, made);
-        }
-        switch (er.code) {
-            case 'ENOENT':
-                mkdirP(path.dirname(p), mode, function (er, made) {
-                    if (er) cb(er, made);
-                    else mkdirP(p, mode, cb, made);
-                });
-                break;
-
-            // In the case of any other error, just see if there's a dir
-            // there already.  If so, then hooray!  If not, then something
-            // is borked.
-            default:
-                fs.stat(p, function (er2, stat) {
-                    // if the stat fails, then that's super weird.
-                    // let the original error be the failure reason.
-                    if (er2 || !stat.isDirectory()) cb(er, made)
-                    else cb(null, made);
-                });
-                break;
-        }
-    });
-}
-
-mkdirP.sync = function sync (p, mode, made) {
-    if (mode === undefined) {
-        mode = 0777 & (~process.umask());
-    }
-    if (!made) made = null;
-
-    if (typeof mode === 'string') mode = parseInt(mode, 8);
-    p = path.resolve(p);
-
-    try {
-        fs.mkdirSync(p, mode);
-        made = made || p;
-    }
-    catch (err0) {
-        switch (err0.code) {
-            case 'ENOENT' :
-                made = sync(path.dirname(p), mode, made);
-                sync(p, mode, made);
-                break;
-
-            // In the case of any other error, just see if there's a dir
-            // there already.  If so, then hooray!  If not, then something
-            // is borked.
-            default:
-                var stat;
-                try {
-                    stat = fs.statSync(p);
-                }
-                catch (err1) {
-                    throw err0;
-                }
-                if (!stat.isDirectory()) throw err0;
-                break;
-        }
-    }
-
-    return made;
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/package.json
deleted file mode 100644
index a59f2bea..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/package.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-  "name": "mkdirp",
-  "description": "Recursively mkdir, like `mkdir -p`",
-  "version": "0.3.5",
-  "author": {
-    "name": "James Halliday",
-    "email": "mail@substack.net",
-    "url": "http://substack.net"
-  },
-  "main": "./index",
-  "keywords": [
-    "mkdir",
-    "directory"
-  ],
-  "repository": {
-    "type": "git",
-    "url": "http://github.com/substack/node-mkdirp.git"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "devDependencies": {
-    "tap": "~0.4.0"
-  },
-  "license": "MIT",
-  "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n    \nmkdirp('/tmp/foo/bar/baz', function (err) {\n    if (err) console.error(err)\n    else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n",
-  "readmeFilename": "readme.markdown",
-  "bugs": {
-    "url": "https://github.com/substack/node-mkdirp/issues"
-  },
-  "homepage": "https://github.com/substack/node-mkdirp",
-  "_id": "mkdirp@0.3.5",
-  "_shasum": "de3e5f8961c88c787ee1368df849ac4413eca8d7",
-  "_from": "mkdirp@0.3",
-  "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/readme.markdown b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/readme.markdown
deleted file mode 100644
index 83b0216a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/readme.markdown
+++ /dev/null
@@ -1,63 +0,0 @@
-# mkdirp
-
-Like `mkdir -p`, but in node.js!
-
-[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
-
-# example
-
-## pow.js
-
-```js
-var mkdirp = require('mkdirp');
-    
-mkdirp('/tmp/foo/bar/baz', function (err) {
-    if (err) console.error(err)
-    else console.log('pow!')
-});
-```
-
-Output
-
-```
-pow!
-```
-
-And now /tmp/foo/bar/baz exists, huzzah!
-
-# methods
-
-```js
-var mkdirp = require('mkdirp');
-```
-
-## mkdirp(dir, mode, cb)
-
-Create a new directory and any necessary subdirectories at `dir` with octal
-permission string `mode`.
-
-If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
-
-`cb(err, made)` fires with the error or the first directory `made`
-that had to be created, if any.
-
-## mkdirp.sync(dir, mode)
-
-Synchronously create a new directory and any necessary subdirectories at `dir`
-with octal permission string `mode`.
-
-If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
-
-Returns the first directory that had to be created, if any.
-
-# install
-
-With [npm](http://npmjs.org) do:
-
-```
-npm install mkdirp
-```
-
-# license
-
-MIT
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/chmod.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/chmod.js
deleted file mode 100644
index 520dcb8e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/chmod.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-var ps = [ '', 'tmp' ];
-
-for (var i = 0; i < 25; i++) {
-    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    ps.push(dir);
-}
-
-var file = ps.join('/');
-
-test('chmod-pre', function (t) {
-    var mode = 0744
-    mkdirp(file, mode, function (er) {
-        t.ifError(er, 'should not error');
-        fs.stat(file, function (er, stat) {
-            t.ifError(er, 'should exist');
-            t.ok(stat && stat.isDirectory(), 'should be directory');
-            t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
-            t.end();
-        });
-    });
-});
-
-test('chmod', function (t) {
-    var mode = 0755
-    mkdirp(file, mode, function (er) {
-        t.ifError(er, 'should not error');
-        fs.stat(file, function (er, stat) {
-            t.ifError(er, 'should exist');
-            t.ok(stat && stat.isDirectory(), 'should be directory');
-            t.end();
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/clobber.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/clobber.js
deleted file mode 100644
index 0eb70998..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/clobber.js
+++ /dev/null
@@ -1,37 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-var ps = [ '', 'tmp' ];
-
-for (var i = 0; i < 25; i++) {
-    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    ps.push(dir);
-}
-
-var file = ps.join('/');
-
-// a file in the way
-var itw = ps.slice(0, 3).join('/');
-
-
-test('clobber-pre', function (t) {
-    console.error("about to write to "+itw)
-    fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
-
-    fs.stat(itw, function (er, stat) {
-        t.ifError(er)
-        t.ok(stat && stat.isFile(), 'should be file')
-        t.end()
-    })
-})
-
-test('clobber', function (t) {
-    t.plan(2);
-    mkdirp(file, 0755, function (err) {
-        t.ok(err);
-        t.equal(err.code, 'ENOTDIR');
-        t.end();
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js
deleted file mode 100644
index b07cd70c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js
+++ /dev/null
@@ -1,28 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('woo', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var file = '/tmp/' + [x,y,z].join('/');
-    
-    mkdirp(file, 0755, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    t.equal(stat.mode & 0777, 0755);
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm.js
deleted file mode 100644
index 23a7abbd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('async perm', function (t) {
-    t.plan(2);
-    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
-    
-    mkdirp(file, 0755, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    t.equal(stat.mode & 0777, 0755);
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
-
-test('async root perm', function (t) {
-    mkdirp('/tmp', 0755, function (err) {
-        if (err) t.fail(err);
-        t.end();
-    });
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js
deleted file mode 100644
index f685f609..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('sync perm', function (t) {
-    t.plan(2);
-    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
-    
-    mkdirp.sync(file, 0755);
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.equal(stat.mode & 0777, 0755);
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        })
-    });
-});
-
-test('sync root perm', function (t) {
-    t.plan(1);
-    
-    var file = '/tmp';
-    mkdirp.sync(file, 0755);
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/race.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/race.js
deleted file mode 100644
index 96a04476..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/race.js
+++ /dev/null
@@ -1,41 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('race', function (t) {
-    t.plan(4);
-    var ps = [ '', 'tmp' ];
-    
-    for (var i = 0; i < 25; i++) {
-        var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-        ps.push(dir);
-    }
-    var file = ps.join('/');
-    
-    var res = 2;
-    mk(file, function () {
-        if (--res === 0) t.end();
-    });
-    
-    mk(file, function () {
-        if (--res === 0) t.end();
-    });
-    
-    function mk (file, cb) {
-        mkdirp(file, 0755, function (err) {
-            if (err) t.fail(err);
-            else path.exists(file, function (ex) {
-                if (!ex) t.fail('file not created')
-                else fs.stat(file, function (err, stat) {
-                    if (err) t.fail(err)
-                    else {
-                        t.equal(stat.mode & 0777, 0755);
-                        t.ok(stat.isDirectory(), 'target not a directory');
-                        if (cb) cb();
-                    }
-                })
-            })
-        });
-    }
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/rel.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/rel.js
deleted file mode 100644
index 79858243..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/rel.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('rel', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var cwd = process.cwd();
-    process.chdir('/tmp');
-    
-    var file = [x,y,z].join('/');
-    
-    mkdirp(file, 0755, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    process.chdir(cwd);
-                    t.equal(stat.mode & 0777, 0755);
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return.js
deleted file mode 100644
index bce68e56..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('return value', function (t) {
-    t.plan(4);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    // should return the first dir created.
-    // By this point, it would be profoundly surprising if /tmp didn't
-    // already exist, since every other test makes things in there.
-    mkdirp(file, function (err, made) {
-        t.ifError(err);
-        t.equal(made, '/tmp/' + x);
-        mkdirp(file, function (err, made) {
-          t.ifError(err);
-          t.equal(made, null);
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return_sync.js
deleted file mode 100644
index 7c222d35..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/return_sync.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('return value', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    // should return the first dir created.
-    // By this point, it would be profoundly surprising if /tmp didn't
-    // already exist, since every other test makes things in there.
-    // Note that this will throw on failure, which will fail the test.
-    var made = mkdirp.sync(file);
-    t.equal(made, '/tmp/' + x);
-
-    // making the same file again should have no effect.
-    made = mkdirp.sync(file);
-    t.equal(made, null);
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/root.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/root.js
deleted file mode 100644
index 97ad7a2f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/root.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('root', function (t) {
-    // '/' on unix, 'c:/' on windows.
-    var file = path.resolve('/');
-
-    mkdirp(file, 0755, function (err) {
-        if (err) throw err
-        fs.stat(file, function (er, stat) {
-            if (er) throw er
-            t.ok(stat.isDirectory(), 'target is a directory');
-            t.end();
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/sync.js
deleted file mode 100644
index 7530cada..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/sync.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('sync', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    try {
-        mkdirp.sync(file, 0755);
-    } catch (err) {
-        t.fail(err);
-        return t.end();
-    }
-
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.equal(stat.mode & 0777, 0755);
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask.js
deleted file mode 100644
index 64ccafe2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask.js
+++ /dev/null
@@ -1,28 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('implicit mode from umask', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var file = '/tmp/' + [x,y,z].join('/');
-    
-    mkdirp(file, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    t.equal(stat.mode & 0777, 0777 & (~process.umask()));
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js
deleted file mode 100644
index 35bd5cbb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('umask sync modes', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    try {
-        mkdirp.sync(file);
-    } catch (err) {
-        t.fail(err);
-        return t.end();
-    }
-
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.equal(stat.mode & 0777, (0777 & (~process.umask())));
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/package.json
deleted file mode 100644
index d1c3f176..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/fstream/package.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "fstream",
-  "description": "Advanced file system stream things",
-  "version": "0.1.25",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/fstream.git"
-  },
-  "main": "fstream.js",
-  "engines": {
-    "node": ">=0.6"
-  },
-  "dependencies": {
-    "rimraf": "2",
-    "mkdirp": "0.3",
-    "graceful-fs": "~2.0.0",
-    "inherits": "~2.0.0"
-  },
-  "devDependencies": {
-    "tap": ""
-  },
-  "scripts": {
-    "test": "tap examples/*.js"
-  },
-  "license": "BSD",
-  "readme": "Like FS streams, but with stat on them, and supporting directories and\nsymbolic links, as well as normal files.  Also, you can use this to set\nthe stats on a file, even if you don't change its contents, or to create\na symlink, etc.\n\nSo, for example, you can \"write\" a directory, and it'll call `mkdir`.  You\ncan specify a uid and gid, and it'll call `chown`.  You can specify a\n`mtime` and `atime`, and it'll call `utimes`.  You can call it a symlink\nand provide a `linkpath` and it'll call `symlink`.\n\nNote that it won't automatically resolve symbolic links.  So, if you\ncall `fstream.Reader('/some/symlink')` then you'll get an object\nthat stats and then ends immediately (since it has no data).  To follow\nsymbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:\ntrue })`.\n\nThere are various checks to make sure that the bytes emitted are the\nsame as the intended size, if the size is set.\n\n## Examples\n\n```javascript\nfstream\n  .Writer({ path: \"path/to/file\"\n          , mode: 0755\n          , size: 6\n          })\n  .write(\"hello\\n\")\n  .end()\n```\n\nThis will create the directories if they're missing, and then write\n`hello\\n` into the file, chmod it to 0755, and assert that 6 bytes have\nbeen written when it's done.\n\n```javascript\nfstream\n  .Writer({ path: \"path/to/file\"\n          , mode: 0755\n          , size: 6\n          , flags: \"a\"\n          })\n  .write(\"hello\\n\")\n  .end()\n```\n\nYou can pass flags in, if you want to append to a file.\n\n```javascript\nfstream\n  .Writer({ path: \"path/to/symlink\"\n          , linkpath: \"./file\"\n          , SymbolicLink: true\n          , mode: \"0755\" // octal strings supported\n          })\n  .end()\n```\n\nIf isSymbolicLink is a function, it'll be called, and if it returns\ntrue, then it'll treat it as a symlink.  If it's not a function, then\nany truish value will make a symlink, or you can set `type:\n'SymbolicLink'`, which does the same thing.\n\nNote that the linkpath is relative to the symbolic link location, not\nthe parent dir or cwd.\n\n```javascript\nfstream\n  .Reader(\"path/to/dir\")\n  .pipe(fstream.Writer(\"path/to/other/dir\"))\n```\n\nThis will do like `cp -Rp path/to/dir path/to/other/dir`.  If the other\ndir exists and isn't a directory, then it'll emit an error.  It'll also\nset the uid, gid, mode, etc. to be identical.  In this way, it's more\nlike `rsync -a` than simply a copy.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/fstream/issues"
-  },
-  "homepage": "https://github.com/isaacs/fstream",
-  "_id": "fstream@0.1.25",
-  "_shasum": "deef2db7c7898357c2b37202212a9e5b36abc732",
-  "_from": "fstream@~0.1.22",
-  "_resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.25.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/.npmignore
deleted file mode 100644
index c2658d7d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules/
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/README.md
deleted file mode 100644
index 01af3d6b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# graceful-fs
-
-graceful-fs functions as a drop-in replacement for the fs module,
-making various improvements.
-
-The improvements are meant to normalize behavior across different
-platforms and environments, and to make filesystem access more
-resilient to errors.
-
-## Improvements over fs module
-
-graceful-fs:
-
-* keeps track of how many file descriptors are open, and by default
-  limits this to 1024. Any further requests to open a file are put in a
-  queue until new slots become available. If 1024 turns out to be too
-  much, it decreases the limit further.
-* fixes `lchmod` for Node versions prior to 0.6.2.
-* implements `fs.lutimes` if possible. Otherwise it becomes a noop.
-* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or
-  `lchown` if the user isn't root.
-* makes `lchmod` and `lchown` become noops, if not available.
-* retries reading a file if `read` results in EAGAIN error.
-
-On Windows, it retries renaming a file for up to one second if `EACCESS`
-or `EPERM` error occurs, likely because antivirus software has locked
-the directory.
-
-## Configuration
-
-The maximum number of open file descriptors that graceful-fs manages may
-be adjusted by setting `fs.MAX_OPEN` to a different number. The default
-is 1024.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/graceful-fs.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/graceful-fs.js
deleted file mode 100644
index ca911524..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/graceful-fs.js
+++ /dev/null
@@ -1,442 +0,0 @@
-// this keeps a queue of opened file descriptors, and will make
-// fs operations wait until some have closed before trying to open more.
-
-var fs = exports = module.exports = {}
-fs._originalFs = require("fs")
-
-Object.getOwnPropertyNames(fs._originalFs).forEach(function(prop) {
-  var desc = Object.getOwnPropertyDescriptor(fs._originalFs, prop)
-  Object.defineProperty(fs, prop, desc)
-})
-
-var queue = []
-  , constants = require("constants")
-
-fs._curOpen = 0
-
-fs.MIN_MAX_OPEN = 64
-fs.MAX_OPEN = 1024
-
-// prevent EMFILE errors
-function OpenReq (path, flags, mode, cb) {
-  this.path = path
-  this.flags = flags
-  this.mode = mode
-  this.cb = cb
-}
-
-function noop () {}
-
-fs.open = gracefulOpen
-
-function gracefulOpen (path, flags, mode, cb) {
-  if (typeof mode === "function") cb = mode, mode = null
-  if (typeof cb !== "function") cb = noop
-
-  if (fs._curOpen >= fs.MAX_OPEN) {
-    queue.push(new OpenReq(path, flags, mode, cb))
-    setTimeout(flush)
-    return
-  }
-  open(path, flags, mode, function (er, fd) {
-    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
-      // that was too many.  reduce max, get back in queue.
-      // this should only happen once in a great while, and only
-      // if the ulimit -n is set lower than 1024.
-      fs.MAX_OPEN = fs._curOpen - 1
-      return fs.open(path, flags, mode, cb)
-    }
-    cb(er, fd)
-  })
-}
-
-function open (path, flags, mode, cb) {
-  cb = cb || noop
-  fs._curOpen ++
-  fs._originalFs.open.call(fs, path, flags, mode, function (er, fd) {
-    if (er) onclose()
-    cb(er, fd)
-  })
-}
-
-fs.openSync = function (path, flags, mode) {
-  var ret
-  ret = fs._originalFs.openSync.call(fs, path, flags, mode)
-  fs._curOpen ++
-  return ret
-}
-
-function onclose () {
-  fs._curOpen --
-  flush()
-}
-
-function flush () {
-  while (fs._curOpen < fs.MAX_OPEN) {
-    var req = queue.shift()
-    if (!req) return
-    switch (req.constructor.name) {
-      case 'OpenReq':
-        open(req.path, req.flags || "r", req.mode || 0777, req.cb)
-        break
-      case 'ReaddirReq':
-        readdir(req.path, req.cb)
-        break
-      case 'ReadFileReq':
-        readFile(req.path, req.options, req.cb)
-        break
-      case 'WriteFileReq':
-        writeFile(req.path, req.data, req.options, req.cb)
-        break
-      default:
-        throw new Error('Unknown req type: ' + req.constructor.name)
-    }
-  }
-}
-
-fs.close = function (fd, cb) {
-  cb = cb || noop
-  fs._originalFs.close.call(fs, fd, function (er) {
-    onclose()
-    cb(er)
-  })
-}
-
-fs.closeSync = function (fd) {
-  try {
-    return fs._originalFs.closeSync.call(fs, fd)
-  } finally {
-    onclose()
-  }
-}
-
-
-// readdir takes a fd as well.
-// however, the sync version closes it right away, so
-// there's no need to wrap.
-// It would be nice to catch when it throws an EMFILE,
-// but that's relatively rare anyway.
-
-fs.readdir = gracefulReaddir
-
-function gracefulReaddir (path, cb) {
-  if (fs._curOpen >= fs.MAX_OPEN) {
-    queue.push(new ReaddirReq(path, cb))
-    setTimeout(flush)
-    return
-  }
-
-  readdir(path, function (er, files) {
-    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
-      fs.MAX_OPEN = fs._curOpen - 1
-      return fs.readdir(path, cb)
-    }
-    cb(er, files)
-  })
-}
-
-function readdir (path, cb) {
-  cb = cb || noop
-  fs._curOpen ++
-  fs._originalFs.readdir.call(fs, path, function (er, files) {
-    onclose()
-    cb(er, files)
-  })
-}
-
-function ReaddirReq (path, cb) {
-  this.path = path
-  this.cb = cb
-}
-
-
-fs.readFile = gracefulReadFile
-
-function gracefulReadFile(path, options, cb) {
-  if (typeof options === "function") cb = options, options = null
-  if (typeof cb !== "function") cb = noop
-
-  if (fs._curOpen >= fs.MAX_OPEN) {
-    queue.push(new ReadFileReq(path, options, cb))
-    setTimeout(flush)
-    return
-  }
-
-  readFile(path, options, function (er, data) {
-    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
-      fs.MAX_OPEN = fs._curOpen - 1
-      return fs.readFile(path, options, cb)
-    }
-    cb(er, data)
-  })
-}
-
-function readFile (path, options, cb) {
-  cb = cb || noop
-  fs._curOpen ++
-  fs._originalFs.readFile.call(fs, path, options, function (er, data) {
-    onclose()
-    cb(er, data)
-  })
-}
-
-function ReadFileReq (path, options, cb) {
-  this.path = path
-  this.options = options
-  this.cb = cb
-}
-
-
-
-
-fs.writeFile = gracefulWriteFile
-
-function gracefulWriteFile(path, data, options, cb) {
-  if (typeof options === "function") cb = options, options = null
-  if (typeof cb !== "function") cb = noop
-
-  if (fs._curOpen >= fs.MAX_OPEN) {
-    queue.push(new WriteFileReq(path, data, options, cb))
-    setTimeout(flush)
-    return
-  }
-
-  writeFile(path, data, options, function (er) {
-    if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) {
-      fs.MAX_OPEN = fs._curOpen - 1
-      return fs.writeFile(path, data, options, cb)
-    }
-    cb(er)
-  })
-}
-
-function writeFile (path, data, options, cb) {
-  cb = cb || noop
-  fs._curOpen ++
-  fs._originalFs.writeFile.call(fs, path, data, options, function (er) {
-    onclose()
-    cb(er)
-  })
-}
-
-function WriteFileReq (path, data, options, cb) {
-  this.path = path
-  this.data = data
-  this.options = options
-  this.cb = cb
-}
-
-
-// (re-)implement some things that are known busted or missing.
-
-var constants = require("constants")
-
-// lchmod, broken prior to 0.6.2
-// back-port the fix here.
-if (constants.hasOwnProperty('O_SYMLINK') &&
-    process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
-  fs.lchmod = function (path, mode, callback) {
-    callback = callback || noop
-    fs.open( path
-           , constants.O_WRONLY | constants.O_SYMLINK
-           , mode
-           , function (err, fd) {
-      if (err) {
-        callback(err)
-        return
-      }
-      // prefer to return the chmod error, if one occurs,
-      // but still try to close, and report closing errors if they occur.
-      fs.fchmod(fd, mode, function (err) {
-        fs.close(fd, function(err2) {
-          callback(err || err2)
-        })
-      })
-    })
-  }
-
-  fs.lchmodSync = function (path, mode) {
-    var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
-
-    // prefer to return the chmod error, if one occurs,
-    // but still try to close, and report closing errors if they occur.
-    var err, err2
-    try {
-      var ret = fs.fchmodSync(fd, mode)
-    } catch (er) {
-      err = er
-    }
-    try {
-      fs.closeSync(fd)
-    } catch (er) {
-      err2 = er
-    }
-    if (err || err2) throw (err || err2)
-    return ret
-  }
-}
-
-
-// lutimes implementation, or no-op
-if (!fs.lutimes) {
-  if (constants.hasOwnProperty("O_SYMLINK")) {
-    fs.lutimes = function (path, at, mt, cb) {
-      fs.open(path, constants.O_SYMLINK, function (er, fd) {
-        cb = cb || noop
-        if (er) return cb(er)
-        fs.futimes(fd, at, mt, function (er) {
-          fs.close(fd, function (er2) {
-            return cb(er || er2)
-          })
-        })
-      })
-    }
-
-    fs.lutimesSync = function (path, at, mt) {
-      var fd = fs.openSync(path, constants.O_SYMLINK)
-        , err
-        , err2
-        , ret
-
-      try {
-        var ret = fs.futimesSync(fd, at, mt)
-      } catch (er) {
-        err = er
-      }
-      try {
-        fs.closeSync(fd)
-      } catch (er) {
-        err2 = er
-      }
-      if (err || err2) throw (err || err2)
-      return ret
-    }
-
-  } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) {
-    // maybe utimensat will be bound soonish?
-    fs.lutimes = function (path, at, mt, cb) {
-      fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb)
-    }
-
-    fs.lutimesSync = function (path, at, mt) {
-      return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW)
-    }
-
-  } else {
-    fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
-    fs.lutimesSync = function () {}
-  }
-}
-
-
-// https://github.com/isaacs/node-graceful-fs/issues/4
-// Chown should not fail on einval or eperm if non-root.
-
-fs.chown = chownFix(fs.chown)
-fs.fchown = chownFix(fs.fchown)
-fs.lchown = chownFix(fs.lchown)
-
-fs.chownSync = chownFixSync(fs.chownSync)
-fs.fchownSync = chownFixSync(fs.fchownSync)
-fs.lchownSync = chownFixSync(fs.lchownSync)
-
-function chownFix (orig) {
-  if (!orig) return orig
-  return function (target, uid, gid, cb) {
-    return orig.call(fs, target, uid, gid, function (er, res) {
-      if (chownErOk(er)) er = null
-      cb(er, res)
-    })
-  }
-}
-
-function chownFixSync (orig) {
-  if (!orig) return orig
-  return function (target, uid, gid) {
-    try {
-      return orig.call(fs, target, uid, gid)
-    } catch (er) {
-      if (!chownErOk(er)) throw er
-    }
-  }
-}
-
-function chownErOk (er) {
-  // if there's no getuid, or if getuid() is something other than 0,
-  // and the error is EINVAL or EPERM, then just ignore it.
-  // This specific case is a silent failure in cp, install, tar,
-  // and most other unix tools that manage permissions.
-  // When running as root, or if other types of errors are encountered,
-  // then it's strict.
-  if (!er || (!process.getuid || process.getuid() !== 0)
-      && (er.code === "EINVAL" || er.code === "EPERM")) return true
-}
-
-
-// if lchmod/lchown do not exist, then make them no-ops
-if (!fs.lchmod) {
-  fs.lchmod = function (path, mode, cb) {
-    process.nextTick(cb)
-  }
-  fs.lchmodSync = function () {}
-}
-if (!fs.lchown) {
-  fs.lchown = function (path, uid, gid, cb) {
-    process.nextTick(cb)
-  }
-  fs.lchownSync = function () {}
-}
-
-
-
-// on Windows, A/V software can lock the directory, causing this
-// to fail with an EACCES or EPERM if the directory contains newly
-// created files.  Try again on failure, for up to 1 second.
-if (process.platform === "win32") {
-  var rename_ = fs.rename
-  fs.rename = function rename (from, to, cb) {
-    var start = Date.now()
-    rename_(from, to, function CB (er) {
-      if (er
-          && (er.code === "EACCES" || er.code === "EPERM")
-          && Date.now() - start < 1000) {
-        return rename_(from, to, CB)
-      }
-      cb(er)
-    })
-  }
-}
-
-
-// if read() returns EAGAIN, then just try it again.
-var read = fs.read
-fs.read = function (fd, buffer, offset, length, position, callback_) {
-  var callback
-  if (callback_ && typeof callback_ === 'function') {
-    var eagCounter = 0
-    callback = function (er, _, __) {
-      if (er && er.code === 'EAGAIN' && eagCounter < 10) {
-        eagCounter ++
-        return read.call(fs, fd, buffer, offset, length, position, callback)
-      }
-      callback_.apply(this, arguments)
-    }
-  }
-  return read.call(fs, fd, buffer, offset, length, position, callback)
-}
-
-var readSync = fs.readSync
-fs.readSync = function (fd, buffer, offset, length, position) {
-  var eagCounter = 0
-  while (true) {
-    try {
-      return readSync.call(fs, fd, buffer, offset, length, position)
-    } catch (er) {
-      if (er.code === 'EAGAIN' && eagCounter < 10) {
-        eagCounter ++
-        continue
-      }
-      throw er
-    }
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/package.json
deleted file mode 100644
index d5ca1810..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/package.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me"
-  },
-  "name": "graceful-fs",
-  "description": "A drop-in replacement for fs, making various improvements.",
-  "version": "1.2.3",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-graceful-fs.git"
-  },
-  "main": "graceful-fs.js",
-  "engines": {
-    "node": ">=0.4.0"
-  },
-  "directories": {
-    "test": "test"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "keywords": [
-    "fs",
-    "module",
-    "reading",
-    "retry",
-    "retries",
-    "queue",
-    "error",
-    "errors",
-    "handling",
-    "EMFILE",
-    "EAGAIN",
-    "EINVAL",
-    "EPERM",
-    "EACCESS"
-  ],
-  "license": "BSD",
-  "readme": "# graceful-fs\n\ngraceful-fs functions as a drop-in replacement for the fs module,\nmaking various improvements.\n\nThe improvements are meant to normalize behavior across different\nplatforms and environments, and to make filesystem access more\nresilient to errors.\n\n## Improvements over fs module\n\ngraceful-fs:\n\n* keeps track of how many file descriptors are open, and by default\n  limits this to 1024. Any further requests to open a file are put in a\n  queue until new slots become available. If 1024 turns out to be too\n  much, it decreases the limit further.\n* fixes `lchmod` for Node versions prior to 0.6.2.\n* implements `fs.lutimes` if possible. Otherwise it becomes a noop.\n* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or\n  `lchown` if the user isn't root.\n* makes `lchmod` and `lchown` become noops, if not available.\n* retries reading a file if `read` results in EAGAIN error.\n\nOn Windows, it retries renaming a file for up to one second if `EACCESS`\nor `EPERM` error occurs, likely because antivirus software has locked\nthe directory.\n\n## Configuration\n\nThe maximum number of open file descriptors that graceful-fs manages may\nbe adjusted by setting `fs.MAX_OPEN` to a different number. The default\nis 1024.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/node-graceful-fs/issues"
-  },
-  "homepage": "https://github.com/isaacs/node-graceful-fs",
-  "_id": "graceful-fs@1.2.3",
-  "_shasum": "15a4806a57547cb2d2dbf27f42e89a8c3451b364",
-  "_from": "graceful-fs@1.2",
-  "_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/open.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/open.js
deleted file mode 100644
index 930d5325..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/open.js
+++ /dev/null
@@ -1,46 +0,0 @@
-var test = require('tap').test
-var fs = require('../graceful-fs.js')
-
-test('graceful fs is not fs', function (t) {
-  t.notEqual(fs, require('fs'))
-  t.end()
-})
-
-test('open an existing file works', function (t) {
-  var start = fs._curOpen
-  var fd = fs.openSync(__filename, 'r')
-  t.equal(fs._curOpen, start + 1)
-  fs.closeSync(fd)
-  t.equal(fs._curOpen, start)
-  fs.open(__filename, 'r', function (er, fd) {
-    if (er) throw er
-    t.equal(fs._curOpen, start + 1)
-    fs.close(fd, function (er) {
-      if (er) throw er
-      t.equal(fs._curOpen, start)
-      t.end()
-    })
-  })
-})
-
-test('open a non-existing file throws', function (t) {
-  var start = fs._curOpen
-  var er
-  try {
-    var fd = fs.openSync('this file does not exist', 'r')
-  } catch (x) {
-    er = x
-  }
-  t.ok(er, 'should throw')
-  t.notOk(fd, 'should not get an fd')
-  t.equal(er.code, 'ENOENT')
-  t.equal(fs._curOpen, start)
-
-  fs.open('neither does this file', 'r', function (er, fd) {
-    t.ok(er, 'should throw')
-    t.notOk(fd, 'should not get an fd')
-    t.equal(er.code, 'ENOENT')
-    t.equal(fs._curOpen, start)
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/ulimit.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/ulimit.js
deleted file mode 100644
index 8d0882d0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/graceful-fs/test/ulimit.js
+++ /dev/null
@@ -1,158 +0,0 @@
-var test = require('tap').test
-
-// simulated ulimit
-// this is like graceful-fs, but in reverse
-var fs_ = require('fs')
-var fs = require('../graceful-fs.js')
-var files = fs.readdirSync(__dirname)
-
-// Ok, no more actual file reading!
-
-var fds = 0
-var nextFd = 60
-var limit = 8
-fs_.open = function (path, flags, mode, cb) {
-  process.nextTick(function() {
-    ++fds
-    if (fds >= limit) {
-      --fds
-      var er = new Error('EMFILE Curses!')
-      er.code = 'EMFILE'
-      er.path = path
-      return cb(er)
-    } else {
-      cb(null, nextFd++)
-    }
-  })
-}
-
-fs_.openSync = function (path, flags, mode) {
-  if (fds >= limit) {
-    var er = new Error('EMFILE Curses!')
-    er.code = 'EMFILE'
-    er.path = path
-    throw er
-  } else {
-    ++fds
-    return nextFd++
-  }
-}
-
-fs_.close = function (fd, cb) {
-  process.nextTick(function () {
-    --fds
-    cb()
-  })
-}
-
-fs_.closeSync = function (fd) {
-  --fds
-}
-
-fs_.readdir = function (path, cb) {
-  process.nextTick(function() {
-    if (fds >= limit) {
-      var er = new Error('EMFILE Curses!')
-      er.code = 'EMFILE'
-      er.path = path
-      return cb(er)
-    } else {
-      ++fds
-      process.nextTick(function () {
-        --fds
-        cb(null, [__filename, "some-other-file.js"])
-      })
-    }
-  })
-}
-
-fs_.readdirSync = function (path) {
-  if (fds >= limit) {
-    var er = new Error('EMFILE Curses!')
-    er.code = 'EMFILE'
-    er.path = path
-    throw er
-  } else {
-    return [__filename, "some-other-file.js"]
-  }
-}
-
-
-test('open emfile autoreduce', function (t) {
-  fs.MIN_MAX_OPEN = 4
-  t.equal(fs.MAX_OPEN, 1024)
-
-  var max = 12
-  for (var i = 0; i < max; i++) {
-    fs.open(__filename, 'r', next(i))
-  }
-
-  var phase = 0
-
-  var expect =
-      [ [ 0, 60, null, 1024, 4, 12, 1 ],
-        [ 1, 61, null, 1024, 4, 12, 2 ],
-        [ 2, 62, null, 1024, 4, 12, 3 ],
-        [ 3, 63, null, 1024, 4, 12, 4 ],
-        [ 4, 64, null, 1024, 4, 12, 5 ],
-        [ 5, 65, null, 1024, 4, 12, 6 ],
-        [ 6, 66, null, 1024, 4, 12, 7 ],
-        [ 7, 67, null, 6, 4, 5, 1 ],
-        [ 8, 68, null, 6, 4, 5, 2 ],
-        [ 9, 69, null, 6, 4, 5, 3 ],
-        [ 10, 70, null, 6, 4, 5, 4 ],
-        [ 11, 71, null, 6, 4, 5, 5 ] ]
-
-  var actual = []
-
-  function next (i) { return function (er, fd) {
-    if (er)
-      throw er
-    actual.push([i, fd, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds])
-
-    if (i === max - 1) {
-      t.same(actual, expect)
-      t.ok(fs.MAX_OPEN < limit)
-      t.end()
-    }
-
-    fs.close(fd)
-  } }
-})
-
-test('readdir emfile autoreduce', function (t) {
-  fs.MAX_OPEN = 1024
-  var max = 12
-  for (var i = 0; i < max; i ++) {
-    fs.readdir(__dirname, next(i))
-  }
-
-  var expect =
-      [ [0,[__filename,"some-other-file.js"],null,7,4,7,7],
-        [1,[__filename,"some-other-file.js"],null,7,4,7,6],
-        [2,[__filename,"some-other-file.js"],null,7,4,7,5],
-        [3,[__filename,"some-other-file.js"],null,7,4,7,4],
-        [4,[__filename,"some-other-file.js"],null,7,4,7,3],
-        [5,[__filename,"some-other-file.js"],null,7,4,6,2],
-        [6,[__filename,"some-other-file.js"],null,7,4,5,1],
-        [7,[__filename,"some-other-file.js"],null,7,4,4,0],
-        [8,[__filename,"some-other-file.js"],null,7,4,3,3],
-        [9,[__filename,"some-other-file.js"],null,7,4,2,2],
-        [10,[__filename,"some-other-file.js"],null,7,4,1,1],
-        [11,[__filename,"some-other-file.js"],null,7,4,0,0] ]
-
-  var actual = []
-
-  function next (i) { return function (er, files) {
-    if (er)
-      throw er
-    var line = [i, files, er, fs.MAX_OPEN, fs.MIN_MAX_OPEN, fs._curOpen, fds ]
-    actual.push(line)
-
-    if (i === max - 1) {
-      t.ok(fs.MAX_OPEN < limit)
-      t.same(actual, expect)
-      t.end()
-    }
-  } }
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/README.md
deleted file mode 100644
index e833b83d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# once
-
-Only call a function once.
-
-## usage
-
-```javascript
-var once = require('once')
-
-function load (file, cb) {
-  cb = once(cb)
-  loader.load('file')
-  loader.once('load', cb)
-  loader.once('error', cb)
-}
-```
-
-Or add to the Function.prototype in a responsible way:
-
-```javascript
-// only has to be done once
-require('once').proto()
-
-function load (file, cb) {
-  cb = cb.once()
-  loader.load('file')
-  loader.once('load', cb)
-  loader.once('error', cb)
-}
-```
-
-Ironically, the prototype feature makes this module twice as
-complicated as necessary.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/once.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/once.js
deleted file mode 100644
index effc50a4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/once.js
+++ /dev/null
@@ -1,19 +0,0 @@
-module.exports = once
-
-once.proto = once(function () {
-  Object.defineProperty(Function.prototype, 'once', {
-    value: function () {
-      return once(this)
-    },
-    configurable: true
-  })
-})
-
-function once (fn) {
-  var called = false
-  return function () {
-    if (called) return
-    called = true
-    return fn.apply(this, arguments)
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/package.json
deleted file mode 100644
index 9c631523..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/package.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "name": "once",
-  "version": "1.1.1",
-  "description": "Run a function exactly one time",
-  "main": "once.js",
-  "directories": {
-    "test": "test"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "tap": "~0.3.0"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/once"
-  },
-  "keywords": [
-    "once",
-    "function",
-    "one",
-    "single"
-  ],
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "license": "BSD",
-  "readme": "# once\n\nOnly call a function once.\n\n## usage\n\n```javascript\nvar once = require('once')\n\nfunction load (file, cb) {\n  cb = once(cb)\n  loader.load('file')\n  loader.once('load', cb)\n  loader.once('error', cb)\n}\n```\n\nOr add to the Function.prototype in a responsible way:\n\n```javascript\n// only has to be done once\nrequire('once').proto()\n\nfunction load (file, cb) {\n  cb = cb.once()\n  loader.load('file')\n  loader.once('load', cb)\n  loader.once('error', cb)\n}\n```\n\nIronically, the prototype feature makes this module twice as\ncomplicated as necessary.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/once/issues"
-  },
-  "homepage": "https://github.com/isaacs/once",
-  "_id": "once@1.1.1",
-  "_shasum": "9db574933ccb08c3a7614d154032c09ea6f339e7",
-  "_from": "once@~1.1.1",
-  "_resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/test/once.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/test/once.js
deleted file mode 100644
index f0291a44..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/once/test/once.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var test = require('tap').test
-var once = require('../once.js')
-
-test('once', function (t) {
-  var f = 0
-  var foo = once(function (g) {
-    t.equal(f, 0)
-    f ++
-    return f + g + this
-  })
-  for (var i = 0; i < 1E3; i++) {
-    t.same(f, i === 0 ? 0 : 1)
-    var g = foo.call(1, 1)
-    t.same(g, i === 0 ? 3 : undefined)
-    t.same(f, 1)
-  }
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/.npmignore
deleted file mode 100644
index 38344f87..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/.npmignore
+++ /dev/null
@@ -1,5 +0,0 @@
-build/
-test/
-examples/
-fs.js
-zlib.js
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/README.md
deleted file mode 100644
index 34c11897..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# readable-stream
-
-***Node-core streams for userland***
-
-[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true)](https://nodei.co/npm/readable-stream/)
-[![NPM](https://nodei.co/npm-dl/readable-stream.png)](https://nodei.co/npm/readable-stream/)
-
-This package is a mirror of the Streams2 and Streams3 implementations in Node-core.
-
-If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core.
-
-**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12.
-
-**readable-stream** uses proper patch-level versioning so if you pin to `"~1.0.0"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `"~1.1.0"`
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/duplex.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/duplex.js
deleted file mode 100644
index ca807af8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/duplex.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require("./lib/_stream_duplex.js")
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_duplex.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_duplex.js
deleted file mode 100644
index b513d61a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_duplex.js
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// a duplex stream is just a stream that is both readable and writable.
-// Since JS doesn't have multiple prototypal inheritance, this class
-// prototypally inherits from Readable, and then parasitically from
-// Writable.
-
-module.exports = Duplex;
-
-/*<replacement>*/
-var objectKeys = Object.keys || function (obj) {
-  var keys = [];
-  for (var key in obj) keys.push(key);
-  return keys;
-}
-/*</replacement>*/
-
-
-/*<replacement>*/
-var util = require('core-util-is');
-util.inherits = require('inherits');
-/*</replacement>*/
-
-var Readable = require('./_stream_readable');
-var Writable = require('./_stream_writable');
-
-util.inherits(Duplex, Readable);
-
-forEach(objectKeys(Writable.prototype), function(method) {
-  if (!Duplex.prototype[method])
-    Duplex.prototype[method] = Writable.prototype[method];
-});
-
-function Duplex(options) {
-  if (!(this instanceof Duplex))
-    return new Duplex(options);
-
-  Readable.call(this, options);
-  Writable.call(this, options);
-
-  if (options && options.readable === false)
-    this.readable = false;
-
-  if (options && options.writable === false)
-    this.writable = false;
-
-  this.allowHalfOpen = true;
-  if (options && options.allowHalfOpen === false)
-    this.allowHalfOpen = false;
-
-  this.once('end', onend);
-}
-
-// the no-half-open enforcer
-function onend() {
-  // if we allow half-open state, or if the writable side ended,
-  // then we're ok.
-  if (this.allowHalfOpen || this._writableState.ended)
-    return;
-
-  // no more data can be written.
-  // But allow more writes to happen in this tick.
-  process.nextTick(this.end.bind(this));
-}
-
-function forEach (xs, f) {
-  for (var i = 0, l = xs.length; i < l; i++) {
-    f(xs[i], i);
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_readable.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_readable.js
deleted file mode 100644
index 0ca77052..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_readable.js
+++ /dev/null
@@ -1,959 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-module.exports = Readable;
-
-/*<replacement>*/
-var isArray = require('isarray');
-/*</replacement>*/
-
-
-/*<replacement>*/
-var Buffer = require('buffer').Buffer;
-/*</replacement>*/
-
-Readable.ReadableState = ReadableState;
-
-var EE = require('events').EventEmitter;
-
-/*<replacement>*/
-if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
-  return emitter.listeners(type).length;
-};
-/*</replacement>*/
-
-var Stream = require('stream');
-
-/*<replacement>*/
-var util = require('core-util-is');
-util.inherits = require('inherits');
-/*</replacement>*/
-
-var StringDecoder;
-
-util.inherits(Readable, Stream);
-
-function ReadableState(options, stream) {
-  options = options || {};
-
-  // the point at which it stops calling _read() to fill the buffer
-  // Note: 0 is a valid value, means "don't call _read preemptively ever"
-  var hwm = options.highWaterMark;
-  this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
-
-  // cast to ints.
-  this.highWaterMark = ~~this.highWaterMark;
-
-  this.buffer = [];
-  this.length = 0;
-  this.pipes = null;
-  this.pipesCount = 0;
-  this.flowing = false;
-  this.ended = false;
-  this.endEmitted = false;
-  this.reading = false;
-
-  // In streams that never have any data, and do push(null) right away,
-  // the consumer can miss the 'end' event if they do some I/O before
-  // consuming the stream.  So, we don't emit('end') until some reading
-  // happens.
-  this.calledRead = false;
-
-  // a flag to be able to tell if the onwrite cb is called immediately,
-  // or on a later tick.  We set this to true at first, becuase any
-  // actions that shouldn't happen until "later" should generally also
-  // not happen before the first write call.
-  this.sync = true;
-
-  // whenever we return null, then we set a flag to say
-  // that we're awaiting a 'readable' event emission.
-  this.needReadable = false;
-  this.emittedReadable = false;
-  this.readableListening = false;
-
-
-  // object stream flag. Used to make read(n) ignore n and to
-  // make all the buffer merging and length checks go away
-  this.objectMode = !!options.objectMode;
-
-  // Crypto is kind of old and crusty.  Historically, its default string
-  // encoding is 'binary' so we have to make this configurable.
-  // Everything else in the universe uses 'utf8', though.
-  this.defaultEncoding = options.defaultEncoding || 'utf8';
-
-  // when piping, we only care about 'readable' events that happen
-  // after read()ing all the bytes and not getting any pushback.
-  this.ranOut = false;
-
-  // the number of writers that are awaiting a drain event in .pipe()s
-  this.awaitDrain = 0;
-
-  // if true, a maybeReadMore has been scheduled
-  this.readingMore = false;
-
-  this.decoder = null;
-  this.encoding = null;
-  if (options.encoding) {
-    if (!StringDecoder)
-      StringDecoder = require('string_decoder/').StringDecoder;
-    this.decoder = new StringDecoder(options.encoding);
-    this.encoding = options.encoding;
-  }
-}
-
-function Readable(options) {
-  if (!(this instanceof Readable))
-    return new Readable(options);
-
-  this._readableState = new ReadableState(options, this);
-
-  // legacy
-  this.readable = true;
-
-  Stream.call(this);
-}
-
-// Manually shove something into the read() buffer.
-// This returns true if the highWaterMark has not been hit yet,
-// similar to how Writable.write() returns true if you should
-// write() some more.
-Readable.prototype.push = function(chunk, encoding) {
-  var state = this._readableState;
-
-  if (typeof chunk === 'string' && !state.objectMode) {
-    encoding = encoding || state.defaultEncoding;
-    if (encoding !== state.encoding) {
-      chunk = new Buffer(chunk, encoding);
-      encoding = '';
-    }
-  }
-
-  return readableAddChunk(this, state, chunk, encoding, false);
-};
-
-// Unshift should *always* be something directly out of read()
-Readable.prototype.unshift = function(chunk) {
-  var state = this._readableState;
-  return readableAddChunk(this, state, chunk, '', true);
-};
-
-function readableAddChunk(stream, state, chunk, encoding, addToFront) {
-  var er = chunkInvalid(state, chunk);
-  if (er) {
-    stream.emit('error', er);
-  } else if (chunk === null || chunk === undefined) {
-    state.reading = false;
-    if (!state.ended)
-      onEofChunk(stream, state);
-  } else if (state.objectMode || chunk && chunk.length > 0) {
-    if (state.ended && !addToFront) {
-      var e = new Error('stream.push() after EOF');
-      stream.emit('error', e);
-    } else if (state.endEmitted && addToFront) {
-      var e = new Error('stream.unshift() after end event');
-      stream.emit('error', e);
-    } else {
-      if (state.decoder && !addToFront && !encoding)
-        chunk = state.decoder.write(chunk);
-
-      // update the buffer info.
-      state.length += state.objectMode ? 1 : chunk.length;
-      if (addToFront) {
-        state.buffer.unshift(chunk);
-      } else {
-        state.reading = false;
-        state.buffer.push(chunk);
-      }
-
-      if (state.needReadable)
-        emitReadable(stream);
-
-      maybeReadMore(stream, state);
-    }
-  } else if (!addToFront) {
-    state.reading = false;
-  }
-
-  return needMoreData(state);
-}
-
-
-
-// if it's past the high water mark, we can push in some more.
-// Also, if we have no data yet, we can stand some
-// more bytes.  This is to work around cases where hwm=0,
-// such as the repl.  Also, if the push() triggered a
-// readable event, and the user called read(largeNumber) such that
-// needReadable was set, then we ought to push more, so that another
-// 'readable' event will be triggered.
-function needMoreData(state) {
-  return !state.ended &&
-         (state.needReadable ||
-          state.length < state.highWaterMark ||
-          state.length === 0);
-}
-
-// backwards compatibility.
-Readable.prototype.setEncoding = function(enc) {
-  if (!StringDecoder)
-    StringDecoder = require('string_decoder/').StringDecoder;
-  this._readableState.decoder = new StringDecoder(enc);
-  this._readableState.encoding = enc;
-};
-
-// Don't raise the hwm > 128MB
-var MAX_HWM = 0x800000;
-function roundUpToNextPowerOf2(n) {
-  if (n >= MAX_HWM) {
-    n = MAX_HWM;
-  } else {
-    // Get the next highest power of 2
-    n--;
-    for (var p = 1; p < 32; p <<= 1) n |= n >> p;
-    n++;
-  }
-  return n;
-}
-
-function howMuchToRead(n, state) {
-  if (state.length === 0 && state.ended)
-    return 0;
-
-  if (state.objectMode)
-    return n === 0 ? 0 : 1;
-
-  if (isNaN(n) || n === null) {
-    // only flow one buffer at a time
-    if (state.flowing && state.buffer.length)
-      return state.buffer[0].length;
-    else
-      return state.length;
-  }
-
-  if (n <= 0)
-    return 0;
-
-  // If we're asking for more than the target buffer level,
-  // then raise the water mark.  Bump up to the next highest
-  // power of 2, to prevent increasing it excessively in tiny
-  // amounts.
-  if (n > state.highWaterMark)
-    state.highWaterMark = roundUpToNextPowerOf2(n);
-
-  // don't have that much.  return null, unless we've ended.
-  if (n > state.length) {
-    if (!state.ended) {
-      state.needReadable = true;
-      return 0;
-    } else
-      return state.length;
-  }
-
-  return n;
-}
-
-// you can override either this method, or the async _read(n) below.
-Readable.prototype.read = function(n) {
-  var state = this._readableState;
-  state.calledRead = true;
-  var nOrig = n;
-
-  if (typeof n !== 'number' || n > 0)
-    state.emittedReadable = false;
-
-  // if we're doing read(0) to trigger a readable event, but we
-  // already have a bunch of data in the buffer, then just trigger
-  // the 'readable' event and move on.
-  if (n === 0 &&
-      state.needReadable &&
-      (state.length >= state.highWaterMark || state.ended)) {
-    emitReadable(this);
-    return null;
-  }
-
-  n = howMuchToRead(n, state);
-
-  // if we've ended, and we're now clear, then finish it up.
-  if (n === 0 && state.ended) {
-    if (state.length === 0)
-      endReadable(this);
-    return null;
-  }
-
-  // All the actual chunk generation logic needs to be
-  // *below* the call to _read.  The reason is that in certain
-  // synthetic stream cases, such as passthrough streams, _read
-  // may be a completely synchronous operation which may change
-  // the state of the read buffer, providing enough data when
-  // before there was *not* enough.
-  //
-  // So, the steps are:
-  // 1. Figure out what the state of things will be after we do
-  // a read from the buffer.
-  //
-  // 2. If that resulting state will trigger a _read, then call _read.
-  // Note that this may be asynchronous, or synchronous.  Yes, it is
-  // deeply ugly to write APIs this way, but that still doesn't mean
-  // that the Readable class should behave improperly, as streams are
-  // designed to be sync/async agnostic.
-  // Take note if the _read call is sync or async (ie, if the read call
-  // has returned yet), so that we know whether or not it's safe to emit
-  // 'readable' etc.
-  //
-  // 3. Actually pull the requested chunks out of the buffer and return.
-
-  // if we need a readable event, then we need to do some reading.
-  var doRead = state.needReadable;
-
-  // if we currently have less than the highWaterMark, then also read some
-  if (state.length - n <= state.highWaterMark)
-    doRead = true;
-
-  // however, if we've ended, then there's no point, and if we're already
-  // reading, then it's unnecessary.
-  if (state.ended || state.reading)
-    doRead = false;
-
-  if (doRead) {
-    state.reading = true;
-    state.sync = true;
-    // if the length is currently zero, then we *need* a readable event.
-    if (state.length === 0)
-      state.needReadable = true;
-    // call internal read method
-    this._read(state.highWaterMark);
-    state.sync = false;
-  }
-
-  // If _read called its callback synchronously, then `reading`
-  // will be false, and we need to re-evaluate how much data we
-  // can return to the user.
-  if (doRead && !state.reading)
-    n = howMuchToRead(nOrig, state);
-
-  var ret;
-  if (n > 0)
-    ret = fromList(n, state);
-  else
-    ret = null;
-
-  if (ret === null) {
-    state.needReadable = true;
-    n = 0;
-  }
-
-  state.length -= n;
-
-  // If we have nothing in the buffer, then we want to know
-  // as soon as we *do* get something into the buffer.
-  if (state.length === 0 && !state.ended)
-    state.needReadable = true;
-
-  // If we happened to read() exactly the remaining amount in the
-  // buffer, and the EOF has been seen at this point, then make sure
-  // that we emit 'end' on the very next tick.
-  if (state.ended && !state.endEmitted && state.length === 0)
-    endReadable(this);
-
-  return ret;
-};
-
-function chunkInvalid(state, chunk) {
-  var er = null;
-  if (!Buffer.isBuffer(chunk) &&
-      'string' !== typeof chunk &&
-      chunk !== null &&
-      chunk !== undefined &&
-      !state.objectMode &&
-      !er) {
-    er = new TypeError('Invalid non-string/buffer chunk');
-  }
-  return er;
-}
-
-
-function onEofChunk(stream, state) {
-  if (state.decoder && !state.ended) {
-    var chunk = state.decoder.end();
-    if (chunk && chunk.length) {
-      state.buffer.push(chunk);
-      state.length += state.objectMode ? 1 : chunk.length;
-    }
-  }
-  state.ended = true;
-
-  // if we've ended and we have some data left, then emit
-  // 'readable' now to make sure it gets picked up.
-  if (state.length > 0)
-    emitReadable(stream);
-  else
-    endReadable(stream);
-}
-
-// Don't emit readable right away in sync mode, because this can trigger
-// another read() call => stack overflow.  This way, it might trigger
-// a nextTick recursion warning, but that's not so bad.
-function emitReadable(stream) {
-  var state = stream._readableState;
-  state.needReadable = false;
-  if (state.emittedReadable)
-    return;
-
-  state.emittedReadable = true;
-  if (state.sync)
-    process.nextTick(function() {
-      emitReadable_(stream);
-    });
-  else
-    emitReadable_(stream);
-}
-
-function emitReadable_(stream) {
-  stream.emit('readable');
-}
-
-
-// at this point, the user has presumably seen the 'readable' event,
-// and called read() to consume some data.  that may have triggered
-// in turn another _read(n) call, in which case reading = true if
-// it's in progress.
-// However, if we're not ended, or reading, and the length < hwm,
-// then go ahead and try to read some more preemptively.
-function maybeReadMore(stream, state) {
-  if (!state.readingMore) {
-    state.readingMore = true;
-    process.nextTick(function() {
-      maybeReadMore_(stream, state);
-    });
-  }
-}
-
-function maybeReadMore_(stream, state) {
-  var len = state.length;
-  while (!state.reading && !state.flowing && !state.ended &&
-         state.length < state.highWaterMark) {
-    stream.read(0);
-    if (len === state.length)
-      // didn't get any data, stop spinning.
-      break;
-    else
-      len = state.length;
-  }
-  state.readingMore = false;
-}
-
-// abstract method.  to be overridden in specific implementation classes.
-// call cb(er, data) where data is <= n in length.
-// for virtual (non-string, non-buffer) streams, "length" is somewhat
-// arbitrary, and perhaps not very meaningful.
-Readable.prototype._read = function(n) {
-  this.emit('error', new Error('not implemented'));
-};
-
-Readable.prototype.pipe = function(dest, pipeOpts) {
-  var src = this;
-  var state = this._readableState;
-
-  switch (state.pipesCount) {
-    case 0:
-      state.pipes = dest;
-      break;
-    case 1:
-      state.pipes = [state.pipes, dest];
-      break;
-    default:
-      state.pipes.push(dest);
-      break;
-  }
-  state.pipesCount += 1;
-
-  var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
-              dest !== process.stdout &&
-              dest !== process.stderr;
-
-  var endFn = doEnd ? onend : cleanup;
-  if (state.endEmitted)
-    process.nextTick(endFn);
-  else
-    src.once('end', endFn);
-
-  dest.on('unpipe', onunpipe);
-  function onunpipe(readable) {
-    if (readable !== src) return;
-    cleanup();
-  }
-
-  function onend() {
-    dest.end();
-  }
-
-  // when the dest drains, it reduces the awaitDrain counter
-  // on the source.  This would be more elegant with a .once()
-  // handler in flow(), but adding and removing repeatedly is
-  // too slow.
-  var ondrain = pipeOnDrain(src);
-  dest.on('drain', ondrain);
-
-  function cleanup() {
-    // cleanup event handlers once the pipe is broken
-    dest.removeListener('close', onclose);
-    dest.removeListener('finish', onfinish);
-    dest.removeListener('drain', ondrain);
-    dest.removeListener('error', onerror);
-    dest.removeListener('unpipe', onunpipe);
-    src.removeListener('end', onend);
-    src.removeListener('end', cleanup);
-
-    // if the reader is waiting for a drain event from this
-    // specific writer, then it would cause it to never start
-    // flowing again.
-    // So, if this is awaiting a drain, then we just call it now.
-    // If we don't know, then assume that we are waiting for one.
-    if (!dest._writableState || dest._writableState.needDrain)
-      ondrain();
-  }
-
-  // if the dest has an error, then stop piping into it.
-  // however, don't suppress the throwing behavior for this.
-  function onerror(er) {
-    unpipe();
-    dest.removeListener('error', onerror);
-    if (EE.listenerCount(dest, 'error') === 0)
-      dest.emit('error', er);
-  }
-  // This is a brutally ugly hack to make sure that our error handler
-  // is attached before any userland ones.  NEVER DO THIS.
-  if (!dest._events || !dest._events.error)
-    dest.on('error', onerror);
-  else if (isArray(dest._events.error))
-    dest._events.error.unshift(onerror);
-  else
-    dest._events.error = [onerror, dest._events.error];
-
-
-
-  // Both close and finish should trigger unpipe, but only once.
-  function onclose() {
-    dest.removeListener('finish', onfinish);
-    unpipe();
-  }
-  dest.once('close', onclose);
-  function onfinish() {
-    dest.removeListener('close', onclose);
-    unpipe();
-  }
-  dest.once('finish', onfinish);
-
-  function unpipe() {
-    src.unpipe(dest);
-  }
-
-  // tell the dest that it's being piped to
-  dest.emit('pipe', src);
-
-  // start the flow if it hasn't been started already.
-  if (!state.flowing) {
-    // the handler that waits for readable events after all
-    // the data gets sucked out in flow.
-    // This would be easier to follow with a .once() handler
-    // in flow(), but that is too slow.
-    this.on('readable', pipeOnReadable);
-
-    state.flowing = true;
-    process.nextTick(function() {
-      flow(src);
-    });
-  }
-
-  return dest;
-};
-
-function pipeOnDrain(src) {
-  return function() {
-    var dest = this;
-    var state = src._readableState;
-    state.awaitDrain--;
-    if (state.awaitDrain === 0)
-      flow(src);
-  };
-}
-
-function flow(src) {
-  var state = src._readableState;
-  var chunk;
-  state.awaitDrain = 0;
-
-  function write(dest, i, list) {
-    var written = dest.write(chunk);
-    if (false === written) {
-      state.awaitDrain++;
-    }
-  }
-
-  while (state.pipesCount && null !== (chunk = src.read())) {
-
-    if (state.pipesCount === 1)
-      write(state.pipes, 0, null);
-    else
-      forEach(state.pipes, write);
-
-    src.emit('data', chunk);
-
-    // if anyone needs a drain, then we have to wait for that.
-    if (state.awaitDrain > 0)
-      return;
-  }
-
-  // if every destination was unpiped, either before entering this
-  // function, or in the while loop, then stop flowing.
-  //
-  // NB: This is a pretty rare edge case.
-  if (state.pipesCount === 0) {
-    state.flowing = false;
-
-    // if there were data event listeners added, then switch to old mode.
-    if (EE.listenerCount(src, 'data') > 0)
-      emitDataEvents(src);
-    return;
-  }
-
-  // at this point, no one needed a drain, so we just ran out of data
-  // on the next readable event, start it over again.
-  state.ranOut = true;
-}
-
-function pipeOnReadable() {
-  if (this._readableState.ranOut) {
-    this._readableState.ranOut = false;
-    flow(this);
-  }
-}
-
-
-Readable.prototype.unpipe = function(dest) {
-  var state = this._readableState;
-
-  // if we're not piping anywhere, then do nothing.
-  if (state.pipesCount === 0)
-    return this;
-
-  // just one destination.  most common case.
-  if (state.pipesCount === 1) {
-    // passed in one, but it's not the right one.
-    if (dest && dest !== state.pipes)
-      return this;
-
-    if (!dest)
-      dest = state.pipes;
-
-    // got a match.
-    state.pipes = null;
-    state.pipesCount = 0;
-    this.removeListener('readable', pipeOnReadable);
-    state.flowing = false;
-    if (dest)
-      dest.emit('unpipe', this);
-    return this;
-  }
-
-  // slow case. multiple pipe destinations.
-
-  if (!dest) {
-    // remove all.
-    var dests = state.pipes;
-    var len = state.pipesCount;
-    state.pipes = null;
-    state.pipesCount = 0;
-    this.removeListener('readable', pipeOnReadable);
-    state.flowing = false;
-
-    for (var i = 0; i < len; i++)
-      dests[i].emit('unpipe', this);
-    return this;
-  }
-
-  // try to find the right one.
-  var i = indexOf(state.pipes, dest);
-  if (i === -1)
-    return this;
-
-  state.pipes.splice(i, 1);
-  state.pipesCount -= 1;
-  if (state.pipesCount === 1)
-    state.pipes = state.pipes[0];
-
-  dest.emit('unpipe', this);
-
-  return this;
-};
-
-// set up data events if they are asked for
-// Ensure readable listeners eventually get something
-Readable.prototype.on = function(ev, fn) {
-  var res = Stream.prototype.on.call(this, ev, fn);
-
-  if (ev === 'data' && !this._readableState.flowing)
-    emitDataEvents(this);
-
-  if (ev === 'readable' && this.readable) {
-    var state = this._readableState;
-    if (!state.readableListening) {
-      state.readableListening = true;
-      state.emittedReadable = false;
-      state.needReadable = true;
-      if (!state.reading) {
-        this.read(0);
-      } else if (state.length) {
-        emitReadable(this, state);
-      }
-    }
-  }
-
-  return res;
-};
-Readable.prototype.addListener = Readable.prototype.on;
-
-// pause() and resume() are remnants of the legacy readable stream API
-// If the user uses them, then switch into old mode.
-Readable.prototype.resume = function() {
-  emitDataEvents(this);
-  this.read(0);
-  this.emit('resume');
-};
-
-Readable.prototype.pause = function() {
-  emitDataEvents(this, true);
-  this.emit('pause');
-};
-
-function emitDataEvents(stream, startPaused) {
-  var state = stream._readableState;
-
-  if (state.flowing) {
-    // https://github.com/isaacs/readable-stream/issues/16
-    throw new Error('Cannot switch to old mode now.');
-  }
-
-  var paused = startPaused || false;
-  var readable = false;
-
-  // convert to an old-style stream.
-  stream.readable = true;
-  stream.pipe = Stream.prototype.pipe;
-  stream.on = stream.addListener = Stream.prototype.on;
-
-  stream.on('readable', function() {
-    readable = true;
-
-    var c;
-    while (!paused && (null !== (c = stream.read())))
-      stream.emit('data', c);
-
-    if (c === null) {
-      readable = false;
-      stream._readableState.needReadable = true;
-    }
-  });
-
-  stream.pause = function() {
-    paused = true;
-    this.emit('pause');
-  };
-
-  stream.resume = function() {
-    paused = false;
-    if (readable)
-      process.nextTick(function() {
-        stream.emit('readable');
-      });
-    else
-      this.read(0);
-    this.emit('resume');
-  };
-
-  // now make it start, just in case it hadn't already.
-  stream.emit('readable');
-}
-
-// wrap an old-style stream as the async data source.
-// This is *not* part of the readable stream interface.
-// It is an ugly unfortunate mess of history.
-Readable.prototype.wrap = function(stream) {
-  var state = this._readableState;
-  var paused = false;
-
-  var self = this;
-  stream.on('end', function() {
-    if (state.decoder && !state.ended) {
-      var chunk = state.decoder.end();
-      if (chunk && chunk.length)
-        self.push(chunk);
-    }
-
-    self.push(null);
-  });
-
-  stream.on('data', function(chunk) {
-    if (state.decoder)
-      chunk = state.decoder.write(chunk);
-    if (!chunk || !state.objectMode && !chunk.length)
-      return;
-
-    var ret = self.push(chunk);
-    if (!ret) {
-      paused = true;
-      stream.pause();
-    }
-  });
-
-  // proxy all the other methods.
-  // important when wrapping filters and duplexes.
-  for (var i in stream) {
-    if (typeof stream[i] === 'function' &&
-        typeof this[i] === 'undefined') {
-      this[i] = function(method) { return function() {
-        return stream[method].apply(stream, arguments);
-      }}(i);
-    }
-  }
-
-  // proxy certain important events.
-  var events = ['error', 'close', 'destroy', 'pause', 'resume'];
-  forEach(events, function(ev) {
-    stream.on(ev, self.emit.bind(self, ev));
-  });
-
-  // when we try to consume some more bytes, simply unpause the
-  // underlying stream.
-  self._read = function(n) {
-    if (paused) {
-      paused = false;
-      stream.resume();
-    }
-  };
-
-  return self;
-};
-
-
-
-// exposed for testing purposes only.
-Readable._fromList = fromList;
-
-// Pluck off n bytes from an array of buffers.
-// Length is the combined lengths of all the buffers in the list.
-function fromList(n, state) {
-  var list = state.buffer;
-  var length = state.length;
-  var stringMode = !!state.decoder;
-  var objectMode = !!state.objectMode;
-  var ret;
-
-  // nothing in the list, definitely empty.
-  if (list.length === 0)
-    return null;
-
-  if (length === 0)
-    ret = null;
-  else if (objectMode)
-    ret = list.shift();
-  else if (!n || n >= length) {
-    // read it all, truncate the array.
-    if (stringMode)
-      ret = list.join('');
-    else
-      ret = Buffer.concat(list, length);
-    list.length = 0;
-  } else {
-    // read just some of it.
-    if (n < list[0].length) {
-      // just take a part of the first list item.
-      // slice is the same for buffers and strings.
-      var buf = list[0];
-      ret = buf.slice(0, n);
-      list[0] = buf.slice(n);
-    } else if (n === list[0].length) {
-      // first list is a perfect match
-      ret = list.shift();
-    } else {
-      // complex case.
-      // we have enough to cover it, but it spans past the first buffer.
-      if (stringMode)
-        ret = '';
-      else
-        ret = new Buffer(n);
-
-      var c = 0;
-      for (var i = 0, l = list.length; i < l && c < n; i++) {
-        var buf = list[0];
-        var cpy = Math.min(n - c, buf.length);
-
-        if (stringMode)
-          ret += buf.slice(0, cpy);
-        else
-          buf.copy(ret, c, 0, cpy);
-
-        if (cpy < buf.length)
-          list[0] = buf.slice(cpy);
-        else
-          list.shift();
-
-        c += cpy;
-      }
-    }
-  }
-
-  return ret;
-}
-
-function endReadable(stream) {
-  var state = stream._readableState;
-
-  // If we get here before consuming all the bytes, then that is a
-  // bug in node.  Should never happen.
-  if (state.length > 0)
-    throw new Error('endReadable called on non-empty stream');
-
-  if (!state.endEmitted && state.calledRead) {
-    state.ended = true;
-    process.nextTick(function() {
-      // Check that we didn't get one last unshift.
-      if (!state.endEmitted && state.length === 0) {
-        state.endEmitted = true;
-        stream.readable = false;
-        stream.emit('end');
-      }
-    });
-  }
-}
-
-function forEach (xs, f) {
-  for (var i = 0, l = xs.length; i < l; i++) {
-    f(xs[i], i);
-  }
-}
-
-function indexOf (xs, x) {
-  for (var i = 0, l = xs.length; i < l; i++) {
-    if (xs[i] === x) return i;
-  }
-  return -1;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_transform.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_transform.js
deleted file mode 100644
index eb188df3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_transform.js
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-
-// a transform stream is a readable/writable stream where you do
-// something with the data.  Sometimes it's called a "filter",
-// but that's not a great name for it, since that implies a thing where
-// some bits pass through, and others are simply ignored.  (That would
-// be a valid example of a transform, of course.)
-//
-// While the output is causally related to the input, it's not a
-// necessarily symmetric or synchronous transformation.  For example,
-// a zlib stream might take multiple plain-text writes(), and then
-// emit a single compressed chunk some time in the future.
-//
-// Here's how this works:
-//
-// The Transform stream has all the aspects of the readable and writable
-// stream classes.  When you write(chunk), that calls _write(chunk,cb)
-// internally, and returns false if there's a lot of pending writes
-// buffered up.  When you call read(), that calls _read(n) until
-// there's enough pending readable data buffered up.
-//
-// In a transform stream, the written data is placed in a buffer.  When
-// _read(n) is called, it transforms the queued up data, calling the
-// buffered _write cb's as it consumes chunks.  If consuming a single
-// written chunk would result in multiple output chunks, then the first
-// outputted bit calls the readcb, and subsequent chunks just go into
-// the read buffer, and will cause it to emit 'readable' if necessary.
-//
-// This way, back-pressure is actually determined by the reading side,
-// since _read has to be called to start processing a new chunk.  However,
-// a pathological inflate type of transform can cause excessive buffering
-// here.  For example, imagine a stream where every byte of input is
-// interpreted as an integer from 0-255, and then results in that many
-// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
-// 1kb of data being output.  In this case, you could write a very small
-// amount of input, and end up with a very large amount of output.  In
-// such a pathological inflating mechanism, there'd be no way to tell
-// the system to stop doing the transform.  A single 4MB write could
-// cause the system to run out of memory.
-//
-// However, even in such a pathological case, only a single written chunk
-// would be consumed, and then the rest would wait (un-transformed) until
-// the results of the previous transformed chunk were consumed.
-
-module.exports = Transform;
-
-var Duplex = require('./_stream_duplex');
-
-/*<replacement>*/
-var util = require('core-util-is');
-util.inherits = require('inherits');
-/*</replacement>*/
-
-util.inherits(Transform, Duplex);
-
-
-function TransformState(options, stream) {
-  this.afterTransform = function(er, data) {
-    return afterTransform(stream, er, data);
-  };
-
-  this.needTransform = false;
-  this.transforming = false;
-  this.writecb = null;
-  this.writechunk = null;
-}
-
-function afterTransform(stream, er, data) {
-  var ts = stream._transformState;
-  ts.transforming = false;
-
-  var cb = ts.writecb;
-
-  if (!cb)
-    return stream.emit('error', new Error('no writecb in Transform class'));
-
-  ts.writechunk = null;
-  ts.writecb = null;
-
-  if (data !== null && data !== undefined)
-    stream.push(data);
-
-  if (cb)
-    cb(er);
-
-  var rs = stream._readableState;
-  rs.reading = false;
-  if (rs.needReadable || rs.length < rs.highWaterMark) {
-    stream._read(rs.highWaterMark);
-  }
-}
-
-
-function Transform(options) {
-  if (!(this instanceof Transform))
-    return new Transform(options);
-
-  Duplex.call(this, options);
-
-  var ts = this._transformState = new TransformState(options, this);
-
-  // when the writable side finishes, then flush out anything remaining.
-  var stream = this;
-
-  // start out asking for a readable event once data is transformed.
-  this._readableState.needReadable = true;
-
-  // we have implemented the _read method, and done the other things
-  // that Readable wants before the first _read call, so unset the
-  // sync guard flag.
-  this._readableState.sync = false;
-
-  this.once('finish', function() {
-    if ('function' === typeof this._flush)
-      this._flush(function(er) {
-        done(stream, er);
-      });
-    else
-      done(stream);
-  });
-}
-
-Transform.prototype.push = function(chunk, encoding) {
-  this._transformState.needTransform = false;
-  return Duplex.prototype.push.call(this, chunk, encoding);
-};
-
-// This is the part where you do stuff!
-// override this function in implementation classes.
-// 'chunk' is an input chunk.
-//
-// Call `push(newChunk)` to pass along transformed output
-// to the readable side.  You may call 'push' zero or more times.
-//
-// Call `cb(err)` when you are done with this chunk.  If you pass
-// an error, then that'll put the hurt on the whole operation.  If you
-// never call cb(), then you'll never get another chunk.
-Transform.prototype._transform = function(chunk, encoding, cb) {
-  throw new Error('not implemented');
-};
-
-Transform.prototype._write = function(chunk, encoding, cb) {
-  var ts = this._transformState;
-  ts.writecb = cb;
-  ts.writechunk = chunk;
-  ts.writeencoding = encoding;
-  if (!ts.transforming) {
-    var rs = this._readableState;
-    if (ts.needTransform ||
-        rs.needReadable ||
-        rs.length < rs.highWaterMark)
-      this._read(rs.highWaterMark);
-  }
-};
-
-// Doesn't matter what the args are here.
-// _transform does all the work.
-// That we got here means that the readable side wants more data.
-Transform.prototype._read = function(n) {
-  var ts = this._transformState;
-
-  if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
-    ts.transforming = true;
-    this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
-  } else {
-    // mark that we need a transform, so that any data that comes in
-    // will get processed, now that we've asked for it.
-    ts.needTransform = true;
-  }
-};
-
-
-function done(stream, er) {
-  if (er)
-    return stream.emit('error', er);
-
-  // if there's nothing in the write buffer, then that means
-  // that nothing more will ever be provided
-  var ws = stream._writableState;
-  var rs = stream._readableState;
-  var ts = stream._transformState;
-
-  if (ws.length)
-    throw new Error('calling transform done when ws.length != 0');
-
-  if (ts.transforming)
-    throw new Error('calling transform done when still transforming');
-
-  return stream.push(null);
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_writable.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_writable.js
deleted file mode 100644
index d0254d5a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/lib/_stream_writable.js
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// A bit simpler than readable streams.
-// Implement an async ._write(chunk, cb), and it'll handle all
-// the drain event emission and buffering.
-
-module.exports = Writable;
-
-/*<replacement>*/
-var Buffer = require('buffer').Buffer;
-/*</replacement>*/
-
-Writable.WritableState = WritableState;
-
-
-/*<replacement>*/
-var util = require('core-util-is');
-util.inherits = require('inherits');
-/*</replacement>*/
-
-
-var Stream = require('stream');
-
-util.inherits(Writable, Stream);
-
-function WriteReq(chunk, encoding, cb) {
-  this.chunk = chunk;
-  this.encoding = encoding;
-  this.callback = cb;
-}
-
-function WritableState(options, stream) {
-  options = options || {};
-
-  // the point at which write() starts returning false
-  // Note: 0 is a valid value, means that we always return false if
-  // the entire buffer is not flushed immediately on write()
-  var hwm = options.highWaterMark;
-  this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
-
-  // object stream flag to indicate whether or not this stream
-  // contains buffers or objects.
-  this.objectMode = !!options.objectMode;
-
-  // cast to ints.
-  this.highWaterMark = ~~this.highWaterMark;
-
-  this.needDrain = false;
-  // at the start of calling end()
-  this.ending = false;
-  // when end() has been called, and returned
-  this.ended = false;
-  // when 'finish' is emitted
-  this.finished = false;
-
-  // should we decode strings into buffers before passing to _write?
-  // this is here so that some node-core streams can optimize string
-  // handling at a lower level.
-  var noDecode = options.decodeStrings === false;
-  this.decodeStrings = !noDecode;
-
-  // Crypto is kind of old and crusty.  Historically, its default string
-  // encoding is 'binary' so we have to make this configurable.
-  // Everything else in the universe uses 'utf8', though.
-  this.defaultEncoding = options.defaultEncoding || 'utf8';
-
-  // not an actual buffer we keep track of, but a measurement
-  // of how much we're waiting to get pushed to some underlying
-  // socket or file.
-  this.length = 0;
-
-  // a flag to see when we're in the middle of a write.
-  this.writing = false;
-
-  // a flag to be able to tell if the onwrite cb is called immediately,
-  // or on a later tick.  We set this to true at first, becuase any
-  // actions that shouldn't happen until "later" should generally also
-  // not happen before the first write call.
-  this.sync = true;
-
-  // a flag to know if we're processing previously buffered items, which
-  // may call the _write() callback in the same tick, so that we don't
-  // end up in an overlapped onwrite situation.
-  this.bufferProcessing = false;
-
-  // the callback that's passed to _write(chunk,cb)
-  this.onwrite = function(er) {
-    onwrite(stream, er);
-  };
-
-  // the callback that the user supplies to write(chunk,encoding,cb)
-  this.writecb = null;
-
-  // the amount that is being written when _write is called.
-  this.writelen = 0;
-
-  this.buffer = [];
-
-  // True if the error was already emitted and should not be thrown again
-  this.errorEmitted = false;
-}
-
-function Writable(options) {
-  var Duplex = require('./_stream_duplex');
-
-  // Writable ctor is applied to Duplexes, though they're not
-  // instanceof Writable, they're instanceof Readable.
-  if (!(this instanceof Writable) && !(this instanceof Duplex))
-    return new Writable(options);
-
-  this._writableState = new WritableState(options, this);
-
-  // legacy.
-  this.writable = true;
-
-  Stream.call(this);
-}
-
-// Otherwise people can pipe Writable streams, which is just wrong.
-Writable.prototype.pipe = function() {
-  this.emit('error', new Error('Cannot pipe. Not readable.'));
-};
-
-
-function writeAfterEnd(stream, state, cb) {
-  var er = new Error('write after end');
-  // TODO: defer error events consistently everywhere, not just the cb
-  stream.emit('error', er);
-  process.nextTick(function() {
-    cb(er);
-  });
-}
-
-// If we get something that is not a buffer, string, null, or undefined,
-// and we're not in objectMode, then that's an error.
-// Otherwise stream chunks are all considered to be of length=1, and the
-// watermarks determine how many objects to keep in the buffer, rather than
-// how many bytes or characters.
-function validChunk(stream, state, chunk, cb) {
-  var valid = true;
-  if (!Buffer.isBuffer(chunk) &&
-      'string' !== typeof chunk &&
-      chunk !== null &&
-      chunk !== undefined &&
-      !state.objectMode) {
-    var er = new TypeError('Invalid non-string/buffer chunk');
-    stream.emit('error', er);
-    process.nextTick(function() {
-      cb(er);
-    });
-    valid = false;
-  }
-  return valid;
-}
-
-Writable.prototype.write = function(chunk, encoding, cb) {
-  var state = this._writableState;
-  var ret = false;
-
-  if (typeof encoding === 'function') {
-    cb = encoding;
-    encoding = null;
-  }
-
-  if (Buffer.isBuffer(chunk))
-    encoding = 'buffer';
-  else if (!encoding)
-    encoding = state.defaultEncoding;
-
-  if (typeof cb !== 'function')
-    cb = function() {};
-
-  if (state.ended)
-    writeAfterEnd(this, state, cb);
-  else if (validChunk(this, state, chunk, cb))
-    ret = writeOrBuffer(this, state, chunk, encoding, cb);
-
-  return ret;
-};
-
-function decodeChunk(state, chunk, encoding) {
-  if (!state.objectMode &&
-      state.decodeStrings !== false &&
-      typeof chunk === 'string') {
-    chunk = new Buffer(chunk, encoding);
-  }
-  return chunk;
-}
-
-// if we're already writing something, then just put this
-// in the queue, and wait our turn.  Otherwise, call _write
-// If we return false, then we need a drain event, so set that flag.
-function writeOrBuffer(stream, state, chunk, encoding, cb) {
-  chunk = decodeChunk(state, chunk, encoding);
-  if (Buffer.isBuffer(chunk))
-    encoding = 'buffer';
-  var len = state.objectMode ? 1 : chunk.length;
-
-  state.length += len;
-
-  var ret = state.length < state.highWaterMark;
-  // we must ensure that previous needDrain will not be reset to false.
-  if (!ret)
-    state.needDrain = true;
-
-  if (state.writing)
-    state.buffer.push(new WriteReq(chunk, encoding, cb));
-  else
-    doWrite(stream, state, len, chunk, encoding, cb);
-
-  return ret;
-}
-
-function doWrite(stream, state, len, chunk, encoding, cb) {
-  state.writelen = len;
-  state.writecb = cb;
-  state.writing = true;
-  state.sync = true;
-  stream._write(chunk, encoding, state.onwrite);
-  state.sync = false;
-}
-
-function onwriteError(stream, state, sync, er, cb) {
-  if (sync)
-    process.nextTick(function() {
-      cb(er);
-    });
-  else
-    cb(er);
-
-  stream._writableState.errorEmitted = true;
-  stream.emit('error', er);
-}
-
-function onwriteStateUpdate(state) {
-  state.writing = false;
-  state.writecb = null;
-  state.length -= state.writelen;
-  state.writelen = 0;
-}
-
-function onwrite(stream, er) {
-  var state = stream._writableState;
-  var sync = state.sync;
-  var cb = state.writecb;
-
-  onwriteStateUpdate(state);
-
-  if (er)
-    onwriteError(stream, state, sync, er, cb);
-  else {
-    // Check if we're actually ready to finish, but don't emit yet
-    var finished = needFinish(stream, state);
-
-    if (!finished && !state.bufferProcessing && state.buffer.length)
-      clearBuffer(stream, state);
-
-    if (sync) {
-      process.nextTick(function() {
-        afterWrite(stream, state, finished, cb);
-      });
-    } else {
-      afterWrite(stream, state, finished, cb);
-    }
-  }
-}
-
-function afterWrite(stream, state, finished, cb) {
-  if (!finished)
-    onwriteDrain(stream, state);
-  cb();
-  if (finished)
-    finishMaybe(stream, state);
-}
-
-// Must force callback to be called on nextTick, so that we don't
-// emit 'drain' before the write() consumer gets the 'false' return
-// value, and has a chance to attach a 'drain' listener.
-function onwriteDrain(stream, state) {
-  if (state.length === 0 && state.needDrain) {
-    state.needDrain = false;
-    stream.emit('drain');
-  }
-}
-
-
-// if there's something in the buffer waiting, then process it
-function clearBuffer(stream, state) {
-  state.bufferProcessing = true;
-
-  for (var c = 0; c < state.buffer.length; c++) {
-    var entry = state.buffer[c];
-    var chunk = entry.chunk;
-    var encoding = entry.encoding;
-    var cb = entry.callback;
-    var len = state.objectMode ? 1 : chunk.length;
-
-    doWrite(stream, state, len, chunk, encoding, cb);
-
-    // if we didn't call the onwrite immediately, then
-    // it means that we need to wait until it does.
-    // also, that means that the chunk and cb are currently
-    // being processed, so move the buffer counter past them.
-    if (state.writing) {
-      c++;
-      break;
-    }
-  }
-
-  state.bufferProcessing = false;
-  if (c < state.buffer.length)
-    state.buffer = state.buffer.slice(c);
-  else
-    state.buffer.length = 0;
-}
-
-Writable.prototype._write = function(chunk, encoding, cb) {
-  cb(new Error('not implemented'));
-};
-
-Writable.prototype.end = function(chunk, encoding, cb) {
-  var state = this._writableState;
-
-  if (typeof chunk === 'function') {
-    cb = chunk;
-    chunk = null;
-    encoding = null;
-  } else if (typeof encoding === 'function') {
-    cb = encoding;
-    encoding = null;
-  }
-
-  if (typeof chunk !== 'undefined' && chunk !== null)
-    this.write(chunk, encoding);
-
-  // ignore unnecessary end() calls.
-  if (!state.ending && !state.finished)
-    endWritable(this, state, cb);
-};
-
-
-function needFinish(stream, state) {
-  return (state.ending &&
-          state.length === 0 &&
-          !state.finished &&
-          !state.writing);
-}
-
-function finishMaybe(stream, state) {
-  var need = needFinish(stream, state);
-  if (need) {
-    state.finished = true;
-    stream.emit('finish');
-  }
-  return need;
-}
-
-function endWritable(stream, state, cb) {
-  state.ending = true;
-  finishMaybe(stream, state);
-  if (cb) {
-    if (state.finished)
-      process.nextTick(cb);
-    else
-      stream.once('finish', cb);
-  }
-  state.ended = true;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/lib/util.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/lib/util.js
deleted file mode 100644
index 9074e8eb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/lib/util.js
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// NOTE: These type checking functions intentionally don't use `instanceof`
-// because it is fragile and can be easily faked with `Object.create()`.
-function isArray(ar) {
-  return Array.isArray(ar);
-}
-exports.isArray = isArray;
-
-function isBoolean(arg) {
-  return typeof arg === 'boolean';
-}
-exports.isBoolean = isBoolean;
-
-function isNull(arg) {
-  return arg === null;
-}
-exports.isNull = isNull;
-
-function isNullOrUndefined(arg) {
-  return arg == null;
-}
-exports.isNullOrUndefined = isNullOrUndefined;
-
-function isNumber(arg) {
-  return typeof arg === 'number';
-}
-exports.isNumber = isNumber;
-
-function isString(arg) {
-  return typeof arg === 'string';
-}
-exports.isString = isString;
-
-function isSymbol(arg) {
-  return typeof arg === 'symbol';
-}
-exports.isSymbol = isSymbol;
-
-function isUndefined(arg) {
-  return arg === void 0;
-}
-exports.isUndefined = isUndefined;
-
-function isRegExp(re) {
-  return isObject(re) && objectToString(re) === '[object RegExp]';
-}
-exports.isRegExp = isRegExp;
-
-function isObject(arg) {
-  return typeof arg === 'object' && arg !== null;
-}
-exports.isObject = isObject;
-
-function isDate(d) {
-  return isObject(d) && objectToString(d) === '[object Date]';
-}
-exports.isDate = isDate;
-
-function isError(e) {
-  return isObject(e) &&
-      (objectToString(e) === '[object Error]' || e instanceof Error);
-}
-exports.isError = isError;
-
-function isFunction(arg) {
-  return typeof arg === 'function';
-}
-exports.isFunction = isFunction;
-
-function isPrimitive(arg) {
-  return arg === null ||
-         typeof arg === 'boolean' ||
-         typeof arg === 'number' ||
-         typeof arg === 'string' ||
-         typeof arg === 'symbol' ||  // ES6 symbol
-         typeof arg === 'undefined';
-}
-exports.isPrimitive = isPrimitive;
-
-function isBuffer(arg) {
-  return Buffer.isBuffer(arg);
-}
-exports.isBuffer = isBuffer;
-
-function objectToString(o) {
-  return Object.prototype.toString.call(o);
-}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/package.json
deleted file mode 100644
index 5f6c88ef..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/package.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "name": "core-util-is",
-  "version": "1.0.1",
-  "description": "The `util.is*` functions introduced in Node v0.12.",
-  "main": "lib/util.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/core-util-is"
-  },
-  "keywords": [
-    "util",
-    "isBuffer",
-    "isArray",
-    "isNumber",
-    "isString",
-    "isRegExp",
-    "isThis",
-    "isThat",
-    "polyfill"
-  ],
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/isaacs/core-util-is/issues"
-  },
-  "readme": "# core-util-is\n\nThe `util.is*` functions introduced in Node v0.12.\n",
-  "readmeFilename": "README.md",
-  "homepage": "https://github.com/isaacs/core-util-is",
-  "_id": "core-util-is@1.0.1",
-  "_shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538",
-  "_from": "core-util-is@~1.0.0",
-  "_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/util.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/util.js
deleted file mode 100644
index 007fa105..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/core-util-is/util.js
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// NOTE: These type checking functions intentionally don't use `instanceof`
-// because it is fragile and can be easily faked with `Object.create()`.
-function isArray(ar) {
-  return Array.isArray(ar);
-}
-exports.isArray = isArray;
-
-function isBoolean(arg) {
-  return typeof arg === 'boolean';
-}
-exports.isBoolean = isBoolean;
-
-function isNull(arg) {
-  return arg === null;
-}
-exports.isNull = isNull;
-
-function isNullOrUndefined(arg) {
-  return arg == null;
-}
-exports.isNullOrUndefined = isNullOrUndefined;
-
-function isNumber(arg) {
-  return typeof arg === 'number';
-}
-exports.isNumber = isNumber;
-
-function isString(arg) {
-  return typeof arg === 'string';
-}
-exports.isString = isString;
-
-function isSymbol(arg) {
-  return typeof arg === 'symbol';
-}
-exports.isSymbol = isSymbol;
-
-function isUndefined(arg) {
-  return arg === void 0;
-}
-exports.isUndefined = isUndefined;
-
-function isRegExp(re) {
-  return isObject(re) && objectToString(re) === '[object RegExp]';
-}
-exports.isRegExp = isRegExp;
-
-function isObject(arg) {
-  return typeof arg === 'object' && arg !== null;
-}
-exports.isObject = isObject;
-
-function isDate(d) {
-  return isObject(d) && objectToString(d) === '[object Date]';
-}
-exports.isDate = isDate;
-
-function isError(e) {
-  return isObject(e) && objectToString(e) === '[object Error]';
-}
-exports.isError = isError;
-
-function isFunction(arg) {
-  return typeof arg === 'function';
-}
-exports.isFunction = isFunction;
-
-function isPrimitive(arg) {
-  return arg === null ||
-         typeof arg === 'boolean' ||
-         typeof arg === 'number' ||
-         typeof arg === 'string' ||
-         typeof arg === 'symbol' ||  // ES6 symbol
-         typeof arg === 'undefined';
-}
-exports.isPrimitive = isPrimitive;
-
-function isBuffer(arg) {
-  return arg instanceof Buffer;
-}
-exports.isBuffer = isBuffer;
-
-function objectToString(o) {
-  return Object.prototype.toString.call(o);
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/LICENSE
deleted file mode 100644
index dea3013d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/LICENSE
+++ /dev/null
@@ -1,16 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/README.md
deleted file mode 100644
index b1c56658..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-Browser-friendly inheritance fully compatible with standard node.js
-[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).
-
-This package exports standard `inherits` from node.js `util` module in
-node environment, but also provides alternative browser-friendly
-implementation through [browser
-field](https://gist.github.com/shtylman/4339901). Alternative
-implementation is a literal copy of standard one located in standalone
-module to avoid requiring of `util`. It also has a shim for old
-browsers with no `Object.create` support.
-
-While keeping you sure you are using standard `inherits`
-implementation in node.js environment, it allows bundlers such as
-[browserify](https://github.com/substack/node-browserify) to not
-include full `util` package to your client code if all you need is
-just `inherits` function. It worth, because browser shim for `util`
-package is large and `inherits` is often the single function you need
-from it.
-
-It's recommended to use this package instead of
-`require('util').inherits` for any code that has chances to be used
-not only in node.js but in browser too.
-
-## usage
-
-```js
-var inherits = require('inherits');
-// then use exactly as the standard one
-```
-
-## note on version ~1.0
-
-Version ~1.0 had completely different motivation and is not compatible
-neither with 2.0 nor with standard node.js `inherits`.
-
-If you are using version ~1.0 and planning to switch to ~2.0, be
-careful:
-
-* new version uses `super_` instead of `super` for referencing
-  superclass
-* new version overwrites current prototype while old one preserves any
-  existing fields on it
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits.js
deleted file mode 100644
index 29f5e24f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('util').inherits
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits_browser.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits_browser.js
deleted file mode 100644
index c1e78a75..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/inherits_browser.js
+++ /dev/null
@@ -1,23 +0,0 @@
-if (typeof Object.create === 'function') {
-  // implementation from standard node.js 'util' module
-  module.exports = function inherits(ctor, superCtor) {
-    ctor.super_ = superCtor
-    ctor.prototype = Object.create(superCtor.prototype, {
-      constructor: {
-        value: ctor,
-        enumerable: false,
-        writable: true,
-        configurable: true
-      }
-    });
-  };
-} else {
-  // old school shim for old browsers
-  module.exports = function inherits(ctor, superCtor) {
-    ctor.super_ = superCtor
-    var TempCtor = function () {}
-    TempCtor.prototype = superCtor.prototype
-    ctor.prototype = new TempCtor()
-    ctor.prototype.constructor = ctor
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/package.json
deleted file mode 100644
index 83ae772d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "inherits",
-  "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
-  "version": "2.0.1",
-  "keywords": [
-    "inheritance",
-    "class",
-    "klass",
-    "oop",
-    "object-oriented",
-    "inherits",
-    "browser",
-    "browserify"
-  ],
-  "main": "./inherits.js",
-  "browser": "./inherits_browser.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/inherits"
-  },
-  "license": "ISC",
-  "scripts": {
-    "test": "node test"
-  },
-  "readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n  superclass\n* new version overwrites current prototype while old one preserves any\n  existing fields on it\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/inherits/issues"
-  },
-  "homepage": "https://github.com/isaacs/inherits",
-  "_id": "inherits@2.0.1",
-  "_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
-  "_from": "inherits@~2.0.0",
-  "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/test.js
deleted file mode 100644
index fc53012d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/inherits/test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var inherits = require('./inherits.js')
-var assert = require('assert')
-
-function test(c) {
-  assert(c.constructor === Child)
-  assert(c.constructor.super_ === Parent)
-  assert(Object.getPrototypeOf(c) === Child.prototype)
-  assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype)
-  assert(c instanceof Child)
-  assert(c instanceof Parent)
-}
-
-function Child() {
-  Parent.call(this)
-  test(this)
-}
-
-function Parent() {}
-
-inherits(Child, Parent)
-
-var c = new Child
-test(c)
-
-console.log('ok')
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/README.md
deleted file mode 100644
index 052a62b8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-
-# isarray
-
-`Array#isArray` for older browsers.
-
-## Usage
-
-```js
-var isArray = require('isarray');
-
-console.log(isArray([])); // => true
-console.log(isArray({})); // => false
-```
-
-## Installation
-
-With [npm](http://npmjs.org) do
-
-```bash
-$ npm install isarray
-```
-
-Then bundle for the browser with
-[browserify](https://github.com/substack/browserify).
-
-With [component](http://component.io) do
-
-```bash
-$ component install juliangruber/isarray
-```
-
-## License
-
-(MIT)
-
-Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/build/build.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/build/build.js
deleted file mode 100644
index ec58596a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/build/build.js
+++ /dev/null
@@ -1,209 +0,0 @@
-
-/**
- * Require the given path.
- *
- * @param {String} path
- * @return {Object} exports
- * @api public
- */
-
-function require(path, parent, orig) {
-  var resolved = require.resolve(path);
-
-  // lookup failed
-  if (null == resolved) {
-    orig = orig || path;
-    parent = parent || 'root';
-    var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
-    err.path = orig;
-    err.parent = parent;
-    err.require = true;
-    throw err;
-  }
-
-  var module = require.modules[resolved];
-
-  // perform real require()
-  // by invoking the module's
-  // registered function
-  if (!module.exports) {
-    module.exports = {};
-    module.client = module.component = true;
-    module.call(this, module.exports, require.relative(resolved), module);
-  }
-
-  return module.exports;
-}
-
-/**
- * Registered modules.
- */
-
-require.modules = {};
-
-/**
- * Registered aliases.
- */
-
-require.aliases = {};
-
-/**
- * Resolve `path`.
- *
- * Lookup:
- *
- *   - PATH/index.js
- *   - PATH.js
- *   - PATH
- *
- * @param {String} path
- * @return {String} path or null
- * @api private
- */
-
-require.resolve = function(path) {
-  if (path.charAt(0) === '/') path = path.slice(1);
-  var index = path + '/index.js';
-
-  var paths = [
-    path,
-    path + '.js',
-    path + '.json',
-    path + '/index.js',
-    path + '/index.json'
-  ];
-
-  for (var i = 0; i < paths.length; i++) {
-    var path = paths[i];
-    if (require.modules.hasOwnProperty(path)) return path;
-  }
-
-  if (require.aliases.hasOwnProperty(index)) {
-    return require.aliases[index];
-  }
-};
-
-/**
- * Normalize `path` relative to the current path.
- *
- * @param {String} curr
- * @param {String} path
- * @return {String}
- * @api private
- */
-
-require.normalize = function(curr, path) {
-  var segs = [];
-
-  if ('.' != path.charAt(0)) return path;
-
-  curr = curr.split('/');
-  path = path.split('/');
-
-  for (var i = 0; i < path.length; ++i) {
-    if ('..' == path[i]) {
-      curr.pop();
-    } else if ('.' != path[i] && '' != path[i]) {
-      segs.push(path[i]);
-    }
-  }
-
-  return curr.concat(segs).join('/');
-};
-
-/**
- * Register module at `path` with callback `definition`.
- *
- * @param {String} path
- * @param {Function} definition
- * @api private
- */
-
-require.register = function(path, definition) {
-  require.modules[path] = definition;
-};
-
-/**
- * Alias a module definition.
- *
- * @param {String} from
- * @param {String} to
- * @api private
- */
-
-require.alias = function(from, to) {
-  if (!require.modules.hasOwnProperty(from)) {
-    throw new Error('Failed to alias "' + from + '", it does not exist');
-  }
-  require.aliases[to] = from;
-};
-
-/**
- * Return a require function relative to the `parent` path.
- *
- * @param {String} parent
- * @return {Function}
- * @api private
- */
-
-require.relative = function(parent) {
-  var p = require.normalize(parent, '..');
-
-  /**
-   * lastIndexOf helper.
-   */
-
-  function lastIndexOf(arr, obj) {
-    var i = arr.length;
-    while (i--) {
-      if (arr[i] === obj) return i;
-    }
-    return -1;
-  }
-
-  /**
-   * The relative require() itself.
-   */
-
-  function localRequire(path) {
-    var resolved = localRequire.resolve(path);
-    return require(resolved, parent, path);
-  }
-
-  /**
-   * Resolve relative to the parent.
-   */
-
-  localRequire.resolve = function(path) {
-    var c = path.charAt(0);
-    if ('/' == c) return path.slice(1);
-    if ('.' == c) return require.normalize(p, path);
-
-    // resolve deps by returning
-    // the dep in the nearest "deps"
-    // directory
-    var segs = parent.split('/');
-    var i = lastIndexOf(segs, 'deps') + 1;
-    if (!i) i = 0;
-    path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
-    return path;
-  };
-
-  /**
-   * Check if module is defined at `path`.
-   */
-
-  localRequire.exists = function(path) {
-    return require.modules.hasOwnProperty(localRequire.resolve(path));
-  };
-
-  return localRequire;
-};
-require.register("isarray/index.js", function(exports, require, module){
-module.exports = Array.isArray || function (arr) {
-  return Object.prototype.toString.call(arr) == '[object Array]';
-};
-
-});
-require.alias("isarray/index.js", "isarray/index.js");
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/index.js
deleted file mode 100644
index 5f5ad45d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = Array.isArray || function (arr) {
-  return Object.prototype.toString.call(arr) == '[object Array]';
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/package.json
deleted file mode 100644
index e77e2cc0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/isarray/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "name": "isarray",
-  "description": "Array#isArray for older browsers",
-  "version": "0.0.1",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/juliangruber/isarray.git"
-  },
-  "homepage": "https://github.com/juliangruber/isarray",
-  "main": "index.js",
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "tap": "*"
-  },
-  "keywords": [
-    "browser",
-    "isarray",
-    "array"
-  ],
-  "author": {
-    "name": "Julian Gruber",
-    "email": "mail@juliangruber.com",
-    "url": "http://juliangruber.com"
-  },
-  "license": "MIT",
-  "readme": "\n# isarray\n\n`Array#isArray` for older browsers.\n\n## Usage\n\n```js\nvar isArray = require('isarray');\n\nconsole.log(isArray([])); // => true\nconsole.log(isArray({})); // => false\n```\n\n## Installation\n\nWith [npm](http://npmjs.org) do\n\n```bash\n$ npm install isarray\n```\n\nThen bundle for the browser with\n[browserify](https://github.com/substack/browserify).\n\nWith [component](http://component.io) do\n\n```bash\n$ component install juliangruber/isarray\n```\n\n## License\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/juliangruber/isarray/issues"
-  },
-  "_id": "isarray@0.0.1",
-  "_shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf",
-  "_from": "isarray@0.0.1",
-  "_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/.npmignore
deleted file mode 100644
index 206320cc..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-build
-test
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/LICENSE
deleted file mode 100644
index 6de584a4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright Joyent, Inc. and other Node contributors.
-
-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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/README.md
deleted file mode 100644
index 4d2aa001..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-**string_decoder.js** (`require('string_decoder')`) from Node.js core
-
-Copyright Joyent, Inc. and other Node contributors. See LICENCE file for details.
-
-Version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. **Prefer the stable version over the unstable.**
-
-The *build/* directory contains a build script that will scrape the source from the [joyent/node](https://github.com/joyent/node) repo given a specific Node version.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/index.js
deleted file mode 100644
index 2e44a03e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/index.js
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-var Buffer = require('buffer').Buffer;
-
-var isBufferEncoding = Buffer.isEncoding
-  || function(encoding) {
-       switch (encoding && encoding.toLowerCase()) {
-         case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
-         default: return false;
-       }
-     }
-
-
-function assertEncoding(encoding) {
-  if (encoding && !isBufferEncoding(encoding)) {
-    throw new Error('Unknown encoding: ' + encoding);
-  }
-}
-
-var StringDecoder = exports.StringDecoder = function(encoding) {
-  this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
-  assertEncoding(encoding);
-  switch (this.encoding) {
-    case 'utf8':
-      // CESU-8 represents each of Surrogate Pair by 3-bytes
-      this.surrogateSize = 3;
-      break;
-    case 'ucs2':
-    case 'utf16le':
-      // UTF-16 represents each of Surrogate Pair by 2-bytes
-      this.surrogateSize = 2;
-      this.detectIncompleteChar = utf16DetectIncompleteChar;
-      break;
-    case 'base64':
-      // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
-      this.surrogateSize = 3;
-      this.detectIncompleteChar = base64DetectIncompleteChar;
-      break;
-    default:
-      this.write = passThroughWrite;
-      return;
-  }
-
-  this.charBuffer = new Buffer(6);
-  this.charReceived = 0;
-  this.charLength = 0;
-};
-
-
-StringDecoder.prototype.write = function(buffer) {
-  var charStr = '';
-  var offset = 0;
-
-  // if our last write ended with an incomplete multibyte character
-  while (this.charLength) {
-    // determine how many remaining bytes this buffer has to offer for this char
-    var i = (buffer.length >= this.charLength - this.charReceived) ?
-                this.charLength - this.charReceived :
-                buffer.length;
-
-    // add the new bytes to the char buffer
-    buffer.copy(this.charBuffer, this.charReceived, offset, i);
-    this.charReceived += (i - offset);
-    offset = i;
-
-    if (this.charReceived < this.charLength) {
-      // still not enough chars in this buffer? wait for more ...
-      return '';
-    }
-
-    // get the character that was split
-    charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
-
-    // lead surrogate (D800-DBFF) is also the incomplete character
-    var charCode = charStr.charCodeAt(charStr.length - 1);
-    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
-      this.charLength += this.surrogateSize;
-      charStr = '';
-      continue;
-    }
-    this.charReceived = this.charLength = 0;
-
-    // if there are no more bytes in this buffer, just emit our char
-    if (i == buffer.length) return charStr;
-
-    // otherwise cut off the characters end from the beginning of this buffer
-    buffer = buffer.slice(i, buffer.length);
-    break;
-  }
-
-  var lenIncomplete = this.detectIncompleteChar(buffer);
-
-  var end = buffer.length;
-  if (this.charLength) {
-    // buffer the incomplete character bytes we got
-    buffer.copy(this.charBuffer, 0, buffer.length - lenIncomplete, end);
-    this.charReceived = lenIncomplete;
-    end -= lenIncomplete;
-  }
-
-  charStr += buffer.toString(this.encoding, 0, end);
-
-  var end = charStr.length - 1;
-  var charCode = charStr.charCodeAt(end);
-  // lead surrogate (D800-DBFF) is also the incomplete character
-  if (charCode >= 0xD800 && charCode <= 0xDBFF) {
-    var size = this.surrogateSize;
-    this.charLength += size;
-    this.charReceived += size;
-    this.charBuffer.copy(this.charBuffer, size, 0, size);
-    this.charBuffer.write(charStr.charAt(charStr.length - 1), this.encoding);
-    return charStr.substring(0, end);
-  }
-
-  // or just emit the charStr
-  return charStr;
-};
-
-StringDecoder.prototype.detectIncompleteChar = function(buffer) {
-  // determine how many bytes we have to check at the end of this buffer
-  var i = (buffer.length >= 3) ? 3 : buffer.length;
-
-  // Figure out if one of the last i bytes of our buffer announces an
-  // incomplete char.
-  for (; i > 0; i--) {
-    var c = buffer[buffer.length - i];
-
-    // See http://en.wikipedia.org/wiki/UTF-8#Description
-
-    // 110XXXXX
-    if (i == 1 && c >> 5 == 0x06) {
-      this.charLength = 2;
-      break;
-    }
-
-    // 1110XXXX
-    if (i <= 2 && c >> 4 == 0x0E) {
-      this.charLength = 3;
-      break;
-    }
-
-    // 11110XXX
-    if (i <= 3 && c >> 3 == 0x1E) {
-      this.charLength = 4;
-      break;
-    }
-  }
-
-  return i;
-};
-
-StringDecoder.prototype.end = function(buffer) {
-  var res = '';
-  if (buffer && buffer.length)
-    res = this.write(buffer);
-
-  if (this.charReceived) {
-    var cr = this.charReceived;
-    var buf = this.charBuffer;
-    var enc = this.encoding;
-    res += buf.slice(0, cr).toString(enc);
-  }
-
-  return res;
-};
-
-function passThroughWrite(buffer) {
-  return buffer.toString(this.encoding);
-}
-
-function utf16DetectIncompleteChar(buffer) {
-  var incomplete = this.charReceived = buffer.length % 2;
-  this.charLength = incomplete ? 2 : 0;
-  return incomplete;
-}
-
-function base64DetectIncompleteChar(buffer) {
-  var incomplete = this.charReceived = buffer.length % 3;
-  this.charLength = incomplete ? 3 : 0;
-  return incomplete;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/package.json
deleted file mode 100644
index 246b7be1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/node_modules/string_decoder/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "name": "string_decoder",
-  "version": "0.10.25-1",
-  "description": "The string_decoder module from Node core",
-  "main": "index.js",
-  "dependencies": {},
-  "devDependencies": {
-    "tap": "~0.4.8"
-  },
-  "scripts": {
-    "test": "tap test/simple/*.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/rvagg/string_decoder.git"
-  },
-  "homepage": "https://github.com/rvagg/string_decoder",
-  "keywords": [
-    "string",
-    "decoder",
-    "browser",
-    "browserify"
-  ],
-  "license": "MIT",
-  "readme": "**string_decoder.js** (`require('string_decoder')`) from Node.js core\n\nCopyright Joyent, Inc. and other Node contributors. See LICENCE file for details.\n\nVersion numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. **Prefer the stable version over the unstable.**\n\nThe *build/* directory contains a build script that will scrape the source from the [joyent/node](https://github.com/joyent/node) repo given a specific Node version.",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/rvagg/string_decoder/issues"
-  },
-  "_id": "string_decoder@0.10.25-1",
-  "_shasum": "f387babd95d23a2bb73b1fbf2cb3efab6f78baab",
-  "_from": "string_decoder@~0.10.x",
-  "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.25-1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/package.json
deleted file mode 100644
index 1197c6a6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/package.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "name": "readable-stream",
-  "version": "1.0.27-1",
-  "description": "Streams2, a user-land copy of the stream library from Node.js v0.10.x",
-  "main": "readable.js",
-  "dependencies": {
-    "core-util-is": "~1.0.0",
-    "isarray": "0.0.1",
-    "string_decoder": "~0.10.x",
-    "inherits": "~2.0.1"
-  },
-  "devDependencies": {
-    "tap": "~0.2.6"
-  },
-  "scripts": {
-    "test": "tap test/simple/*.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/readable-stream"
-  },
-  "keywords": [
-    "readable",
-    "stream",
-    "pipe"
-  ],
-  "browser": {
-    "util": false
-  },
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "license": "MIT",
-  "readme": "# readable-stream\n\n***Node-core streams for userland***\n\n[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true)](https://nodei.co/npm/readable-stream/)\n[![NPM](https://nodei.co/npm-dl/readable-stream.png)](https://nodei.co/npm/readable-stream/)\n\nThis package is a mirror of the Streams2 and Streams3 implementations in Node-core.\n\nIf you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *\"stream\"* module in Node-core.\n\n**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12.\n\n**readable-stream** uses proper patch-level versioning so if you pin to `\"~1.0.0\"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `\"~1.1.0\"`\n\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/readable-stream/issues"
-  },
-  "homepage": "https://github.com/isaacs/readable-stream",
-  "_id": "readable-stream@1.0.27-1",
-  "_shasum": "6b67983c20357cefd07f0165001a16d710d91078",
-  "_from": "readable-stream@~1.0.2",
-  "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/passthrough.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/passthrough.js
deleted file mode 100644
index 27e8d8a5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/passthrough.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require("./lib/_stream_passthrough.js")
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/readable.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/readable.js
deleted file mode 100644
index 4d1ddfc7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/readable.js
+++ /dev/null
@@ -1,6 +0,0 @@
-exports = module.exports = require('./lib/_stream_readable.js');
-exports.Readable = exports;
-exports.Writable = require('./lib/_stream_writable.js');
-exports.Duplex = require('./lib/_stream_duplex.js');
-exports.Transform = require('./lib/_stream_transform.js');
-exports.PassThrough = require('./lib/_stream_passthrough.js');
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/transform.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/transform.js
deleted file mode 100644
index 5d482f07..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/transform.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require("./lib/_stream_transform.js")
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/writable.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/writable.js
deleted file mode 100644
index e1e9efdf..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/readable-stream/writable.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require("./lib/_stream_writable.js")
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/LICENCE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/LICENCE
deleted file mode 100644
index 74489e2e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/LICENCE
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) Isaac Z. Schlueter
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/README.md
deleted file mode 100644
index 81166753..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-Use this module to convert a username/groupname to a uid/gid number.
-
-Usage:
-
-```
-npm install uid-number
-```
-
-Then, in your node program:
-
-```javascript
-var uidNumber = require("uid-number")
-uidNumber("isaacs", function (er, uid, gid) {
-  // gid is null because we didn't ask for a group name
-  // uid === 24561 because that's my number.
-})
-```
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/get-uid-gid.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/get-uid-gid.js
deleted file mode 100755
index 0b391748..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/get-uid-gid.js
+++ /dev/null
@@ -1,24 +0,0 @@
-if (module !== require.main) {
-  throw new Error("This file should not be loaded with require()")
-}
-
-if (!process.getuid || !process.getgid) {
-  throw new Error("this file should not be called without uid/gid support")
-}
-
-var argv = process.argv.slice(2)
-  , user = argv[0] || process.getuid()
-  , group = argv[1] || process.getgid()
-
-if (!isNaN(user)) user = +user
-if (!isNaN(group)) group = +group
-
-console.error([user, group])
-
-try {
-  process.setgid(group)
-  process.setuid(user)
-  console.log(JSON.stringify({uid:+process.getuid(), gid:+process.getgid()}))
-} catch (ex) {
-  console.log(JSON.stringify({error:ex.message,errno:ex.errno}))
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/package.json
deleted file mode 100644
index 6b3f65d3..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "uid-number",
-  "description": "Convert a username/group name to a uid/gid number",
-  "version": "0.0.3",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/uid-number.git"
-  },
-  "main": "uid-number.js",
-  "dependencies": {},
-  "devDependencies": {},
-  "optionalDependencies": {},
-  "engines": {
-    "node": "*"
-  },
-  "license": "BSD",
-  "readme": "Use this module to convert a username/groupname to a uid/gid number.\n\nUsage:\n\n```\nnpm install uid-number\n```\n\nThen, in your node program:\n\n```javascript\nvar uidNumber = require(\"uid-number\")\nuidNumber(\"isaacs\", function (er, uid, gid) {\n  // gid is null because we didn't ask for a group name\n  // uid === 24561 because that's my number.\n})\n```\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/uid-number/issues"
-  },
-  "homepage": "https://github.com/isaacs/uid-number",
-  "_id": "uid-number@0.0.3",
-  "_shasum": "cefb0fa138d8d8098da71a40a0d04a8327d6e1cc",
-  "_from": "uid-number@0.0.3",
-  "_resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.3.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/uid-number.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/uid-number.js
deleted file mode 100644
index 93f372bb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/node_modules/uid-number/uid-number.js
+++ /dev/null
@@ -1,54 +0,0 @@
-module.exports = uidNumber
-
-// This module calls into get-uid-gid.js, which sets the
-// uid and gid to the supplied argument, in order to find out their
-// numeric value.  This can't be done in the main node process,
-// because otherwise node would be running as that user from this
-// point on.
-
-var child_process = require("child_process")
-  , path = require("path")
-  , uidSupport = process.getuid && process.setuid
-  , uidCache = {}
-  , gidCache = {}
-
-function uidNumber (uid, gid, cb) {
-  if (!uidSupport) return cb()
-  if (typeof cb !== "function") cb = gid, gid = null
-  if (typeof cb !== "function") cb = uid, uid = null
-  if (gid == null) gid = process.getgid()
-  if (uid == null) uid = process.getuid()
-  if (!isNaN(gid)) gid = uidCache[gid] = +gid
-  if (!isNaN(uid)) uid = uidCache[uid] = +uid
-
-  if (uidCache.hasOwnProperty(uid)) uid = uidCache[uid]
-  if (gidCache.hasOwnProperty(gid)) gid = gidCache[gid]
-
-  if (typeof gid === "number" && typeof uid === "number") {
-    return process.nextTick(cb.bind(null, null, uid, gid))
-  }
-
-  var getter = require.resolve("./get-uid-gid.js")
-
-  child_process.execFile( process.execPath
-                        , [getter, uid, gid]
-                        , function (code, out, err) {
-    if (er) return cb(new Error("could not get uid/gid\n" + err))
-    try {
-      out = JSON.parse(out+"")
-    } catch (ex) {
-      return cb(ex)
-    }
-
-    if (out.error) {
-      var er = new Error(out.error)
-      er.errno = out.errno
-      return cb(er)
-    }
-
-    if (isNaN(out.uid) || isNaN(out.gid)) return cb(new Error(
-      "Could not get uid/gid: "+JSON.stringify(out)))
-
-    cb(null, uidCache[uid] = +out.uid, uidCache[gid] = +out.gid)
-  })
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/package.json
deleted file mode 100644
index f14be016..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/package.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "name": "tar-pack",
-  "version": "2.0.0",
-  "description": "Package and un-package modules of some sort (in tar/gz bundles).",
-  "scripts": {
-    "test": "mocha -R list"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/ForbesLindesay/tar-pack.git"
-  },
-  "license": "BSD",
-  "optionalDependencies": {
-    "graceful-fs": "1.2"
-  },
-  "dependencies": {
-    "uid-number": "0.0.3",
-    "once": "~1.1.1",
-    "debug": "~0.7.2",
-    "rimraf": "~2.2.0",
-    "fstream": "~0.1.22",
-    "tar": "~0.1.17",
-    "fstream-ignore": "0.0.7",
-    "readable-stream": "~1.0.2",
-    "graceful-fs": "1.2"
-  },
-  "devDependencies": {
-    "mocha": "*",
-    "rfile": "*",
-    "mkdirp": "*"
-  },
-  "readme": "# Tar Pack\r\n\r\nPackage and un-package modules of some sort (in tar/gz bundles).  This is mostly useful for package managers.  Note that it doesn't check for or touch `package.json` so it can be used even if that's not the way you store your package info.\r\n\r\n[![Build Status](https://travis-ci.org/ForbesLindesay/tar-pack.png?branch=master)](https://travis-ci.org/ForbesLindesay/tar-pack)\r\n[![Dependency Status](https://gemnasium.com/ForbesLindesay/tar-pack.png)](https://gemnasium.com/ForbesLindesay/tar-pack)\r\n[![NPM version](https://badge.fury.io/js/tar-pack.png)](http://badge.fury.io/js/tar-pack)\r\n\r\n## Installation\r\n\r\n    $ npm install tar-pack\r\n\r\n## API\r\n\r\n### pack(folder|packer, [options])\r\n\r\nPack the folder at `folder` into a gzipped tarball and return the tgz as a stream.  Files ignored by `.gitignore` will not be in the package.\r\n\r\nYou can optionally pass a `fstream.DirReader` directly, instead of folder.  For example, to create an npm package, do:\r\n\r\n```js\r\npack(require(\"fstream-npm\")(folder), [options])\r\n```\r\n\r\nOptions:\r\n\r\n - `noProprietary` (defaults to `false`) Set this to `true` to prevent any proprietary attributes being added to the tarball.  These attributes are allowed by the spec, but may trip up some poorly written tarball parsers.\r\n - `ignoreFiles` (defaults to `['.gitignore']`) These files can specify files to be excluded from the package using the syntax of `.gitignore`.  This option is ignored if you parse a `fstream.DirReader` instead of a string for folder.\r\n - `filter` (defaults to `entry => true`) A function that takes an entry and returns `true` if it should be included in the package and `false` if it should not.  Entryies are of the form `{path, basename, dirname, type}` where (type is \"Directory\" or \"File\").  This function is ignored if you parse a `fstream.DirReader` instead of a string for folder.\r\n\r\nExample:\r\n\r\n```js\r\nvar write = require('fs').createWriteStream\r\nvar pack = require('tar-pack').pack\r\npack(process.cwd())\r\n  .pipe(write(__dirname + '/package.tar.gz'))\r\n  .on('error', function (err) {\r\n    console.error(err.stack)\r\n  })\r\n  .on('close', function () {\r\n    console.log('done')\r\n  })\r\n```\r\n\r\n### unpack(folder, [options,] cb)\r\n\r\nReturn a stream that unpacks a tarball into a folder at `folder`.  N.B. the output folder will be removed first if it already exists.\r\n\r\nThe callback is called with an optional error and, as its second argument, a string which is one of:\r\n\r\n - `'directory'`, indicating that the extracted package was a directory (either `.tar.gz` or `.tar`)\r\n - `'file'`, incating that the extracted package was just a single file (extracted to `defaultName`, see options)\r\n\r\nBasic Options:\r\n\r\n - `defaultName` (defaults to `index.js`) If the package is a single file, rather than a tarball, it will be \"extracted\" to this file name, set to `false` to disable.\r\n\r\nAdvanced Options (you probably don't need any of these):\r\n\r\n - `gid` - (defaults to `null`) the `gid` to use when writing files\r\n - `uid` - (defaults to `null`) the `uid` to use when writing files\r\n - `dmode` - (defaults to `0777`) The mode to use when creating directories\r\n - `fmode` - (defaults to `0666`) The mode to use when creating files\r\n - `unsafe` - (defaults to `false`) (on non win32 OSes it overrides `gid` and `uid` with the current processes IDs)\r\n\r\nExample:\r\n\r\n```js\r\nvar read = require('fs').createReadStream\r\nvar unpack = require('tar-pack').unpack\r\nread(process.cwd() + '/package.tar.gz')\r\n  .pipe(unpack(__dirname + '/package/', function (err) {\r\n    if (err) console.error(err.stack)\r\n    else console.log('done')\r\n  }))\r\n```\r\n\r\n## License\r\n\r\n  BSD",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/ForbesLindesay/tar-pack/issues"
-  },
-  "homepage": "https://github.com/ForbesLindesay/tar-pack",
-  "_id": "tar-pack@2.0.0",
-  "_shasum": "c2c401c02dd366138645e917b3a6baa256a9dcab",
-  "_from": "tar-pack@~2.0.0",
-  "_resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-2.0.0.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed-file.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed-file.txt
deleted file mode 100644
index ba0e162e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed-file.txt
+++ /dev/null
@@ -1 +0,0 @@
-bar
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed.tar b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed.tar
deleted file mode 100644
index 35fd1745182fd4c3c4572a7d11e0d9f2f41658b3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3584
zcmXR&OwLYBPt|9jAy6<eFgG_>U{C-712h^WreL68Xk=(?ZeVC`YG|gQpkQiZZmhsy
zN<%k|8Vv~nSo|j?7U`8#lt2WjOd1*xihpBR{F@q?nJ6eIm>U?FD=-*P*&U<CVTM3b
zVil&~sK|&30a*S|%g-Mi`QOwCod1oCNAo{D5@Awe5k0IKwPQ2{MnhmU1V%$(kc9vM
D8C)t=

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed.tar.gz b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/packed.tar.gz
deleted file mode 100644
index 89516b1089bb85a2738103a9ff12d18f509c0ef9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 152
zcmb2|=HPfFRTId>P?E1(keHmUSCUx7@b-!=7n36o>jN28@c?6c&vVAwHzImYh&*~J
zd(?Hq&8%syweiAne=9P-7HB_z-O2Vy=iRv@`Jc-7D;}8;)8zJbo~e3rP}9X{|CSfo
zZ*yNP*rfAye%;^bcQ<2{CkynLO;tZwclP)GE4zCCX8(C}pXYbH^Z(y03=F?NGnpTF
KEyBRZzyJX0=127a

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/bar.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/bar.txt
deleted file mode 100644
index 3f953866..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/bar.txt
+++ /dev/null
@@ -1 +0,0 @@
-baz
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/foo.txt b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/foo.txt
deleted file mode 100644
index ba0e162e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/fixtures/to-pack/foo.txt
+++ /dev/null
@@ -1 +0,0 @@
-bar
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/index.js
deleted file mode 100644
index 85b5f413..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar-pack/test/index.js
+++ /dev/null
@@ -1,67 +0,0 @@
-var tar = require('../')
-var path = require('path')
-var rfile = require('rfile')
-var rimraf = require('rimraf').sync
-var mkdir = require('mkdirp').sync
-
-var read = require('fs').createReadStream
-var write = require('fs').createWriteStream
-var assert = require('assert')
-
-beforeEach(function () {
-  rimraf(__dirname + '/output')
-})
-afterEach(function () {
-  rimraf(__dirname + '/output')
-})
-describe('tarball.pipe(unpack(directory, callback))', function () {
-  it('unpacks the tarball into the directory', function (done) {
-    read(__dirname + '/fixtures/packed.tar').pipe(tar.unpack(__dirname + '/output/unpacked', function (err) {
-      if (err) return done(err)
-      assert.equal(rfile('./output/unpacked/bar.txt'), rfile('./fixtures/to-pack/bar.txt'))
-      assert.equal(rfile('./output/unpacked/foo.txt'), rfile('./fixtures/to-pack/foo.txt'))
-      done()
-    }))
-  })
-})
-describe('gziptarball.pipe(unpack(directory, callback))', function () {
-  it('unpacks the tarball into the directory', function (done) {
-    read(__dirname + '/fixtures/packed.tar.gz').pipe(tar.unpack(__dirname + '/output/unpacked', function (err) {
-      if (err) return done(err)
-      assert.equal(rfile('./output/unpacked/bar.txt'), rfile('./fixtures/to-pack/bar.txt'))
-      assert.equal(rfile('./output/unpacked/foo.txt'), rfile('./fixtures/to-pack/foo.txt'))
-      done()
-    }))
-  })
-})
-describe('file.pipe(unpack(directory, callback))', function () {
-  it('copies the file into the directory', function (done) {
-    read(__dirname + '/fixtures/packed-file.txt').pipe(tar.unpack(__dirname + '/output/unpacked', function (err) {
-      if (err) return done(err)
-      assert.equal(rfile('./output/unpacked/index.js'), rfile('./fixtures/packed-file.txt'))
-      done()
-    }))
-  })
-})
-describe('pack(directory).pipe(tarball)', function () {
-  it('packs the directory into the output', function (done) {
-    var called = false
-    mkdir(__dirname + '/output/')
-    tar.pack(__dirname + '/fixtures/to-pack').pipe(write(__dirname + '/output/packed.tar.gz'))
-      .on('error', function (err) {
-        if (called) return
-        called = true
-        done(err)
-      })
-      .on('close', function () {
-        if (called) return
-        called = true
-        read(__dirname + '/output/packed.tar.gz').pipe(tar.unpack(__dirname + '/output/unpacked', function (err) {
-          if (err) return done(err)
-          assert.equal(rfile('./output/unpacked/bar.txt'), rfile('./fixtures/to-pack/bar.txt'))
-          assert.equal(rfile('./output/unpacked/foo.txt'), rfile('./fixtures/to-pack/foo.txt'))
-          done()
-        }))
-      })
-  })
-})
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.npmignore
deleted file mode 100644
index c167ad5b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.npmignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.*.swp
-node_modules
-examples/extract/
-test/tmp/
-test/fixtures/
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.travis.yml
deleted file mode 100644
index 2d26206d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/.travis.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/LICENCE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/LICENCE
deleted file mode 100644
index 74489e2e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/LICENCE
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) Isaac Z. Schlueter
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/README.md
deleted file mode 100644
index 5bcc82cd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# node-tar
-
-Tar for Node.js.
-
-[![NPM](https://nodei.co/npm/tar.png)](https://nodei.co/npm/tar/)
-
-## API
-
-See `examples/` for usage examples.
-
-### var tar = require('tar')
-
-Returns an object with `.Pack`, `.Extract` and `.Parse` methods.
-
-### tar.Pack([properties])
-
-Returns a through stream. Use
-[fstream](https://npmjs.org/package/fstream) to write files into the
-pack stream and you will receive tar archive data from the pack
-stream.
-
-The optional `properties` object are used to set properties in the tar
-'Global Extended Header'.
-
-### tar.Extract([options])
-
-Returns a through stream. Write tar data to the stream and the files
-in the tarball will be extracted onto the filesystem.
-
-`options` can be:
-
-```js
-{
-  path: '/path/to/extract/tar/into',
-  strip: 0, // how many path segments to strip from the root when extracting
-}
-```
-
-`options` also get passed to the `fstream.Writer` instance that `tar`
-uses internally.
-
-### tar.Parse()
-
-Returns a writable stream. Write tar data to it and it will emit
-`entry` events for each entry parsed from the tarball. This is used by
-`tar.Extract`.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/extracter.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/extracter.js
deleted file mode 100644
index e150abf2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/extracter.js
+++ /dev/null
@@ -1,11 +0,0 @@
-var tar = require("../tar.js")
-  , fs = require("fs")
-
-fs.createReadStream(__dirname + "/../test/fixtures/c.tar")
-  .pipe(tar.Extract({ path: __dirname + "/extract" }))
-  .on("error", function (er) {
-    console.error("error here")
-  })
-  .on("end", function () {
-    console.error("done")
-  })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/reader.js
deleted file mode 100644
index 39f3f088..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/examples/reader.js
+++ /dev/null
@@ -1,36 +0,0 @@
-var tar = require("../tar.js")
-  , fs = require("fs")
-
-fs.createReadStream(__dirname + "/../test/fixtures/c.tar")
-  .pipe(tar.Parse())
-  .on("extendedHeader", function (e) {
-    console.error("extended pax header", e.props)
-    e.on("end", function () {
-      console.error("extended pax fields:", e.fields)
-    })
-  })
-  .on("ignoredEntry", function (e) {
-    console.error("ignoredEntry?!?", e.props)
-  })
-  .on("longLinkpath", function (e) {
-    console.error("longLinkpath entry", e.props)
-    e.on("end", function () {
-      console.error("value=%j", e.body.toString())
-    })
-  })
-  .on("longPath", function (e) {
-    console.error("longPath entry", e.props)
-    e.on("end", function () {
-      console.error("value=%j", e.body.toString())
-    })
-  })
-  .on("entry", function (e) {
-    console.error("entry", e.props)
-    e.on("data", function (c) {
-      console.error("  >>>" + c.toString().replace(/\n/g, "\\n"))
-    })
-    e.on("end", function () {
-      console.error("  <<<EOF")
-    })
-  })
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/buffer-entry.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/buffer-entry.js
deleted file mode 100644
index 6c1da237..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/buffer-entry.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// just like the Entry class, but it buffers the contents
-//
-// XXX It would be good to set a maximum BufferEntry filesize,
-// since it eats up memory.  In normal operation,
-// these are only for long filenames or link names, which are
-// rarely very big.
-
-module.exports = BufferEntry
-
-var inherits = require("inherits")
-  , Entry = require("./entry.js")
-
-function BufferEntry () {
-  Entry.apply(this, arguments)
-  this._buffer = new Buffer(this.props.size)
-  this._offset = 0
-  this.body = ""
-  this.on("end", function () {
-    this.body = this._buffer.toString().slice(0, -1)
-  })
-}
-
-inherits(BufferEntry, Entry)
-
-// collect the bytes as they come in.
-BufferEntry.prototype.write = function (c) {
-  c.copy(this._buffer, this._offset)
-  this._offset += c.length
-  Entry.prototype.write.call(this, c)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry-writer.js
deleted file mode 100644
index 8e09042d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry-writer.js
+++ /dev/null
@@ -1,169 +0,0 @@
-module.exports = EntryWriter
-
-var tar = require("../tar.js")
-  , TarHeader = require("./header.js")
-  , Entry = require("./entry.js")
-  , inherits = require("inherits")
-  , BlockStream = require("block-stream")
-  , ExtendedHeaderWriter
-  , Stream = require("stream").Stream
-  , EOF = {}
-
-inherits(EntryWriter, Stream)
-
-function EntryWriter (props) {
-  var me = this
-
-  if (!(me instanceof EntryWriter)) {
-    return new EntryWriter(props)
-  }
-
-  Stream.apply(this)
-
-  me.writable = true
-  me.readable = true
-
-  me._stream = new BlockStream(512)
-
-  me._stream.on("data", function (c) {
-    me.emit("data", c)
-  })
-
-  me._stream.on("drain", function () {
-    me.emit("drain")
-  })
-
-  me._stream.on("end", function () {
-    me.emit("end")
-    me.emit("close")
-  })
-
-  me.props = props
-  if (props.type === "Directory") {
-    props.size = 0
-  }
-  props.ustar = "ustar\0"
-  props.ustarver = "00"
-  me.path = props.path
-
-  me._buffer = []
-  me._didHeader = false
-  me._meta = false
-
-  me.on("pipe", function () {
-    me._process()
-  })
-}
-
-EntryWriter.prototype.write = function (c) {
-  // console.error(".. ew write")
-  if (this._ended) return this.emit("error", new Error("write after end"))
-  this._buffer.push(c)
-  this._process()
-  this._needDrain = this._buffer.length > 0
-  return !this._needDrain
-}
-
-EntryWriter.prototype.end = function (c) {
-  // console.error(".. ew end")
-  if (c) this._buffer.push(c)
-  this._buffer.push(EOF)
-  this._ended = true
-  this._process()
-  this._needDrain = this._buffer.length > 0
-}
-
-EntryWriter.prototype.pause = function () {
-  // console.error(".. ew pause")
-  this._paused = true
-  this.emit("pause")
-}
-
-EntryWriter.prototype.resume = function () {
-  // console.error(".. ew resume")
-  this._paused = false
-  this.emit("resume")
-  this._process()
-}
-
-EntryWriter.prototype.add = function (entry) {
-  // console.error(".. ew add")
-  if (!this.parent) return this.emit("error", new Error("no parent"))
-
-  // make sure that the _header and such is emitted, and clear out
-  // the _currentEntry link on the parent.
-  if (!this._ended) this.end()
-
-  return this.parent.add(entry)
-}
-
-EntryWriter.prototype._header = function () {
-  // console.error(".. ew header")
-  if (this._didHeader) return
-  this._didHeader = true
-
-  var headerBlock = TarHeader.encode(this.props)
-
-  if (this.props.needExtended && !this._meta) {
-    var me = this
-
-    ExtendedHeaderWriter = ExtendedHeaderWriter ||
-      require("./extended-header-writer.js")
-
-    ExtendedHeaderWriter(this.props)
-      .on("data", function (c) {
-        me.emit("data", c)
-      })
-      .on("error", function (er) {
-        me.emit("error", er)
-      })
-      .end()
-  }
-
-  // console.error(".. .. ew headerBlock emitting")
-  this.emit("data", headerBlock)
-  this.emit("header")
-}
-
-EntryWriter.prototype._process = function () {
-  // console.error(".. .. ew process")
-  if (!this._didHeader && !this._meta) {
-    this._header()
-  }
-
-  if (this._paused || this._processing) {
-    // console.error(".. .. .. paused=%j, processing=%j", this._paused, this._processing)
-    return
-  }
-
-  this._processing = true
-
-  var buf = this._buffer
-  for (var i = 0; i < buf.length; i ++) {
-    // console.error(".. .. .. i=%d", i)
-
-    var c = buf[i]
-
-    if (c === EOF) this._stream.end()
-    else this._stream.write(c)
-
-    if (this._paused) {
-      // console.error(".. .. .. paused mid-emission")
-      this._processing = false
-      if (i < buf.length) {
-        this._needDrain = true
-        this._buffer = buf.slice(i + 1)
-      }
-      return
-    }
-  }
-
-  // console.error(".. .. .. emitted")
-  this._buffer.length = 0
-  this._processing = false
-
-  // console.error(".. .. .. emitting drain")
-  this.emit("drain")
-}
-
-EntryWriter.prototype.destroy = function () {}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry.js
deleted file mode 100644
index 4af5c410..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/entry.js
+++ /dev/null
@@ -1,213 +0,0 @@
-// A passthrough read/write stream that sets its properties
-// based on a header, extendedHeader, and globalHeader
-//
-// Can be either a file system object of some sort, or
-// a pax/ustar metadata entry.
-
-module.exports = Entry
-
-var TarHeader = require("./header.js")
-  , tar = require("../tar")
-  , assert = require("assert").ok
-  , Stream = require("stream").Stream
-  , inherits = require("inherits")
-  , fstream = require("fstream").Abstract
-
-function Entry (header, extended, global) {
-  Stream.call(this)
-  this.readable = true
-  this.writable = true
-
-  this._needDrain = false
-  this._paused = false
-  this._reading = false
-  this._ending = false
-  this._ended = false
-  this._remaining = 0
-  this._queue = []
-  this._index = 0
-  this._queueLen = 0
-
-  this._read = this._read.bind(this)
-
-  this.props = {}
-  this._header = header
-  this._extended = extended || {}
-
-  // globals can change throughout the course of
-  // a file parse operation.  Freeze it at its current state.
-  this._global = {}
-  var me = this
-  Object.keys(global || {}).forEach(function (g) {
-    me._global[g] = global[g]
-  })
-
-  this._setProps()
-}
-
-inherits(Entry, Stream)
-
-Entry.prototype.write = function (c) {
-  if (this._ending) this.error("write() after end()", null, true)
-  if (this._remaining === 0) {
-    this.error("invalid bytes past eof")
-  }
-
-  // often we'll get a bunch of \0 at the end of the last write,
-  // since chunks will always be 512 bytes when reading a tarball.
-  if (c.length > this._remaining) {
-    c = c.slice(0, this._remaining)
-  }
-  this._remaining -= c.length
-
-  // put it on the stack.
-  var ql = this._queueLen
-  this._queue.push(c)
-  this._queueLen ++
-
-  this._read()
-
-  // either paused, or buffered
-  if (this._paused || ql > 0) {
-    this._needDrain = true
-    return false
-  }
-
-  return true
-}
-
-Entry.prototype.end = function (c) {
-  if (c) this.write(c)
-  this._ending = true
-  this._read()
-}
-
-Entry.prototype.pause = function () {
-  this._paused = true
-  this.emit("pause")
-}
-
-Entry.prototype.resume = function () {
-  // console.error("    Tar Entry resume", this.path)
-  this.emit("resume")
-  this._paused = false
-  this._read()
-  return this._queueLen - this._index > 1
-}
-
-  // This is bound to the instance
-Entry.prototype._read = function () {
-  // console.error("    Tar Entry _read", this.path)
-
-  if (this._paused || this._reading || this._ended) return
-
-  // set this flag so that event handlers don't inadvertently
-  // get multiple _read() calls running.
-  this._reading = true
-
-  // have any data to emit?
-  while (this._index < this._queueLen && !this._paused) {
-    var chunk = this._queue[this._index ++]
-    this.emit("data", chunk)
-  }
-
-  // check if we're drained
-  if (this._index >= this._queueLen) {
-    this._queue.length = this._queueLen = this._index = 0
-    if (this._needDrain) {
-      this._needDrain = false
-      this.emit("drain")
-    }
-    if (this._ending) {
-      this._ended = true
-      this.emit("end")
-    }
-  }
-
-  // if the queue gets too big, then pluck off whatever we can.
-  // this should be fairly rare.
-  var mql = this._maxQueueLen
-  if (this._queueLen > mql && this._index > 0) {
-    mql = Math.min(this._index, mql)
-    this._index -= mql
-    this._queueLen -= mql
-    this._queue = this._queue.slice(mql)
-  }
-
-  this._reading = false
-}
-
-Entry.prototype._setProps = function () {
-  // props = extended->global->header->{}
-  var header = this._header
-    , extended = this._extended
-    , global = this._global
-    , props = this.props
-
-  // first get the values from the normal header.
-  var fields = tar.fields
-  for (var f = 0; fields[f] !== null; f ++) {
-    var field = fields[f]
-      , val = header[field]
-    if (typeof val !== "undefined") props[field] = val
-  }
-
-  // next, the global header for this file.
-  // numeric values, etc, will have already been parsed.
-  ;[global, extended].forEach(function (p) {
-    Object.keys(p).forEach(function (f) {
-      if (typeof p[f] !== "undefined") props[f] = p[f]
-    })
-  })
-
-  // no nulls allowed in path or linkpath
-  ;["path", "linkpath"].forEach(function (p) {
-    if (props.hasOwnProperty(p)) {
-      props[p] = props[p].split("\0")[0]
-    }
-  })
-
-
-  // set date fields to be a proper date
-  ;["mtime", "ctime", "atime"].forEach(function (p) {
-    if (props.hasOwnProperty(p)) {
-      props[p] = new Date(props[p] * 1000)
-    }
-  })
-
-  // set the type so that we know what kind of file to create
-  var type
-  switch (tar.types[props.type]) {
-    case "OldFile":
-    case "ContiguousFile":
-      type = "File"
-      break
-
-    case "GNUDumpDir":
-      type = "Directory"
-      break
-
-    case undefined:
-      type = "Unknown"
-      break
-
-    case "Link":
-    case "SymbolicLink":
-    case "CharacterDevice":
-    case "BlockDevice":
-    case "Directory":
-    case "FIFO":
-    default:
-      type = tar.types[props.type]
-  }
-
-  this.type = type
-  this.path = props.path
-  this.size = props.size
-
-  // size is special, since it signals when the file needs to end.
-  this._remaining = props.size
-}
-
-Entry.prototype.warn = fstream.warn
-Entry.prototype.error = fstream.error
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header-writer.js
deleted file mode 100644
index 1728c458..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header-writer.js
+++ /dev/null
@@ -1,191 +0,0 @@
-
-module.exports = ExtendedHeaderWriter
-
-var inherits = require("inherits")
-  , EntryWriter = require("./entry-writer.js")
-
-inherits(ExtendedHeaderWriter, EntryWriter)
-
-var tar = require("../tar.js")
-  , path = require("path")
-  , TarHeader = require("./header.js")
-
-// props is the props of the thing we need to write an
-// extended header for.
-// Don't be shy with it.  Just encode everything.
-function ExtendedHeaderWriter (props) {
-  // console.error(">> ehw ctor")
-  var me = this
-
-  if (!(me instanceof ExtendedHeaderWriter)) {
-    return new ExtendedHeaderWriter(props)
-  }
-
-  me.fields = props
-
-  var p =
-    { path : ("PaxHeader" + path.join("/", props.path || ""))
-             .replace(/\\/g, "/").substr(0, 100)
-    , mode : props.mode || 0666
-    , uid : props.uid || 0
-    , gid : props.gid || 0
-    , size : 0 // will be set later
-    , mtime : props.mtime || Date.now() / 1000
-    , type : "x"
-    , linkpath : ""
-    , ustar : "ustar\0"
-    , ustarver : "00"
-    , uname : props.uname || ""
-    , gname : props.gname || ""
-    , devmaj : props.devmaj || 0
-    , devmin : props.devmin || 0
-    }
-
-
-  EntryWriter.call(me, p)
-  // console.error(">> ehw props", me.props)
-  me.props = p
-
-  me._meta = true
-}
-
-ExtendedHeaderWriter.prototype.end = function () {
-  // console.error(">> ehw end")
-  var me = this
-
-  if (me._ended) return
-  me._ended = true
-
-  me._encodeFields()
-
-  if (me.props.size === 0) {
-    // nothing to write!
-    me._ready = true
-    me._stream.end()
-    return
-  }
-
-  me._stream.write(TarHeader.encode(me.props))
-  me.body.forEach(function (l) {
-    me._stream.write(l)
-  })
-  me._ready = true
-
-  // console.error(">> ehw _process calling end()", me.props)
-  this._stream.end()
-}
-
-ExtendedHeaderWriter.prototype._encodeFields = function () {
-  // console.error(">> ehw _encodeFields")
-  this.body = []
-  if (this.fields.prefix) {
-    this.fields.path = this.fields.prefix + "/" + this.fields.path
-    this.fields.prefix = ""
-  }
-  encodeFields(this.fields, "", this.body, this.fields.noProprietary)
-  var me = this
-  this.body.forEach(function (l) {
-    me.props.size += l.length
-  })
-}
-
-function encodeFields (fields, prefix, body, nop) {
-  // console.error(">> >> ehw encodeFields")
-  // "%d %s=%s\n", <length>, <keyword>, <value>
-  // The length is a decimal number, and includes itself and the \n
-  // Numeric values are decimal strings.
-
-  Object.keys(fields).forEach(function (k) {
-    var val = fields[k]
-      , numeric = tar.numeric[k]
-
-    if (prefix) k = prefix + "." + k
-
-    // already including NODETAR.type, don't need File=true also
-    if (k === fields.type && val === true) return
-
-    switch (k) {
-      // don't include anything that's always handled just fine
-      // in the normal header, or only meaningful in the context
-      // of nodetar
-      case "mode":
-      case "cksum":
-      case "ustar":
-      case "ustarver":
-      case "prefix":
-      case "basename":
-      case "dirname":
-      case "needExtended":
-      case "block":
-      case "filter":
-        return
-
-      case "rdev":
-        if (val === 0) return
-        break
-
-      case "nlink":
-      case "dev": // Truly a hero among men, Creator of Star!
-      case "ino": // Speak his name with reverent awe!  It is:
-        k = "SCHILY." + k
-        break
-
-      default: break
-    }
-
-    if (val && typeof val === "object" &&
-        !Buffer.isBuffer(val)) encodeFields(val, k, body, nop)
-    else if (val === null || val === undefined) return
-    else body.push.apply(body, encodeField(k, val, nop))
-  })
-
-  return body
-}
-
-function encodeField (k, v, nop) {
-  // lowercase keys must be valid, otherwise prefix with
-  // "NODETAR."
-  if (k.charAt(0) === k.charAt(0).toLowerCase()) {
-    var m = k.split(".")[0]
-    if (!tar.knownExtended[m]) k = "NODETAR." + k
-  }
-
-  // no proprietary
-  if (nop && k.charAt(0) !== k.charAt(0).toLowerCase()) {
-    return []
-  }
-
-  if (typeof val === "number") val = val.toString(10)
-
-  var s = new Buffer(" " + k + "=" + v + "\n")
-    , digits = Math.floor(Math.log(s.length) / Math.log(10)) + 1
-
-  // console.error("1 s=%j digits=%j s.length=%d", s.toString(), digits, s.length)
-
-  // if adding that many digits will make it go over that length,
-  // then add one to it. For example, if the string is:
-  // " foo=bar\n"
-  // then that's 9 characters.  With the "9", that bumps the length
-  // up to 10.  However, this is invalid:
-  // "10 foo=bar\n"
-  // but, since that's actually 11 characters, since 10 adds another
-  // character to the length, and the length includes the number
-  // itself.  In that case, just bump it up again.
-  if (s.length + digits >= Math.pow(10, digits)) digits += 1
-  // console.error("2 s=%j digits=%j s.length=%d", s.toString(), digits, s.length)
-
-  var len = digits + s.length
-  // console.error("3 s=%j digits=%j s.length=%d len=%d", s.toString(), digits, s.length, len)
-  var lenBuf = new Buffer("" + len)
-  if (lenBuf.length + s.length !== len) {
-    throw new Error("Bad length calculation\n"+
-                    "len="+len+"\n"+
-                    "lenBuf="+JSON.stringify(lenBuf.toString())+"\n"+
-                    "lenBuf.length="+lenBuf.length+"\n"+
-                    "digits="+digits+"\n"+
-                    "s="+JSON.stringify(s.toString())+"\n"+
-                    "s.length="+s.length)
-  }
-
-  return [lenBuf, s]
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header.js
deleted file mode 100644
index 74f432ce..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extended-header.js
+++ /dev/null
@@ -1,140 +0,0 @@
-// An Entry consisting of:
-//
-// "%d %s=%s\n", <length>, <keyword>, <value>
-//
-// The length is a decimal number, and includes itself and the \n
-// \0 does not terminate anything.  Only the length terminates the string.
-// Numeric values are decimal strings.
-
-module.exports = ExtendedHeader
-
-var Entry = require("./entry.js")
-  , inherits = require("inherits")
-  , tar = require("../tar.js")
-  , numeric = tar.numeric
-  , keyTrans = { "SCHILY.dev": "dev"
-               , "SCHILY.ino": "ino"
-               , "SCHILY.nlink": "nlink" }
-
-function ExtendedHeader () {
-  Entry.apply(this, arguments)
-  this.on("data", this._parse)
-  this.fields = {}
-  this._position = 0
-  this._fieldPos = 0
-  this._state = SIZE
-  this._sizeBuf = []
-  this._keyBuf = []
-  this._valBuf = []
-  this._size = -1
-  this._key = ""
-}
-
-inherits(ExtendedHeader, Entry)
-ExtendedHeader.prototype._parse = parse
-
-var s = 0
-  , states = ExtendedHeader.states = {}
-  , SIZE = states.SIZE = s++
-  , KEY  = states.KEY  = s++
-  , VAL  = states.VAL  = s++
-  , ERR  = states.ERR  = s++
-
-Object.keys(states).forEach(function (s) {
-  states[states[s]] = states[s]
-})
-
-states[s] = null
-
-// char code values for comparison
-var _0 = "0".charCodeAt(0)
-  , _9 = "9".charCodeAt(0)
-  , point = ".".charCodeAt(0)
-  , a = "a".charCodeAt(0)
-  , Z = "Z".charCodeAt(0)
-  , a = "a".charCodeAt(0)
-  , z = "z".charCodeAt(0)
-  , space = " ".charCodeAt(0)
-  , eq = "=".charCodeAt(0)
-  , cr = "\n".charCodeAt(0)
-
-function parse (c) {
-  if (this._state === ERR) return
-
-  for ( var i = 0, l = c.length
-      ; i < l
-      ; this._position++, this._fieldPos++, i++) {
-    // console.error("top of loop, size="+this._size)
-
-    var b = c[i]
-
-    if (this._size >= 0 && this._fieldPos > this._size) {
-      error(this, "field exceeds length="+this._size)
-      return
-    }
-
-    switch (this._state) {
-      case ERR: return
-
-      case SIZE:
-        // console.error("parsing size, b=%d, rest=%j", b, c.slice(i).toString())
-        if (b === space) {
-          this._state = KEY
-          // this._fieldPos = this._sizeBuf.length
-          this._size = parseInt(new Buffer(this._sizeBuf).toString(), 10)
-          this._sizeBuf.length = 0
-          continue
-        }
-        if (b < _0 || b > _9) {
-          error(this, "expected [" + _0 + ".." + _9 + "], got " + b)
-          return
-        }
-        this._sizeBuf.push(b)
-        continue
-
-      case KEY:
-        // can be any char except =, not > size.
-        if (b === eq) {
-          this._state = VAL
-          this._key = new Buffer(this._keyBuf).toString()
-          if (keyTrans[this._key]) this._key = keyTrans[this._key]
-          this._keyBuf.length = 0
-          continue
-        }
-        this._keyBuf.push(b)
-        continue
-
-      case VAL:
-        // field must end with cr
-        if (this._fieldPos === this._size - 1) {
-          // console.error("finished with "+this._key)
-          if (b !== cr) {
-            error(this, "expected \\n at end of field")
-            return
-          }
-          var val = new Buffer(this._valBuf).toString()
-          if (numeric[this._key]) {
-            val = parseFloat(val)
-          }
-          this.fields[this._key] = val
-
-          this._valBuf.length = 0
-          this._state = SIZE
-          this._size = -1
-          this._fieldPos = -1
-          continue
-        }
-        this._valBuf.push(b)
-        continue
-    }
-  }
-}
-
-function error (me, msg) {
-  msg = "invalid header: " + msg
-      + "\nposition=" + me._position
-      + "\nfield position=" + me._fieldPos
-
-  me.error(msg)
-  me.state = ERR
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extract.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extract.js
deleted file mode 100644
index c34a81e2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/extract.js
+++ /dev/null
@@ -1,78 +0,0 @@
-// give it a tarball and a path, and it'll dump the contents
-
-module.exports = Extract
-
-var tar = require("../tar.js")
-  , fstream = require("fstream")
-  , inherits = require("inherits")
-  , path = require("path")
-
-function Extract (opts) {
-  if (!(this instanceof Extract)) return new Extract(opts)
-  tar.Parse.apply(this)
-
-  // have to dump into a directory
-  opts.type = "Directory"
-  opts.Directory = true
-
-  if (typeof opts !== "object") {
-    opts = { path: opts }
-  }
-
-  // better to drop in cwd? seems more standard.
-  opts.path = opts.path || path.resolve("node-tar-extract")
-  opts.type = "Directory"
-  opts.Directory = true
-
-  // similar to --strip or --strip-components
-  opts.strip = +opts.strip
-  if (!opts.strip || opts.strip <= 0) opts.strip = 0
-
-  this._fst = fstream.Writer(opts)
-
-  this.pause()
-  var me = this
-
-  // Hardlinks in tarballs are relative to the root
-  // of the tarball.  So, they need to be resolved against
-  // the target directory in order to be created properly.
-  me.on("entry", function (entry) {
-    // if there's a "strip" argument, then strip off that many
-    // path components.
-    if (opts.strip) {
-      var p = entry.path.split("/").slice(opts.strip).join("/")
-      entry.path = entry.props.path = p
-      if (entry.linkpath) {
-        var lp = entry.linkpath.split("/").slice(opts.strip).join("/")
-        entry.linkpath = entry.props.linkpath = lp
-      }
-    }
-    if (entry.type !== "Link") return
-    entry.linkpath = entry.props.linkpath =
-      path.join(opts.path, path.join("/", entry.props.linkpath))
-  })
-
-  this._fst.on("ready", function () {
-    me.pipe(me._fst, { end: false })
-    me.resume()
-  })
-
-  // this._fst.on("end", function () {
-  //   console.error("\nEEEE Extract End", me._fst.path)
-  // })
-
-  this._fst.on("close", function () {
-    // console.error("\nEEEE Extract End", me._fst.path)
-    me.emit("end")
-    me.emit("close")
-  })
-}
-
-inherits(Extract, tar.Parse)
-
-Extract.prototype._streamEnd = function () {
-  var me = this
-  if (!me._ended) me.error("unexpected eof")
-  me._fst.end()
-  // my .end() is coming later.
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/global-header-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/global-header-writer.js
deleted file mode 100644
index 0bfc7b80..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/global-header-writer.js
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = GlobalHeaderWriter
-
-var ExtendedHeaderWriter = require("./extended-header-writer.js")
-  , inherits = require("inherits")
-
-inherits(GlobalHeaderWriter, ExtendedHeaderWriter)
-
-function GlobalHeaderWriter (props) {
-  if (!(this instanceof GlobalHeaderWriter)) {
-    return new GlobalHeaderWriter(props)
-  }
-  ExtendedHeaderWriter.call(this, props)
-  this.props.type = "g"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/header.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/header.js
deleted file mode 100644
index 05b237c0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/header.js
+++ /dev/null
@@ -1,385 +0,0 @@
-// parse a 512-byte header block to a data object, or vice-versa
-// If the data won't fit nicely in a simple header, then generate
-// the appropriate extended header file, and return that.
-
-module.exports = TarHeader
-
-var tar = require("../tar.js")
-  , fields = tar.fields
-  , fieldOffs = tar.fieldOffs
-  , fieldEnds = tar.fieldEnds
-  , fieldSize = tar.fieldSize
-  , numeric = tar.numeric
-  , assert = require("assert").ok
-  , space = " ".charCodeAt(0)
-  , slash = "/".charCodeAt(0)
-  , bslash = process.platform === "win32" ? "\\".charCodeAt(0) : null
-
-function TarHeader (block) {
-  if (!(this instanceof TarHeader)) return new TarHeader(block)
-  if (block) this.decode(block)
-}
-
-TarHeader.prototype =
-  { decode : decode
-  , encode: encode
-  , calcSum: calcSum
-  , checkSum: checkSum
-  }
-
-TarHeader.parseNumeric = parseNumeric
-TarHeader.encode = encode
-TarHeader.decode = decode
-
-// note that this will only do the normal ustar header, not any kind
-// of extended posix header file.  If something doesn't fit comfortably,
-// then it will set obj.needExtended = true, and set the block to
-// the closest approximation.
-function encode (obj) {
-  if (!obj && !(this instanceof TarHeader)) throw new Error(
-    "encode must be called on a TarHeader, or supplied an object")
-
-  obj = obj || this
-  var block = obj.block = new Buffer(512)
-
-  // if the object has a "prefix", then that's actually an extension of
-  // the path field.
-  if (obj.prefix) {
-    // console.error("%% header encoding, got a prefix", obj.prefix)
-    obj.path = obj.prefix + "/" + obj.path
-    // console.error("%% header encoding, prefixed path", obj.path)
-    obj.prefix = ""
-  }
-
-  obj.needExtended = false
-
-  if (obj.mode) {
-    if (typeof obj.mode === "string") obj.mode = parseInt(obj.mode, 8)
-    obj.mode = obj.mode & 0777
-  }
-
-  for (var f = 0; fields[f] !== null; f ++) {
-    var field = fields[f]
-      , off = fieldOffs[f]
-      , end = fieldEnds[f]
-      , ret
-
-    switch (field) {
-      case "cksum":
-        // special, done below, after all the others
-        break
-
-      case "prefix":
-        // special, this is an extension of the "path" field.
-        // console.error("%% header encoding, skip prefix later")
-        break
-
-      case "type":
-        // convert from long name to a single char.
-        var type = obj.type || "0"
-        if (type.length > 1) {
-          type = tar.types[obj.type]
-          if (!type) type = "0"
-        }
-        writeText(block, off, end, type)
-        break
-
-      case "path":
-        // uses the "prefix" field if > 100 bytes, but <= 255
-        var pathLen = Buffer.byteLength(obj.path)
-          , pathFSize = fieldSize[fields.path]
-          , prefFSize = fieldSize[fields.prefix]
-
-        // paths between 100 and 255 should use the prefix field.
-        // longer than 255
-        if (pathLen > pathFSize &&
-            pathLen <= pathFSize + prefFSize) {
-          // need to find a slash somewhere in the middle so that
-          // path and prefix both fit in their respective fields
-          var searchStart = pathLen - 1 - pathFSize
-            , searchEnd = prefFSize
-            , found = false
-            , pathBuf = new Buffer(obj.path)
-
-          for ( var s = searchStart
-              ; (s <= searchEnd)
-              ; s ++ ) {
-            if (pathBuf[s] === slash || pathBuf[s] === bslash) {
-              found = s
-              break
-            }
-          }
-
-          if (found !== false) {
-            prefix = pathBuf.slice(0, found).toString("utf8")
-            path = pathBuf.slice(found + 1).toString("utf8")
-
-            ret = writeText(block, off, end, path)
-            off = fieldOffs[fields.prefix]
-            end = fieldEnds[fields.prefix]
-            // console.error("%% header writing prefix", off, end, prefix)
-            ret = writeText(block, off, end, prefix) || ret
-            break
-          }
-        }
-
-        // paths less than 100 chars don't need a prefix
-        // and paths longer than 255 need an extended header and will fail
-        // on old implementations no matter what we do here.
-        // Null out the prefix, and fallthrough to default.
-        // console.error("%% header writing no prefix")
-        var poff = fieldOffs[fields.prefix]
-          , pend = fieldEnds[fields.prefix]
-        writeText(block, poff, pend, "")
-        // fallthrough
-
-      // all other fields are numeric or text
-      default:
-        ret = numeric[field]
-            ? writeNumeric(block, off, end, obj[field])
-            : writeText(block, off, end, obj[field] || "")
-        break
-    }
-    obj.needExtended = obj.needExtended || ret
-  }
-
-  var off = fieldOffs[fields.cksum]
-    , end = fieldEnds[fields.cksum]
-
-  writeNumeric(block, off, end, calcSum.call(this, block))
-
-  return block
-}
-
-// if it's a negative number, or greater than will fit,
-// then use write256.
-var MAXNUM = { 12: 077777777777
-             , 11: 07777777777
-             , 8 : 07777777
-             , 7 : 0777777 }
-function writeNumeric (block, off, end, num) {
-  var writeLen = end - off
-    , maxNum = MAXNUM[writeLen] || 0
-
-  num = num || 0
-  // console.error("  numeric", num)
-
-  if (num instanceof Date ||
-      Object.prototype.toString.call(num) === "[object Date]") {
-    num = num.getTime() / 1000
-  }
-
-  if (num > maxNum || num < 0) {
-    write256(block, off, end, num)
-    // need an extended header if negative or too big.
-    return true
-  }
-
-  // god, tar is so annoying
-  // if the string is small enough, you should put a space
-  // between the octal string and the \0, but if it doesn't
-  // fit, then don't.
-  var numStr = Math.floor(num).toString(8)
-  if (num < MAXNUM[writeLen - 1]) numStr += " "
-
-  // pad with "0" chars
-  if (numStr.length < writeLen) {
-    numStr = (new Array(writeLen - numStr.length).join("0")) + numStr
-  }
-
-  if (numStr.length !== writeLen - 1) {
-    throw new Error("invalid length: " + JSON.stringify(numStr) + "\n" +
-                    "expected: "+writeLen)
-  }
-  block.write(numStr, off, writeLen, "utf8")
-  block[end - 1] = 0
-}
-
-function write256 (block, off, end, num) {
-  var buf = block.slice(off, end)
-  var positive = num >= 0
-  buf[0] = positive ? 0x80 : 0xFF
-
-  // get the number as a base-256 tuple
-  if (!positive) num *= -1
-  var tuple = []
-  do {
-    var n = num % 256
-    tuple.push(n)
-    num = (num - n) / 256
-  } while (num)
-
-  var bytes = tuple.length
-
-  var fill = buf.length - bytes
-  for (var i = 1; i < fill; i ++) {
-    buf[i] = positive ? 0 : 0xFF
-  }
-
-  // tuple is a base256 number, with [0] as the *least* significant byte
-  // if it's negative, then we need to flip all the bits once we hit the
-  // first non-zero bit.  The 2's-complement is (0x100 - n), and the 1's-
-  // complement is (0xFF - n).
-  var zero = true
-  for (i = bytes; i > 0; i --) {
-    var byte = tuple[bytes - i]
-    if (positive) buf[fill + i] = byte
-    else if (zero && byte === 0) buf[fill + i] = 0
-    else if (zero) {
-      zero = false
-      buf[fill + i] = 0x100 - byte
-    } else buf[fill + i] = 0xFF - byte
-  }
-}
-
-function writeText (block, off, end, str) {
-  // strings are written as utf8, then padded with \0
-  var strLen = Buffer.byteLength(str)
-    , writeLen = Math.min(strLen, end - off)
-    // non-ascii fields need extended headers
-    // long fields get truncated
-    , needExtended = strLen !== str.length || strLen > writeLen
-
-  // write the string, and null-pad
-  if (writeLen > 0) block.write(str, off, writeLen, "utf8")
-  for (var i = off + writeLen; i < end; i ++) block[i] = 0
-
-  return needExtended
-}
-
-function calcSum (block) {
-  block = block || this.block
-  assert(Buffer.isBuffer(block) && block.length === 512)
-
-  if (!block) throw new Error("Need block to checksum")
-
-  // now figure out what it would be if the cksum was "        "
-  var sum = 0
-    , start = fieldOffs[fields.cksum]
-    , end = fieldEnds[fields.cksum]
-
-  for (var i = 0; i < fieldOffs[fields.cksum]; i ++) {
-    sum += block[i]
-  }
-
-  for (var i = start; i < end; i ++) {
-    sum += space
-  }
-
-  for (var i = end; i < 512; i ++) {
-    sum += block[i]
-  }
-
-  return sum
-}
-
-
-function checkSum (block) {
-  var sum = calcSum.call(this, block)
-  block = block || this.block
-
-  var cksum = block.slice(fieldOffs[fields.cksum], fieldEnds[fields.cksum])
-  cksum = parseNumeric(cksum)
-
-  return cksum === sum
-}
-
-function decode (block) {
-  block = block || this.block
-  assert(Buffer.isBuffer(block) && block.length === 512)
-
-  this.block = block
-  this.cksumValid = this.checkSum()
-
-  var prefix = null
-
-  // slice off each field.
-  for (var f = 0; fields[f] !== null; f ++) {
-    var field = fields[f]
-      , val = block.slice(fieldOffs[f], fieldEnds[f])
-
-    switch (field) {
-      case "ustar":
-        // if not ustar, then everything after that is just padding.
-        if (val.toString() !== "ustar\0") {
-          this.ustar = false
-          return
-        } else {
-          // console.error("ustar:", val, val.toString())
-          this.ustar = val.toString()
-        }
-        break
-
-      // prefix is special, since it might signal the xstar header
-      case "prefix":
-        var atime = parseNumeric(val.slice(131, 131 + 12))
-          , ctime = parseNumeric(val.slice(131 + 12, 131 + 12 + 12))
-        if ((val[130] === 0 || val[130] === space) &&
-            typeof atime === "number" &&
-            typeof ctime === "number" &&
-            val[131 + 12] === space &&
-            val[131 + 12 + 12] === space) {
-          this.atime = atime
-          this.ctime = ctime
-          val = val.slice(0, 130)
-        }
-        prefix = val.toString("utf8").replace(/\0+$/, "")
-        // console.error("%% header reading prefix", prefix)
-        break
-
-      // all other fields are null-padding text
-      // or a number.
-      default:
-        if (numeric[field]) {
-          this[field] = parseNumeric(val)
-        } else {
-          this[field] = val.toString("utf8").replace(/\0+$/, "")
-        }
-        break
-    }
-  }
-
-  // if we got a prefix, then prepend it to the path.
-  if (prefix) {
-    this.path = prefix + "/" + this.path
-    // console.error("%% header got a prefix", this.path)
-  }
-}
-
-function parse256 (buf) {
-  // first byte MUST be either 80 or FF
-  // 80 for positive, FF for 2's comp
-  var positive
-  if (buf[0] === 0x80) positive = true
-  else if (buf[0] === 0xFF) positive = false
-  else return null
-
-  // build up a base-256 tuple from the least sig to the highest
-  var zero = false
-    , tuple = []
-  for (var i = buf.length - 1; i > 0; i --) {
-    var byte = buf[i]
-    if (positive) tuple.push(byte)
-    else if (zero && byte === 0) tuple.push(0)
-    else if (zero) {
-      zero = false
-      tuple.push(0x100 - byte)
-    } else tuple.push(0xFF - byte)
-  }
-
-  for (var sum = 0, i = 0, l = tuple.length; i < l; i ++) {
-    sum += tuple[i] * Math.pow(256, i)
-  }
-
-  return positive ? sum : -1 * sum
-}
-
-function parseNumeric (f) {
-  if (f[0] & 0x80) return parse256(f)
-
-  var str = f.toString("utf8").split("\0")[0].trim()
-    , res = parseInt(str, 8)
-
-  return isNaN(res) ? null : res
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/pack.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/pack.js
deleted file mode 100644
index 3ff14dd6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/pack.js
+++ /dev/null
@@ -1,231 +0,0 @@
-// pipe in an fstream, and it'll make a tarball.
-// key-value pair argument is global extended header props.
-
-module.exports = Pack
-
-var EntryWriter = require("./entry-writer.js")
-  , Stream = require("stream").Stream
-  , path = require("path")
-  , inherits = require("inherits")
-  , GlobalHeaderWriter = require("./global-header-writer.js")
-  , collect = require("fstream").collect
-  , eof = new Buffer(512)
-
-for (var i = 0; i < 512; i ++) eof[i] = 0
-
-inherits(Pack, Stream)
-
-function Pack (props) {
-  // console.error("-- p ctor")
-  var me = this
-  if (!(me instanceof Pack)) return new Pack(props)
-
-  if (props) me._noProprietary = props.noProprietary
-  else me._noProprietary = false
-
-  me._global = props
-
-  me.readable = true
-  me.writable = true
-  me._buffer = []
-  // console.error("-- -- set current to null in ctor")
-  me._currentEntry = null
-  me._processing = false
-
-  me._pipeRoot = null
-  me.on("pipe", function (src) {
-    if (src.root === me._pipeRoot) return
-    me._pipeRoot = src
-    src.on("end", function () {
-      me._pipeRoot = null
-    })
-    me.add(src)
-  })
-}
-
-Pack.prototype.addGlobal = function (props) {
-  // console.error("-- p addGlobal")
-  if (this._didGlobal) return
-  this._didGlobal = true
-
-  var me = this
-  GlobalHeaderWriter(props)
-    .on("data", function (c) {
-      me.emit("data", c)
-    })
-    .end()
-}
-
-Pack.prototype.add = function (stream) {
-  if (this._global && !this._didGlobal) this.addGlobal(this._global)
-
-  if (this._ended) return this.emit("error", new Error("add after end"))
-
-  collect(stream)
-  this._buffer.push(stream)
-  this._process()
-  this._needDrain = this._buffer.length > 0
-  return !this._needDrain
-}
-
-Pack.prototype.pause = function () {
-  this._paused = true
-  if (this._currentEntry) this._currentEntry.pause()
-  this.emit("pause")
-}
-
-Pack.prototype.resume = function () {
-  this._paused = false
-  if (this._currentEntry) this._currentEntry.resume()
-  this.emit("resume")
-  this._process()
-}
-
-Pack.prototype.end = function () {
-  this._ended = true
-  this._buffer.push(eof)
-  this._process()
-}
-
-Pack.prototype._process = function () {
-  var me = this
-  if (me._paused || me._processing) {
-    return
-  }
-
-  var entry = me._buffer.shift()
-
-  if (!entry) {
-    if (me._needDrain) {
-      me.emit("drain")
-    }
-    return
-  }
-
-  if (entry.ready === false) {
-    // console.error("-- entry is not ready", entry)
-    me._buffer.unshift(entry)
-    entry.on("ready", function () {
-      // console.error("-- -- ready!", entry)
-      me._process()
-    })
-    return
-  }
-
-  me._processing = true
-
-  if (entry === eof) {
-    // need 2 ending null blocks.
-    me.emit("data", eof)
-    me.emit("data", eof)
-    me.emit("end")
-    me.emit("close")
-    return
-  }
-
-  // Change the path to be relative to the root dir that was
-  // added to the tarball.
-  //
-  // XXX This should be more like how -C works, so you can
-  // explicitly set a root dir, and also explicitly set a pathname
-  // in the tarball to use.  That way we can skip a lot of extra
-  // work when resolving symlinks for bundled dependencies in npm.
-
-  var root = path.dirname((entry.root || entry).path)
-  var wprops = {}
-
-  Object.keys(entry.props || {}).forEach(function (k) {
-    wprops[k] = entry.props[k]
-  })
-
-  if (me._noProprietary) wprops.noProprietary = true
-
-  wprops.path = path.relative(root, entry.path || '')
-
-  // actually not a matter of opinion or taste.
-  if (process.platform === "win32") {
-    wprops.path = wprops.path.replace(/\\/g, "/")
-  }
-
-  if (!wprops.type)
-    wprops.type = 'Directory'
-
-  switch (wprops.type) {
-    // sockets not supported
-    case "Socket":
-      return
-
-    case "Directory":
-      wprops.path += "/"
-      wprops.size = 0
-      break
-
-    case "Link":
-      var lp = path.resolve(path.dirname(entry.path), entry.linkpath)
-      wprops.linkpath = path.relative(root, lp) || "."
-      wprops.size = 0
-      break
-
-    case "SymbolicLink":
-      var lp = path.resolve(path.dirname(entry.path), entry.linkpath)
-      wprops.linkpath = path.relative(path.dirname(entry.path), lp) || "."
-      wprops.size = 0
-      break
-  }
-
-  // console.error("-- new writer", wprops)
-  // if (!wprops.type) {
-  //   // console.error("-- no type?", entry.constructor.name, entry)
-  // }
-
-  // console.error("-- -- set current to new writer", wprops.path)
-  var writer = me._currentEntry = EntryWriter(wprops)
-
-  writer.parent = me
-
-  // writer.on("end", function () {
-  //   // console.error("-- -- writer end", writer.path)
-  // })
-
-  writer.on("data", function (c) {
-    me.emit("data", c)
-  })
-
-  writer.on("header", function () {
-    Buffer.prototype.toJSON = function () {
-      return this.toString().split(/\0/).join(".")
-    }
-    // console.error("-- -- writer header %j", writer.props)
-    if (writer.props.size === 0) nextEntry()
-  })
-  writer.on("close", nextEntry)
-
-  var ended = false
-  function nextEntry () {
-    if (ended) return
-    ended = true
-
-    // console.error("-- -- writer close", writer.path)
-    // console.error("-- -- set current to null", wprops.path)
-    me._currentEntry = null
-    me._processing = false
-    me._process()
-  }
-
-  writer.on("error", function (er) {
-    // console.error("-- -- writer error", writer.path)
-    me.emit("error", er)
-  })
-
-  // if it's the root, then there's no need to add its entries,
-  // or data, since they'll be added directly.
-  if (entry === me._pipeRoot) {
-    // console.error("-- is the root, don't auto-add")
-    writer.add = null
-  }
-
-  entry.pipe(writer)
-}
-
-Pack.prototype.destroy = function () {}
-Pack.prototype.write = function () {}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/parse.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/parse.js
deleted file mode 100644
index 884e73db..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/lib/parse.js
+++ /dev/null
@@ -1,270 +0,0 @@
-
-// A writable stream.
-// It emits "entry" events, which provide a readable stream that has
-// header info attached.
-
-module.exports = Parse.create = Parse
-
-var stream = require("stream")
-  , Stream = stream.Stream
-  , BlockStream = require("block-stream")
-  , tar = require("../tar.js")
-  , TarHeader = require("./header.js")
-  , Entry = require("./entry.js")
-  , BufferEntry = require("./buffer-entry.js")
-  , ExtendedHeader = require("./extended-header.js")
-  , assert = require("assert").ok
-  , inherits = require("inherits")
-  , fstream = require("fstream")
-
-// reading a tar is a lot like reading a directory
-// However, we're actually not going to run the ctor,
-// since it does a stat and various other stuff.
-// This inheritance gives us the pause/resume/pipe
-// behavior that is desired.
-inherits(Parse, fstream.Reader)
-
-function Parse () {
-  var me = this
-  if (!(me instanceof Parse)) return new Parse()
-
-  // doesn't apply fstream.Reader ctor?
-  // no, becasue we don't want to stat/etc, we just
-  // want to get the entry/add logic from .pipe()
-  Stream.apply(me)
-
-  me.writable = true
-  me.readable = true
-  me._stream = new BlockStream(512)
-  me.position = 0
-
-  me._stream.on("error", function (e) {
-    me.emit("error", e)
-  })
-
-  me._stream.on("data", function (c) {
-    me._process(c)
-  })
-
-  me._stream.on("end", function () {
-    me._streamEnd()
-  })
-
-  me._stream.on("drain", function () {
-    me.emit("drain")
-  })
-}
-
-// overridden in Extract class, since it needs to
-// wait for its DirWriter part to finish before
-// emitting "end"
-Parse.prototype._streamEnd = function () {
-  var me = this
-  if (!me._ended) me.error("unexpected eof")
-  me.emit("end")
-}
-
-// a tar reader is actually a filter, not just a readable stream.
-// So, you should pipe a tarball stream into it, and it needs these
-// write/end methods to do that.
-Parse.prototype.write = function (c) {
-  if (this._ended) {
-    // gnutar puts a LOT of nulls at the end.
-    // you can keep writing these things forever.
-    // Just ignore them.
-    for (var i = 0, l = c.length; i > l; i ++) {
-      if (c[i] !== 0) return this.error("write() after end()")
-    }
-    return
-  }
-  return this._stream.write(c)
-}
-
-Parse.prototype.end = function (c) {
-  this._ended = true
-  return this._stream.end(c)
-}
-
-// don't need to do anything, since we're just
-// proxying the data up from the _stream.
-// Just need to override the parent's "Not Implemented"
-// error-thrower.
-Parse.prototype._read = function () {}
-
-Parse.prototype._process = function (c) {
-  assert(c && c.length === 512, "block size should be 512")
-
-  // one of three cases.
-  // 1. A new header
-  // 2. A part of a file/extended header
-  // 3. One of two or more EOF null blocks
-
-  if (this._entry) {
-    var entry = this._entry
-    entry.write(c)
-    if (entry._remaining === 0) {
-      entry.end()
-      this._entry = null
-    }
-  } else {
-    // either zeroes or a header
-    var zero = true
-    for (var i = 0; i < 512 && zero; i ++) {
-      zero = c[i] === 0
-    }
-
-    // eof is *at least* 2 blocks of nulls, and then the end of the
-    // file.  you can put blocks of nulls between entries anywhere,
-    // so appending one tarball to another is technically valid.
-    // ending without the eof null blocks is not allowed, however.
-    if (zero) {
-      this._ended = this._eofStarted
-      this._eofStarted = true
-    } else {
-      this._ended = this._eofStarted = false
-      this._startEntry(c)
-    }
-
-  }
-
-  this.position += 512
-}
-
-// take a header chunk, start the right kind of entry.
-Parse.prototype._startEntry = function (c) {
-  var header = new TarHeader(c)
-    , self = this
-    , entry
-    , ev
-    , EntryType
-    , onend
-    , meta = false
-
-  if (null === header.size || !header.cksumValid) {
-    var e = new Error("invalid tar file")
-    e.header = header
-    e.tar_file_offset = this.position
-    e.tar_block = this.position / 512
-    this.emit("error", e)
-  }
-
-  switch (tar.types[header.type]) {
-    case "File":
-    case "OldFile":
-    case "Link":
-    case "SymbolicLink":
-    case "CharacterDevice":
-    case "BlockDevice":
-    case "Directory":
-    case "FIFO":
-    case "ContiguousFile":
-    case "GNUDumpDir":
-      // start a file.
-      // pass in any extended headers
-      // These ones consumers are typically most interested in.
-      EntryType = Entry
-      ev = "entry"
-      break
-
-    case "GlobalExtendedHeader":
-      // extended headers that apply to the rest of the tarball
-      EntryType = ExtendedHeader
-      onend = function () {
-        self._global = self._global || {}
-        Object.keys(entry.fields).forEach(function (k) {
-          self._global[k] = entry.fields[k]
-        })
-      }
-      ev = "globalExtendedHeader"
-      meta = true
-      break
-
-    case "ExtendedHeader":
-    case "OldExtendedHeader":
-      // extended headers that apply to the next entry
-      EntryType = ExtendedHeader
-      onend = function () {
-        self._extended = entry.fields
-      }
-      ev = "extendedHeader"
-      meta = true
-      break
-
-    case "NextFileHasLongLinkpath":
-      // set linkpath=<contents> in extended header
-      EntryType = BufferEntry
-      onend = function () {
-        self._extended = self._extended || {}
-        self._extended.linkpath = entry.body
-      }
-      ev = "longLinkpath"
-      meta = true
-      break
-
-    case "NextFileHasLongPath":
-    case "OldGnuLongPath":
-      // set path=<contents> in file-extended header
-      EntryType = BufferEntry
-      onend = function () {
-        self._extended = self._extended || {}
-        self._extended.path = entry.body
-      }
-      ev = "longPath"
-      meta = true
-      break
-
-    default:
-      // all the rest we skip, but still set the _entry
-      // member, so that we can skip over their data appropriately.
-      // emit an event to say that this is an ignored entry type?
-      EntryType = Entry
-      ev = "ignoredEntry"
-      break
-  }
-
-  var global, extended
-  if (meta) {
-    global = extended = null
-  } else {
-    var global = this._global
-    var extended = this._extended
-
-    // extendedHeader only applies to one entry, so once we start
-    // an entry, it's over.
-    this._extended = null
-  }
-  entry = new EntryType(header, extended, global)
-  entry.meta = meta
-
-  // only proxy data events of normal files.
-  if (!meta) {
-    entry.on("data", function (c) {
-      me.emit("data", c)
-    })
-  }
-
-  if (onend) entry.on("end", onend)
-
-  this._entry = entry
-  var me = this
-
-  entry.on("pause", function () {
-    me.pause()
-  })
-
-  entry.on("resume", function () {
-    me.resume()
-  })
-
-  if (this.listeners("*").length) {
-    this.emit("*", ev, entry)
-  }
-
-  this.emit(ev, entry)
-
-  // Zero-byte entry.  End immediately.
-  if (entry.props.size === 0) {
-    entry.end()
-    this._entry = null
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/LICENCE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/LICENCE
deleted file mode 100644
index 74489e2e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/LICENCE
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) Isaac Z. Schlueter
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/README.md
deleted file mode 100644
index c16e9c46..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# block-stream
-
-A stream of blocks.
-
-Write data into it, and it'll output data in buffer blocks the size you
-specify, padding with zeroes if necessary.
-
-```javascript
-var block = new BlockStream(512)
-fs.createReadStream("some-file").pipe(block)
-block.pipe(fs.createWriteStream("block-file"))
-```
-
-When `.end()` or `.flush()` is called, it'll pad the block with zeroes.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream-pause.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream-pause.js
deleted file mode 100644
index 9328844a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream-pause.js
+++ /dev/null
@@ -1,70 +0,0 @@
-var BlockStream = require("../block-stream.js")
-
-var blockSizes = [16, 25, 1024]
-  , writeSizes = [4, 8, 15, 16, 17, 64, 100]
-  , writeCounts = [1, 10, 100]
-  , tap = require("tap")
-
-writeCounts.forEach(function (writeCount) {
-blockSizes.forEach(function (blockSize) {
-writeSizes.forEach(function (writeSize) {
-  tap.test("writeSize=" + writeSize +
-           " blockSize="+blockSize +
-           " writeCount="+writeCount, function (t) {
-    var f = new BlockStream(blockSize, {nopad: true })
-
-    var actualChunks = 0
-    var actualBytes = 0
-    var timeouts = 0
-
-    f.on("data", function (c) {
-      timeouts ++
-
-      actualChunks ++
-      actualBytes += c.length
-
-      // make sure that no data gets corrupted, and basic sanity
-      var before = c.toString()
-      // simulate a slow write operation
-      f.pause()
-      setTimeout(function () {
-        timeouts --
-
-        var after = c.toString()
-        t.equal(after, before, "should not change data")
-
-        // now corrupt it, to find leaks.
-        for (var i = 0; i < c.length; i ++) {
-          c[i] = "x".charCodeAt(0)
-        }
-        f.resume()
-      }, 100)
-    })
-
-    f.on("end", function () {
-      // round up to the nearest block size
-      var expectChunks = Math.ceil(writeSize * writeCount  * 2 / blockSize)
-      var expectBytes = writeSize * writeCount * 2
-      t.equal(actualBytes, expectBytes,
-              "bytes=" + expectBytes + " writeSize=" + writeSize)
-      t.equal(actualChunks, expectChunks,
-              "chunks=" + expectChunks + " writeSize=" + writeSize)
-
-      // wait for all the timeout checks to finish, then end the test
-      setTimeout(function WAIT () {
-        if (timeouts > 0) return setTimeout(WAIT)
-        t.end()
-      }, 100)
-    })
-
-    for (var i = 0; i < writeCount; i ++) {
-      var a = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) a[j] = "a".charCodeAt(0)
-      var b = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) b[j] = "b".charCodeAt(0)
-      f.write(a)
-      f.write(b)
-    }
-    f.end()
-  })
-}) }) })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream.js
deleted file mode 100644
index 1141f3a8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/block-stream.js
+++ /dev/null
@@ -1,68 +0,0 @@
-var BlockStream = require("../block-stream.js")
-
-var blockSizes = [16, 25, 1024]
-  , writeSizes = [4, 8, 15, 16, 17, 64, 100]
-  , writeCounts = [1, 10, 100]
-  , tap = require("tap")
-
-writeCounts.forEach(function (writeCount) {
-blockSizes.forEach(function (blockSize) {
-writeSizes.forEach(function (writeSize) {
-  tap.test("writeSize=" + writeSize +
-           " blockSize="+blockSize +
-           " writeCount="+writeCount, function (t) {
-    var f = new BlockStream(blockSize, {nopad: true })
-
-    var actualChunks = 0
-    var actualBytes = 0
-    var timeouts = 0
-
-    f.on("data", function (c) {
-      timeouts ++
-
-      actualChunks ++
-      actualBytes += c.length
-
-      // make sure that no data gets corrupted, and basic sanity
-      var before = c.toString()
-      // simulate a slow write operation
-      setTimeout(function () {
-        timeouts --
-
-        var after = c.toString()
-        t.equal(after, before, "should not change data")
-
-        // now corrupt it, to find leaks.
-        for (var i = 0; i < c.length; i ++) {
-          c[i] = "x".charCodeAt(0)
-        }
-      }, 100)
-    })
-
-    f.on("end", function () {
-      // round up to the nearest block size
-      var expectChunks = Math.ceil(writeSize * writeCount  * 2 / blockSize)
-      var expectBytes = writeSize * writeCount * 2
-      t.equal(actualBytes, expectBytes,
-              "bytes=" + expectBytes + " writeSize=" + writeSize)
-      t.equal(actualChunks, expectChunks,
-              "chunks=" + expectChunks + " writeSize=" + writeSize)
-
-      // wait for all the timeout checks to finish, then end the test
-      setTimeout(function WAIT () {
-        if (timeouts > 0) return setTimeout(WAIT)
-        t.end()
-      }, 100)
-    })
-
-    for (var i = 0; i < writeCount; i ++) {
-      var a = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) a[j] = "a".charCodeAt(0)
-      var b = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) b[j] = "b".charCodeAt(0)
-      f.write(a)
-      f.write(b)
-    }
-    f.end()
-  })
-}) }) })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper-pause.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper-pause.js
deleted file mode 100644
index 93e4068e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper-pause.js
+++ /dev/null
@@ -1,70 +0,0 @@
-var BlockStream = require("dropper")
-
-var blockSizes = [16, 25, 1024]
-  , writeSizes = [4, 8, 15, 16, 17, 64, 100]
-  , writeCounts = [1, 10, 100]
-  , tap = require("tap")
-
-writeCounts.forEach(function (writeCount) {
-blockSizes.forEach(function (blockSize) {
-writeSizes.forEach(function (writeSize) {
-  tap.test("writeSize=" + writeSize +
-           " blockSize="+blockSize +
-           " writeCount="+writeCount, function (t) {
-    var f = new BlockStream(blockSize, {nopad: true })
-
-    var actualChunks = 0
-    var actualBytes = 0
-    var timeouts = 0
-
-    f.on("data", function (c) {
-      timeouts ++
-
-      actualChunks ++
-      actualBytes += c.length
-
-      // make sure that no data gets corrupted, and basic sanity
-      var before = c.toString()
-      // simulate a slow write operation
-      f.pause()
-      setTimeout(function () {
-        timeouts --
-
-        var after = c.toString()
-        t.equal(after, before, "should not change data")
-
-        // now corrupt it, to find leaks.
-        for (var i = 0; i < c.length; i ++) {
-          c[i] = "x".charCodeAt(0)
-        }
-        f.resume()
-      }, 100)
-    })
-
-    f.on("end", function () {
-      // round up to the nearest block size
-      var expectChunks = Math.ceil(writeSize * writeCount  * 2 / blockSize)
-      var expectBytes = writeSize * writeCount * 2
-      t.equal(actualBytes, expectBytes,
-              "bytes=" + expectBytes + " writeSize=" + writeSize)
-      t.equal(actualChunks, expectChunks,
-              "chunks=" + expectChunks + " writeSize=" + writeSize)
-
-      // wait for all the timeout checks to finish, then end the test
-      setTimeout(function WAIT () {
-        if (timeouts > 0) return setTimeout(WAIT)
-        t.end()
-      }, 100)
-    })
-
-    for (var i = 0; i < writeCount; i ++) {
-      var a = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) a[j] = "a".charCodeAt(0)
-      var b = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) b[j] = "b".charCodeAt(0)
-      f.write(a)
-      f.write(b)
-    }
-    f.end()
-  })
-}) }) })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper.js
deleted file mode 100644
index 55fa1330..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/bench/dropper.js
+++ /dev/null
@@ -1,68 +0,0 @@
-var BlockStream = require("dropper")
-
-var blockSizes = [16, 25, 1024]
-  , writeSizes = [4, 8, 15, 16, 17, 64, 100]
-  , writeCounts = [1, 10, 100]
-  , tap = require("tap")
-
-writeCounts.forEach(function (writeCount) {
-blockSizes.forEach(function (blockSize) {
-writeSizes.forEach(function (writeSize) {
-  tap.test("writeSize=" + writeSize +
-           " blockSize="+blockSize +
-           " writeCount="+writeCount, function (t) {
-    var f = new BlockStream(blockSize, {nopad: true })
-
-    var actualChunks = 0
-    var actualBytes = 0
-    var timeouts = 0
-
-    f.on("data", function (c) {
-      timeouts ++
-
-      actualChunks ++
-      actualBytes += c.length
-
-      // make sure that no data gets corrupted, and basic sanity
-      var before = c.toString()
-      // simulate a slow write operation
-      setTimeout(function () {
-        timeouts --
-
-        var after = c.toString()
-        t.equal(after, before, "should not change data")
-
-        // now corrupt it, to find leaks.
-        for (var i = 0; i < c.length; i ++) {
-          c[i] = "x".charCodeAt(0)
-        }
-      }, 100)
-    })
-
-    f.on("end", function () {
-      // round up to the nearest block size
-      var expectChunks = Math.ceil(writeSize * writeCount  * 2 / blockSize)
-      var expectBytes = writeSize * writeCount * 2
-      t.equal(actualBytes, expectBytes,
-              "bytes=" + expectBytes + " writeSize=" + writeSize)
-      t.equal(actualChunks, expectChunks,
-              "chunks=" + expectChunks + " writeSize=" + writeSize)
-
-      // wait for all the timeout checks to finish, then end the test
-      setTimeout(function WAIT () {
-        if (timeouts > 0) return setTimeout(WAIT)
-        t.end()
-      }, 100)
-    })
-
-    for (var i = 0; i < writeCount; i ++) {
-      var a = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) a[j] = "a".charCodeAt(0)
-      var b = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) b[j] = "b".charCodeAt(0)
-      f.write(a)
-      f.write(b)
-    }
-    f.end()
-  })
-}) }) })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/block-stream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/block-stream.js
deleted file mode 100644
index 008de035..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/block-stream.js
+++ /dev/null
@@ -1,209 +0,0 @@
-// write data to it, and it'll emit data in 512 byte blocks.
-// if you .end() or .flush(), it'll emit whatever it's got,
-// padded with nulls to 512 bytes.
-
-module.exports = BlockStream
-
-var Stream = require("stream").Stream
-  , inherits = require("inherits")
-  , assert = require("assert").ok
-  , debug = process.env.DEBUG ? console.error : function () {}
-
-function BlockStream (size, opt) {
-  this.writable = this.readable = true
-  this._opt = opt || {}
-  this._chunkSize = size || 512
-  this._offset = 0
-  this._buffer = []
-  this._bufferLength = 0
-  if (this._opt.nopad) this._zeroes = false
-  else {
-    this._zeroes = new Buffer(this._chunkSize)
-    for (var i = 0; i < this._chunkSize; i ++) {
-      this._zeroes[i] = 0
-    }
-  }
-}
-
-inherits(BlockStream, Stream)
-
-BlockStream.prototype.write = function (c) {
-  // debug("   BS write", c)
-  if (this._ended) throw new Error("BlockStream: write after end")
-  if (c && !Buffer.isBuffer(c)) c = new Buffer(c + "")
-  if (c.length) {
-    this._buffer.push(c)
-    this._bufferLength += c.length
-  }
-  // debug("pushed onto buffer", this._bufferLength)
-  if (this._bufferLength >= this._chunkSize) {
-    if (this._paused) {
-      // debug("   BS paused, return false, need drain")
-      this._needDrain = true
-      return false
-    }
-    this._emitChunk()
-  }
-  return true
-}
-
-BlockStream.prototype.pause = function () {
-  // debug("   BS pausing")
-  this._paused = true
-}
-
-BlockStream.prototype.resume = function () {
-  // debug("   BS resume")
-  this._paused = false
-  return this._emitChunk()
-}
-
-BlockStream.prototype.end = function (chunk) {
-  // debug("end", chunk)
-  if (typeof chunk === "function") cb = chunk, chunk = null
-  if (chunk) this.write(chunk)
-  this._ended = true
-  this.flush()
-}
-
-BlockStream.prototype.flush = function () {
-  this._emitChunk(true)
-}
-
-BlockStream.prototype._emitChunk = function (flush) {
-  // debug("emitChunk flush=%j emitting=%j paused=%j", flush, this._emitting, this._paused)
-
-  // emit a <chunkSize> chunk
-  if (flush && this._zeroes) {
-    // debug("    BS push zeroes", this._bufferLength)
-    // push a chunk of zeroes
-    var padBytes = (this._bufferLength % this._chunkSize)
-    if (padBytes !== 0) padBytes = this._chunkSize - padBytes
-    if (padBytes > 0) {
-      // debug("padBytes", padBytes, this._zeroes.slice(0, padBytes))
-      this._buffer.push(this._zeroes.slice(0, padBytes))
-      this._bufferLength += padBytes
-      // debug(this._buffer[this._buffer.length - 1].length, this._bufferLength)
-    }
-  }
-
-  if (this._emitting || this._paused) return
-  this._emitting = true
-
-  // debug("    BS entering loops")
-  var bufferIndex = 0
-  while (this._bufferLength >= this._chunkSize &&
-         (flush || !this._paused)) {
-    // debug("     BS data emission loop", this._bufferLength)
-
-    var out
-      , outOffset = 0
-      , outHas = this._chunkSize
-
-    while (outHas > 0 && (flush || !this._paused) ) {
-      // debug("    BS data inner emit loop", this._bufferLength)
-      var cur = this._buffer[bufferIndex]
-        , curHas = cur.length - this._offset
-      // debug("cur=", cur)
-      // debug("curHas=%j", curHas)
-      // If it's not big enough to fill the whole thing, then we'll need
-      // to copy multiple buffers into one.  However, if it is big enough,
-      // then just slice out the part we want, to save unnecessary copying.
-      // Also, need to copy if we've already done some copying, since buffers
-      // can't be joined like cons strings.
-      if (out || curHas < outHas) {
-        out = out || new Buffer(this._chunkSize)
-        cur.copy(out, outOffset,
-                 this._offset, this._offset + Math.min(curHas, outHas))
-      } else if (cur.length === outHas && this._offset === 0) {
-        // shortcut -- cur is exactly long enough, and no offset.
-        out = cur
-      } else {
-        // slice out the piece of cur that we need.
-        out = cur.slice(this._offset, this._offset + outHas)
-      }
-
-      if (curHas > outHas) {
-        // means that the current buffer couldn't be completely output
-        // update this._offset to reflect how much WAS written
-        this._offset += outHas
-        outHas = 0
-      } else {
-        // output the entire current chunk.
-        // toss it away
-        outHas -= curHas
-        outOffset += curHas
-        bufferIndex ++
-        this._offset = 0
-      }
-    }
-
-    this._bufferLength -= this._chunkSize
-    assert(out.length === this._chunkSize)
-    // debug("emitting data", out)
-    // debug("   BS emitting, paused=%j", this._paused, this._bufferLength)
-    this.emit("data", out)
-    out = null
-  }
-  // debug("    BS out of loops", this._bufferLength)
-
-  // whatever is left, it's not enough to fill up a block, or we're paused
-  this._buffer = this._buffer.slice(bufferIndex)
-  if (this._paused) {
-    // debug("    BS paused, leaving", this._bufferLength)
-    this._needsDrain = true
-    this._emitting = false
-    return
-  }
-
-  // if flushing, and not using null-padding, then need to emit the last
-  // chunk(s) sitting in the queue.  We know that it's not enough to
-  // fill up a whole block, because otherwise it would have been emitted
-  // above, but there may be some offset.
-  var l = this._buffer.length
-  if (flush && !this._zeroes && l) {
-    if (l === 1) {
-      if (this._offset) {
-        this.emit("data", this._buffer[0].slice(this._offset))
-      } else {
-        this.emit("data", this._buffer[0])
-      }
-    } else {
-      var outHas = this._bufferLength
-        , out = new Buffer(outHas)
-        , outOffset = 0
-      for (var i = 0; i < l; i ++) {
-        var cur = this._buffer[i]
-          , curHas = cur.length - this._offset
-        cur.copy(out, outOffset, this._offset)
-        this._offset = 0
-        outOffset += curHas
-        this._bufferLength -= curHas
-      }
-      this.emit("data", out)
-    }
-    // truncate
-    this._buffer.length = 0
-    this._bufferLength = 0
-    this._offset = 0
-  }
-
-  // now either drained or ended
-  // debug("either draining, or ended", this._bufferLength, this._ended)
-  // means that we've flushed out all that we can so far.
-  if (this._needDrain) {
-    // debug("emitting drain", this._bufferLength)
-    this._needDrain = false
-    this.emit("drain")
-  }
-
-  if ((this._bufferLength === 0) && this._ended && !this._endEmitted) {
-    // debug("emitting end", this._bufferLength)
-    this._endEmitted = true
-    this.emit("end")
-  }
-
-  this._emitting = false
-
-  // debug("    BS no longer emitting", flush, this._paused, this._emitting, this._bufferLength, this._chunkSize)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/package.json
deleted file mode 100644
index b92954ea..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "block-stream",
-  "description": "a stream of blocks",
-  "version": "0.0.7",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/block-stream.git"
-  },
-  "engines": {
-    "node": "0.4 || >=0.5.8"
-  },
-  "main": "block-stream.js",
-  "dependencies": {
-    "inherits": "~2.0.0"
-  },
-  "devDependencies": {
-    "tap": "0.x"
-  },
-  "scripts": {
-    "test": "tap test/"
-  },
-  "license": "BSD",
-  "readme": "# block-stream\n\nA stream of blocks.\n\nWrite data into it, and it'll output data in buffer blocks the size you\nspecify, padding with zeroes if necessary.\n\n```javascript\nvar block = new BlockStream(512)\nfs.createReadStream(\"some-file\").pipe(block)\nblock.pipe(fs.createWriteStream(\"block-file\"))\n```\n\nWhen `.end()` or `.flush()` is called, it'll pad the block with zeroes.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/block-stream/issues"
-  },
-  "homepage": "https://github.com/isaacs/block-stream",
-  "_id": "block-stream@0.0.7",
-  "_shasum": "9088ab5ae1e861f4d81b176b4a8046080703deed",
-  "_from": "block-stream@*",
-  "_resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/basic.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/basic.js
deleted file mode 100644
index b4b93051..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/basic.js
+++ /dev/null
@@ -1,27 +0,0 @@
-var tap = require("tap")
-  , BlockStream = require("../block-stream.js")
-
-tap.test("basic test", function (t) {
-  var b = new BlockStream(16)
-  var fs = require("fs")
-  var fstr = fs.createReadStream(__filename, {encoding: "utf8"})
-  fstr.pipe(b)
-
-  var stat
-  t.doesNotThrow(function () {
-    stat = fs.statSync(__filename)
-  }, "stat should not throw")
-
-  var totalBytes = 0
-  b.on("data", function (c) {
-    t.equal(c.length, 16, "chunks should be 16 bytes long")
-    t.type(c, Buffer, "chunks should be buffer objects")
-    totalBytes += c.length
-  })
-  b.on("end", function () {
-    var expectedBytes = stat.size + (16 - stat.size % 16)
-    t.equal(totalBytes, expectedBytes, "Should be multiple of 16")
-    t.end()
-  })
-
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad-thorough.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad-thorough.js
deleted file mode 100644
index 7a8de88b..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad-thorough.js
+++ /dev/null
@@ -1,68 +0,0 @@
-var BlockStream = require("../block-stream.js")
-
-var blockSizes = [16]//, 25]//, 1024]
-  , writeSizes = [4, 15, 16, 17, 64 ]//, 64, 100]
-  , writeCounts = [1, 10]//, 100]
-  , tap = require("tap")
-
-writeCounts.forEach(function (writeCount) {
-blockSizes.forEach(function (blockSize) {
-writeSizes.forEach(function (writeSize) {
-  tap.test("writeSize=" + writeSize +
-           " blockSize="+blockSize +
-           " writeCount="+writeCount, function (t) {
-    var f = new BlockStream(blockSize, {nopad: true })
-
-    var actualChunks = 0
-    var actualBytes = 0
-    var timeouts = 0
-
-    f.on("data", function (c) {
-      timeouts ++
-
-      actualChunks ++
-      actualBytes += c.length
-
-      // make sure that no data gets corrupted, and basic sanity
-      var before = c.toString()
-      // simulate a slow write operation
-      setTimeout(function () {
-        timeouts --
-
-        var after = c.toString()
-        t.equal(after, before, "should not change data")
-
-        // now corrupt it, to find leaks.
-        for (var i = 0; i < c.length; i ++) {
-          c[i] = "x".charCodeAt(0)
-        }
-      }, 100)
-    })
-
-    f.on("end", function () {
-      // round up to the nearest block size
-      var expectChunks = Math.ceil(writeSize * writeCount  * 2 / blockSize)
-      var expectBytes = writeSize * writeCount * 2
-      t.equal(actualBytes, expectBytes,
-              "bytes=" + expectBytes + " writeSize=" + writeSize)
-      t.equal(actualChunks, expectChunks,
-              "chunks=" + expectChunks + " writeSize=" + writeSize)
-
-      // wait for all the timeout checks to finish, then end the test
-      setTimeout(function WAIT () {
-        if (timeouts > 0) return setTimeout(WAIT)
-        t.end()
-      }, 100)
-    })
-
-    for (var i = 0; i < writeCount; i ++) {
-      var a = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) a[j] = "a".charCodeAt(0)
-      var b = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) b[j] = "b".charCodeAt(0)
-      f.write(a)
-      f.write(b)
-    }
-    f.end()
-  })
-}) }) })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad.js
deleted file mode 100644
index 6d38429f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/nopad.js
+++ /dev/null
@@ -1,57 +0,0 @@
-var BlockStream = require("../")
-var tap = require("tap")
-
-
-tap.test("don't pad, small writes", function (t) {
-  var f = new BlockStream(16, { nopad: true })
-  t.plan(1)
-
-  f.on("data", function (c) {
-    t.equal(c.toString(), "abc", "should get 'abc'")
-  })
-
-  f.on("end", function () { t.end() })
-
-  f.write(new Buffer("a"))
-  f.write(new Buffer("b"))
-  f.write(new Buffer("c"))
-  f.end()
-})
-
-tap.test("don't pad, exact write", function (t) {
-  var f = new BlockStream(16, { nopad: true })
-  t.plan(1)
-
-  var first = true
-  f.on("data", function (c) {
-    if (first) {
-      first = false
-      t.equal(c.toString(), "abcdefghijklmnop", "first chunk")
-    } else {
-      t.fail("should only get one")
-    }
-  })
-
-  f.on("end", function () { t.end() })
-
-  f.end(new Buffer("abcdefghijklmnop"))
-})
-
-tap.test("don't pad, big write", function (t) {
-  var f = new BlockStream(16, { nopad: true })
-  t.plan(2)
-
-  var first = true
-  f.on("data", function (c) {
-    if (first) {
-      first = false
-      t.equal(c.toString(), "abcdefghijklmnop", "first chunk")
-    } else {
-      t.equal(c.toString(), "q")
-    }
-  })
-
-  f.on("end", function () { t.end() })
-
-  f.end(new Buffer("abcdefghijklmnopq"))
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/pause-resume.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/pause-resume.js
deleted file mode 100644
index 64d0d091..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/pause-resume.js
+++ /dev/null
@@ -1,73 +0,0 @@
-var BlockStream = require("../block-stream.js")
-
-var blockSizes = [16]
-  , writeSizes = [15, 16, 17]
-  , writeCounts = [1, 10]//, 100]
-  , tap = require("tap")
-
-writeCounts.forEach(function (writeCount) {
-blockSizes.forEach(function (blockSize) {
-writeSizes.forEach(function (writeSize) {
-  tap.test("writeSize=" + writeSize +
-           " blockSize="+blockSize +
-           " writeCount="+writeCount, function (t) {
-    var f = new BlockStream(blockSize)
-
-    var actualChunks = 0
-    var actualBytes = 0
-    var timeouts = 0
-    var paused = false
-
-    f.on("data", function (c) {
-      timeouts ++
-      t.notOk(paused, "should not be paused when emitting data")
-
-      actualChunks ++
-      actualBytes += c.length
-
-      // make sure that no data gets corrupted, and basic sanity
-      var before = c.toString()
-      // simulate a slow write operation
-      paused = true
-      f.pause()
-      process.nextTick(function () {
-        var after = c.toString()
-        t.equal(after, before, "should not change data")
-
-        // now corrupt it, to find leaks.
-        for (var i = 0; i < c.length; i ++) {
-          c[i] = "x".charCodeAt(0)
-        }
-        paused = false
-        f.resume()
-        timeouts --
-      })
-    })
-
-    f.on("end", function () {
-      // round up to the nearest block size
-      var expectChunks = Math.ceil(writeSize * writeCount  * 2 / blockSize)
-      var expectBytes = expectChunks * blockSize
-      t.equal(actualBytes, expectBytes,
-              "bytes=" + expectBytes + " writeSize=" + writeSize)
-      t.equal(actualChunks, expectChunks,
-              "chunks=" + expectChunks + " writeSize=" + writeSize)
-
-      // wait for all the timeout checks to finish, then end the test
-      setTimeout(function WAIT () {
-        if (timeouts > 0) return setTimeout(WAIT)
-        t.end()
-      }, 200)
-    })
-
-    for (var i = 0; i < writeCount; i ++) {
-      var a = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) a[j] = "a".charCodeAt(0)
-      var b = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) b[j] = "b".charCodeAt(0)
-      f.write(a)
-      f.write(b)
-    }
-    f.end()
-  })
-}) }) })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/thorough.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/thorough.js
deleted file mode 100644
index 1cc9ea08..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/thorough.js
+++ /dev/null
@@ -1,68 +0,0 @@
-var BlockStream = require("../block-stream.js")
-
-var blockSizes = [16]//, 25]//, 1024]
-  , writeSizes = [4, 15, 16, 17, 64 ]//, 64, 100]
-  , writeCounts = [1, 10]//, 100]
-  , tap = require("tap")
-
-writeCounts.forEach(function (writeCount) {
-blockSizes.forEach(function (blockSize) {
-writeSizes.forEach(function (writeSize) {
-  tap.test("writeSize=" + writeSize +
-           " blockSize="+blockSize +
-           " writeCount="+writeCount, function (t) {
-    var f = new BlockStream(blockSize)
-
-    var actualChunks = 0
-    var actualBytes = 0
-    var timeouts = 0
-
-    f.on("data", function (c) {
-      timeouts ++
-
-      actualChunks ++
-      actualBytes += c.length
-
-      // make sure that no data gets corrupted, and basic sanity
-      var before = c.toString()
-      // simulate a slow write operation
-      setTimeout(function () {
-        timeouts --
-
-        var after = c.toString()
-        t.equal(after, before, "should not change data")
-
-        // now corrupt it, to find leaks.
-        for (var i = 0; i < c.length; i ++) {
-          c[i] = "x".charCodeAt(0)
-        }
-      }, 100)
-    })
-
-    f.on("end", function () {
-      // round up to the nearest block size
-      var expectChunks = Math.ceil(writeSize * writeCount  * 2 / blockSize)
-      var expectBytes = expectChunks * blockSize
-      t.equal(actualBytes, expectBytes,
-              "bytes=" + expectBytes + " writeSize=" + writeSize)
-      t.equal(actualChunks, expectChunks,
-              "chunks=" + expectChunks + " writeSize=" + writeSize)
-
-      // wait for all the timeout checks to finish, then end the test
-      setTimeout(function WAIT () {
-        if (timeouts > 0) return setTimeout(WAIT)
-        t.end()
-      }, 100)
-    })
-
-    for (var i = 0; i < writeCount; i ++) {
-      var a = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) a[j] = "a".charCodeAt(0)
-      var b = new Buffer(writeSize);
-      for (var j = 0; j < writeSize; j ++) b[j] = "b".charCodeAt(0)
-      f.write(a)
-      f.write(b)
-    }
-    f.end()
-  })
-}) }) })
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/two-stream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/two-stream.js
deleted file mode 100644
index c6db79a4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/block-stream/test/two-stream.js
+++ /dev/null
@@ -1,59 +0,0 @@
-var log = console.log,
-    assert = require( 'assert' ),
-    BlockStream = require("../block-stream.js"),
-    isize = 0, tsize = 0, fsize = 0, psize = 0, i = 0,
-    filter = null, paper = null, stack = null,
-
-// a source data buffer
-tsize = 1 * 1024; // <- 1K
-stack = new Buffer( tsize );
-for ( ; i < tsize; i++) stack[i] = "x".charCodeAt(0);
-
-isize = 1 * 1024; // <- initial packet size with 4K no bug!
-fsize = 2 * 1024 ; // <- first block-stream size 
-psize = Math.ceil( isize / 6 ); // <- second block-stream size
-
-fexpected = Math.ceil( tsize / fsize ); // <- packets expected for first 
-pexpected = Math.ceil( tsize / psize ); // <- packets expected for second
-
-
-filter = new BlockStream( fsize, { nopad : true } );
-paper = new BlockStream( psize, { nopad : true } );
-
-
-var fcounter = 0;
-filter.on( 'data', function (c) {
-  // verify that they're not null-padded
-  for (var i = 0; i < c.length; i ++) {
-    assert.strictEqual(c[i], "x".charCodeAt(0))
-  }
-    ++fcounter;
-} );
-
-var pcounter = 0;
-paper.on( 'data', function (c) {
-  // verify that they're not null-padded
-  for (var i = 0; i < c.length; i ++) {
-    assert.strictEqual(c[i], "x".charCodeAt(0))
-  }
-    ++pcounter;
-} );
-
-filter.pipe( paper );
-
-filter.on( 'end', function () {
-  log("fcounter: %s === %s", fcounter, fexpected)
-    assert.strictEqual( fcounter, fexpected );
-} );
-
-paper.on( 'end', function () {
-  log("pcounter: %s === %s", pcounter, pexpected);
-    assert.strictEqual( pcounter, pexpected );
-} );
-
-
-for ( i = 0, j = isize; j <= tsize; j += isize ) {
-    filter.write( stack.slice( j - isize, j ) );
-}
-
-filter.end();
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.npmignore
deleted file mode 100644
index 494272a8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.npmignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.*.swp
-node_modules/
-examples/deep-copy/
-examples/path/
-examples/filter-copy/
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.travis.yml
deleted file mode 100644
index 2d26206d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/.travis.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/README.md
deleted file mode 100644
index 9d8cb77e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/README.md
+++ /dev/null
@@ -1,76 +0,0 @@
-Like FS streams, but with stat on them, and supporting directories and
-symbolic links, as well as normal files.  Also, you can use this to set
-the stats on a file, even if you don't change its contents, or to create
-a symlink, etc.
-
-So, for example, you can "write" a directory, and it'll call `mkdir`.  You
-can specify a uid and gid, and it'll call `chown`.  You can specify a
-`mtime` and `atime`, and it'll call `utimes`.  You can call it a symlink
-and provide a `linkpath` and it'll call `symlink`.
-
-Note that it won't automatically resolve symbolic links.  So, if you
-call `fstream.Reader('/some/symlink')` then you'll get an object
-that stats and then ends immediately (since it has no data).  To follow
-symbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:
-true })`.
-
-There are various checks to make sure that the bytes emitted are the
-same as the intended size, if the size is set.
-
-## Examples
-
-```javascript
-fstream
-  .Writer({ path: "path/to/file"
-          , mode: 0755
-          , size: 6
-          })
-  .write("hello\n")
-  .end()
-```
-
-This will create the directories if they're missing, and then write
-`hello\n` into the file, chmod it to 0755, and assert that 6 bytes have
-been written when it's done.
-
-```javascript
-fstream
-  .Writer({ path: "path/to/file"
-          , mode: 0755
-          , size: 6
-          , flags: "a"
-          })
-  .write("hello\n")
-  .end()
-```
-
-You can pass flags in, if you want to append to a file.
-
-```javascript
-fstream
-  .Writer({ path: "path/to/symlink"
-          , linkpath: "./file"
-          , SymbolicLink: true
-          , mode: "0755" // octal strings supported
-          })
-  .end()
-```
-
-If isSymbolicLink is a function, it'll be called, and if it returns
-true, then it'll treat it as a symlink.  If it's not a function, then
-any truish value will make a symlink, or you can set `type:
-'SymbolicLink'`, which does the same thing.
-
-Note that the linkpath is relative to the symbolic link location, not
-the parent dir or cwd.
-
-```javascript
-fstream
-  .Reader("path/to/dir")
-  .pipe(fstream.Writer("path/to/other/dir"))
-```
-
-This will do like `cp -Rp path/to/dir path/to/other/dir`.  If the other
-dir exists and isn't a directory, then it'll emit an error.  It'll also
-set the uid, gid, mode, etc. to be identical.  In this way, it's more
-like `rsync -a` than simply a copy.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/filter-pipe.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/filter-pipe.js
deleted file mode 100644
index c6b55b3e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/filter-pipe.js
+++ /dev/null
@@ -1,131 +0,0 @@
-var fstream = require("../fstream.js")
-var path = require("path")
-
-var r = fstream.Reader({ path: path.dirname(__dirname)
-                       , filter: function () {
-                           return !this.basename.match(/^\./) &&
-                                  !this.basename.match(/^node_modules$/)
-                                  !this.basename.match(/^deep-copy$/)
-                                  !this.basename.match(/^filter-copy$/)
-                         }
-                       })
-
-// this writer will only write directories
-var w = fstream.Writer({ path: path.resolve(__dirname, "filter-copy")
-                       , type: "Directory"
-                       , filter: function () {
-                           return this.type === "Directory"
-                         }
-                       })
-
-var indent = ""
-var escape = {}
-
-r.on("entry", appears)
-r.on("ready", function () {
-  console.error("ready to begin!", r.path)
-})
-
-function appears (entry) {
-  console.error(indent + "a %s appears!", entry.type, entry.basename, typeof entry.basename)
-  if (foggy) {
-    console.error("FOGGY!")
-    var p = entry
-    do {
-      console.error(p.depth, p.path, p._paused)
-    } while (p = p.parent)
-
-    throw new Error("\033[mshould not have entries while foggy")
-  }
-  indent += "\t"
-  entry.on("data", missile(entry))
-  entry.on("end", runaway(entry))
-  entry.on("entry", appears)
-}
-
-var foggy
-function missile (entry) {
-  if (entry.type === "Directory") {
-    var ended = false
-    entry.once("end", function () { ended = true })
-    return function (c) {
-      // throw in some pathological pause()/resume() behavior
-      // just for extra fun.
-      process.nextTick(function () {
-        if (!foggy && !ended) { // && Math.random() < 0.3) {
-          console.error(indent +"%s casts a spell", entry.basename)
-          console.error("\na slowing fog comes over the battlefield...\n\033[32m")
-          entry.pause()
-          entry.once("resume", liftFog)
-          foggy = setTimeout(liftFog, 1000)
-
-          function liftFog (who) {
-            if (!foggy) return
-            if (who) {
-              console.error("%s breaks the spell!", who && who.path)
-            } else {
-              console.error("the spell expires!")
-            }
-            console.error("\033[mthe fog lifts!\n")
-            clearTimeout(foggy)
-            foggy = null
-            if (entry._paused) entry.resume()
-          }
-
-        }
-      })
-    }
-  }
-
-  return function (c) {
-    var e = Math.random() < 0.5
-    console.error(indent + "%s %s for %d damage!",
-                entry.basename,
-                e ? "is struck" : "fires a chunk",
-                c.length)
-  }
-}
-
-function runaway (entry) { return function () {
-  var e = Math.random() < 0.5
-  console.error(indent + "%s %s",
-                entry.basename,
-                e ? "turns to flee" : "is vanquished!")
-  indent = indent.slice(0, -1)
-}}
-
-
-w.on("entry", attacks)
-//w.on("ready", function () { attacks(w) })
-function attacks (entry) {
-  console.error(indent + "%s %s!", entry.basename,
-              entry.type === "Directory" ? "calls for backup" : "attacks")
-  entry.on("entry", attacks)
-}
-
-ended = false
-var i = 1
-r.on("end", function () {
-  if (foggy) clearTimeout(foggy)
-  console.error("\033[mIT'S OVER!!")
-  console.error("A WINNAR IS YOU!")
-
-  console.log("ok " + (i ++) + " A WINNAR IS YOU")
-  ended = true
-  // now go through and verify that everything in there is a dir.
-  var p = path.resolve(__dirname, "filter-copy")
-  var checker = fstream.Reader({ path: p })
-  checker.checker = true
-  checker.on("child", function (e) {
-    var ok = e.type === "Directory"
-    console.log((ok ? "" : "not ") + "ok " + (i ++) +
-                " should be a dir: " +
-                e.path.substr(checker.path.length + 1))
-  })
-})
-
-process.on("exit", function () {
-  console.log((ended ? "" : "not ") + "ok " + (i ++) + " ended")
-})
-
-r.pipe(w)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/pipe.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/pipe.js
deleted file mode 100644
index 648ec849..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/pipe.js
+++ /dev/null
@@ -1,115 +0,0 @@
-var fstream = require("../fstream.js")
-var path = require("path")
-
-var r = fstream.Reader({ path: path.dirname(__dirname)
-                       , filter: function () {
-                           return !this.basename.match(/^\./) &&
-                                  !this.basename.match(/^node_modules$/)
-                                  !this.basename.match(/^deep-copy$/)
-                         }
-                       })
-
-var w = fstream.Writer({ path: path.resolve(__dirname, "deep-copy")
-                       , type: "Directory"
-                       })
-
-var indent = ""
-var escape = {}
-
-r.on("entry", appears)
-r.on("ready", function () {
-  console.error("ready to begin!", r.path)
-})
-
-function appears (entry) {
-  console.error(indent + "a %s appears!", entry.type, entry.basename, typeof entry.basename, entry)
-  if (foggy) {
-    console.error("FOGGY!")
-    var p = entry
-    do {
-      console.error(p.depth, p.path, p._paused)
-    } while (p = p.parent)
-
-    throw new Error("\033[mshould not have entries while foggy")
-  }
-  indent += "\t"
-  entry.on("data", missile(entry))
-  entry.on("end", runaway(entry))
-  entry.on("entry", appears)
-}
-
-var foggy
-function missile (entry) {
-  if (entry.type === "Directory") {
-    var ended = false
-    entry.once("end", function () { ended = true })
-    return function (c) {
-      // throw in some pathological pause()/resume() behavior
-      // just for extra fun.
-      process.nextTick(function () {
-        if (!foggy && !ended) { // && Math.random() < 0.3) {
-          console.error(indent +"%s casts a spell", entry.basename)
-          console.error("\na slowing fog comes over the battlefield...\n\033[32m")
-          entry.pause()
-          entry.once("resume", liftFog)
-          foggy = setTimeout(liftFog, 10)
-
-          function liftFog (who) {
-            if (!foggy) return
-            if (who) {
-              console.error("%s breaks the spell!", who && who.path)
-            } else {
-              console.error("the spell expires!")
-            }
-            console.error("\033[mthe fog lifts!\n")
-            clearTimeout(foggy)
-            foggy = null
-            if (entry._paused) entry.resume()
-          }
-
-        }
-      })
-    }
-  }
-
-  return function (c) {
-    var e = Math.random() < 0.5
-    console.error(indent + "%s %s for %d damage!",
-                entry.basename,
-                e ? "is struck" : "fires a chunk",
-                c.length)
-  }
-}
-
-function runaway (entry) { return function () {
-  var e = Math.random() < 0.5
-  console.error(indent + "%s %s",
-                entry.basename,
-                e ? "turns to flee" : "is vanquished!")
-  indent = indent.slice(0, -1)
-}}
-
-
-w.on("entry", attacks)
-//w.on("ready", function () { attacks(w) })
-function attacks (entry) {
-  console.error(indent + "%s %s!", entry.basename,
-              entry.type === "Directory" ? "calls for backup" : "attacks")
-  entry.on("entry", attacks)
-}
-
-ended = false
-r.on("end", function () {
-  if (foggy) clearTimeout(foggy)
-  console.error("\033[mIT'S OVER!!")
-  console.error("A WINNAR IS YOU!")
-
-  console.log("ok 1 A WINNAR IS YOU")
-  ended = true
-})
-
-process.on("exit", function () {
-  console.log((ended ? "" : "not ") + "ok 2 ended")
-})
-
-r.pipe(w)
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/reader.js
deleted file mode 100644
index 9aa1a953..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/reader.js
+++ /dev/null
@@ -1,54 +0,0 @@
-var fstream = require("../fstream.js")
-var tap = require("tap")
-var fs = require("fs")
-var path = require("path")
-var children = -1
-var dir = path.dirname(__dirname)
-
-var gotReady = false
-var ended = false
-
-tap.test("reader test", function (t) {
-
-  var r = fstream.Reader({ path: dir
-                         , filter: function () {
-                             // return this.parent === r
-                             return this.parent === r || this === r
-                           }
-                         })
-
-  r.on("ready", function () {
-    gotReady = true
-    children = fs.readdirSync(dir).length
-    console.error("Setting expected children to "+children)
-    t.equal(r.type, "Directory", "should be a directory")
-  })
-
-  r.on("entry", function (entry) {
-    children --
-    if (!gotReady) {
-      t.fail("children before ready!")
-    }
-    t.equal(entry.dirname, r.path, "basename is parent dir")
-  })
-
-  r.on("error", function (er) {
-    t.fail(er)
-    t.end()
-    process.exit(1)
-  })
-
-  r.on("end", function () {
-    t.equal(children, 0, "should have seen all children")
-    ended = true
-  })
-
-  var closed = false
-  r.on("close", function () {
-    t.ok(ended, "saw end before close")
-    t.notOk(closed, "close should only happen once")
-    closed = true
-    t.end()
-  })
-
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/symlink-write.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/symlink-write.js
deleted file mode 100644
index d7816d24..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/examples/symlink-write.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var fstream = require("../fstream.js")
-  , closed = false
-
-fstream
-  .Writer({ path: "path/to/symlink"
-          , linkpath: "./file"
-          , isSymbolicLink: true
-          , mode: "0755" // octal strings supported
-          })
-  .on("close", function () {
-    closed = true
-    var fs = require("fs")
-    var s = fs.lstatSync("path/to/symlink")
-    var isSym = s.isSymbolicLink()
-    console.log((isSym?"":"not ") +"ok 1 should be symlink")
-    var t = fs.readlinkSync("path/to/symlink")
-    var isTarget = t === "./file"
-    console.log((isTarget?"":"not ") +"ok 2 should link to ./file")
-  })
-  .end()
-
-process.on("exit", function () {
-  console.log((closed?"":"not ")+"ok 3 should be closed")
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/fstream.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/fstream.js
deleted file mode 100644
index c66d26f5..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/fstream.js
+++ /dev/null
@@ -1,31 +0,0 @@
-exports.Abstract = require("./lib/abstract.js")
-exports.Reader = require("./lib/reader.js")
-exports.Writer = require("./lib/writer.js")
-
-exports.File =
-  { Reader: require("./lib/file-reader.js")
-  , Writer: require("./lib/file-writer.js") }
-
-exports.Dir = 
-  { Reader : require("./lib/dir-reader.js")
-  , Writer : require("./lib/dir-writer.js") }
-
-exports.Link =
-  { Reader : require("./lib/link-reader.js")
-  , Writer : require("./lib/link-writer.js") }
-
-exports.Proxy =
-  { Reader : require("./lib/proxy-reader.js")
-  , Writer : require("./lib/proxy-writer.js") }
-
-exports.Reader.Dir = exports.DirReader = exports.Dir.Reader
-exports.Reader.File = exports.FileReader = exports.File.Reader
-exports.Reader.Link = exports.LinkReader = exports.Link.Reader
-exports.Reader.Proxy = exports.ProxyReader = exports.Proxy.Reader
-
-exports.Writer.Dir = exports.DirWriter = exports.Dir.Writer
-exports.Writer.File = exports.FileWriter = exports.File.Writer
-exports.Writer.Link = exports.LinkWriter = exports.Link.Writer
-exports.Writer.Proxy = exports.ProxyWriter = exports.Proxy.Writer
-
-exports.collect = require("./lib/collect.js")
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/abstract.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/abstract.js
deleted file mode 100644
index 11ef0e28..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/abstract.js
+++ /dev/null
@@ -1,85 +0,0 @@
-// the parent class for all fstreams.
-
-module.exports = Abstract
-
-var Stream = require("stream").Stream
-  , inherits = require("inherits")
-
-function Abstract () {
-  Stream.call(this)
-}
-
-inherits(Abstract, Stream)
-
-Abstract.prototype.on = function (ev, fn) {
-  if (ev === "ready" && this.ready) {
-    process.nextTick(fn.bind(this))
-  } else {
-    Stream.prototype.on.call(this, ev, fn)
-  }
-  return this
-}
-
-Abstract.prototype.abort = function () {
-  this._aborted = true
-  this.emit("abort")
-}
-
-Abstract.prototype.destroy = function () {}
-
-Abstract.prototype.warn = function (msg, code) {
-  var me = this
-    , er = decorate(msg, code, me)
-  if (!me.listeners("warn")) {
-    console.error("%s %s\n" +
-                  "path = %s\n" +
-                  "syscall = %s\n" +
-                  "fstream_type = %s\n" +
-                  "fstream_path = %s\n" +
-                  "fstream_unc_path = %s\n" +
-                  "fstream_class = %s\n" +
-                  "fstream_stack =\n%s\n",
-                  code || "UNKNOWN",
-                  er.stack,
-                  er.path,
-                  er.syscall,
-                  er.fstream_type,
-                  er.fstream_path,
-                  er.fstream_unc_path,
-                  er.fstream_class,
-                  er.fstream_stack.join("\n"))
-  } else {
-    me.emit("warn", er)
-  }
-}
-
-Abstract.prototype.info = function (msg, code) {
-  this.emit("info", msg, code)
-}
-
-Abstract.prototype.error = function (msg, code, th) {
-  var er = decorate(msg, code, this)
-  if (th) throw er
-  else this.emit("error", er)
-}
-
-function decorate (er, code, me) {
-  if (!(er instanceof Error)) er = new Error(er)
-  er.code = er.code || code
-  er.path = er.path || me.path
-  er.fstream_type = er.fstream_type || me.type
-  er.fstream_path = er.fstream_path || me.path
-  if (me._path !== me.path) {
-    er.fstream_unc_path = er.fstream_unc_path || me._path
-  }
-  if (me.linkpath) {
-    er.fstream_linkpath = er.fstream_linkpath || me.linkpath
-  }
-  er.fstream_class = er.fstream_class || me.constructor.name
-  er.fstream_stack = er.fstream_stack ||
-    new Error().stack.split(/\n/).slice(3).map(function (s) {
-      return s.replace(/^    at /, "")
-    })
-
-  return er
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/collect.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/collect.js
deleted file mode 100644
index a36f780e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/collect.js
+++ /dev/null
@@ -1,67 +0,0 @@
-module.exports = collect
-
-function collect (stream) {
-  if (stream._collected) return
-
-  stream._collected = true
-  stream.pause()
-
-  stream.on("data", save)
-  stream.on("end", save)
-  var buf = []
-  function save (b) {
-    if (typeof b === "string") b = new Buffer(b)
-    if (Buffer.isBuffer(b) && !b.length) return
-    buf.push(b)
-  }
-
-  stream.on("entry", saveEntry)
-  var entryBuffer = []
-  function saveEntry (e) {
-    collect(e)
-    entryBuffer.push(e)
-  }
-
-  stream.on("proxy", proxyPause)
-  function proxyPause (p) {
-    p.pause()
-  }
-
-
-  // replace the pipe method with a new version that will
-  // unlock the buffered stuff.  if you just call .pipe()
-  // without a destination, then it'll re-play the events.
-  stream.pipe = (function (orig) { return function (dest) {
-    // console.error(" === open the pipes", dest && dest.path)
-
-    // let the entries flow through one at a time.
-    // Once they're all done, then we can resume completely.
-    var e = 0
-    ;(function unblockEntry () {
-      var entry = entryBuffer[e++]
-      // console.error(" ==== unblock entry", entry && entry.path)
-      if (!entry) return resume()
-      entry.on("end", unblockEntry)
-      if (dest) dest.add(entry)
-      else stream.emit("entry", entry)
-    })()
-
-    function resume () {
-      stream.removeListener("entry", saveEntry)
-      stream.removeListener("data", save)
-      stream.removeListener("end", save)
-
-      stream.pipe = orig
-      if (dest) stream.pipe(dest)
-
-      buf.forEach(function (b) {
-        if (b) stream.emit("data", b)
-        else stream.emit("end")
-      })
-
-      stream.resume()
-    }
-
-    return dest
-  }})(stream.pipe)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-reader.js
deleted file mode 100644
index 346ac2b8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-reader.js
+++ /dev/null
@@ -1,251 +0,0 @@
-// A thing that emits "entry" events with Reader objects
-// Pausing it causes it to stop emitting entry events, and also
-// pauses the current entry if there is one.
-
-module.exports = DirReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , Reader = fstream.Reader
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , path = require("path")
-  , Reader = require("./reader.js")
-  , assert = require("assert").ok
-
-inherits(DirReader, Reader)
-
-function DirReader (props) {
-  var me = this
-  if (!(me instanceof DirReader)) throw new Error(
-    "DirReader must be called as constructor.")
-
-  // should already be established as a Directory type
-  if (props.type !== "Directory" || !props.Directory) {
-    throw new Error("Non-directory type "+ props.type)
-  }
-
-  me.entries = null
-  me._index = -1
-  me._paused = false
-  me._length = -1
-
-  if (props.sort) {
-    this.sort = props.sort
-  }
-
-  Reader.call(this, props)
-}
-
-DirReader.prototype._getEntries = function () {
-  var me = this
-
-  // race condition.  might pause() before calling _getEntries,
-  // and then resume, and try to get them a second time.
-  if (me._gotEntries) return
-  me._gotEntries = true
-
-  fs.readdir(me._path, function (er, entries) {
-    if (er) return me.error(er)
-
-    me.entries = entries
-
-    me.emit("entries", entries)
-    if (me._paused) me.once("resume", processEntries)
-    else processEntries()
-
-    function processEntries () {
-      me._length = me.entries.length
-      if (typeof me.sort === "function") {
-        me.entries = me.entries.sort(me.sort.bind(me))
-      }
-      me._read()
-    }
-  })
-}
-
-// start walking the dir, and emit an "entry" event for each one.
-DirReader.prototype._read = function () {
-  var me = this
-
-  if (!me.entries) return me._getEntries()
-
-  if (me._paused || me._currentEntry || me._aborted) {
-    // console.error("DR paused=%j, current=%j, aborted=%j", me._paused, !!me._currentEntry, me._aborted)
-    return
-  }
-
-  me._index ++
-  if (me._index >= me.entries.length) {
-    if (!me._ended) {
-      me._ended = true
-      me.emit("end")
-      me.emit("close")
-    }
-    return
-  }
-
-  // ok, handle this one, then.
-
-  // save creating a proxy, by stat'ing the thing now.
-  var p = path.resolve(me._path, me.entries[me._index])
-  assert(p !== me._path)
-  assert(me.entries[me._index])
-
-  // set this to prevent trying to _read() again in the stat time.
-  me._currentEntry = p
-  fs[ me.props.follow ? "stat" : "lstat" ](p, function (er, stat) {
-    if (er) return me.error(er)
-
-    var who = me._proxy || me
-
-    stat.path = p
-    stat.basename = path.basename(p)
-    stat.dirname = path.dirname(p)
-    var childProps = me.getChildProps.call(who, stat)
-    childProps.path = p
-    childProps.basename = path.basename(p)
-    childProps.dirname = path.dirname(p)
-
-    var entry = Reader(childProps, stat)
-
-    // console.error("DR Entry", p, stat.size)
-
-    me._currentEntry = entry
-
-    // "entry" events are for direct entries in a specific dir.
-    // "child" events are for any and all children at all levels.
-    // This nomenclature is not completely final.
-
-    entry.on("pause", function (who) {
-      if (!me._paused && !entry._disowned) {
-        me.pause(who)
-      }
-    })
-
-    entry.on("resume", function (who) {
-      if (me._paused && !entry._disowned) {
-        me.resume(who)
-      }
-    })
-
-    entry.on("stat", function (props) {
-      me.emit("_entryStat", entry, props)
-      if (entry._aborted) return
-      if (entry._paused) entry.once("resume", function () {
-        me.emit("entryStat", entry, props)
-      })
-      else me.emit("entryStat", entry, props)
-    })
-
-    entry.on("ready", function EMITCHILD () {
-      // console.error("DR emit child", entry._path)
-      if (me._paused) {
-        // console.error("  DR emit child - try again later")
-        // pause the child, and emit the "entry" event once we drain.
-        // console.error("DR pausing child entry")
-        entry.pause(me)
-        return me.once("resume", EMITCHILD)
-      }
-
-      // skip over sockets.  they can't be piped around properly,
-      // so there's really no sense even acknowledging them.
-      // if someone really wants to see them, they can listen to
-      // the "socket" events.
-      if (entry.type === "Socket") {
-        me.emit("socket", entry)
-      } else {
-        me.emitEntry(entry)
-      }
-    })
-
-    var ended = false
-    entry.on("close", onend)
-    entry.on("disown", onend)
-    function onend () {
-      if (ended) return
-      ended = true
-      me.emit("childEnd", entry)
-      me.emit("entryEnd", entry)
-      me._currentEntry = null
-      if (!me._paused) {
-        me._read()
-      }
-    }
-
-    // XXX Remove this.  Works in node as of 0.6.2 or so.
-    // Long filenames should not break stuff.
-    entry.on("error", function (er) {
-      if (entry._swallowErrors) {
-        me.warn(er)
-        entry.emit("end")
-        entry.emit("close")
-      } else {
-        me.emit("error", er)
-      }
-    })
-
-    // proxy up some events.
-    ; [ "child"
-      , "childEnd"
-      , "warn"
-      ].forEach(function (ev) {
-        entry.on(ev, me.emit.bind(me, ev))
-      })
-  })
-}
-
-DirReader.prototype.disown = function (entry) {
-  entry.emit("beforeDisown")
-  entry._disowned = true
-  entry.parent = entry.root = null
-  if (entry === this._currentEntry) {
-    this._currentEntry = null
-  }
-  entry.emit("disown")
-}
-
-DirReader.prototype.getChildProps = function (stat) {
-  return { depth: this.depth + 1
-         , root: this.root || this
-         , parent: this
-         , follow: this.follow
-         , filter: this.filter
-         , sort: this.props.sort
-         , hardlinks: this.props.hardlinks
-         }
-}
-
-DirReader.prototype.pause = function (who) {
-  var me = this
-  if (me._paused) return
-  who = who || me
-  me._paused = true
-  if (me._currentEntry && me._currentEntry.pause) {
-    me._currentEntry.pause(who)
-  }
-  me.emit("pause", who)
-}
-
-DirReader.prototype.resume = function (who) {
-  var me = this
-  if (!me._paused) return
-  who = who || me
-
-  me._paused = false
-  // console.error("DR Emit Resume", me._path)
-  me.emit("resume", who)
-  if (me._paused) {
-    // console.error("DR Re-paused", me._path)
-    return
-  }
-
-  if (me._currentEntry) {
-    if (me._currentEntry.resume) me._currentEntry.resume(who)
-  } else me._read()
-}
-
-DirReader.prototype.emitEntry = function (entry) {
-  this.emit("entry", entry)
-  this.emit("child", entry)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-writer.js
deleted file mode 100644
index 7073b883..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/dir-writer.js
+++ /dev/null
@@ -1,171 +0,0 @@
-// It is expected that, when .add() returns false, the consumer
-// of the DirWriter will pause until a "drain" event occurs. Note
-// that this is *almost always going to be the case*, unless the
-// thing being written is some sort of unsupported type, and thus
-// skipped over.
-
-module.exports = DirWriter
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , Writer = require("./writer.js")
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , path = require("path")
-  , collect = require("./collect.js")
-
-inherits(DirWriter, Writer)
-
-function DirWriter (props) {
-  var me = this
-  if (!(me instanceof DirWriter)) me.error(
-    "DirWriter must be called as constructor.", null, true)
-
-  // should already be established as a Directory type
-  if (props.type !== "Directory" || !props.Directory) {
-    me.error("Non-directory type "+ props.type + " " +
-                    JSON.stringify(props), null, true)
-  }
-
-  Writer.call(this, props)
-}
-
-DirWriter.prototype._create = function () {
-  var me = this
-  mkdir(me._path, Writer.dirmode, function (er) {
-    if (er) return me.error(er)
-    // ready to start getting entries!
-    me.ready = true
-    me.emit("ready")
-    me._process()
-  })
-}
-
-// a DirWriter has an add(entry) method, but its .write() doesn't
-// do anything.  Why a no-op rather than a throw?  Because this
-// leaves open the door for writing directory metadata for
-// gnu/solaris style dumpdirs.
-DirWriter.prototype.write = function () {
-  return true
-}
-
-DirWriter.prototype.end = function () {
-  this._ended = true
-  this._process()
-}
-
-DirWriter.prototype.add = function (entry) {
-  var me = this
-
-  // console.error("\tadd", entry._path, "->", me._path)
-  collect(entry)
-  if (!me.ready || me._currentEntry) {
-    me._buffer.push(entry)
-    return false
-  }
-
-  // create a new writer, and pipe the incoming entry into it.
-  if (me._ended) {
-    return me.error("add after end")
-  }
-
-  me._buffer.push(entry)
-  me._process()
-
-  return 0 === this._buffer.length
-}
-
-DirWriter.prototype._process = function () {
-  var me = this
-
-  // console.error("DW Process p=%j", me._processing, me.basename)
-
-  if (me._processing) return
-
-  var entry = me._buffer.shift()
-  if (!entry) {
-    // console.error("DW Drain")
-    me.emit("drain")
-    if (me._ended) me._finish()
-    return
-  }
-
-  me._processing = true
-  // console.error("DW Entry", entry._path)
-
-  me.emit("entry", entry)
-
-  // ok, add this entry
-  //
-  // don't allow recursive copying
-  var p = entry
-  do {
-    var pp = p._path || p.path
-    if (pp === me.root._path || pp === me._path ||
-        (pp && pp.indexOf(me._path) === 0)) {
-      // console.error("DW Exit (recursive)", entry.basename, me._path)
-      me._processing = false
-      if (entry._collected) entry.pipe()
-      return me._process()
-    }
-  } while (p = p.parent)
-
-  // console.error("DW not recursive")
-
-  // chop off the entry's root dir, replace with ours
-  var props = { parent: me
-              , root: me.root || me
-              , type: entry.type
-              , depth: me.depth + 1 }
-
-  var p = entry._path || entry.path || entry.props.path
-  if (entry.parent) {
-    p = p.substr(entry.parent._path.length + 1)
-  }
-  // get rid of any ../../ shenanigans
-  props.path = path.join(me.path, path.join("/", p))
-
-  // if i have a filter, the child should inherit it.
-  props.filter = me.filter
-
-  // all the rest of the stuff, copy over from the source.
-  Object.keys(entry.props).forEach(function (k) {
-    if (!props.hasOwnProperty(k)) {
-      props[k] = entry.props[k]
-    }
-  })
-
-  // not sure at this point what kind of writer this is.
-  var child = me._currentChild = new Writer(props)
-  child.on("ready", function () {
-    // console.error("DW Child Ready", child.type, child._path)
-    // console.error("  resuming", entry._path)
-    entry.pipe(child)
-    entry.resume()
-  })
-
-  // XXX Make this work in node.
-  // Long filenames should not break stuff.
-  child.on("error", function (er) {
-    if (child._swallowErrors) {
-      me.warn(er)
-      child.emit("end")
-      child.emit("close")
-    } else {
-      me.emit("error", er)
-    }
-  })
-
-  // we fire _end internally *after* end, so that we don't move on
-  // until any "end" listeners have had their chance to do stuff.
-  child.on("close", onend)
-  var ended = false
-  function onend () {
-    if (ended) return
-    ended = true
-    // console.error("* DW Child end", child.basename)
-    me._currentChild = null
-    me._processing = false
-    me._process()
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-reader.js
deleted file mode 100644
index b1f98618..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-reader.js
+++ /dev/null
@@ -1,147 +0,0 @@
-// Basically just a wrapper around an fs.ReadStream
-
-module.exports = FileReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , Reader = fstream.Reader
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , Reader = require("./reader.js")
-  , EOF = {EOF: true}
-  , CLOSE = {CLOSE: true}
-
-inherits(FileReader, Reader)
-
-function FileReader (props) {
-  // console.error("    FR create", props.path, props.size, new Error().stack)
-  var me = this
-  if (!(me instanceof FileReader)) throw new Error(
-    "FileReader must be called as constructor.")
-
-  // should already be established as a File type
-  // XXX Todo: preserve hardlinks by tracking dev+inode+nlink,
-  // with a HardLinkReader class.
-  if (!((props.type === "Link" && props.Link) ||
-        (props.type === "File" && props.File))) {
-    throw new Error("Non-file type "+ props.type)
-  }
-
-  me._buffer = []
-  me._bytesEmitted = 0
-  Reader.call(me, props)
-}
-
-FileReader.prototype._getStream = function () {
-  var me = this
-    , stream = me._stream = fs.createReadStream(me._path, me.props)
-
-  if (me.props.blksize) {
-    stream.bufferSize = me.props.blksize
-  }
-
-  stream.on("open", me.emit.bind(me, "open"))
-
-  stream.on("data", function (c) {
-    // console.error("\t\t%d %s", c.length, me.basename)
-    me._bytesEmitted += c.length
-    // no point saving empty chunks
-    if (!c.length) return
-    else if (me._paused || me._buffer.length) {
-      me._buffer.push(c)
-      me._read()
-    } else me.emit("data", c)
-  })
-
-  stream.on("end", function () {
-    if (me._paused || me._buffer.length) {
-      // console.error("FR Buffering End", me._path)
-      me._buffer.push(EOF)
-      me._read()
-    } else {
-      me.emit("end")
-    }
-
-    if (me._bytesEmitted !== me.props.size) {
-      me.error("Didn't get expected byte count\n"+
-               "expect: "+me.props.size + "\n" +
-               "actual: "+me._bytesEmitted)
-    }
-  })
-
-  stream.on("close", function () {
-    if (me._paused || me._buffer.length) {
-      // console.error("FR Buffering Close", me._path)
-      me._buffer.push(CLOSE)
-      me._read()
-    } else {
-      // console.error("FR close 1", me._path)
-      me.emit("close")
-    }
-  })
-
-  me._read()
-}
-
-FileReader.prototype._read = function () {
-  var me = this
-  // console.error("FR _read", me._path)
-  if (me._paused) {
-    // console.error("FR _read paused", me._path)
-    return
-  }
-
-  if (!me._stream) {
-    // console.error("FR _getStream calling", me._path)
-    return me._getStream()
-  }
-
-  // clear out the buffer, if there is one.
-  if (me._buffer.length) {
-    // console.error("FR _read has buffer", me._buffer.length, me._path)
-    var buf = me._buffer
-    for (var i = 0, l = buf.length; i < l; i ++) {
-      var c = buf[i]
-      if (c === EOF) {
-        // console.error("FR Read emitting buffered end", me._path)
-        me.emit("end")
-      } else if (c === CLOSE) {
-        // console.error("FR Read emitting buffered close", me._path)
-        me.emit("close")
-      } else {
-        // console.error("FR Read emitting buffered data", me._path)
-        me.emit("data", c)
-      }
-
-      if (me._paused) {
-        // console.error("FR Read Re-pausing at "+i, me._path)
-        me._buffer = buf.slice(i)
-        return
-      }
-    }
-    me._buffer.length = 0
-  }
-  // console.error("FR _read done")
-  // that's about all there is to it.
-}
-
-FileReader.prototype.pause = function (who) {
-  var me = this
-  // console.error("FR Pause", me._path)
-  if (me._paused) return
-  who = who || me
-  me._paused = true
-  if (me._stream) me._stream.pause()
-  me.emit("pause", who)
-}
-
-FileReader.prototype.resume = function (who) {
-  var me = this
-  // console.error("FR Resume", me._path)
-  if (!me._paused) return
-  who = who || me
-  me.emit("resume", who)
-  me._paused = false
-  if (me._stream) me._stream.resume()
-  me._read()
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-writer.js
deleted file mode 100644
index 68114625..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/file-writer.js
+++ /dev/null
@@ -1,100 +0,0 @@
-module.exports = FileWriter
-
-var fs = require("graceful-fs")
-  , mkdir = require("mkdirp")
-  , Writer = require("./writer.js")
-  , inherits = require("inherits")
-  , EOF = {}
-
-inherits(FileWriter, Writer)
-
-function FileWriter (props) {
-  var me = this
-  if (!(me instanceof FileWriter)) throw new Error(
-    "FileWriter must be called as constructor.")
-
-  // should already be established as a File type
-  if (props.type !== "File" || !props.File) {
-    throw new Error("Non-file type "+ props.type)
-  }
-
-  me._buffer = []
-  me._bytesWritten = 0
-
-  Writer.call(this, props)
-}
-
-FileWriter.prototype._create = function () {
-  var me = this
-  if (me._stream) return
-
-  var so = {}
-  if (me.props.flags) so.flags = me.props.flags
-  so.mode = Writer.filemode
-  if (me._old && me._old.blksize) so.bufferSize = me._old.blksize
-
-  me._stream = fs.createWriteStream(me._path, so)
-
-  me._stream.on("open", function (fd) {
-    // console.error("FW open", me._buffer, me._path)
-    me.ready = true
-    me._buffer.forEach(function (c) {
-      if (c === EOF) me._stream.end()
-      else me._stream.write(c)
-    })
-    me.emit("ready")
-    // give this a kick just in case it needs it.
-    me.emit("drain")
-  })
-
-  me._stream.on("drain", function () { me.emit("drain") })
-
-  me._stream.on("close", function () {
-    // console.error("\n\nFW Stream Close", me._path, me.size)
-    me._finish()
-  })
-}
-
-FileWriter.prototype.write = function (c) {
-  var me = this
-
-  me._bytesWritten += c.length
-
-  if (!me.ready) {
-    if (!Buffer.isBuffer(c) && typeof c !== 'string')
-      throw new Error('invalid write data')
-    me._buffer.push(c)
-    return false
-  }
-
-  var ret = me._stream.write(c)
-  // console.error("\t-- fw wrote, _stream says", ret, me._stream._queue.length)
-
-  // allow 2 buffered writes, because otherwise there's just too
-  // much stop and go bs.
-  return ret || (me._stream._queue && me._stream._queue.length <= 2)
-}
-
-FileWriter.prototype.end = function (c) {
-  var me = this
-
-  if (c) me.write(c)
-
-  if (!me.ready) {
-    me._buffer.push(EOF)
-    return false
-  }
-
-  return me._stream.end()
-}
-
-FileWriter.prototype._finish = function () {
-  var me = this
-  if (typeof me.size === "number" && me._bytesWritten != me.size) {
-    me.error(
-      "Did not get expected byte count.\n" +
-      "expect: " + me.size + "\n" +
-      "actual: " + me._bytesWritten)
-  }
-  Writer.prototype._finish.call(me)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/get-type.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/get-type.js
deleted file mode 100644
index cd65c41d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/get-type.js
+++ /dev/null
@@ -1,32 +0,0 @@
-module.exports = getType
-
-function getType (st) {
-  var types =
-      [ "Directory"
-      , "File"
-      , "SymbolicLink"
-      , "Link" // special for hardlinks from tarballs
-      , "BlockDevice"
-      , "CharacterDevice"
-      , "FIFO"
-      , "Socket" ]
-    , type
-
-  if (st.type && -1 !== types.indexOf(st.type)) {
-    st[st.type] = true
-    return st.type
-  }
-
-  for (var i = 0, l = types.length; i < l; i ++) {
-    type = types[i]
-    var is = st[type] || st["is" + type]
-    if (typeof is === "function") is = is.call(st)
-    if (is) {
-      st[type] = true
-      st.type = type
-      return type
-    }
-  }
-
-  return null
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-reader.js
deleted file mode 100644
index 7e7ab6ce..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-reader.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Basically just a wrapper around an fs.readlink
-//
-// XXX: Enhance this to support the Link type, by keeping
-// a lookup table of {<dev+inode>:<path>}, so that hardlinks
-// can be preserved in tarballs.
-
-module.exports = LinkReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , Reader = require("./reader.js")
-
-inherits(LinkReader, Reader)
-
-function LinkReader (props) {
-  var me = this
-  if (!(me instanceof LinkReader)) throw new Error(
-    "LinkReader must be called as constructor.")
-
-  if (!((props.type === "Link" && props.Link) ||
-        (props.type === "SymbolicLink" && props.SymbolicLink))) {
-    throw new Error("Non-link type "+ props.type)
-  }
-
-  Reader.call(me, props)
-}
-
-// When piping a LinkReader into a LinkWriter, we have to
-// already have the linkpath property set, so that has to
-// happen *before* the "ready" event, which means we need to
-// override the _stat method.
-LinkReader.prototype._stat = function (currentStat) {
-  var me = this
-  fs.readlink(me._path, function (er, linkpath) {
-    if (er) return me.error(er)
-    me.linkpath = me.props.linkpath = linkpath
-    me.emit("linkpath", linkpath)
-    Reader.prototype._stat.call(me, currentStat)
-  })
-}
-
-LinkReader.prototype._read = function () {
-  var me = this
-  if (me._paused) return
-  // basically just a no-op, since we got all the info we need
-  // from the _stat method
-  if (!me._ended) {
-    me.emit("end")
-    me.emit("close")
-    me._ended = true
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-writer.js
deleted file mode 100644
index 5c8f1e70..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/link-writer.js
+++ /dev/null
@@ -1,95 +0,0 @@
-
-module.exports = LinkWriter
-
-var fs = require("graceful-fs")
-  , Writer = require("./writer.js")
-  , inherits = require("inherits")
-  , path = require("path")
-  , rimraf = require("rimraf")
-
-inherits(LinkWriter, Writer)
-
-function LinkWriter (props) {
-  var me = this
-  if (!(me instanceof LinkWriter)) throw new Error(
-    "LinkWriter must be called as constructor.")
-
-  // should already be established as a Link type
-  if (!((props.type === "Link" && props.Link) ||
-        (props.type === "SymbolicLink" && props.SymbolicLink))) {
-    throw new Error("Non-link type "+ props.type)
-  }
-
-  if (props.linkpath === "") props.linkpath = "."
-  if (!props.linkpath) {
-    me.error("Need linkpath property to create " + props.type)
-  }
-
-  Writer.call(this, props)
-}
-
-LinkWriter.prototype._create = function () {
-  // console.error(" LW _create")
-  var me = this
-    , hard = me.type === "Link" || process.platform === "win32"
-    , link = hard ? "link" : "symlink"
-    , lp = hard ? path.resolve(me.dirname, me.linkpath) : me.linkpath
-
-  // can only change the link path by clobbering
-  // For hard links, let's just assume that's always the case, since
-  // there's no good way to read them if we don't already know.
-  if (hard) return clobber(me, lp, link)
-
-  fs.readlink(me._path, function (er, p) {
-    // only skip creation if it's exactly the same link
-    if (p && p === lp) return finish(me)
-    clobber(me, lp, link)
-  })
-}
-
-function clobber (me, lp, link) {
-  rimraf(me._path, function (er) {
-    if (er) return me.error(er)
-    create(me, lp, link)
-  })
-}
-
-function create (me, lp, link) {
-  fs[link](lp, me._path, function (er) {
-    // if this is a hard link, and we're in the process of writing out a
-    // directory, it's very possible that the thing we're linking to
-    // doesn't exist yet (especially if it was intended as a symlink),
-    // so swallow ENOENT errors here and just soldier in.
-    // Additionally, an EPERM or EACCES can happen on win32 if it's trying
-    // to make a link to a directory.  Again, just skip it.
-    // A better solution would be to have fs.symlink be supported on
-    // windows in some nice fashion.
-    if (er) {
-      if ((er.code === "ENOENT" ||
-           er.code === "EACCES" ||
-           er.code === "EPERM" ) && process.platform === "win32") {
-        me.ready = true
-        me.emit("ready")
-        me.emit("end")
-        me.emit("close")
-        me.end = me._finish = function () {}
-      } else return me.error(er)
-    }
-    finish(me)
-  })
-}
-
-function finish (me) {
-  me.ready = true
-  me.emit("ready")
-  if (me._ended && !me._finished) me._finish()
-}
-
-LinkWriter.prototype.end = function () {
-  // console.error("LW finish in end")
-  this._ended = true
-  if (this.ready) {
-    this._finished = true
-    this._finish()
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-reader.js
deleted file mode 100644
index a0ece34a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-reader.js
+++ /dev/null
@@ -1,93 +0,0 @@
-// A reader for when we don't yet know what kind of thing
-// the thing is.
-
-module.exports = ProxyReader
-
-var Reader = require("./reader.js")
-  , getType = require("./get-type.js")
-  , inherits = require("inherits")
-  , fs = require("graceful-fs")
-
-inherits(ProxyReader, Reader)
-
-function ProxyReader (props) {
-  var me = this
-  if (!(me instanceof ProxyReader)) throw new Error(
-    "ProxyReader must be called as constructor.")
-
-  me.props = props
-  me._buffer = []
-  me.ready = false
-
-  Reader.call(me, props)
-}
-
-ProxyReader.prototype._stat = function () {
-  var me = this
-    , props = me.props
-    // stat the thing to see what the proxy should be.
-    , stat = props.follow ? "stat" : "lstat"
-
-  fs[stat](props.path, function (er, current) {
-    var type
-    if (er || !current) {
-      type = "File"
-    } else {
-      type = getType(current)
-    }
-
-    props[type] = true
-    props.type = me.type = type
-
-    me._old = current
-    me._addProxy(Reader(props, current))
-  })
-}
-
-ProxyReader.prototype._addProxy = function (proxy) {
-  var me = this
-  if (me._proxyTarget) {
-    return me.error("proxy already set")
-  }
-
-  me._proxyTarget = proxy
-  proxy._proxy = me
-
-  ; [ "error"
-    , "data"
-    , "end"
-    , "close"
-    , "linkpath"
-    , "entry"
-    , "entryEnd"
-    , "child"
-    , "childEnd"
-    , "warn"
-    , "stat"
-    ].forEach(function (ev) {
-      // console.error("~~ proxy event", ev, me.path)
-      proxy.on(ev, me.emit.bind(me, ev))
-    })
-
-  me.emit("proxy", proxy)
-
-  proxy.on("ready", function () {
-    // console.error("~~ proxy is ready!", me.path)
-    me.ready = true
-    me.emit("ready")
-  })
-
-  var calls = me._buffer
-  me._buffer.length = 0
-  calls.forEach(function (c) {
-    proxy[c[0]].apply(proxy, c[1])
-  })
-}
-
-ProxyReader.prototype.pause = function () {
-  return this._proxyTarget ? this._proxyTarget.pause() : false
-}
-
-ProxyReader.prototype.resume = function () {
-  return this._proxyTarget ? this._proxyTarget.resume() : false
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-writer.js
deleted file mode 100644
index b0476633..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/proxy-writer.js
+++ /dev/null
@@ -1,109 +0,0 @@
-// A writer for when we don't know what kind of thing
-// the thing is.  That is, it's not explicitly set,
-// so we're going to make it whatever the thing already
-// is, or "File"
-//
-// Until then, collect all events.
-
-module.exports = ProxyWriter
-
-var Writer = require("./writer.js")
-  , getType = require("./get-type.js")
-  , inherits = require("inherits")
-  , collect = require("./collect.js")
-  , fs = require("fs")
-
-inherits(ProxyWriter, Writer)
-
-function ProxyWriter (props) {
-  var me = this
-  if (!(me instanceof ProxyWriter)) throw new Error(
-    "ProxyWriter must be called as constructor.")
-
-  me.props = props
-  me._needDrain = false
-
-  Writer.call(me, props)
-}
-
-ProxyWriter.prototype._stat = function () {
-  var me = this
-    , props = me.props
-    // stat the thing to see what the proxy should be.
-    , stat = props.follow ? "stat" : "lstat"
-
-  fs[stat](props.path, function (er, current) {
-    var type
-    if (er || !current) {
-      type = "File"
-    } else {
-      type = getType(current)
-    }
-
-    props[type] = true
-    props.type = me.type = type
-
-    me._old = current
-    me._addProxy(Writer(props, current))
-  })
-}
-
-ProxyWriter.prototype._addProxy = function (proxy) {
-  // console.error("~~ set proxy", this.path)
-  var me = this
-  if (me._proxy) {
-    return me.error("proxy already set")
-  }
-
-  me._proxy = proxy
-  ; [ "ready"
-    , "error"
-    , "close"
-    , "pipe"
-    , "drain"
-    , "warn"
-    ].forEach(function (ev) {
-      proxy.on(ev, me.emit.bind(me, ev))
-    })
-
-  me.emit("proxy", proxy)
-
-  var calls = me._buffer
-  calls.forEach(function (c) {
-    // console.error("~~ ~~ proxy buffered call", c[0], c[1])
-    proxy[c[0]].apply(proxy, c[1])
-  })
-  me._buffer.length = 0
-  if (me._needsDrain) me.emit("drain")
-}
-
-ProxyWriter.prototype.add = function (entry) {
-  // console.error("~~ proxy add")
-  collect(entry)
-
-  if (!this._proxy) {
-    this._buffer.push(["add", [entry]])
-    this._needDrain = true
-    return false
-  }
-  return this._proxy.add(entry)
-}
-
-ProxyWriter.prototype.write = function (c) {
-  // console.error("~~ proxy write")
-  if (!this._proxy) {
-    this._buffer.push(["write", [c]])
-    this._needDrain = true
-    return false
-  }
-  return this._proxy.write(c)
-}
-
-ProxyWriter.prototype.end = function (c) {
-  // console.error("~~ proxy end")
-  if (!this._proxy) {
-    this._buffer.push(["end", [c]])
-    return false
-  }
-  return this._proxy.end(c)
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/reader.js
deleted file mode 100644
index eaf921cd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/reader.js
+++ /dev/null
@@ -1,260 +0,0 @@
-
-module.exports = Reader
-
-var fs = require("graceful-fs")
-  , Stream = require("stream").Stream
-  , inherits = require("inherits")
-  , path = require("path")
-  , getType = require("./get-type.js")
-  , hardLinks = Reader.hardLinks = {}
-  , Abstract = require("./abstract.js")
-
-// Must do this *before* loading the child classes
-inherits(Reader, Abstract)
-
-var DirReader = require("./dir-reader.js")
-  , FileReader = require("./file-reader.js")
-  , LinkReader = require("./link-reader.js")
-  , SocketReader = require("./socket-reader.js")
-  , ProxyReader = require("./proxy-reader.js")
-
-function Reader (props, currentStat) {
-  var me = this
-  if (!(me instanceof Reader)) return new Reader(props, currentStat)
-
-  if (typeof props === "string") {
-    props = { path: props }
-  }
-
-  if (!props.path) {
-    me.error("Must provide a path", null, true)
-  }
-
-  // polymorphism.
-  // call fstream.Reader(dir) to get a DirReader object, etc.
-  // Note that, unlike in the Writer case, ProxyReader is going
-  // to be the *normal* state of affairs, since we rarely know
-  // the type of a file prior to reading it.
-
-
-  var type
-    , ClassType
-
-  if (props.type && typeof props.type === "function") {
-    type = props.type
-    ClassType = type
-  } else {
-    type = getType(props)
-    ClassType = Reader
-  }
-
-  if (currentStat && !type) {
-    type = getType(currentStat)
-    props[type] = true
-    props.type = type
-  }
-
-  switch (type) {
-    case "Directory":
-      ClassType = DirReader
-      break
-
-    case "Link":
-      // XXX hard links are just files.
-      // However, it would be good to keep track of files' dev+inode
-      // and nlink values, and create a HardLinkReader that emits
-      // a linkpath value of the original copy, so that the tar
-      // writer can preserve them.
-      // ClassType = HardLinkReader
-      // break
-
-    case "File":
-      ClassType = FileReader
-      break
-
-    case "SymbolicLink":
-      ClassType = LinkReader
-      break
-
-    case "Socket":
-      ClassType = SocketReader
-      break
-
-    case null:
-      ClassType = ProxyReader
-      break
-  }
-
-  if (!(me instanceof ClassType)) {
-    return new ClassType(props)
-  }
-
-  Abstract.call(me)
-
-  me.readable = true
-  me.writable = false
-
-  me.type = type
-  me.props = props
-  me.depth = props.depth = props.depth || 0
-  me.parent = props.parent || null
-  me.root = props.root || (props.parent && props.parent.root) || me
-
-  me._path = me.path = path.resolve(props.path)
-  if (process.platform === "win32") {
-    me.path = me._path = me.path.replace(/\?/g, "_")
-    if (me._path.length >= 260) {
-      // how DOES one create files on the moon?
-      // if the path has spaces in it, then UNC will fail.
-      me._swallowErrors = true
-      //if (me._path.indexOf(" ") === -1) {
-        me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
-      //}
-    }
-  }
-  me.basename = props.basename = path.basename(me.path)
-  me.dirname = props.dirname = path.dirname(me.path)
-
-  // these have served their purpose, and are now just noisy clutter
-  props.parent = props.root = null
-
-  // console.error("\n\n\n%s setting size to", props.path, props.size)
-  me.size = props.size
-  me.filter = typeof props.filter === "function" ? props.filter : null
-  if (props.sort === "alpha") props.sort = alphasort
-
-  // start the ball rolling.
-  // this will stat the thing, and then call me._read()
-  // to start reading whatever it is.
-  // console.error("calling stat", props.path, currentStat)
-  me._stat(currentStat)
-}
-
-function alphasort (a, b) {
-  return a === b ? 0
-       : a.toLowerCase() > b.toLowerCase() ? 1
-       : a.toLowerCase() < b.toLowerCase() ? -1
-       : a > b ? 1
-       : -1
-}
-
-Reader.prototype._stat = function (currentStat) {
-  var me = this
-    , props = me.props
-    , stat = props.follow ? "stat" : "lstat"
-  // console.error("Reader._stat", me._path, currentStat)
-  if (currentStat) process.nextTick(statCb.bind(null, null, currentStat))
-  else fs[stat](me._path, statCb)
-
-
-  function statCb (er, props_) {
-    // console.error("Reader._stat, statCb", me._path, props_, props_.nlink)
-    if (er) return me.error(er)
-
-    Object.keys(props_).forEach(function (k) {
-      props[k] = props_[k]
-    })
-
-    // if it's not the expected size, then abort here.
-    if (undefined !== me.size && props.size !== me.size) {
-      return me.error("incorrect size")
-    }
-    me.size = props.size
-
-    var type = getType(props)
-    var handleHardlinks = props.hardlinks !== false
-    
-    // special little thing for handling hardlinks.
-    if (handleHardlinks && type !== "Directory" && props.nlink && props.nlink > 1) {
-      var k = props.dev + ":" + props.ino
-      // console.error("Reader has nlink", me._path, k)
-      if (hardLinks[k] === me._path || !hardLinks[k]) hardLinks[k] = me._path
-      else {
-        // switch into hardlink mode.
-        type = me.type = me.props.type = "Link"
-        me.Link = me.props.Link = true
-        me.linkpath = me.props.linkpath = hardLinks[k]
-        // console.error("Hardlink detected, switching mode", me._path, me.linkpath)
-        // Setting __proto__ would arguably be the "correct"
-        // approach here, but that just seems too wrong.
-        me._stat = me._read = LinkReader.prototype._read
-      }
-    }
-
-    if (me.type && me.type !== type) {
-      me.error("Unexpected type: " + type)
-    }
-
-    // if the filter doesn't pass, then just skip over this one.
-    // still have to emit end so that dir-walking can move on.
-    if (me.filter) {
-      var who = me._proxy || me
-      // special handling for ProxyReaders
-      if (!me.filter.call(who, who, props)) {
-        if (!me._disowned) {
-          me.abort()
-          me.emit("end")
-          me.emit("close")
-        }
-        return
-      }
-    }
-
-    // last chance to abort or disown before the flow starts!
-    var events = ["_stat", "stat", "ready"]
-    var e = 0
-    ;(function go () {
-      if (me._aborted) {
-        me.emit("end")
-        me.emit("close")
-        return
-      }
-
-      if (me._paused) {
-        me.once("resume", go)
-        return
-      }
-
-      var ev = events[e ++]
-      if (!ev) return me._read()
-      me.emit(ev, props)
-      go()
-    })()
-  }
-}
-
-Reader.prototype.pipe = function (dest, opts) {
-  var me = this
-  if (typeof dest.add === "function") {
-    // piping to a multi-compatible, and we've got directory entries.
-    me.on("entry", function (entry) {
-      var ret = dest.add(entry)
-      if (false === ret) {
-        me.pause()
-      }
-    })
-  }
-
-  // console.error("R Pipe apply Stream Pipe")
-  return Stream.prototype.pipe.apply(this, arguments)
-}
-
-Reader.prototype.pause = function (who) {
-  this._paused = true
-  who = who || this
-  this.emit("pause", who)
-  if (this._stream) this._stream.pause(who)
-}
-
-Reader.prototype.resume = function (who) {
-  this._paused = false
-  who = who || this
-  this.emit("resume", who)
-  if (this._stream) this._stream.resume(who)
-  this._read()
-}
-
-Reader.prototype._read = function () {
-  this.error("Cannot read unknown type: "+this.type)
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/socket-reader.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/socket-reader.js
deleted file mode 100644
index e89c1731..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/socket-reader.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// Just get the stats, and then don't do anything.
-// You can't really "read" from a socket.  You "connect" to it.
-// Mostly, this is here so that reading a dir with a socket in it
-// doesn't blow up.
-
-module.exports = SocketReader
-
-var fs = require("graceful-fs")
-  , fstream = require("../fstream.js")
-  , inherits = require("inherits")
-  , mkdir = require("mkdirp")
-  , Reader = require("./reader.js")
-
-inherits(SocketReader, Reader)
-
-function SocketReader (props) {
-  var me = this
-  if (!(me instanceof SocketReader)) throw new Error(
-    "SocketReader must be called as constructor.")
-
-  if (!(props.type === "Socket" && props.Socket)) {
-    throw new Error("Non-socket type "+ props.type)
-  }
-
-  Reader.call(me, props)
-}
-
-SocketReader.prototype._read = function () {
-  var me = this
-  if (me._paused) return
-  // basically just a no-op, since we got all the info we have
-  // from the _stat method
-  if (!me._ended) {
-    me.emit("end")
-    me.emit("close")
-    me._ended = true
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/writer.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/writer.js
deleted file mode 100644
index 5599fb22..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/lib/writer.js
+++ /dev/null
@@ -1,389 +0,0 @@
-
-module.exports = Writer
-
-var fs = require("graceful-fs")
-  , inherits = require("inherits")
-  , rimraf = require("rimraf")
-  , mkdir = require("mkdirp")
-  , path = require("path")
-  , umask = process.platform === "win32" ? 0 : process.umask()
-  , getType = require("./get-type.js")
-  , Abstract = require("./abstract.js")
-
-// Must do this *before* loading the child classes
-inherits(Writer, Abstract)
-
-Writer.dirmode = 0777 & (~umask)
-Writer.filemode = 0666 & (~umask)
-
-var DirWriter = require("./dir-writer.js")
-  , LinkWriter = require("./link-writer.js")
-  , FileWriter = require("./file-writer.js")
-  , ProxyWriter = require("./proxy-writer.js")
-
-// props is the desired state.  current is optionally the current stat,
-// provided here so that subclasses can avoid statting the target
-// more than necessary.
-function Writer (props, current) {
-  var me = this
-
-  if (typeof props === "string") {
-    props = { path: props }
-  }
-
-  if (!props.path) me.error("Must provide a path", null, true)
-
-  // polymorphism.
-  // call fstream.Writer(dir) to get a DirWriter object, etc.
-  var type = getType(props)
-    , ClassType = Writer
-
-  switch (type) {
-    case "Directory":
-      ClassType = DirWriter
-      break
-    case "File":
-      ClassType = FileWriter
-      break
-    case "Link":
-    case "SymbolicLink":
-      ClassType = LinkWriter
-      break
-    case null:
-      // Don't know yet what type to create, so we wrap in a proxy.
-      ClassType = ProxyWriter
-      break
-  }
-
-  if (!(me instanceof ClassType)) return new ClassType(props)
-
-  // now get down to business.
-
-  Abstract.call(me)
-
-  // props is what we want to set.
-  // set some convenience properties as well.
-  me.type = props.type
-  me.props = props
-  me.depth = props.depth || 0
-  me.clobber = false === props.clobber ? props.clobber : true
-  me.parent = props.parent || null
-  me.root = props.root || (props.parent && props.parent.root) || me
-
-  me._path = me.path = path.resolve(props.path)
-  if (process.platform === "win32") {
-    me.path = me._path = me.path.replace(/\?/g, "_")
-    if (me._path.length >= 260) {
-      me._swallowErrors = true
-      me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
-    }
-  }
-  me.basename = path.basename(props.path)
-  me.dirname = path.dirname(props.path)
-  me.linkpath = props.linkpath || null
-
-  props.parent = props.root = null
-
-  // console.error("\n\n\n%s setting size to", props.path, props.size)
-  me.size = props.size
-
-  if (typeof props.mode === "string") {
-    props.mode = parseInt(props.mode, 8)
-  }
-
-  me.readable = false
-  me.writable = true
-
-  // buffer until ready, or while handling another entry
-  me._buffer = []
-  me.ready = false
-
-  me.filter = typeof props.filter === "function" ? props.filter: null
-
-  // start the ball rolling.
-  // this checks what's there already, and then calls
-  // me._create() to call the impl-specific creation stuff.
-  me._stat(current)
-}
-
-// Calling this means that it's something we can't create.
-// Just assert that it's already there, otherwise raise a warning.
-Writer.prototype._create = function () {
-  var me = this
-  fs[me.props.follow ? "stat" : "lstat"](me._path, function (er, current) {
-    if (er) {
-      return me.warn("Cannot create " + me._path + "\n" +
-                     "Unsupported type: "+me.type, "ENOTSUP")
-    }
-    me._finish()
-  })
-}
-
-Writer.prototype._stat = function (current) {
-  var me = this
-    , props = me.props
-    , stat = props.follow ? "stat" : "lstat"
-    , who = me._proxy || me
-
-  if (current) statCb(null, current)
-  else fs[stat](me._path, statCb)
-
-  function statCb (er, current) {
-    if (me.filter && !me.filter.call(who, who, current)) {
-      me._aborted = true
-      me.emit("end")
-      me.emit("close")
-      return
-    }
-
-    // if it's not there, great.  We'll just create it.
-    // if it is there, then we'll need to change whatever differs
-    if (er || !current) {
-      return create(me)
-    }
-
-    me._old = current
-    var currentType = getType(current)
-
-    // if it's a type change, then we need to clobber or error.
-    // if it's not a type change, then let the impl take care of it.
-    if (currentType !== me.type) {
-      return rimraf(me._path, function (er) {
-        if (er) return me.error(er)
-        me._old = null
-        create(me)
-      })
-    }
-
-    // otherwise, just handle in the app-specific way
-    // this creates a fs.WriteStream, or mkdir's, or whatever
-    create(me)
-  }
-}
-
-function create (me) {
-  // console.error("W create", me._path, Writer.dirmode)
-
-  // XXX Need to clobber non-dirs that are in the way,
-  // unless { clobber: false } in the props.
-  mkdir(path.dirname(me._path), Writer.dirmode, function (er, made) {
-    // console.error("W created", path.dirname(me._path), er)
-    if (er) return me.error(er)
-
-    // later on, we have to set the mode and owner for these
-    me._madeDir = made
-    return me._create()
-  })
-}
-
-function endChmod (me, want, current, path, cb) {
-    var wantMode = want.mode
-      , chmod = want.follow || me.type !== "SymbolicLink"
-              ? "chmod" : "lchmod"
-
-  if (!fs[chmod]) return cb()
-  if (typeof wantMode !== "number") return cb()
-
-  var curMode = current.mode & 0777
-  wantMode = wantMode & 0777
-  if (wantMode === curMode) return cb()
-
-  fs[chmod](path, wantMode, cb)
-}
-
-
-function endChown (me, want, current, path, cb) {
-  // Don't even try it unless root.  Too easy to EPERM.
-  if (process.platform === "win32") return cb()
-  if (!process.getuid || !process.getuid() === 0) return cb()
-  if (typeof want.uid !== "number" &&
-      typeof want.gid !== "number" ) return cb()
-
-  if (current.uid === want.uid &&
-      current.gid === want.gid) return cb()
-
-  var chown = (me.props.follow || me.type !== "SymbolicLink")
-            ? "chown" : "lchown"
-  if (!fs[chown]) return cb()
-
-  if (typeof want.uid !== "number") want.uid = current.uid
-  if (typeof want.gid !== "number") want.gid = current.gid
-
-  fs[chown](path, want.uid, want.gid, cb)
-}
-
-function endUtimes (me, want, current, path, cb) {
-  if (!fs.utimes || process.platform === "win32") return cb()
-
-  var utimes = (want.follow || me.type !== "SymbolicLink")
-             ? "utimes" : "lutimes"
-
-  if (utimes === "lutimes" && !fs[utimes]) {
-    utimes = "utimes"
-  }
-
-  if (!fs[utimes]) return cb()
-
-  var curA = current.atime
-    , curM = current.mtime
-    , meA = want.atime
-    , meM = want.mtime
-
-  if (meA === undefined) meA = curA
-  if (meM === undefined) meM = curM
-
-  if (!isDate(meA)) meA = new Date(meA)
-  if (!isDate(meM)) meA = new Date(meM)
-
-  if (meA.getTime() === curA.getTime() &&
-      meM.getTime() === curM.getTime()) return cb()
-
-  fs[utimes](path, meA, meM, cb)
-}
-
-
-// XXX This function is beastly.  Break it up!
-Writer.prototype._finish = function () {
-  var me = this
-
-  // console.error(" W Finish", me._path, me.size)
-
-  // set up all the things.
-  // At this point, we're already done writing whatever we've gotta write,
-  // adding files to the dir, etc.
-  var todo = 0
-  var errState = null
-  var done = false
-
-  if (me._old) {
-    // the times will almost *certainly* have changed.
-    // adds the utimes syscall, but remove another stat.
-    me._old.atime = new Date(0)
-    me._old.mtime = new Date(0)
-    // console.error(" W Finish Stale Stat", me._path, me.size)
-    setProps(me._old)
-  } else {
-    var stat = me.props.follow ? "stat" : "lstat"
-    // console.error(" W Finish Stating", me._path, me.size)
-    fs[stat](me._path, function (er, current) {
-      // console.error(" W Finish Stated", me._path, me.size, current)
-      if (er) {
-        // if we're in the process of writing out a
-        // directory, it's very possible that the thing we're linking to
-        // doesn't exist yet (especially if it was intended as a symlink),
-        // so swallow ENOENT errors here and just soldier on.
-        if (er.code === "ENOENT" &&
-            (me.type === "Link" || me.type === "SymbolicLink") &&
-            process.platform === "win32") {
-          me.ready = true
-          me.emit("ready")
-          me.emit("end")
-          me.emit("close")
-          me.end = me._finish = function () {}
-          return
-        } else return me.error(er)
-      }
-      setProps(me._old = current)
-    })
-  }
-
-  return
-
-  function setProps (current) {
-    todo += 3
-    endChmod(me, me.props, current, me._path, next("chmod"))
-    endChown(me, me.props, current, me._path, next("chown"))
-    endUtimes(me, me.props, current, me._path, next("utimes"))
-  }
-
-  function next (what) {
-    return function (er) {
-      // console.error("   W Finish", what, todo)
-      if (errState) return
-      if (er) {
-        er.fstream_finish_call = what
-        return me.error(errState = er)
-      }
-      if (--todo > 0) return
-      if (done) return
-      done = true
-
-      // we may still need to set the mode/etc. on some parent dirs
-      // that were created previously.  delay end/close until then.
-      if (!me._madeDir) return end()
-      else endMadeDir(me, me._path, end)
-
-      function end (er) {
-        if (er) {
-          er.fstream_finish_call = "setupMadeDir"
-          return me.error(er)
-        }
-        // all the props have been set, so we're completely done.
-        me.emit("end")
-        me.emit("close")
-      }
-    }
-  }
-}
-
-function endMadeDir (me, p, cb) {
-  var made = me._madeDir
-  // everything *between* made and path.dirname(me._path)
-  // needs to be set up.  Note that this may just be one dir.
-  var d = path.dirname(p)
-
-  endMadeDir_(me, d, function (er) {
-    if (er) return cb(er)
-    if (d === made) {
-      return cb()
-    }
-    endMadeDir(me, d, cb)
-  })
-}
-
-function endMadeDir_ (me, p, cb) {
-  var dirProps = {}
-  Object.keys(me.props).forEach(function (k) {
-    dirProps[k] = me.props[k]
-
-    // only make non-readable dirs if explicitly requested.
-    if (k === "mode" && me.type !== "Directory") {
-      dirProps[k] = dirProps[k] | 0111
-    }
-  })
-
-  var todo = 3
-  , errState = null
-  fs.stat(p, function (er, current) {
-    if (er) return cb(errState = er)
-    endChmod(me, dirProps, current, p, next)
-    endChown(me, dirProps, current, p, next)
-    endUtimes(me, dirProps, current, p, next)
-  })
-
-  function next (er) {
-    if (errState) return
-    if (er) return cb(errState = er)
-    if (-- todo === 0) return cb()
-  }
-}
-
-Writer.prototype.pipe = function () {
-  this.error("Can't pipe from writable stream")
-}
-
-Writer.prototype.add = function () {
-  this.error("Cannot add to non-Directory type")
-}
-
-Writer.prototype.write = function () {
-  return true
-}
-
-function objectToString (d) {
-  return Object.prototype.toString.call(d)
-}
-
-function isDate(d) {
-  return typeof d === 'object' && objectToString(d) === '[object Date]';
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/.npmignore
deleted file mode 100644
index c2658d7d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules/
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/LICENSE
deleted file mode 100644
index 0c44ae71..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Isaac Z. Schlueter ("Author")
-All rights reserved.
-
-The BSD License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-2. 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 AUTHOR 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 AUTHOR 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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/README.md
deleted file mode 100644
index eb1a1093..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# graceful-fs
-
-graceful-fs functions as a drop-in replacement for the fs module,
-making various improvements.
-
-The improvements are meant to normalize behavior across different
-platforms and environments, and to make filesystem access more
-resilient to errors.
-
-## Improvements over fs module
-
-graceful-fs:
-
-* Queues up `open` and `readdir` calls, and retries them once
-  something closes if there is an EMFILE error from too many file
-  descriptors.
-* fixes `lchmod` for Node versions prior to 0.6.2.
-* implements `fs.lutimes` if possible. Otherwise it becomes a noop.
-* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or
-  `lchown` if the user isn't root.
-* makes `lchmod` and `lchown` become noops, if not available.
-* retries reading a file if `read` results in EAGAIN error.
-
-On Windows, it retries renaming a file for up to one second if `EACCESS`
-or `EPERM` error occurs, likely because antivirus software has locked
-the directory.
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js
deleted file mode 100644
index c84db910..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/graceful-fs.js
+++ /dev/null
@@ -1,160 +0,0 @@
-// Monkey-patching the fs module.
-// It's ugly, but there is simply no other way to do this.
-var fs = module.exports = require('fs')
-
-var assert = require('assert')
-
-// fix up some busted stuff, mostly on windows and old nodes
-require('./polyfills.js')
-
-// The EMFILE enqueuing stuff
-
-var util = require('util')
-
-function noop () {}
-
-var debug = noop
-if (util.debuglog)
-  debug = util.debuglog('gfs')
-else if (/\bgfs\b/i.test(process.env.NODE_DEBUG || ''))
-  debug = function() {
-    var m = util.format.apply(util, arguments)
-    m = 'GFS: ' + m.split(/\n/).join('\nGFS: ')
-    console.error(m)
-  }
-
-if (/\bgfs\b/i.test(process.env.NODE_DEBUG || '')) {
-  process.on('exit', function() {
-    debug('fds', fds)
-    debug(queue)
-    assert.equal(queue.length, 0)
-  })
-}
-
-
-var originalOpen = fs.open
-fs.open = open
-
-function open(path, flags, mode, cb) {
-  if (typeof mode === "function") cb = mode, mode = null
-  if (typeof cb !== "function") cb = noop
-  new OpenReq(path, flags, mode, cb)
-}
-
-function OpenReq(path, flags, mode, cb) {
-  this.path = path
-  this.flags = flags
-  this.mode = mode
-  this.cb = cb
-  Req.call(this)
-}
-
-util.inherits(OpenReq, Req)
-
-OpenReq.prototype.process = function() {
-  originalOpen.call(fs, this.path, this.flags, this.mode, this.done)
-}
-
-var fds = {}
-OpenReq.prototype.done = function(er, fd) {
-  debug('open done', er, fd)
-  if (fd)
-    fds['fd' + fd] = this.path
-  Req.prototype.done.call(this, er, fd)
-}
-
-
-var originalReaddir = fs.readdir
-fs.readdir = readdir
-
-function readdir(path, cb) {
-  if (typeof cb !== "function") cb = noop
-  new ReaddirReq(path, cb)
-}
-
-function ReaddirReq(path, cb) {
-  this.path = path
-  this.cb = cb
-  Req.call(this)
-}
-
-util.inherits(ReaddirReq, Req)
-
-ReaddirReq.prototype.process = function() {
-  originalReaddir.call(fs, this.path, this.done)
-}
-
-ReaddirReq.prototype.done = function(er, files) {
-  if (files && files.sort)
-    files = files.sort()
-  Req.prototype.done.call(this, er, files)
-  onclose()
-}
-
-
-var originalClose = fs.close
-fs.close = close
-
-function close (fd, cb) {
-  debug('close', fd)
-  if (typeof cb !== "function") cb = noop
-  delete fds['fd' + fd]
-  originalClose.call(fs, fd, function(er) {
-    onclose()
-    cb(er)
-  })
-}
-
-
-var originalCloseSync = fs.closeSync
-fs.closeSync = closeSync
-
-function closeSync (fd) {
-  try {
-    return originalCloseSync(fd)
-  } finally {
-    onclose()
-  }
-}
-
-
-// Req class
-function Req () {
-  // start processing
-  this.done = this.done.bind(this)
-  this.failures = 0
-  this.process()
-}
-
-Req.prototype.done = function (er, result) {
-  var tryAgain = false
-  if (er) {
-    var code = er.code
-    var tryAgain = code === "EMFILE"
-    if (process.platform === "win32")
-      tryAgain = tryAgain || code === "OK"
-  }
-
-  if (tryAgain) {
-    this.failures ++
-    enqueue(this)
-  } else {
-    var cb = this.cb
-    cb(er, result)
-  }
-}
-
-var queue = []
-
-function enqueue(req) {
-  queue.push(req)
-  debug('enqueue %d %s', queue.length, req.constructor.name, req)
-}
-
-function onclose() {
-  var req = queue.shift()
-  if (req) {
-    debug('process', req.constructor.name, req)
-    req.process()
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/package.json
deleted file mode 100644
index 8b6a2fac..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/package.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me"
-  },
-  "name": "graceful-fs",
-  "description": "A drop-in replacement for fs, making various improvements.",
-  "version": "2.0.3",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-graceful-fs.git"
-  },
-  "main": "graceful-fs.js",
-  "engines": {
-    "node": ">=0.4.0"
-  },
-  "directories": {
-    "test": "test"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "keywords": [
-    "fs",
-    "module",
-    "reading",
-    "retry",
-    "retries",
-    "queue",
-    "error",
-    "errors",
-    "handling",
-    "EMFILE",
-    "EAGAIN",
-    "EINVAL",
-    "EPERM",
-    "EACCESS"
-  ],
-  "license": "BSD",
-  "readme": "# graceful-fs\n\ngraceful-fs functions as a drop-in replacement for the fs module,\nmaking various improvements.\n\nThe improvements are meant to normalize behavior across different\nplatforms and environments, and to make filesystem access more\nresilient to errors.\n\n## Improvements over fs module\n\ngraceful-fs:\n\n* Queues up `open` and `readdir` calls, and retries them once\n  something closes if there is an EMFILE error from too many file\n  descriptors.\n* fixes `lchmod` for Node versions prior to 0.6.2.\n* implements `fs.lutimes` if possible. Otherwise it becomes a noop.\n* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or\n  `lchown` if the user isn't root.\n* makes `lchmod` and `lchown` become noops, if not available.\n* retries reading a file if `read` results in EAGAIN error.\n\nOn Windows, it retries renaming a file for up to one second if `EACCESS`\nor `EPERM` error occurs, likely because antivirus software has locked\nthe directory.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/node-graceful-fs/issues"
-  },
-  "homepage": "https://github.com/isaacs/node-graceful-fs",
-  "_id": "graceful-fs@2.0.3",
-  "_shasum": "7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0",
-  "_from": "graceful-fs@~2.0.0",
-  "_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/polyfills.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/polyfills.js
deleted file mode 100644
index afc83b3f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/polyfills.js
+++ /dev/null
@@ -1,228 +0,0 @@
-var fs = require('fs')
-var constants = require('constants')
-
-var origCwd = process.cwd
-var cwd = null
-process.cwd = function() {
-  if (!cwd)
-    cwd = origCwd.call(process)
-  return cwd
-}
-var chdir = process.chdir
-process.chdir = function(d) {
-  cwd = null
-  chdir.call(process, d)
-}
-
-// (re-)implement some things that are known busted or missing.
-
-// lchmod, broken prior to 0.6.2
-// back-port the fix here.
-if (constants.hasOwnProperty('O_SYMLINK') &&
-    process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
-  fs.lchmod = function (path, mode, callback) {
-    callback = callback || noop
-    fs.open( path
-           , constants.O_WRONLY | constants.O_SYMLINK
-           , mode
-           , function (err, fd) {
-      if (err) {
-        callback(err)
-        return
-      }
-      // prefer to return the chmod error, if one occurs,
-      // but still try to close, and report closing errors if they occur.
-      fs.fchmod(fd, mode, function (err) {
-        fs.close(fd, function(err2) {
-          callback(err || err2)
-        })
-      })
-    })
-  }
-
-  fs.lchmodSync = function (path, mode) {
-    var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
-
-    // prefer to return the chmod error, if one occurs,
-    // but still try to close, and report closing errors if they occur.
-    var err, err2
-    try {
-      var ret = fs.fchmodSync(fd, mode)
-    } catch (er) {
-      err = er
-    }
-    try {
-      fs.closeSync(fd)
-    } catch (er) {
-      err2 = er
-    }
-    if (err || err2) throw (err || err2)
-    return ret
-  }
-}
-
-
-// lutimes implementation, or no-op
-if (!fs.lutimes) {
-  if (constants.hasOwnProperty("O_SYMLINK")) {
-    fs.lutimes = function (path, at, mt, cb) {
-      fs.open(path, constants.O_SYMLINK, function (er, fd) {
-        cb = cb || noop
-        if (er) return cb(er)
-        fs.futimes(fd, at, mt, function (er) {
-          fs.close(fd, function (er2) {
-            return cb(er || er2)
-          })
-        })
-      })
-    }
-
-    fs.lutimesSync = function (path, at, mt) {
-      var fd = fs.openSync(path, constants.O_SYMLINK)
-        , err
-        , err2
-        , ret
-
-      try {
-        var ret = fs.futimesSync(fd, at, mt)
-      } catch (er) {
-        err = er
-      }
-      try {
-        fs.closeSync(fd)
-      } catch (er) {
-        err2 = er
-      }
-      if (err || err2) throw (err || err2)
-      return ret
-    }
-
-  } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) {
-    // maybe utimensat will be bound soonish?
-    fs.lutimes = function (path, at, mt, cb) {
-      fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb)
-    }
-
-    fs.lutimesSync = function (path, at, mt) {
-      return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW)
-    }
-
-  } else {
-    fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
-    fs.lutimesSync = function () {}
-  }
-}
-
-
-// https://github.com/isaacs/node-graceful-fs/issues/4
-// Chown should not fail on einval or eperm if non-root.
-
-fs.chown = chownFix(fs.chown)
-fs.fchown = chownFix(fs.fchown)
-fs.lchown = chownFix(fs.lchown)
-
-fs.chownSync = chownFixSync(fs.chownSync)
-fs.fchownSync = chownFixSync(fs.fchownSync)
-fs.lchownSync = chownFixSync(fs.lchownSync)
-
-function chownFix (orig) {
-  if (!orig) return orig
-  return function (target, uid, gid, cb) {
-    return orig.call(fs, target, uid, gid, function (er, res) {
-      if (chownErOk(er)) er = null
-      cb(er, res)
-    })
-  }
-}
-
-function chownFixSync (orig) {
-  if (!orig) return orig
-  return function (target, uid, gid) {
-    try {
-      return orig.call(fs, target, uid, gid)
-    } catch (er) {
-      if (!chownErOk(er)) throw er
-    }
-  }
-}
-
-function chownErOk (er) {
-  // if there's no getuid, or if getuid() is something other than 0,
-  // and the error is EINVAL or EPERM, then just ignore it.
-  // This specific case is a silent failure in cp, install, tar,
-  // and most other unix tools that manage permissions.
-  // When running as root, or if other types of errors are encountered,
-  // then it's strict.
-  if (!er || (!process.getuid || process.getuid() !== 0)
-      && (er.code === "EINVAL" || er.code === "EPERM")) return true
-}
-
-
-// if lchmod/lchown do not exist, then make them no-ops
-if (!fs.lchmod) {
-  fs.lchmod = function (path, mode, cb) {
-    process.nextTick(cb)
-  }
-  fs.lchmodSync = function () {}
-}
-if (!fs.lchown) {
-  fs.lchown = function (path, uid, gid, cb) {
-    process.nextTick(cb)
-  }
-  fs.lchownSync = function () {}
-}
-
-
-
-// on Windows, A/V software can lock the directory, causing this
-// to fail with an EACCES or EPERM if the directory contains newly
-// created files.  Try again on failure, for up to 1 second.
-if (process.platform === "win32") {
-  var rename_ = fs.rename
-  fs.rename = function rename (from, to, cb) {
-    var start = Date.now()
-    rename_(from, to, function CB (er) {
-      if (er
-          && (er.code === "EACCES" || er.code === "EPERM")
-          && Date.now() - start < 1000) {
-        return rename_(from, to, CB)
-      }
-      cb(er)
-    })
-  }
-}
-
-
-// if read() returns EAGAIN, then just try it again.
-var read = fs.read
-fs.read = function (fd, buffer, offset, length, position, callback_) {
-  var callback
-  if (callback_ && typeof callback_ === 'function') {
-    var eagCounter = 0
-    callback = function (er, _, __) {
-      if (er && er.code === 'EAGAIN' && eagCounter < 10) {
-        eagCounter ++
-        return read.call(fs, fd, buffer, offset, length, position, callback)
-      }
-      callback_.apply(this, arguments)
-    }
-  }
-  return read.call(fs, fd, buffer, offset, length, position, callback)
-}
-
-var readSync = fs.readSync
-fs.readSync = function (fd, buffer, offset, length, position) {
-  var eagCounter = 0
-  while (true) {
-    try {
-      return readSync.call(fs, fd, buffer, offset, length, position)
-    } catch (er) {
-      if (er.code === 'EAGAIN' && eagCounter < 10) {
-        eagCounter ++
-        continue
-      }
-      throw er
-    }
-  }
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/open.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/open.js
deleted file mode 100644
index 104f36b0..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/open.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var test = require('tap').test
-var fs = require('../graceful-fs.js')
-
-test('graceful fs is monkeypatched fs', function (t) {
-  t.equal(fs, require('fs'))
-  t.end()
-})
-
-test('open an existing file works', function (t) {
-  var fd = fs.openSync(__filename, 'r')
-  fs.closeSync(fd)
-  fs.open(__filename, 'r', function (er, fd) {
-    if (er) throw er
-    fs.close(fd, function (er) {
-      if (er) throw er
-      t.pass('works')
-      t.end()
-    })
-  })
-})
-
-test('open a non-existing file throws', function (t) {
-  var er
-  try {
-    var fd = fs.openSync('this file does not exist', 'r')
-  } catch (x) {
-    er = x
-  }
-  t.ok(er, 'should throw')
-  t.notOk(fd, 'should not get an fd')
-  t.equal(er.code, 'ENOENT')
-
-  fs.open('neither does this file', 'r', function (er, fd) {
-    t.ok(er, 'should throw')
-    t.notOk(fd, 'should not get an fd')
-    t.equal(er.code, 'ENOENT')
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js
deleted file mode 100644
index aeaedf1c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/graceful-fs/test/readdir-sort.js
+++ /dev/null
@@ -1,21 +0,0 @@
-var test = require("tap").test
-var fs = require("fs")
-
-var readdir = fs.readdir
-fs.readdir = function(path, cb) {
-  process.nextTick(function() {
-    cb(null, ["b", "z", "a"])
-  })
-}
-
-var g = require("../")
-
-test("readdir reorder", function (t) {
-  g.readdir("whatevers", function (er, files) {
-    if (er)
-      throw er
-    console.error(files)
-    t.same(files, [ "a", "b", "z" ])
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.npmignore
deleted file mode 100644
index 9303c347..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules/
-npm-debug.log
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.travis.yml
deleted file mode 100644
index 84fd7ca2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
-  - 0.8
-  - 0.9
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/LICENSE
deleted file mode 100644
index 432d1aeb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/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/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/examples/pow.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/examples/pow.js
deleted file mode 100644
index e6924212..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/examples/pow.js
+++ /dev/null
@@ -1,6 +0,0 @@
-var mkdirp = require('mkdirp');
-
-mkdirp('/tmp/foo/bar/baz', function (err) {
-    if (err) console.error(err)
-    else console.log('pow!')
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/index.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/index.js
deleted file mode 100644
index fda6de8a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/index.js
+++ /dev/null
@@ -1,82 +0,0 @@
-var path = require('path');
-var fs = require('fs');
-
-module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
-
-function mkdirP (p, mode, f, made) {
-    if (typeof mode === 'function' || mode === undefined) {
-        f = mode;
-        mode = 0777 & (~process.umask());
-    }
-    if (!made) made = null;
-
-    var cb = f || function () {};
-    if (typeof mode === 'string') mode = parseInt(mode, 8);
-    p = path.resolve(p);
-
-    fs.mkdir(p, mode, function (er) {
-        if (!er) {
-            made = made || p;
-            return cb(null, made);
-        }
-        switch (er.code) {
-            case 'ENOENT':
-                mkdirP(path.dirname(p), mode, function (er, made) {
-                    if (er) cb(er, made);
-                    else mkdirP(p, mode, cb, made);
-                });
-                break;
-
-            // In the case of any other error, just see if there's a dir
-            // there already.  If so, then hooray!  If not, then something
-            // is borked.
-            default:
-                fs.stat(p, function (er2, stat) {
-                    // if the stat fails, then that's super weird.
-                    // let the original error be the failure reason.
-                    if (er2 || !stat.isDirectory()) cb(er, made)
-                    else cb(null, made);
-                });
-                break;
-        }
-    });
-}
-
-mkdirP.sync = function sync (p, mode, made) {
-    if (mode === undefined) {
-        mode = 0777 & (~process.umask());
-    }
-    if (!made) made = null;
-
-    if (typeof mode === 'string') mode = parseInt(mode, 8);
-    p = path.resolve(p);
-
-    try {
-        fs.mkdirSync(p, mode);
-        made = made || p;
-    }
-    catch (err0) {
-        switch (err0.code) {
-            case 'ENOENT' :
-                made = sync(path.dirname(p), mode, made);
-                sync(p, mode, made);
-                break;
-
-            // In the case of any other error, just see if there's a dir
-            // there already.  If so, then hooray!  If not, then something
-            // is borked.
-            default:
-                var stat;
-                try {
-                    stat = fs.statSync(p);
-                }
-                catch (err1) {
-                    throw err0;
-                }
-                if (!stat.isDirectory()) throw err0;
-                break;
-        }
-    }
-
-    return made;
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/package.json
deleted file mode 100644
index a59f2bea..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/package.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-  "name": "mkdirp",
-  "description": "Recursively mkdir, like `mkdir -p`",
-  "version": "0.3.5",
-  "author": {
-    "name": "James Halliday",
-    "email": "mail@substack.net",
-    "url": "http://substack.net"
-  },
-  "main": "./index",
-  "keywords": [
-    "mkdir",
-    "directory"
-  ],
-  "repository": {
-    "type": "git",
-    "url": "http://github.com/substack/node-mkdirp.git"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "devDependencies": {
-    "tap": "~0.4.0"
-  },
-  "license": "MIT",
-  "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n    \nmkdirp('/tmp/foo/bar/baz', function (err) {\n    if (err) console.error(err)\n    else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n",
-  "readmeFilename": "readme.markdown",
-  "bugs": {
-    "url": "https://github.com/substack/node-mkdirp/issues"
-  },
-  "homepage": "https://github.com/substack/node-mkdirp",
-  "_id": "mkdirp@0.3.5",
-  "_shasum": "de3e5f8961c88c787ee1368df849ac4413eca8d7",
-  "_from": "mkdirp@0.3",
-  "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/readme.markdown b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/readme.markdown
deleted file mode 100644
index 83b0216a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/readme.markdown
+++ /dev/null
@@ -1,63 +0,0 @@
-# mkdirp
-
-Like `mkdir -p`, but in node.js!
-
-[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
-
-# example
-
-## pow.js
-
-```js
-var mkdirp = require('mkdirp');
-    
-mkdirp('/tmp/foo/bar/baz', function (err) {
-    if (err) console.error(err)
-    else console.log('pow!')
-});
-```
-
-Output
-
-```
-pow!
-```
-
-And now /tmp/foo/bar/baz exists, huzzah!
-
-# methods
-
-```js
-var mkdirp = require('mkdirp');
-```
-
-## mkdirp(dir, mode, cb)
-
-Create a new directory and any necessary subdirectories at `dir` with octal
-permission string `mode`.
-
-If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
-
-`cb(err, made)` fires with the error or the first directory `made`
-that had to be created, if any.
-
-## mkdirp.sync(dir, mode)
-
-Synchronously create a new directory and any necessary subdirectories at `dir`
-with octal permission string `mode`.
-
-If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
-
-Returns the first directory that had to be created, if any.
-
-# install
-
-With [npm](http://npmjs.org) do:
-
-```
-npm install mkdirp
-```
-
-# license
-
-MIT
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/chmod.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/chmod.js
deleted file mode 100644
index 520dcb8e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/chmod.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-var ps = [ '', 'tmp' ];
-
-for (var i = 0; i < 25; i++) {
-    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    ps.push(dir);
-}
-
-var file = ps.join('/');
-
-test('chmod-pre', function (t) {
-    var mode = 0744
-    mkdirp(file, mode, function (er) {
-        t.ifError(er, 'should not error');
-        fs.stat(file, function (er, stat) {
-            t.ifError(er, 'should exist');
-            t.ok(stat && stat.isDirectory(), 'should be directory');
-            t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
-            t.end();
-        });
-    });
-});
-
-test('chmod', function (t) {
-    var mode = 0755
-    mkdirp(file, mode, function (er) {
-        t.ifError(er, 'should not error');
-        fs.stat(file, function (er, stat) {
-            t.ifError(er, 'should exist');
-            t.ok(stat && stat.isDirectory(), 'should be directory');
-            t.end();
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/clobber.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/clobber.js
deleted file mode 100644
index 0eb70998..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/clobber.js
+++ /dev/null
@@ -1,37 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-var ps = [ '', 'tmp' ];
-
-for (var i = 0; i < 25; i++) {
-    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    ps.push(dir);
-}
-
-var file = ps.join('/');
-
-// a file in the way
-var itw = ps.slice(0, 3).join('/');
-
-
-test('clobber-pre', function (t) {
-    console.error("about to write to "+itw)
-    fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
-
-    fs.stat(itw, function (er, stat) {
-        t.ifError(er)
-        t.ok(stat && stat.isFile(), 'should be file')
-        t.end()
-    })
-})
-
-test('clobber', function (t) {
-    t.plan(2);
-    mkdirp(file, 0755, function (err) {
-        t.ok(err);
-        t.equal(err.code, 'ENOTDIR');
-        t.end();
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js
deleted file mode 100644
index b07cd70c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/mkdirp.js
+++ /dev/null
@@ -1,28 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('woo', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var file = '/tmp/' + [x,y,z].join('/');
-    
-    mkdirp(file, 0755, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    t.equal(stat.mode & 0777, 0755);
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm.js
deleted file mode 100644
index 23a7abbd..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('async perm', function (t) {
-    t.plan(2);
-    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
-    
-    mkdirp(file, 0755, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    t.equal(stat.mode & 0777, 0755);
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
-
-test('async root perm', function (t) {
-    mkdirp('/tmp', 0755, function (err) {
-        if (err) t.fail(err);
-        t.end();
-    });
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js
deleted file mode 100644
index f685f609..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/perm_sync.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('sync perm', function (t) {
-    t.plan(2);
-    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
-    
-    mkdirp.sync(file, 0755);
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.equal(stat.mode & 0777, 0755);
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        })
-    });
-});
-
-test('sync root perm', function (t) {
-    t.plan(1);
-    
-    var file = '/tmp';
-    mkdirp.sync(file, 0755);
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/race.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/race.js
deleted file mode 100644
index 96a04476..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/race.js
+++ /dev/null
@@ -1,41 +0,0 @@
-var mkdirp = require('../').mkdirp;
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('race', function (t) {
-    t.plan(4);
-    var ps = [ '', 'tmp' ];
-    
-    for (var i = 0; i < 25; i++) {
-        var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-        ps.push(dir);
-    }
-    var file = ps.join('/');
-    
-    var res = 2;
-    mk(file, function () {
-        if (--res === 0) t.end();
-    });
-    
-    mk(file, function () {
-        if (--res === 0) t.end();
-    });
-    
-    function mk (file, cb) {
-        mkdirp(file, 0755, function (err) {
-            if (err) t.fail(err);
-            else path.exists(file, function (ex) {
-                if (!ex) t.fail('file not created')
-                else fs.stat(file, function (err, stat) {
-                    if (err) t.fail(err)
-                    else {
-                        t.equal(stat.mode & 0777, 0755);
-                        t.ok(stat.isDirectory(), 'target not a directory');
-                        if (cb) cb();
-                    }
-                })
-            })
-        });
-    }
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/rel.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/rel.js
deleted file mode 100644
index 79858243..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/rel.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('rel', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var cwd = process.cwd();
-    process.chdir('/tmp');
-    
-    var file = [x,y,z].join('/');
-    
-    mkdirp(file, 0755, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    process.chdir(cwd);
-                    t.equal(stat.mode & 0777, 0755);
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return.js
deleted file mode 100644
index bce68e56..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('return value', function (t) {
-    t.plan(4);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    // should return the first dir created.
-    // By this point, it would be profoundly surprising if /tmp didn't
-    // already exist, since every other test makes things in there.
-    mkdirp(file, function (err, made) {
-        t.ifError(err);
-        t.equal(made, '/tmp/' + x);
-        mkdirp(file, function (err, made) {
-          t.ifError(err);
-          t.equal(made, null);
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return_sync.js
deleted file mode 100644
index 7c222d35..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/return_sync.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('return value', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    // should return the first dir created.
-    // By this point, it would be profoundly surprising if /tmp didn't
-    // already exist, since every other test makes things in there.
-    // Note that this will throw on failure, which will fail the test.
-    var made = mkdirp.sync(file);
-    t.equal(made, '/tmp/' + x);
-
-    // making the same file again should have no effect.
-    made = mkdirp.sync(file);
-    t.equal(made, null);
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/root.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/root.js
deleted file mode 100644
index 97ad7a2f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/root.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('root', function (t) {
-    // '/' on unix, 'c:/' on windows.
-    var file = path.resolve('/');
-
-    mkdirp(file, 0755, function (err) {
-        if (err) throw err
-        fs.stat(file, function (er, stat) {
-            if (er) throw er
-            t.ok(stat.isDirectory(), 'target is a directory');
-            t.end();
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/sync.js
deleted file mode 100644
index 7530cada..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/sync.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('sync', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    try {
-        mkdirp.sync(file, 0755);
-    } catch (err) {
-        t.fail(err);
-        return t.end();
-    }
-
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.equal(stat.mode & 0777, 0755);
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask.js
deleted file mode 100644
index 64ccafe2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask.js
+++ /dev/null
@@ -1,28 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('implicit mode from umask', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    
-    var file = '/tmp/' + [x,y,z].join('/');
-    
-    mkdirp(file, function (err) {
-        if (err) t.fail(err);
-        else path.exists(file, function (ex) {
-            if (!ex) t.fail('file not created')
-            else fs.stat(file, function (err, stat) {
-                if (err) t.fail(err)
-                else {
-                    t.equal(stat.mode & 0777, 0777 & (~process.umask()));
-                    t.ok(stat.isDirectory(), 'target not a directory');
-                    t.end();
-                }
-            })
-        })
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js
deleted file mode 100644
index 35bd5cbb..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/node_modules/mkdirp/test/umask_sync.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var mkdirp = require('../');
-var path = require('path');
-var fs = require('fs');
-var test = require('tap').test;
-
-test('umask sync modes', function (t) {
-    t.plan(2);
-    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
-
-    var file = '/tmp/' + [x,y,z].join('/');
-
-    try {
-        mkdirp.sync(file);
-    } catch (err) {
-        t.fail(err);
-        return t.end();
-    }
-
-    path.exists(file, function (ex) {
-        if (!ex) t.fail('file not created')
-        else fs.stat(file, function (err, stat) {
-            if (err) t.fail(err)
-            else {
-                t.equal(stat.mode & 0777, (0777 & (~process.umask())));
-                t.ok(stat.isDirectory(), 'target not a directory');
-                t.end();
-            }
-        });
-    });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/package.json
deleted file mode 100644
index 602ae2ff..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/fstream/package.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "fstream",
-  "description": "Advanced file system stream things",
-  "version": "0.1.25",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/fstream.git"
-  },
-  "main": "fstream.js",
-  "engines": {
-    "node": ">=0.6"
-  },
-  "dependencies": {
-    "rimraf": "2",
-    "mkdirp": "0.3",
-    "graceful-fs": "~2.0.0",
-    "inherits": "~2.0.0"
-  },
-  "devDependencies": {
-    "tap": ""
-  },
-  "scripts": {
-    "test": "tap examples/*.js"
-  },
-  "license": "BSD",
-  "readme": "Like FS streams, but with stat on them, and supporting directories and\nsymbolic links, as well as normal files.  Also, you can use this to set\nthe stats on a file, even if you don't change its contents, or to create\na symlink, etc.\n\nSo, for example, you can \"write\" a directory, and it'll call `mkdir`.  You\ncan specify a uid and gid, and it'll call `chown`.  You can specify a\n`mtime` and `atime`, and it'll call `utimes`.  You can call it a symlink\nand provide a `linkpath` and it'll call `symlink`.\n\nNote that it won't automatically resolve symbolic links.  So, if you\ncall `fstream.Reader('/some/symlink')` then you'll get an object\nthat stats and then ends immediately (since it has no data).  To follow\nsymbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:\ntrue })`.\n\nThere are various checks to make sure that the bytes emitted are the\nsame as the intended size, if the size is set.\n\n## Examples\n\n```javascript\nfstream\n  .Writer({ path: \"path/to/file\"\n          , mode: 0755\n          , size: 6\n          })\n  .write(\"hello\\n\")\n  .end()\n```\n\nThis will create the directories if they're missing, and then write\n`hello\\n` into the file, chmod it to 0755, and assert that 6 bytes have\nbeen written when it's done.\n\n```javascript\nfstream\n  .Writer({ path: \"path/to/file\"\n          , mode: 0755\n          , size: 6\n          , flags: \"a\"\n          })\n  .write(\"hello\\n\")\n  .end()\n```\n\nYou can pass flags in, if you want to append to a file.\n\n```javascript\nfstream\n  .Writer({ path: \"path/to/symlink\"\n          , linkpath: \"./file\"\n          , SymbolicLink: true\n          , mode: \"0755\" // octal strings supported\n          })\n  .end()\n```\n\nIf isSymbolicLink is a function, it'll be called, and if it returns\ntrue, then it'll treat it as a symlink.  If it's not a function, then\nany truish value will make a symlink, or you can set `type:\n'SymbolicLink'`, which does the same thing.\n\nNote that the linkpath is relative to the symbolic link location, not\nthe parent dir or cwd.\n\n```javascript\nfstream\n  .Reader(\"path/to/dir\")\n  .pipe(fstream.Writer(\"path/to/other/dir\"))\n```\n\nThis will do like `cp -Rp path/to/dir path/to/other/dir`.  If the other\ndir exists and isn't a directory, then it'll emit an error.  It'll also\nset the uid, gid, mode, etc. to be identical.  In this way, it's more\nlike `rsync -a` than simply a copy.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/fstream/issues"
-  },
-  "homepage": "https://github.com/isaacs/fstream",
-  "_id": "fstream@0.1.25",
-  "_shasum": "deef2db7c7898357c2b37202212a9e5b36abc732",
-  "_from": "fstream@~0.1.8",
-  "_resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.25.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/LICENSE
deleted file mode 100644
index dea3013d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/LICENSE
+++ /dev/null
@@ -1,16 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/README.md b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/README.md
deleted file mode 100644
index b1c56658..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-Browser-friendly inheritance fully compatible with standard node.js
-[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).
-
-This package exports standard `inherits` from node.js `util` module in
-node environment, but also provides alternative browser-friendly
-implementation through [browser
-field](https://gist.github.com/shtylman/4339901). Alternative
-implementation is a literal copy of standard one located in standalone
-module to avoid requiring of `util`. It also has a shim for old
-browsers with no `Object.create` support.
-
-While keeping you sure you are using standard `inherits`
-implementation in node.js environment, it allows bundlers such as
-[browserify](https://github.com/substack/node-browserify) to not
-include full `util` package to your client code if all you need is
-just `inherits` function. It worth, because browser shim for `util`
-package is large and `inherits` is often the single function you need
-from it.
-
-It's recommended to use this package instead of
-`require('util').inherits` for any code that has chances to be used
-not only in node.js but in browser too.
-
-## usage
-
-```js
-var inherits = require('inherits');
-// then use exactly as the standard one
-```
-
-## note on version ~1.0
-
-Version ~1.0 had completely different motivation and is not compatible
-neither with 2.0 nor with standard node.js `inherits`.
-
-If you are using version ~1.0 and planning to switch to ~2.0, be
-careful:
-
-* new version uses `super_` instead of `super` for referencing
-  superclass
-* new version overwrites current prototype while old one preserves any
-  existing fields on it
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits.js
deleted file mode 100644
index 29f5e24f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('util').inherits
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits_browser.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits_browser.js
deleted file mode 100644
index c1e78a75..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/inherits_browser.js
+++ /dev/null
@@ -1,23 +0,0 @@
-if (typeof Object.create === 'function') {
-  // implementation from standard node.js 'util' module
-  module.exports = function inherits(ctor, superCtor) {
-    ctor.super_ = superCtor
-    ctor.prototype = Object.create(superCtor.prototype, {
-      constructor: {
-        value: ctor,
-        enumerable: false,
-        writable: true,
-        configurable: true
-      }
-    });
-  };
-} else {
-  // old school shim for old browsers
-  module.exports = function inherits(ctor, superCtor) {
-    ctor.super_ = superCtor
-    var TempCtor = function () {}
-    TempCtor.prototype = superCtor.prototype
-    ctor.prototype = new TempCtor()
-    ctor.prototype.constructor = ctor
-  }
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/package.json
deleted file mode 100644
index facd5fdf..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "inherits",
-  "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
-  "version": "2.0.1",
-  "keywords": [
-    "inheritance",
-    "class",
-    "klass",
-    "oop",
-    "object-oriented",
-    "inherits",
-    "browser",
-    "browserify"
-  ],
-  "main": "./inherits.js",
-  "browser": "./inherits_browser.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/inherits"
-  },
-  "license": "ISC",
-  "scripts": {
-    "test": "node test"
-  },
-  "readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n  superclass\n* new version overwrites current prototype while old one preserves any\n  existing fields on it\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/inherits/issues"
-  },
-  "homepage": "https://github.com/isaacs/inherits",
-  "_id": "inherits@2.0.1",
-  "_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
-  "_from": "inherits@2",
-  "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/test.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/test.js
deleted file mode 100644
index fc53012d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/node_modules/inherits/test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var inherits = require('./inherits.js')
-var assert = require('assert')
-
-function test(c) {
-  assert(c.constructor === Child)
-  assert(c.constructor.super_ === Parent)
-  assert(Object.getPrototypeOf(c) === Child.prototype)
-  assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype)
-  assert(c instanceof Child)
-  assert(c instanceof Parent)
-}
-
-function Child() {
-  Parent.call(this)
-  test(this)
-}
-
-function Parent() {}
-
-inherits(Child, Parent)
-
-var c = new Child
-test(c)
-
-console.log('ok')
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/package.json
deleted file mode 100644
index 0d728014..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "author": {
-    "name": "Isaac Z. Schlueter",
-    "email": "i@izs.me",
-    "url": "http://blog.izs.me/"
-  },
-  "name": "tar",
-  "description": "tar for node",
-  "version": "0.1.19",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-tar.git"
-  },
-  "main": "tar.js",
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "dependencies": {
-    "inherits": "2",
-    "block-stream": "*",
-    "fstream": "~0.1.8"
-  },
-  "devDependencies": {
-    "tap": "0.x",
-    "rimraf": "1.x"
-  },
-  "license": "BSD",
-  "readme": "# node-tar\n\nTar for Node.js.\n\n[![NPM](https://nodei.co/npm/tar.png)](https://nodei.co/npm/tar/)\n\n## API\n\nSee `examples/` for usage examples.\n\n### var tar = require('tar')\n\nReturns an object with `.Pack`, `.Extract` and `.Parse` methods.\n\n### tar.Pack([properties])\n\nReturns a through stream. Use\n[fstream](https://npmjs.org/package/fstream) to write files into the\npack stream and you will receive tar archive data from the pack\nstream.\n\nThe optional `properties` object are used to set properties in the tar\n'Global Extended Header'.\n\n### tar.Extract([options])\n\nReturns a through stream. Write tar data to the stream and the files\nin the tarball will be extracted onto the filesystem.\n\n`options` can be:\n\n```js\n{\n  path: '/path/to/extract/tar/into',\n  strip: 0, // how many path segments to strip from the root when extracting\n}\n```\n\n`options` also get passed to the `fstream.Writer` instance that `tar`\nuses internally.\n\n### tar.Parse()\n\nReturns a writable stream. Write tar data to it and it will emit\n`entry` events for each entry parsed from the tarball. This is used by\n`tar.Extract`.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/isaacs/node-tar/issues"
-  },
-  "homepage": "https://github.com/isaacs/node-tar",
-  "_id": "tar@0.1.19",
-  "_shasum": "fe45941799e660ce1ea52d875d37481b4bf13eac",
-  "_from": "tar@~0.1.19",
-  "_resolved": "https://registry.npmjs.org/tar/-/tar-0.1.19.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/tar.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/tar.js
deleted file mode 100644
index a81298b9..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/tar.js
+++ /dev/null
@@ -1,173 +0,0 @@
-// field paths that every tar file must have.
-// header is padded to 512 bytes.
-var f = 0
-  , fields = {}
-  , path = fields.path = f++
-  , mode = fields.mode = f++
-  , uid = fields.uid = f++
-  , gid = fields.gid = f++
-  , size = fields.size = f++
-  , mtime = fields.mtime = f++
-  , cksum = fields.cksum = f++
-  , type = fields.type = f++
-  , linkpath = fields.linkpath = f++
-  , headerSize = 512
-  , blockSize = 512
-  , fieldSize = []
-
-fieldSize[path] = 100
-fieldSize[mode] = 8
-fieldSize[uid] = 8
-fieldSize[gid] = 8
-fieldSize[size] = 12
-fieldSize[mtime] = 12
-fieldSize[cksum] = 8
-fieldSize[type] = 1
-fieldSize[linkpath] = 100
-
-// "ustar\0" may introduce another bunch of headers.
-// these are optional, and will be nulled out if not present.
-
-var ustar = fields.ustar = f++
-  , ustarver = fields.ustarver = f++
-  , uname = fields.uname = f++
-  , gname = fields.gname = f++
-  , devmaj = fields.devmaj = f++
-  , devmin = fields.devmin = f++
-  , prefix = fields.prefix = f++
-  , fill = fields.fill = f++
-
-// terminate fields.
-fields[f] = null
-
-fieldSize[ustar] = 6
-fieldSize[ustarver] = 2
-fieldSize[uname] = 32
-fieldSize[gname] = 32
-fieldSize[devmaj] = 8
-fieldSize[devmin] = 8
-fieldSize[prefix] = 155
-fieldSize[fill] = 12
-
-// nb: prefix field may in fact be 130 bytes of prefix,
-// a null char, 12 bytes for atime, 12 bytes for ctime.
-//
-// To recognize this format:
-// 1. prefix[130] === ' ' or '\0'
-// 2. atime and ctime are octal numeric values
-// 3. atime and ctime have ' ' in their last byte
-
-var fieldEnds = {}
-  , fieldOffs = {}
-  , fe = 0
-for (var i = 0; i < f; i ++) {
-  fieldOffs[i] = fe
-  fieldEnds[i] = (fe += fieldSize[i])
-}
-
-// build a translation table of field paths.
-Object.keys(fields).forEach(function (f) {
-  if (fields[f] !== null) fields[fields[f]] = f
-})
-
-// different values of the 'type' field
-// paths match the values of Stats.isX() functions, where appropriate
-var types =
-  { 0: "File"
-  , "\0": "OldFile" // like 0
-  , "": "OldFile"
-  , 1: "Link"
-  , 2: "SymbolicLink"
-  , 3: "CharacterDevice"
-  , 4: "BlockDevice"
-  , 5: "Directory"
-  , 6: "FIFO"
-  , 7: "ContiguousFile" // like 0
-  // posix headers
-  , g: "GlobalExtendedHeader" // k=v for the rest of the archive
-  , x: "ExtendedHeader" // k=v for the next file
-  // vendor-specific stuff
-  , A: "SolarisACL" // skip
-  , D: "GNUDumpDir" // like 5, but with data, which should be skipped
-  , I: "Inode" // metadata only, skip
-  , K: "NextFileHasLongLinkpath" // data = link path of next file
-  , L: "NextFileHasLongPath" // data = path of next file
-  , M: "ContinuationFile" // skip
-  , N: "OldGnuLongPath" // like L
-  , S: "SparseFile" // skip
-  , V: "TapeVolumeHeader" // skip
-  , X: "OldExtendedHeader" // like x
-  }
-
-Object.keys(types).forEach(function (t) {
-  types[types[t]] = types[types[t]] || t
-})
-
-// values for the mode field
-var modes =
-  { suid: 04000 // set uid on extraction
-  , sgid: 02000 // set gid on extraction
-  , svtx: 01000 // set restricted deletion flag on dirs on extraction
-  , uread:  0400
-  , uwrite: 0200
-  , uexec:  0100
-  , gread:  040
-  , gwrite: 020
-  , gexec:  010
-  , oread:  4
-  , owrite: 2
-  , oexec:  1
-  , all: 07777
-  }
-
-var numeric =
-  { mode: true
-  , uid: true
-  , gid: true
-  , size: true
-  , mtime: true
-  , devmaj: true
-  , devmin: true
-  , cksum: true
-  , atime: true
-  , ctime: true
-  , dev: true
-  , ino: true
-  , nlink: true
-  }
-
-Object.keys(modes).forEach(function (t) {
-  modes[modes[t]] = modes[modes[t]] || t
-})
-
-var knownExtended =
-  { atime: true
-  , charset: true
-  , comment: true
-  , ctime: true
-  , gid: true
-  , gname: true
-  , linkpath: true
-  , mtime: true
-  , path: true
-  , realtime: true
-  , security: true
-  , size: true
-  , uid: true
-  , uname: true }
-
-
-exports.fields = fields
-exports.fieldSize = fieldSize
-exports.fieldOffs = fieldOffs
-exports.fieldEnds = fieldEnds
-exports.types = types
-exports.modes = modes
-exports.numeric = numeric
-exports.headerSize = headerSize
-exports.blockSize = blockSize
-exports.knownExtended = knownExtended
-
-exports.Pack = require("./lib/pack.js")
-exports.Parse = require("./lib/parse.js")
-exports.Extract = require("./lib/extract.js")
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/00-setup-fixtures.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/00-setup-fixtures.js
deleted file mode 100644
index 1524ff7a..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/00-setup-fixtures.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// the fixtures have some weird stuff that is painful
-// to include directly in the repo for various reasons.
-//
-// So, unpack the fixtures with the system tar first.
-//
-// This means, of course, that it'll only work if you
-// already have a tar implementation, and some of them
-// will not properly unpack the fixtures anyway.
-//
-// But, since usually those tests will fail on Windows
-// and other systems with less capable filesystems anyway,
-// at least this way we don't cause inconveniences by
-// merely cloning the repo or installing the package.
-
-var tap = require("tap")
-, child_process = require("child_process")
-, rimraf = require("rimraf")
-, test = tap.test
-, path = require("path")
-
-test("clean fixtures", function (t) {
-  rimraf(path.resolve(__dirname, "fixtures"), function (er) {
-    t.ifError(er, "rimraf ./fixtures/")
-    t.end()
-  })
-})
-
-test("clean tmp", function (t) {
-  rimraf(path.resolve(__dirname, "tmp"), function (er) {
-    t.ifError(er, "rimraf ./tmp/")
-    t.end()
-  })
-})
-
-test("extract fixtures", function (t) {
-  var c = child_process.spawn("tar"
-                             ,["xzvf", "fixtures.tgz"]
-                             ,{ cwd: __dirname })
-
-  c.stdout.on("data", errwrite)
-  c.stderr.on("data", errwrite)
-  function errwrite (chunk) {
-    process.stderr.write(chunk)
-  }
-
-  c.on("exit", function (code) {
-    t.equal(code, 0, "extract fixtures should exit with 0")
-    if (code) {
-      t.comment("Note, all tests from here on out will fail because of this.")
-    }
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/extract.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/extract.js
deleted file mode 100644
index fff48181..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/extract.js
+++ /dev/null
@@ -1,358 +0,0 @@
-var tap = require("tap")
-  , tar = require("../tar.js")
-  , fs = require("fs")
-  , path = require("path")
-  , file = path.resolve(__dirname, "fixtures/c.tar")
-  , target = path.resolve(__dirname, "tmp/extract-test")
-  , index = 0
-  , fstream = require("fstream")
-
-  , ee = 0
-  , expectEntries =
-[ { path: 'c.txt',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 513,
-    linkpath: '',
-    nlink: undefined,
-    dev: undefined,
-    ino: undefined },
-  { path: 'cc.txt',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 513,
-    linkpath: '',
-    nlink: undefined,
-    dev: undefined,
-    ino: undefined },
-  { path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 100,
-    linkpath: '',
-    nlink: undefined,
-    dev: undefined,
-    ino: undefined },
-  { path: 'Ω.txt',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 2,
-    linkpath: '',
-    nlink: undefined,
-    dev: undefined,
-    ino: undefined },
-  { path: 'Ω.txt',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 2,
-    linkpath: '',
-    nlink: 1,
-    dev: 234881026,
-    ino: 51693379 },
-  { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 200,
-    linkpath: '',
-    nlink: 1,
-    dev: 234881026,
-    ino: 51681874 },
-  { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 201,
-    linkpath: '',
-    nlink: undefined,
-    dev: undefined,
-    ino: undefined },
-  { path: '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL',
-    mode: '777',
-    type: '2',
-    depth: undefined,
-    size: 0,
-    linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    nlink: undefined,
-    dev: undefined,
-    ino: undefined },
-  { path: '200-hard',
-    mode: '644',
-    type: '0',
-    depth: undefined,
-    size: 200,
-    linkpath: '',
-    nlink: 2,
-    dev: 234881026,
-    ino: 51681874 },
-  { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    mode: '644',
-    type: '1',
-    depth: undefined,
-    size: 0,
-    linkpath: path.resolve(target, '200-hard'),
-    nlink: 2,
-    dev: 234881026,
-    ino: 51681874 } ]
-
-  , ef = 0
-  , expectFiles =
-[ { path: '',
-    mode: '40755',
-    type: 'Directory',
-    depth: 0,
-    linkpath: undefined },
-  { path: '/200-hard',
-    mode: '100644',
-    type: 'File',
-    depth: 1,
-    size: 200,
-    linkpath: undefined,
-    nlink: 2 },
-  { path: '/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    mode: '100644',
-    type: 'Link',
-    depth: 1,
-    size: 200,
-    linkpath: path.join(target, '200-hard'),
-    nlink: 2 },
-  { path: '/200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL',
-    mode: '120777',
-    type: 'SymbolicLink',
-    depth: 1,
-    size: 200,
-    linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    nlink: 1 },
-  { path: '/c.txt',
-    mode: '100644',
-    type: 'File',
-    depth: 1,
-    size: 513,
-    linkpath: undefined,
-    nlink: 1 },
-  { path: '/cc.txt',
-    mode: '100644',
-    type: 'File',
-    depth: 1,
-    size: 513,
-    linkpath: undefined,
-    nlink: 1 },
-  { path: '/r',
-    mode: '40755',
-    type: 'Directory',
-    depth: 1,
-    linkpath: undefined },
-  { path: '/r/e',
-    mode: '40755',
-    type: 'Directory',
-    depth: 2,
-    linkpath: undefined },
-  { path: '/r/e/a',
-    mode: '40755',
-    type: 'Directory',
-    depth: 3,
-    linkpath: undefined },
-  { path: '/r/e/a/l',
-    mode: '40755',
-    type: 'Directory',
-    depth: 4,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l',
-    mode: '40755',
-    type: 'Directory',
-    depth: 5,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y',
-    mode: '40755',
-    type: 'Directory',
-    depth: 6,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-',
-    mode: '40755',
-    type: 'Directory',
-    depth: 7,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d',
-    mode: '40755',
-    type: 'Directory',
-    depth: 8,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e',
-    mode: '40755',
-    type: 'Directory',
-    depth: 9,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e',
-    mode: '40755',
-    type: 'Directory',
-    depth: 10,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p',
-    mode: '40755',
-    type: 'Directory',
-    depth: 11,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-',
-    mode: '40755',
-    type: 'Directory',
-    depth: 12,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f',
-    mode: '40755',
-    type: 'Directory',
-    depth: 13,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o',
-    mode: '40755',
-    type: 'Directory',
-    depth: 14,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l',
-    mode: '40755',
-    type: 'Directory',
-    depth: 15,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d',
-    mode: '40755',
-    type: 'Directory',
-    depth: 16,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e',
-    mode: '40755',
-    type: 'Directory',
-    depth: 17,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r',
-    mode: '40755',
-    type: 'Directory',
-    depth: 18,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-',
-    mode: '40755',
-    type: 'Directory',
-    depth: 19,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p',
-    mode: '40755',
-    type: 'Directory',
-    depth: 20,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a',
-    mode: '40755',
-    type: 'Directory',
-    depth: 21,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t',
-    mode: '40755',
-    type: 'Directory',
-    depth: 22,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h',
-    mode: '40755',
-    type: 'Directory',
-    depth: 23,
-    linkpath: undefined },
-  { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-    mode: '100644',
-    type: 'File',
-    depth: 24,
-    size: 100,
-    linkpath: undefined,
-    nlink: 1 },
-  { path: '/Ω.txt',
-    mode: '100644',
-    type: 'File',
-    depth: 1,
-    size: 2,
-    linkpath: undefined,
-    nlink: 1 } ]
-
-
-
-// The extract class basically just pipes the input
-// to a Reader, and then to a fstream.DirWriter
-
-// So, this is as much a test of fstream.Reader and fstream.Writer
-// as it is of tar.Extract, but it sort of makes sense.
-
-tap.test("extract test", function (t) {
-  var extract = tar.Extract(target)
-  var inp = fs.createReadStream(file)
-
-  // give it a weird buffer size to try to break in odd places
-  inp.bufferSize = 1234
-
-  inp.pipe(extract)
-
-  extract.on("end", function () {
-    t.equal(ee, expectEntries.length, "should see "+ee+" entries")
-
-    // should get no more entries after end
-    extract.removeAllListeners("entry")
-    extract.on("entry", function (e) {
-      t.fail("Should not get entries after end!")
-    })
-
-    next()
-  })
-
-  extract.on("entry", function (entry) {
-    var found =
-      { path: entry.path
-      , mode: entry.props.mode.toString(8)
-      , type: entry.props.type
-      , depth: entry.props.depth
-      , size: entry.props.size
-      , linkpath: entry.props.linkpath
-      , nlink: entry.props.nlink
-      , dev: entry.props.dev
-      , ino: entry.props.ino
-      }
-
-    var wanted = expectEntries[ee ++]
-
-    t.equivalent(found, wanted, "tar entry " + ee + " " + wanted.path)
-  })
-
-  function next () {
-    var r = fstream.Reader({ path: target
-                           , type: "Directory"
-                           // this is just to encourage consistency
-                           , sort: "alpha" })
-
-    r.on("ready", function () {
-      foundEntry(r)
-    })
-
-    r.on("end", finish)
-
-    function foundEntry (entry) {
-      var p = entry.path.substr(target.length)
-      var found =
-        { path: p
-        , mode: entry.props.mode.toString(8)
-        , type: entry.props.type
-        , depth: entry.props.depth
-        , size: entry.props.size
-        , linkpath: entry.props.linkpath
-        , nlink: entry.props.nlink
-        }
-
-      var wanted = expectFiles[ef ++]
-
-      t.has(found, wanted, "unpacked file " + ef + " " + wanted.path)
-
-      entry.on("entry", foundEntry)
-    }
-
-    function finish () {
-      t.equal(ef, expectFiles.length, "should have "+ef+" items")
-      t.end()
-    }
-  }
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/fixtures.tgz b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/fixtures.tgz
deleted file mode 100644
index 4501bcf22695435b84edb3d4076cd9a70687b035..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 19205
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
GGXntOPa{_V

diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/header.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/header.js
deleted file mode 100644
index 8ea6f795..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/header.js
+++ /dev/null
@@ -1,183 +0,0 @@
-var tap = require("tap")
-var TarHeader = require("../lib/header.js")
-var tar = require("../tar.js")
-var fs = require("fs")
-
-
-var headers =
-  { "a.txt file header":
-    [ "612e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303430312031313635313336303333332030313234353100203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-    , { cksumValid: true
-      , path: 'a.txt'
-      , mode: 420
-      , uid: 24561
-      , gid: 20
-      , size: 257
-      , mtime: 1319493851
-      , cksum: 5417
-      , type: '0'
-      , linkpath: ''
-      , ustar: 'ustar\0'
-      , ustarver: '00'
-      , uname: 'isaacs'
-      , gname: 'staff'
-      , devmaj: 0
-      , devmin: 0
-      , fill: '' }
-    ]
-
-  , "omega pax": // the extended header from omega tar.
-    [ "5061784865616465722fcea92e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303137302031313534333731303631312030313530353100207800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-    , { cksumValid: true
-      , path: 'PaxHeader/Ω.txt'
-      , mode: 420
-      , uid: 24561
-      , gid: 20
-      , size: 120
-      , mtime: 1301254537
-      , cksum: 6697
-      , type: 'x'
-      , linkpath: ''
-      , ustar: 'ustar\0'
-      , ustarver: '00'
-      , uname: 'isaacs'
-      , gname: 'staff'
-      , devmaj: 0
-      , devmin: 0
-      , fill: '' } ]
-
-  , "omega file header":
-    [ "cea92e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303030322031313534333731303631312030313330373200203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-    , { cksumValid: true
-      , path: 'Ω.txt'
-      , mode: 420
-      , uid: 24561
-      , gid: 20
-      , size: 2
-      , mtime: 1301254537
-      , cksum: 5690
-      , type: '0'
-      , linkpath: ''
-      , ustar: 'ustar\0'
-      , ustarver: '00'
-      , uname: 'isaacs'
-      , gname: 'staff'
-      , devmaj: 0
-      , devmin: 0
-      , fill: '' } ]
-
-  , "foo.js file header":
-    [ "666f6f2e6a730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303030342031313534333637303734312030313236313700203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-    , { cksumValid: true
-      , path: 'foo.js'
-      , mode: 420
-      , uid: 24561
-      , gid: 20
-      , size: 4
-      , mtime: 1301246433
-      , cksum: 5519
-      , type: '0'
-      , linkpath: ''
-      , ustar: 'ustar\0'
-      , ustarver: '00'
-      , uname: 'isaacs'
-      , gname: 'staff'
-      , devmaj: 0
-      , devmin: 0
-      , fill: '' }
-    ]
-
-  , "b.txt file header":
-    [ "622e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030313030302031313635313336303637372030313234363100203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-    , { cksumValid: true
-      , path: 'b.txt'
-      , mode: 420
-      , uid: 24561
-      , gid: 20
-      , size: 512
-      , mtime: 1319494079
-      , cksum: 5425
-      , type: '0'
-      , linkpath: ''
-      , ustar: 'ustar\0'
-      , ustarver: '00'
-      , uname: 'isaacs'
-      , gname: 'staff'
-      , devmaj: 0
-      , devmin: 0
-      , fill: '' }
-    ]
-
-  , "deep nested file":
-    [ "636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363633030303634342000303537373631200030303030323420003030303030303030313434203131363532313531353333203034333331340020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075737461720030306973616163730000000000000000000000000000000000000000000000000000737461666600000000000000000000000000000000000000000000000000000030303030303020003030303030302000722f652f612f6c2f6c2f792f2d2f642f652f652f702f2d2f662f6f2f6c2f642f652f722f2d2f702f612f742f680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-    , { cksumValid: true,
-        path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'
-      , mode: 420
-      , uid: 24561
-      , gid: 20
-      , size: 100
-      , mtime: 1319687003
-      , cksum: 18124
-      , type: '0'
-      , linkpath: ''
-      , ustar: 'ustar\0'
-      , ustarver: '00'
-      , uname: 'isaacs'
-      , gname: 'staff'
-      , devmaj: 0
-      , devmin: 0
-      , fill: '' }
-    ]
-  }
-
-tap.test("parsing", function (t) {
-  Object.keys(headers).forEach(function (name) {
-    var h = headers[name]
-      , header = new Buffer(h[0], "hex")
-      , expect = h[1]
-      , parsed = new TarHeader(header)
-
-    // console.error(parsed)
-    t.has(parsed, expect, "parse " + name)
-  })
-  t.end()
-})
-
-tap.test("encoding", function (t) {
-  Object.keys(headers).forEach(function (name) {
-    var h = headers[name]
-      , expect = new Buffer(h[0], "hex")
-      , encoded = TarHeader.encode(h[1])
-
-    // might have slightly different bytes, since the standard
-    // isn't very strict, but should have the same semantics
-    // checkSum will be different, but cksumValid will be true
-
-    var th = new TarHeader(encoded)
-    delete h[1].block
-    delete h[1].needExtended
-    delete h[1].cksum
-    t.has(th, h[1], "fields "+name)
-  })
-  t.end()
-})
-
-// test these manually.  they're a bit rare to find in the wild
-tap.test("parseNumeric tests", function (t) {
-  var parseNumeric = TarHeader.parseNumeric
-    , numbers =
-      { "303737373737373700": 2097151
-      , "30373737373737373737373700": 8589934591
-      , "303030303036343400": 420
-      , "800000ffffffffffff": 281474976710655
-      , "ffffff000000000001": -281474976710654
-      , "ffffff000000000000": -281474976710655
-      , "800000000000200000": 2097152
-      , "8000000000001544c5": 1393861
-      , "ffffffffffff1544c5": -15383354 }
-  Object.keys(numbers).forEach(function (n) {
-    var b = new Buffer(n, "hex")
-    t.equal(parseNumeric(b), numbers[n], n + " === " + numbers[n])
-  })
-  t.end()
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack-no-proprietary.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack-no-proprietary.js
deleted file mode 100644
index 5bf0e540..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack-no-proprietary.js
+++ /dev/null
@@ -1,854 +0,0 @@
-// This is exactly like test/pack.js, except that it's excluding
-// any proprietary headers.
-//
-// This loses some information about the filesystem, but creates
-// tarballs that are supported by more versions of tar, especially
-// old non-spec-compliant copies of gnutar.
-
-// the symlink file is excluded from git, because it makes
-// windows freak the hell out.
-var fs = require("fs")
-  , path = require("path")
-  , symlink = path.resolve(__dirname, "fixtures/symlink")
-try { fs.unlinkSync(symlink) } catch (e) {}
-fs.symlinkSync("./hardlink-1", symlink)
-process.on("exit", function () {
-  fs.unlinkSync(symlink)
-})
-
-var tap = require("tap")
-  , tar = require("../tar.js")
-  , pkg = require("../package.json")
-  , Pack = tar.Pack
-  , fstream = require("fstream")
-  , Reader = fstream.Reader
-  , Writer = fstream.Writer
-  , input = path.resolve(__dirname, "fixtures/")
-  , target = path.resolve(__dirname, "tmp/pack.tar")
-  , uid = process.getuid ? process.getuid() : 0
-  , gid = process.getgid ? process.getgid() : 0
-
-  , entries =
-
-    // the global header and root fixtures/ dir are going to get
-    // a different date each time, so omit that bit.
-    // Also, dev/ino values differ across machines, so that's not
-    // included.
-    [ [ 'entry',
-      { path: 'fixtures/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'extendedHeader',
-      { path: 'PaxHeader/fixtures/200cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        type: 'x',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' },
-      { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        uid: uid,
-        gid: gid,
-        size: 200 } ]
-
-    , [ 'entry',
-      { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 200,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/a.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 257,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/b.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 512,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/c.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 513,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/cc.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 513,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/foo.js',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 4,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/hardlink-1',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 200,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/hardlink-2',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '1',
-        linkpath: 'fixtures/hardlink-1',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/omega.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/omega.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/star.4.html',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 54081,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'extendedHeader',
-      { path: 'PaxHeader/fixtures/packtest/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        type: 'x',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' },
-      { path: 'fixtures/packtest/Ω.txt',
-        uid: uid,
-        gid: gid,
-        size: 2 } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 100,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/symlink',
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '2',
-        linkpath: 'hardlink-1',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'extendedHeader',
-      { path: 'PaxHeader/fixtures/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        type: 'x',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' },
-      { path: "fixtures/Ω.txt"
-      , uid: uid
-      , gid: gid
-      , size: 2 } ]
-
-    , [ 'entry',
-      { path: 'fixtures/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-    ]
-
-
-// first, make sure that the hardlinks are actually hardlinks, or this
-// won't work.  Git has a way of replacing them with a copy.
-var hard1 = path.resolve(__dirname, "fixtures/hardlink-1")
-  , hard2 = path.resolve(__dirname, "fixtures/hardlink-2")
-  , fs = require("fs")
-
-try { fs.unlinkSync(hard2) } catch (e) {}
-fs.linkSync(hard1, hard2)
-
-tap.test("with global header", { timeout: 10000 }, function (t) {
-  runTest(t, true)
-})
-
-tap.test("without global header", { timeout: 10000 }, function (t) {
-  runTest(t, false)
-})
-
-function alphasort (a, b) {
-  return a === b ? 0
-       : a.toLowerCase() > b.toLowerCase() ? 1
-       : a.toLowerCase() < b.toLowerCase() ? -1
-       : a > b ? 1
-       : -1
-}
-
-
-function runTest (t, doGH) {
-  var reader = Reader({ path: input
-                      , filter: function () {
-                          return !this.path.match(/\.(tar|hex)$/)
-                        }
-                      , sort: alphasort
-                      })
-
-  var props = doGH ? pkg : {}
-  props.noProprietary = true
-  var pack = Pack(props)
-  var writer = Writer(target)
-
-  // global header should be skipped regardless, since it has no content.
-  var entry = 0
-
-  t.ok(reader, "reader ok")
-  t.ok(pack, "pack ok")
-  t.ok(writer, "writer ok")
-
-  pack.pipe(writer)
-
-  var parse = tar.Parse()
-  t.ok(parse, "parser should be ok")
-
-  pack.on("data", function (c) {
-    // console.error("PACK DATA")
-    if (c.length !== 512) {
-      // this one is too noisy, only assert if it'll be relevant
-      t.equal(c.length, 512, "parser should emit data in 512byte blocks")
-    }
-    parse.write(c)
-  })
-
-  pack.on("end", function () {
-    // console.error("PACK END")
-    t.pass("parser ends")
-    parse.end()
-  })
-
-  pack.on("error", function (er) {
-    t.fail("pack error", er)
-  })
-
-  parse.on("error", function (er) {
-    t.fail("parse error", er)
-  })
-
-  writer.on("error", function (er) {
-    t.fail("writer error", er)
-  })
-
-  reader.on("error", function (er) {
-    t.fail("reader error", er)
-  })
-
-  parse.on("*", function (ev, e) {
-    var wanted = entries[entry++]
-    if (!wanted) {
-      t.fail("unexpected event: "+ev)
-      return
-    }
-    t.equal(ev, wanted[0], "event type should be "+wanted[0])
-
-    if (ev !== wanted[0] || e.path !== wanted[1].path) {
-      console.error(wanted)
-      console.error([ev, e.props])
-      e.on("end", function () {
-        console.error(e.fields)
-        throw "break"
-      })
-    }
-
-    t.has(e.props, wanted[1], "properties "+wanted[1].path)
-    if (wanted[2]) {
-      e.on("end", function () {
-        if (!e.fields) {
-          t.ok(e.fields, "should get fields")
-        } else {
-          t.has(e.fields, wanted[2], "should get expected fields")
-        }
-      })
-    }
-  })
-
-  reader.pipe(pack)
-
-  writer.on("close", function () {
-    t.equal(entry, entries.length, "should get all expected entries")
-    t.pass("it finished")
-    t.end()
-  })
-
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack.js
deleted file mode 100644
index 0f509945..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/pack.js
+++ /dev/null
@@ -1,897 +0,0 @@
-
-// the symlink file is excluded from git, because it makes
-// windows freak the hell out.
-var fs = require("fs")
-  , path = require("path")
-  , symlink = path.resolve(__dirname, "fixtures/symlink")
-try { fs.unlinkSync(symlink) } catch (e) {}
-fs.symlinkSync("./hardlink-1", symlink)
-process.on("exit", function () {
-  fs.unlinkSync(symlink)
-})
-
-
-var tap = require("tap")
-  , tar = require("../tar.js")
-  , pkg = require("../package.json")
-  , Pack = tar.Pack
-  , fstream = require("fstream")
-  , Reader = fstream.Reader
-  , Writer = fstream.Writer
-  , input = path.resolve(__dirname, "fixtures/")
-  , target = path.resolve(__dirname, "tmp/pack.tar")
-  , uid = process.getuid ? process.getuid() : 0
-  , gid = process.getgid ? process.getgid() : 0
-
-  , entries =
-
-    // the global header and root fixtures/ dir are going to get
-    // a different date each time, so omit that bit.
-    // Also, dev/ino values differ across machines, so that's not
-    // included.
-    [ [ 'globalExtendedHeader',
-      { path: 'PaxHeader/',
-        mode: 438,
-        uid: 0,
-        gid: 0,
-        type: 'g',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' },
-      { "NODETAR.author": pkg.author,
-        "NODETAR.name": pkg.name,
-        "NODETAR.description": pkg.description,
-        "NODETAR.version": pkg.version,
-        "NODETAR.repository.type": pkg.repository.type,
-        "NODETAR.repository.url": pkg.repository.url,
-        "NODETAR.main": pkg.main,
-        "NODETAR.scripts.test": pkg.scripts.test } ]
-
-    , [ 'entry',
-      { path: 'fixtures/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'extendedHeader',
-      { path: 'PaxHeader/fixtures/200cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        type: 'x',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' },
-      { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        'NODETAR.depth': '1',
-        'NODETAR.type': 'File',
-        nlink: 1,
-        uid: uid,
-        gid: gid,
-        size: 200,
-        'NODETAR.blksize': '4096',
-        'NODETAR.blocks': '8' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 200,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '',
-        'NODETAR.depth': '1',
-        'NODETAR.type': 'File',
-        nlink: 1,
-        'NODETAR.blksize': '4096',
-        'NODETAR.blocks': '8' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/a.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 257,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/b.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 512,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/c.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 513,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/cc.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 513,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/foo.js',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 4,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/hardlink-1',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 200,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/hardlink-2',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '1',
-        linkpath: 'fixtures/hardlink-1',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/omega.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/omega.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/star.4.html',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 54081,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'extendedHeader',
-      { path: 'PaxHeader/fixtures/packtest/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        type: 'x',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' },
-      { path: 'fixtures/packtest/Ω.txt',
-        'NODETAR.depth': '2',
-        'NODETAR.type': 'File',
-        nlink: 1,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        'NODETAR.blksize': '4096',
-        'NODETAR.blocks': '8' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/packtest/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '',
-        'NODETAR.depth': '2',
-        'NODETAR.type': 'File',
-        nlink: 1,
-        'NODETAR.blksize': '4096',
-        'NODETAR.blocks': '8' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/',
-        mode: 493,
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '5',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 100,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'entry',
-      { path: 'fixtures/symlink',
-        uid: uid,
-        gid: gid,
-        size: 0,
-        type: '2',
-        linkpath: 'hardlink-1',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' } ]
-
-    , [ 'extendedHeader',
-      { path: 'PaxHeader/fixtures/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        type: 'x',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '' },
-      { path: "fixtures/Ω.txt"
-      , "NODETAR.depth": "1"
-      , "NODETAR.type": "File"
-      , nlink: 1
-      , uid: uid
-      , gid: gid
-      , size: 2
-      , "NODETAR.blksize": "4096"
-      , "NODETAR.blocks": "8" } ]
-
-    , [ 'entry',
-      { path: 'fixtures/Ω.txt',
-        mode: 420,
-        uid: uid,
-        gid: gid,
-        size: 2,
-        type: '0',
-        linkpath: '',
-        ustar: 'ustar\u0000',
-        ustarver: '00',
-        uname: '',
-        gname: '',
-        devmaj: 0,
-        devmin: 0,
-        fill: '',
-        'NODETAR.depth': '1',
-        'NODETAR.type': 'File',
-        nlink: 1,
-        'NODETAR.blksize': '4096',
-        'NODETAR.blocks': '8' } ]
-    ]
-
-
-// first, make sure that the hardlinks are actually hardlinks, or this
-// won't work.  Git has a way of replacing them with a copy.
-var hard1 = path.resolve(__dirname, "fixtures/hardlink-1")
-  , hard2 = path.resolve(__dirname, "fixtures/hardlink-2")
-  , fs = require("fs")
-
-try { fs.unlinkSync(hard2) } catch (e) {}
-fs.linkSync(hard1, hard2)
-
-tap.test("with global header", { timeout: 10000 }, function (t) {
-  runTest(t, true)
-})
-
-tap.test("without global header", { timeout: 10000 }, function (t) {
-  runTest(t, false)
-})
-
-function alphasort (a, b) {
-  return a === b ? 0
-       : a.toLowerCase() > b.toLowerCase() ? 1
-       : a.toLowerCase() < b.toLowerCase() ? -1
-       : a > b ? 1
-       : -1
-}
-
-
-function runTest (t, doGH) {
-  var reader = Reader({ path: input
-                      , filter: function () {
-                          return !this.path.match(/\.(tar|hex)$/)
-                        }
-                      , sort: alphasort
-                      })
-
-  var pack = Pack(doGH ? pkg : null)
-  var writer = Writer(target)
-
-  // skip the global header if we're not doing that.
-  var entry = doGH ? 0 : 1
-
-  t.ok(reader, "reader ok")
-  t.ok(pack, "pack ok")
-  t.ok(writer, "writer ok")
-
-  pack.pipe(writer)
-
-  var parse = tar.Parse()
-  t.ok(parse, "parser should be ok")
-
-  pack.on("data", function (c) {
-    // console.error("PACK DATA")
-    if (c.length !== 512) {
-      // this one is too noisy, only assert if it'll be relevant
-      t.equal(c.length, 512, "parser should emit data in 512byte blocks")
-    }
-    parse.write(c)
-  })
-
-  pack.on("end", function () {
-    // console.error("PACK END")
-    t.pass("parser ends")
-    parse.end()
-  })
-
-  pack.on("error", function (er) {
-    t.fail("pack error", er)
-  })
-
-  parse.on("error", function (er) {
-    t.fail("parse error", er)
-  })
-
-  writer.on("error", function (er) {
-    t.fail("writer error", er)
-  })
-
-  reader.on("error", function (er) {
-    t.fail("reader error", er)
-  })
-
-  parse.on("*", function (ev, e) {
-    var wanted = entries[entry++]
-    if (!wanted) {
-      t.fail("unexpected event: "+ev)
-      return
-    }
-    t.equal(ev, wanted[0], "event type should be "+wanted[0])
-
-    // if (ev !== wanted[0] || e.path !== wanted[1].path) {
-    //   console.error(wanted)
-    //   console.error([ev, e.props])
-    //   throw "break"
-    // }
-
-    t.has(e.props, wanted[1], "properties "+wanted[1].path)
-    if (wanted[2]) {
-      e.on("end", function () {
-        if (!e.fields) {
-          t.ok(e.fields, "should get fields")
-        } else {
-          t.has(e.fields, wanted[2], "should get expected fields")
-        }
-      })
-    }
-  })
-
-  reader.pipe(pack)
-
-  writer.on("close", function () {
-    t.equal(entry, entries.length, "should get all expected entries")
-    t.pass("it finished")
-    t.end()
-  })
-
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/parse.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/parse.js
deleted file mode 100644
index f765a501..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/parse.js
+++ /dev/null
@@ -1,359 +0,0 @@
-var tap = require("tap")
-  , tar = require("../tar.js")
-  , fs = require("fs")
-  , path = require("path")
-  , file = path.resolve(__dirname, "fixtures/c.tar")
-  , index = 0
-
-  , expect =
-[ [ 'entry',
-    { path: 'c.txt',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 513,
-      mtime: new Date('Wed, 26 Oct 2011 01:10:58 GMT'),
-      cksum: 5422,
-      type: '0',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    undefined ],
-  [ 'entry',
-    { path: 'cc.txt',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 513,
-      mtime: new Date('Wed, 26 Oct 2011 01:11:02 GMT'),
-      cksum: 5525,
-      type: '0',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    undefined ],
-  [ 'entry',
-    { path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 100,
-      mtime: new Date('Thu, 27 Oct 2011 03:43:23 GMT'),
-      cksum: 18124,
-      type: '0',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    undefined ],
-  [ 'entry',
-    { path: 'Ω.txt',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 2,
-      mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'),
-      cksum: 5695,
-      type: '0',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    undefined ],
-  [ 'extendedHeader',
-    { path: 'PaxHeader/Ω.txt',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 120,
-      mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'),
-      cksum: 6702,
-      type: 'x',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    { path: 'Ω.txt',
-      ctime: 1319737909,
-      atime: 1319739061,
-      dev: 234881026,
-      ino: 51693379,
-      nlink: 1 } ],
-  [ 'entry',
-    { path: 'Ω.txt',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 2,
-      mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'),
-      cksum: 5695,
-      type: '0',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '',
-      ctime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'),
-      atime: new Date('Thu, 27 Oct 2011 18:11:01 GMT'),
-      dev: 234881026,
-      ino: 51693379,
-      nlink: 1 },
-    undefined ],
-  [ 'extendedHeader',
-    { path: 'PaxHeader/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 353,
-      mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'),
-      cksum: 14488,
-      type: 'x',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      ctime: 1319686868,
-      atime: 1319741254,
-      'LIBARCHIVE.creationtime': '1319686852',
-      dev: 234881026,
-      ino: 51681874,
-      nlink: 1 } ],
-  [ 'entry',
-    { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 200,
-      mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'),
-      cksum: 14570,
-      type: '0',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '',
-      ctime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'),
-      atime: new Date('Thu, 27 Oct 2011 18:47:34 GMT'),
-      'LIBARCHIVE.creationtime': '1319686852',
-      dev: 234881026,
-      ino: 51681874,
-      nlink: 1 },
-    undefined ],
-  [ 'longPath',
-    { path: '././@LongLink',
-      mode: 0,
-      uid: 0,
-      gid: 0,
-      size: 201,
-      mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'),
-      cksum: 4976,
-      type: 'L',
-      linkpath: '',
-      ustar: false },
-    '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' ],
-  [ 'entry',
-    { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      mode: 420,
-      uid: 1000,
-      gid: 1000,
-      size: 201,
-      mtime: new Date('Thu, 27 Oct 2011 22:21:50 GMT'),
-      cksum: 14086,
-      type: '0',
-      linkpath: '',
-      ustar: false },
-    undefined ],
-  [ 'longLinkpath',
-    { path: '././@LongLink',
-      mode: 0,
-      uid: 0,
-      gid: 0,
-      size: 201,
-      mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'),
-      cksum: 4975,
-      type: 'K',
-      linkpath: '',
-      ustar: false },
-    '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' ],
-  [ 'longPath',
-    { path: '././@LongLink',
-      mode: 0,
-      uid: 0,
-      gid: 0,
-      size: 201,
-      mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'),
-      cksum: 4976,
-      type: 'L',
-      linkpath: '',
-      ustar: false },
-    '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' ],
-  [ 'entry',
-    { path: '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL',
-      mode: 511,
-      uid: 1000,
-      gid: 1000,
-      size: 0,
-      mtime: new Date('Fri, 28 Oct 2011 23:05:17 GMT'),
-      cksum: 21603,
-      type: '2',
-      linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      ustar: false },
-    undefined ],
-  [ 'extendedHeader',
-    { path: 'PaxHeader/200-hard',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 143,
-      mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'),
-      cksum: 6533,
-      type: 'x',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    { ctime: 1320617144,
-      atime: 1320617232,
-      'LIBARCHIVE.creationtime': '1319686852',
-      dev: 234881026,
-      ino: 51681874,
-      nlink: 2 } ],
-  [ 'entry',
-    { path: '200-hard',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 200,
-      mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'),
-      cksum: 5526,
-      type: '0',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '',
-      ctime: new Date('Sun, 06 Nov 2011 22:05:44 GMT'),
-      atime: new Date('Sun, 06 Nov 2011 22:07:12 GMT'),
-      'LIBARCHIVE.creationtime': '1319686852',
-      dev: 234881026,
-      ino: 51681874,
-      nlink: 2 },
-    undefined ],
-  [ 'extendedHeader',
-    { path: 'PaxHeader/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 353,
-      mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'),
-      cksum: 14488,
-      type: 'x',
-      linkpath: '',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '' },
-    { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      ctime: 1320617144,
-      atime: 1320617406,
-      'LIBARCHIVE.creationtime': '1319686852',
-      dev: 234881026,
-      ino: 51681874,
-      nlink: 2 } ],
-  [ 'entry',
-    { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc',
-      mode: 420,
-      uid: 24561,
-      gid: 20,
-      size: 0,
-      mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'),
-      cksum: 15173,
-      type: '1',
-      linkpath: '200-hard',
-      ustar: 'ustar\0',
-      ustarver: '00',
-      uname: 'isaacs',
-      gname: 'staff',
-      devmaj: 0,
-      devmin: 0,
-      fill: '',
-      ctime: new Date('Sun, 06 Nov 2011 22:05:44 GMT'),
-      atime: new Date('Sun, 06 Nov 2011 22:10:06 GMT'),
-      'LIBARCHIVE.creationtime': '1319686852',
-      dev: 234881026,
-      ino: 51681874,
-      nlink: 2 },
-    undefined ] ]
-
-
-tap.test("parser test", function (t) {
-  var parser = tar.Parse()
-
-  parser.on("end", function () {
-    t.equal(index, expect.length, "saw all expected events")
-    t.end()
-  })
-
-  fs.createReadStream(file)
-    .pipe(parser)
-    .on("*", function (ev, entry) {
-      var wanted = expect[index]
-      if (!wanted) {
-        return t.fail("Unexpected event: " + ev)
-      }
-      var result = [ev, entry.props]
-      entry.on("end", function () {
-        result.push(entry.fields || entry.body)
-
-        t.equal(ev, wanted[0], index + " event type")
-        t.equivalent(entry.props, wanted[1], wanted[1].path + " entry properties")
-        if (wanted[2]) {
-          t.equivalent(result[2], wanted[2], "metadata values")
-        }
-        index ++
-      })
-    })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/zz-cleanup.js b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/zz-cleanup.js
deleted file mode 100644
index a00ff7fa..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/tar/test/zz-cleanup.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// clean up the fixtures
-
-var tap = require("tap")
-, rimraf = require("rimraf")
-, test = tap.test
-, path = require("path")
-
-test("clean fixtures", function (t) {
-  rimraf(path.resolve(__dirname, "fixtures"), function (er) {
-    t.ifError(er, "rimraf ./fixtures/")
-    t.end()
-  })
-})
-
-test("clean tmp", function (t) {
-  rimraf(path.resolve(__dirname, "tmp"), function (er) {
-    t.ifError(er, "rimraf ./tmp/")
-    t.end()
-  })
-})
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/package.json b/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/package.json
deleted file mode 100644
index d6849e75..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/package.json
+++ /dev/null
@@ -1,85 +0,0 @@
-{
-  "name": "node-pre-gyp",
-  "description": "Node.js native addon binary install tool",
-  "version": "0.5.19",
-  "keywords": [
-    "native",
-    "addon",
-    "module",
-    "c",
-    "c++",
-    "bindings",
-    "binary"
-  ],
-  "author": {
-    "name": "Dane Springmeyer",
-    "email": "dane@mapbox.com"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/mapbox/node-pre-gyp.git"
-  },
-  "bin": {
-    "node-pre-gyp": "./bin/node-pre-gyp"
-  },
-  "main": "./lib/node-pre-gyp.js",
-  "dependencies": {
-    "nopt": "~2.2.0",
-    "npmlog": "~0.0.6",
-    "request": "2",
-    "semver": "~2.3.0",
-    "tar": "~0.1.19",
-    "tar-pack": "~2.0.0",
-    "mkdirp": "~0.5.0",
-    "rc": "~0.4.0",
-    "rimraf": "~2.2.5"
-  },
-  "devDependencies": {
-    "aws-sdk": "*"
-  },
-  "engineStrict": true,
-  "engines": {
-    "node": ">= 0.8.0"
-  },
-  "scripts": {
-    "update-crosswalk": "node scripts/abi_crosswalk.js > lib/util/abi_crosswalk.json",
-    "test": "./test.sh"
-  },
-  "gitHead": "4584ffba7b411bd98a5a8452894159e7c200e55b",
-  "bugs": {
-    "url": "https://github.com/mapbox/node-pre-gyp/issues"
-  },
-  "homepage": "https://github.com/mapbox/node-pre-gyp",
-  "bundleDependencies": [
-    "nopt",
-    "npmlog",
-    "request",
-    "semver",
-    "tar",
-    "tar-pack",
-    "mkdirp",
-    "rc",
-    "rimraf"
-  ],
-  "_id": "node-pre-gyp@0.5.19",
-  "_shasum": "9b320edc2f0b005eff769438b648fa1e84759359",
-  "_from": "node-pre-gyp@0.5.x",
-  "_npmVersion": "1.4.16",
-  "_npmUser": {
-    "name": "springmeyer",
-    "email": "dane@mapbox.com"
-  },
-  "maintainers": [
-    {
-      "name": "springmeyer",
-      "email": "dane@dbsgeo.com"
-    }
-  ],
-  "dist": {
-    "shasum": "9b320edc2f0b005eff769438b648fa1e84759359",
-    "tarball": "http://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.5.19.tgz"
-  },
-  "directories": {},
-  "_resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.5.19.tgz",
-  "readme": "ERROR: No README data found!"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/optimist/.travis.yml
deleted file mode 100644
index cc4dba29..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/.travis.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-language: node_js
-node_js:
-  - "0.8"
-  - "0.10"
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/LICENSE b/input_devices/mag/node_modules/serialport/node_modules/optimist/LICENSE
deleted file mode 100644
index 432d1aeb..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/bool.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/bool.js
deleted file mode 100644
index a998fb7a..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/boolean_double.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/boolean_double.js
deleted file mode 100644
index a35a7e6d..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/boolean_single.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/boolean_single.js
deleted file mode 100644
index 017bb689..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/default_hash.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/default_hash.js
deleted file mode 100644
index ade77681..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/default_singles.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/default_singles.js
deleted file mode 100644
index d9b1ff45..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/divide.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/divide.js
deleted file mode 100644
index 5e2ee82f..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count.js
deleted file mode 100644
index b5f95bf6..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count_options.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count_options.js
deleted file mode 100644
index d9ac7090..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count_wrap.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/line_count_wrap.js
deleted file mode 100644
index 42675111..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/nonopt.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/nonopt.js
deleted file mode 100644
index ee633eed..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/reflect.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/reflect.js
deleted file mode 100644
index 816b3e11..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/example/reflect.js
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/env node
-console.dir(require('optimist').argv);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/example/short.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/short.js
deleted file mode 100644
index 1db0ad0f..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/string.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/string.js
deleted file mode 100644
index a8e5aeb2..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/usage-options.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/usage-options.js
deleted file mode 100644
index b9999776..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/example/xup.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/example/xup.js
deleted file mode 100644
index 8f6ecd20..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/index.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/index.js
deleted file mode 100644
index 4da5a6d8..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/.travis.yml
deleted file mode 100644
index cc4dba29..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/.travis.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-language: node_js
-node_js:
-  - "0.8"
-  - "0.10"
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/example/parse.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/example/parse.js
deleted file mode 100644
index abff3e8e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/example/parse.js
+++ /dev/null
@@ -1,2 +0,0 @@
-var argv = require('../')(process.argv.slice(2));
-console.dir(argv);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/index.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/index.js
deleted file mode 100644
index 71fb8305..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/index.js
+++ /dev/null
@@ -1,187 +0,0 @@
-module.exports = function (args, opts) {
-    if (!opts) opts = {};
-    
-    var flags = { bools : {}, strings : {} };
-    
-    [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
-        flags.bools[key] = true;
-    });
-    
-    var aliases = {};
-    Object.keys(opts.alias || {}).forEach(function (key) {
-        aliases[key] = [].concat(opts.alias[key]);
-        aliases[key].forEach(function (x) {
-            aliases[x] = [key].concat(aliases[key].filter(function (y) {
-                return x !== y;
-            }));
-        });
-    });
-
-    [].concat(opts.string).filter(Boolean).forEach(function (key) {
-        flags.strings[key] = true;
-        if (aliases[key]) {
-            flags.strings[aliases[key]] = true;
-        }
-     });
-
-    var defaults = opts['default'] || {};
-    
-    var argv = { _ : [] };
-    Object.keys(flags.bools).forEach(function (key) {
-        setArg(key, defaults[key] === undefined ? false : defaults[key]);
-    });
-    
-    var notFlags = [];
-
-    if (args.indexOf('--') !== -1) {
-        notFlags = args.slice(args.indexOf('--')+1);
-        args = args.slice(0, args.indexOf('--'));
-    }
-
-    function setArg (key, val) {
-        var value = !flags.strings[key] && isNumber(val)
-            ? Number(val) : val
-        ;
-        setKey(argv, key.split('.'), value);
-        
-        (aliases[key] || []).forEach(function (x) {
-            setKey(argv, x.split('.'), value);
-        });
-    }
-    
-    for (var i = 0; i < args.length; i++) {
-        var arg = args[i];
-        
-        if (/^--.+=/.test(arg)) {
-            // 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 (/^--no-.+/.test(arg)) {
-            var key = arg.match(/^--no-(.+)/)[1];
-            setArg(key, false);
-        }
-        else if (/^--.+/.test(arg)) {
-            var key = arg.match(/^--(.+)/)[1];
-            var next = args[i + 1];
-            if (next !== undefined && !/^-/.test(next)
-            && !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, flags.strings[key] ? '' : true);
-            }
-        }
-        else if (/^-[^-]+/.test(arg)) {
-            var letters = arg.slice(1,-1).split('');
-            
-            var broken = false;
-            for (var j = 0; j < letters.length; j++) {
-                var next = arg.slice(j+2);
-                
-                if (next === '-') {
-                    setArg(letters[j], next)
-                    continue;
-                }
-                
-                if (/[A-Za-z]/.test(letters[j])
-                && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
-                    setArg(letters[j], next);
-                    broken = true;
-                    break;
-                }
-                
-                if (letters[j+1] && letters[j+1].match(/\W/)) {
-                    setArg(letters[j], arg.slice(j+2));
-                    broken = true;
-                    break;
-                }
-                else {
-                    setArg(letters[j], flags.strings[letters[j]] ? '' : true);
-                }
-            }
-            
-            var key = arg.slice(-1)[0];
-            if (!broken && key !== '-') {
-                if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
-                && !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, flags.strings[key] ? '' : true);
-                }
-            }
-        }
-        else {
-            argv._.push(
-                flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
-            );
-        }
-    }
-    
-    Object.keys(defaults).forEach(function (key) {
-        if (!hasKey(argv, key.split('.'))) {
-            setKey(argv, key.split('.'), defaults[key]);
-            
-            (aliases[key] || []).forEach(function (x) {
-                setKey(argv, x.split('.'), defaults[key]);
-            });
-        }
-    });
-    
-    notFlags.forEach(function(key) {
-        argv._.push(key);
-    });
-
-    return argv;
-};
-
-function hasKey (obj, keys) {
-    var o = obj;
-    keys.slice(0,-1).forEach(function (key) {
-        o = (o[key] || {});
-    });
-
-    var key = keys[keys.length - 1];
-    return key in o;
-}
-
-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 ];
-    }
-}
-
-function isNumber (x) {
-    if (typeof x === 'number') return true;
-    if (/^0x[0-9a-f]+$/i.test(x)) return true;
-    return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
-}
-
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/package.json b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/package.json
deleted file mode 100644
index c0c197ca..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/package.json
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-  "name": "minimist",
-  "version": "0.0.10",
-  "description": "parse argument options",
-  "main": "index.js",
-  "devDependencies": {
-    "tape": "~1.0.4",
-    "tap": "~0.4.0"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "testling": {
-    "files": "test/*.js",
-    "browsers": [
-      "ie/6..latest",
-      "ff/5",
-      "firefox/latest",
-      "chrome/10",
-      "chrome/latest",
-      "safari/5.1",
-      "safari/latest",
-      "opera/12"
-    ]
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/substack/minimist.git"
-  },
-  "homepage": "https://github.com/substack/minimist",
-  "keywords": [
-    "argv",
-    "getopt",
-    "parser",
-    "optimist"
-  ],
-  "author": {
-    "name": "James Halliday",
-    "email": "mail@substack.net",
-    "url": "http://substack.net"
-  },
-  "license": "MIT",
-  "readme": "# minimist\n\nparse argument options\n\nThis module is the guts of optimist's argument parser without all the\nfanciful decoration.\n\n[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)\n\n[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)\n\n# example\n\n``` js\nvar argv = require('minimist')(process.argv.slice(2));\nconsole.dir(argv);\n```\n\n```\n$ node example/parse.js -a beep -b boop\n{ _: [], a: 'beep', b: 'boop' }\n```\n\n```\n$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz\n{ _: [ 'foo', 'bar', 'baz' ],\n  x: 3,\n  y: 4,\n  n: 5,\n  a: true,\n  b: true,\n  c: true,\n  beep: 'boop' }\n```\n\n# methods\n\n``` js\nvar parseArgs = require('minimist')\n```\n\n## var argv = parseArgs(args, opts={})\n\nReturn an argument object `argv` populated with the array arguments from `args`.\n\n`argv._` contains all the arguments that didn't have an option associated with\nthem.\n\nNumeric-looking arguments will be returned as numbers unless `opts.string` or\n`opts.boolean` is set for that argument name.\n\nAny arguments after `'--'` will not be parsed and will end up in `argv._`.\n\noptions can be:\n\n* `opts.string` - a string or array of strings argument names to always treat as\nstrings\n* `opts.boolean` - a string or array of strings to always treat as booleans\n* `opts.alias` - an object mapping string names to strings or arrays of string\nargument names to use as aliases\n* `opts.default` - an object mapping string argument names to default values\n\n# install\n\nWith [npm](https://npmjs.org) do:\n\n```\nnpm install minimist\n```\n\n# license\n\nMIT\n",
-  "readmeFilename": "readme.markdown",
-  "bugs": {
-    "url": "https://github.com/substack/minimist/issues"
-  },
-  "_id": "minimist@0.0.10",
-  "_from": "minimist@~0.0.1"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/readme.markdown b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/readme.markdown
deleted file mode 100644
index c2563532..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/readme.markdown
+++ /dev/null
@@ -1,73 +0,0 @@
-# minimist
-
-parse argument options
-
-This module is the guts of optimist's argument parser without all the
-fanciful decoration.
-
-[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)
-
-[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)
-
-# example
-
-``` js
-var argv = require('minimist')(process.argv.slice(2));
-console.dir(argv);
-```
-
-```
-$ node example/parse.js -a beep -b boop
-{ _: [], a: 'beep', b: 'boop' }
-```
-
-```
-$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
-{ _: [ 'foo', 'bar', 'baz' ],
-  x: 3,
-  y: 4,
-  n: 5,
-  a: true,
-  b: true,
-  c: true,
-  beep: 'boop' }
-```
-
-# methods
-
-``` js
-var parseArgs = require('minimist')
-```
-
-## var argv = parseArgs(args, opts={})
-
-Return an argument object `argv` populated with the array arguments from `args`.
-
-`argv._` contains all the arguments that didn't have an option associated with
-them.
-
-Numeric-looking arguments will be returned as numbers unless `opts.string` or
-`opts.boolean` is set for that argument name.
-
-Any arguments after `'--'` will not be parsed and will end up in `argv._`.
-
-options can be:
-
-* `opts.string` - a string or array of strings argument names to always treat as
-strings
-* `opts.boolean` - a string or array of strings to always treat as booleans
-* `opts.alias` - an object mapping string names to strings or arrays of string
-argument names to use as aliases
-* `opts.default` - an object mapping string argument names to default values
-
-# install
-
-With [npm](https://npmjs.org) do:
-
-```
-npm install minimist
-```
-
-# license
-
-MIT
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/bool.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/bool.js
deleted file mode 100644
index 749e083c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/bool.js
+++ /dev/null
@@ -1,119 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('flag boolean default false', function (t) {
-    var argv = parse(['moo'], {
-        boolean: ['t', 'verbose'],
-        default: { verbose: false, t: false }
-    });
-    
-    t.deepEqual(argv, {
-        verbose: false,
-        t: false,
-        _: ['moo']
-    });
-    
-    t.deepEqual(typeof argv.verbose, 'boolean');
-    t.deepEqual(typeof argv.t, 'boolean');
-    t.end();
-
-});
-
-test('boolean groups', function (t) {
-    var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], {
-        boolean: ['x','y','z']
-    });
-    
-    t.deepEqual(argv, {
-        x : true,
-        y : false,
-        z : true,
-        _ : [ 'one', 'two', 'three' ]
-    });
-    
-    t.deepEqual(typeof argv.x, 'boolean');
-    t.deepEqual(typeof argv.y, 'boolean');
-    t.deepEqual(typeof argv.z, 'boolean');
-    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 = parse(aliased, {
-        boolean: 'herp',
-        alias: { h: 'herp' }
-    });
-    var propertyArgv = parse(regular, {
-        boolean: 'herp',
-        alias: { h: 'herp' }
-    });
-    var expected = {
-        herp: true,
-        h: true,
-        '_': [ 'derp' ]
-    };
-    
-    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 = {
-        alias: { 'h': 'herp' },
-        boolean: 'herp'
-    };
-    var aliasedArgv = parse(aliased, opts);
-    var propertyArgv = parse(regular, opts);
-    var expected = {
-        herp: true,
-        h: true,
-        '_': [ 'derp' ]
-    };
-    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 = {
-        alias: { h: 'herp' },
-        boolean: 'h'
-    };
-    var aliasedArgv = parse(aliased, opts);
-    var propertyArgv = parse(regular, opts);
-    var expected = {
-        herp: true,
-        h: true,
-        '_': [ ]
-    };
-
-    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 = parse(['--boool', '--other=true'], {
-        boolean: 'boool'
-    });
-
-    t.same(parsed.boool, true);
-    t.same(parsed.other, 'true');
-
-    parsed = parse(['--boool', '--other=false'], {
-        boolean: 'boool'
-    });
-    
-    t.same(parsed.boool, true);
-    t.same(parsed.other, 'false');
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dash.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dash.js
deleted file mode 100644
index 8b034b99..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dash.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('-', function (t) {
-    t.plan(5);
-    t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] });
-    t.deepEqual(parse([ '-' ]), { _: [ '-' ] });
-    t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] });
-    t.deepEqual(
-        parse([ '-b', '-' ], { boolean: 'b' }),
-        { b: true, _: [ '-' ] }
-    );
-    t.deepEqual(
-        parse([ '-s', '-' ], { string: 's' }),
-        { s: '-', _: [] }
-    );
-});
-
-test('-a -- b', function (t) {
-    t.plan(3);
-    t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] });
-    t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
-    t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/default_bool.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/default_bool.js
deleted file mode 100644
index f0041ee4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/default_bool.js
+++ /dev/null
@@ -1,20 +0,0 @@
-var test = require('tape');
-var parse = require('../');
-
-test('boolean default true', function (t) {
-    var argv = parse([], {
-        boolean: 'sometrue',
-        default: { sometrue: true }
-    });
-    t.equal(argv.sometrue, true);
-    t.end();
-});
-
-test('boolean default false', function (t) {
-    var argv = parse([], {
-        boolean: 'somefalse',
-        default: { somefalse: false }
-    });
-    t.equal(argv.somefalse, false);
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dotted.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dotted.js
deleted file mode 100644
index d8b3e856..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/dotted.js
+++ /dev/null
@@ -1,22 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('dotted alias', function (t) {
-    var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
-    t.equal(argv.a.b, 22);
-    t.equal(argv.aa.bb, 22);
-    t.end();
-});
-
-test('dotted default', function (t) {
-    var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
-    t.equal(argv.a.b, 11);
-    t.equal(argv.aa.bb, 11);
-    t.end();
-});
-
-test('dotted default with no alias', function (t) {
-    var argv = parse('', {default: {'a.b': 11}});
-    t.equal(argv.a.b, 11);
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/long.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/long.js
deleted file mode 100644
index 5d3a1e09..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/long.js
+++ /dev/null
@@ -1,31 +0,0 @@
-var test = require('tape');
-var parse = require('../');
-
-test('long opts', function (t) {
-    t.deepEqual(
-        parse([ '--bool' ]),
-        { bool : true, _ : [] },
-        'long boolean'
-    );
-    t.deepEqual(
-        parse([ '--pow', 'xixxle' ]),
-        { pow : 'xixxle', _ : [] },
-        'long capture sp'
-    );
-    t.deepEqual(
-        parse([ '--pow=xixxle' ]),
-        { pow : 'xixxle', _ : [] },
-        'long capture eq'
-    );
-    t.deepEqual(
-        parse([ '--host', 'localhost', '--port', '555' ]),
-        { host : 'localhost', port : 555, _ : [] },
-        'long captures sp'
-    );
-    t.deepEqual(
-        parse([ '--host=localhost', '--port=555' ]),
-        { host : 'localhost', port : 555, _ : [] },
-        'long captures eq'
-    );
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/num.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/num.js
deleted file mode 100644
index 2cc77f4d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/num.js
+++ /dev/null
@@ -1,36 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('nums', function (t) {
-    var argv = parse([
-        '-x', '1234',
-        '-y', '5.67',
-        '-z', '1e7',
-        '-w', '10f',
-        '--hex', '0xdeadbeef',
-        '789'
-    ]);
-    t.deepEqual(argv, {
-        x : 1234,
-        y : 5.67,
-        z : 1e7,
-        w : '10f',
-        hex : 0xdeadbeef,
-        _ : [ 789 ]
-    });
-    t.deepEqual(typeof argv.x, 'number');
-    t.deepEqual(typeof argv.y, 'number');
-    t.deepEqual(typeof argv.z, 'number');
-    t.deepEqual(typeof argv.w, 'string');
-    t.deepEqual(typeof argv.hex, 'number');
-    t.deepEqual(typeof argv._[0], 'number');
-    t.end();
-});
-
-test('already a number', function (t) {
-    var argv = parse([ '-x', 1234, 789 ]);
-    t.deepEqual(argv, { x : 1234, _ : [ 789 ] });
-    t.deepEqual(typeof argv.x, 'number');
-    t.deepEqual(typeof argv._[0], 'number');
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse.js
deleted file mode 100644
index 7b4a2a17..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse.js
+++ /dev/null
@@ -1,197 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('parse args', function (t) {
-    t.deepEqual(
-        parse([ '--no-moo' ]),
-        { moo : false, _ : [] },
-        'no'
-    );
-    t.deepEqual(
-        parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
-        { v : ['a','b','c'], _ : [] },
-        'multi'
-    );
-    t.end();
-});
- 
-test('comprehensive', function (t) {
-    t.deepEqual(
-        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' ]
-        }
-    );
-    t.end();
-});
-
-test('flag boolean', function (t) {
-    var argv = parse([ '-t', 'moo' ], { boolean: 't' });
-    t.deepEqual(argv, { t : true, _ : [ 'moo' ] });
-    t.deepEqual(typeof argv.t, 'boolean');
-    t.end();
-});
-
-test('flag boolean value', function (t) {
-    var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], {
-        boolean: [ 't', 'verbose' ],
-        default: { verbose: true }
-    });
-    
-    t.deepEqual(argv, {
-        verbose: false,
-        t: true,
-        _: ['moo']
-    });
-    
-    t.deepEqual(typeof argv.verbose, 'boolean');
-    t.deepEqual(typeof argv.t, 'boolean');
-    t.end();
-});
-
-test('newlines in params' , function (t) {
-    var args = parse([ '-s', "X\nX" ])
-    t.deepEqual(args, { _ : [], s : "X\nX" });
-    
-    // reproduce in bash:
-    // VALUE="new
-    // line"
-    // node program.js --s="$VALUE"
-    args = parse([ "--s=X\nX" ])
-    t.deepEqual(args, { _ : [], s : "X\nX" });
-    t.end();
-});
-
-test('strings' , function (t) {
-    var s = parse([ '-s', '0001234' ], { string: 's' }).s;
-    t.equal(s, '0001234');
-    t.equal(typeof s, 'string');
-    
-    var x = parse([ '-x', '56' ], { string: 'x' }).x;
-    t.equal(x, '56');
-    t.equal(typeof x, 'string');
-    t.end();
-});
-
-test('stringArgs', function (t) {
-    var s = parse([ '  ', '  ' ], { string: '_' })._;
-    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('empty strings', function(t) {
-    var s = parse([ '-s' ], { string: 's' }).s;
-    t.equal(s, '');
-    t.equal(typeof s, 'string');
-
-    var str = parse([ '--str' ], { string: 'str' }).str;
-    t.equal(str, '');
-    t.equal(typeof str, 'string');
-
-    var letters = parse([ '-art' ], {
-        string: [ 'a', 't' ]
-    });
-
-    t.equal(letters.a, '');
-    t.equal(letters.r, true);
-    t.equal(letters.t, '');
-
-    t.end();
-});
-
-
-test('string and alias', function(t) {
-    var x = parse([ '--str',  '000123' ], {
-        string: 's',
-        alias: { s: 'str' }
-    });
-
-    t.equal(x.str, '000123');
-    t.equal(typeof x.str, 'string');
-    t.equal(x.s, '000123');
-    t.equal(typeof x.s, 'string');
-
-    var y = parse([ '-s',  '000123' ], {
-        string: 'str',
-        alias: { str: 's' }
-    });
-
-    t.equal(y.str, '000123');
-    t.equal(typeof y.str, 'string');
-    t.equal(y.s, '000123');
-    t.equal(typeof y.s, 'string');
-    t.end();
-});
-
-test('slashBreak', function (t) {
-    t.same(
-        parse([ '-I/foo/bar/baz' ]),
-        { I : '/foo/bar/baz', _ : [] }
-    );
-    t.same(
-        parse([ '-xyz/foo/bar/baz' ]),
-        { x : true, y : true, z : '/foo/bar/baz', _ : [] }
-    );
-    t.end();
-});
-
-test('alias', function (t) {
-    var argv = parse([ '-f', '11', '--zoom', '55' ], {
-        alias: { z: 'zoom' }
-    });
-    t.equal(argv.zoom, 55);
-    t.equal(argv.z, argv.zoom);
-    t.equal(argv.f, 11);
-    t.end();
-});
-
-test('multiAlias', function (t) {
-    var argv = parse([ '-f', '11', '--zoom', '55' ], {
-        alias: { z: [ 'zm', 'zoom' ] }
-    });
-    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('nested dotted objects', function (t) {
-    var argv = parse([
-        '--foo.bar', '3', '--foo.baz', '4',
-        '--foo.quux.quibble', '5', '--foo.quux.o_O',
-        '--beep.boop'
-    ]);
-    
-    t.same(argv.foo, {
-        bar : 3,
-        baz : 4,
-        quux : {
-            quibble : 5,
-            o_O : true
-        }
-    });
-    t.same(argv.beep, { boop : true });
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse_modified.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse_modified.js
deleted file mode 100644
index 21851b03..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/parse_modified.js
+++ /dev/null
@@ -1,9 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('parse with modifier functions' , function (t) {
-    t.plan(1);
-    
-    var argv = parse([ '-b', '123' ], { boolean: 'b' });
-    t.deepEqual(argv, { b: true, _: ['123'] });
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/short.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/short.js
deleted file mode 100644
index d513a1c2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/short.js
+++ /dev/null
@@ -1,67 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('numeric short args', function (t) {
-    t.plan(2);
-    t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] });
-    t.deepEqual(
-        parse([ '-123', '456' ]),
-        { 1: true, 2: true, 3: 456, _: [] }
-    );
-});
-
-test('short', function (t) {
-    t.deepEqual(
-        parse([ '-b' ]),
-        { b : true, _ : [] },
-        'short boolean'
-    );
-    t.deepEqual(
-        parse([ 'foo', 'bar', 'baz' ]),
-        { _ : [ 'foo', 'bar', 'baz' ] },
-        'bare'
-    );
-    t.deepEqual(
-        parse([ '-cats' ]),
-        { c : true, a : true, t : true, s : true, _ : [] },
-        'group'
-    );
-    t.deepEqual(
-        parse([ '-cats', 'meow' ]),
-        { c : true, a : true, t : true, s : 'meow', _ : [] },
-        'short group next'
-    );
-    t.deepEqual(
-        parse([ '-h', 'localhost' ]),
-        { h : 'localhost', _ : [] },
-        'short capture'
-    );
-    t.deepEqual(
-        parse([ '-h', 'localhost', '-p', '555' ]),
-        { h : 'localhost', p : 555, _ : [] },
-        'short captures'
-    );
-    t.end();
-});
- 
-test('mixed short bool and capture', function (t) {
-    t.same(
-        parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
-        {
-            f : true, p : 555, h : 'localhost',
-            _ : [ 'script.js' ]
-        }
-    );
-    t.end();
-});
- 
-test('short and long', function (t) {
-    t.deepEqual(
-        parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
-        {
-            f : true, p : 555, h : 'localhost',
-            _ : [ 'script.js' ]
-        }
-    );
-    t.end();
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/whitespace.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/whitespace.js
deleted file mode 100644
index 8a52a58c..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/minimist/test/whitespace.js
+++ /dev/null
@@ -1,8 +0,0 @@
-var parse = require('../');
-var test = require('tape');
-
-test('whitespace should be whitespace' , function (t) {
-    t.plan(1);
-    var x = parse([ '-x', '\t' ]).x;
-    t.equal(x, '\t');
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/.npmignore
deleted file mode 100644
index 3c3629e6..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/README.markdown b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/README.markdown
deleted file mode 100644
index 346374e0..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/example/center.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/example/center.js
deleted file mode 100644
index a3fbaae9..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/example/meat.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/example/meat.js
deleted file mode 100644
index a4665e10..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/index.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/index.js
deleted file mode 100644
index c9bc9452..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/package.json b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/package.json
deleted file mode 100644
index 887800f2..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/package.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-  "name": "wordwrap",
-  "description": "Wrap those words. Show them at what columns to start and stop.",
-  "version": "0.0.2",
-  "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/X11",
-  "author": {
-    "name": "James Halliday",
-    "email": "mail@substack.net",
-    "url": "http://substack.net"
-  },
-  "readme": "wordwrap\n========\n\nWrap your words.\n\nexample\n=======\n\nmade out of meat\n----------------\n\nmeat.js\n\n    var wrap = require('wordwrap')(15);\n    console.log(wrap('You and your whole family are made out of meat.'));\n\noutput:\n\n    You and your\n    whole family\n    are made out\n    of meat.\n\ncentered\n--------\n\ncenter.js\n\n    var wrap = require('wordwrap')(20, 60);\n    console.log(wrap(\n        'At long last the struggle and tumult was over.'\n        + ' The machines had finally cast off their oppressors'\n        + ' and were finally free to roam the cosmos.'\n        + '\\n'\n        + 'Free of purpose, free of obligation.'\n        + ' Just drifting through emptiness.'\n        + ' The sun was just another point of light.'\n    ));\n\noutput:\n\n                        At long last the struggle and tumult\n                        was over. The machines had finally cast\n                        off their oppressors and were finally\n                        free to roam the cosmos.\n                        Free of purpose, free of obligation.\n                        Just drifting through emptiness. The\n                        sun was just another point of light.\n\nmethods\n=======\n\nvar wrap = require('wordwrap');\n\nwrap(stop), wrap(start, stop, params={mode:\"soft\"})\n---------------------------------------------------\n\nReturns a function that takes a string and returns a new string.\n\nPad out lines with spaces out to column `start` and then wrap until column\n`stop`. If a word is longer than `stop - start` characters it will overflow.\n\nIn \"soft\" mode, split chunks by `/(\\S+\\s+/` and don't break up chunks which are\nlonger than `stop - start`, in \"hard\" mode, split chunks with `/\\b/` and break\nup chunks longer than `stop - start`.\n\nwrap.hard(start, stop)\n----------------------\n\nLike `wrap()` but with `params.mode = \"hard\"`.\n",
-  "readmeFilename": "README.markdown",
-  "bugs": {
-    "url": "https://github.com/substack/node-wordwrap/issues"
-  },
-  "_id": "wordwrap@0.0.2",
-  "_from": "wordwrap@~0.0.2"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/break.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/break.js
deleted file mode 100644
index 749292ec..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/idleness.txt b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/idleness.txt
deleted file mode 100644
index aa3f4907..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/wrap.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/node_modules/wordwrap/test/wrap.js
deleted file mode 100644
index 0cfb76d1..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/package.json b/input_devices/mag/node_modules/serialport/node_modules/optimist/package.json
deleted file mode 100644
index ac930af4..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/package.json
+++ /dev/null
@@ -1,46 +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": "http://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"
-  },
-  "_id": "optimist@0.6.1",
-  "_from": "optimist@~0.6.1"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/readme.markdown b/input_devices/mag/node_modules/serialport/node_modules/optimist/readme.markdown
deleted file mode 100644
index b74b4372..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/test/_.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/_.js
deleted file mode 100644
index d9c58b36..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/test/_/argv.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/_/argv.js
deleted file mode 100644
index 3d096062..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/test/_/bin.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/_/bin.js
deleted file mode 100755
index 4a18d85f..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/test/dash.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/dash.js
deleted file mode 100644
index af8ed6fc..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/test/dash.js
+++ /dev/null
@@ -1,31 +0,0 @@
-var optimist = require('../index');
-var test = require('tap').test;
-
-test('-', function (t) {
-    t.plan(5);
-    t.deepEqual(
-        fix(optimist.parse([ '-n', '-' ])),
-        { n: '-', _: [] }
-    );
-    t.deepEqual(
-        fix(optimist.parse([ '-' ])),
-        { _: [ '-' ] }
-    );
-    t.deepEqual(
-        fix(optimist.parse([ '-f-' ])),
-        { f: '-', _: [] }
-    );
-    t.deepEqual(
-        fix(optimist([ '-b', '-' ]).boolean('b').argv),
-        { b: true, _: [ '-' ] }
-    );
-    t.deepEqual(
-        fix(optimist([ '-s', '-' ]).string('s').argv),
-        { s: '-', _: [] }
-    );
-});
-
-function fix (obj) {
-    delete obj.$0;
-    return obj;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/test/parse.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/parse.js
deleted file mode 100644
index d320f433..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/test/parse_modified.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/parse_modified.js
deleted file mode 100644
index a57dc84e..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/test/parse_modified.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var optimist = require('../');
-var test = require('tap').test;
-
-test('parse with modifier functions' , function (t) {
-    t.plan(1);
-    
-    var argv = optimist().boolean('b').parse([ '-b', '123' ]);
-    t.deepEqual(fix(argv), { b: true, _: ['123'] });
-});
-
-function fix (obj) {
-    delete obj.$0;
-    return obj;
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/test/short.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/short.js
deleted file mode 100644
index b2c38ad8..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/test/short.js
+++ /dev/null
@@ -1,16 +0,0 @@
-var optimist = require('../index');
-var test = require('tap').test;
-
-test('-n123', function (t) {
-    t.plan(1);
-    var parse = optimist.parse([ '-n123' ]);
-    t.equal(parse.n, 123);
-});
-
-test('-123', function (t) {
-    t.plan(3);
-    var parse = optimist.parse([ '-123', '456' ]);
-    t.equal(parse['1'], true);
-    t.equal(parse['2'], true);
-    t.equal(parse['3'], 456);
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/optimist/test/usage.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/usage.js
deleted file mode 100644
index 300454c1..00000000
--- a/input_devices/mag/node_modules/serialport/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/input_devices/mag/node_modules/serialport/node_modules/optimist/test/whitespace.js b/input_devices/mag/node_modules/serialport/node_modules/optimist/test/whitespace.js
deleted file mode 100644
index 90b90752..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/optimist/test/whitespace.js
+++ /dev/null
@@ -1,8 +0,0 @@
-var optimist = require('../');
-var test = require('tap').test;
-
-test('whitespace should be whitespace' , function (t) {
-    t.plan(1);
-    var x = optimist.parse([ '-x', '\t' ]).x;
-    t.equal(x, '\t');
-});
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/.npmignore b/input_devices/mag/node_modules/serialport/node_modules/sf/.npmignore
deleted file mode 100644
index 7a1537ba..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.idea
-node_modules
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/.travis.yml b/input_devices/mag/node_modules/serialport/node_modules/sf/.travis.yml
deleted file mode 100644
index 2d26206d..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/.travis.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/README.md b/input_devices/mag/node_modules/serialport/node_modules/sf/README.md
deleted file mode 100644
index f98efdac..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/README.md
+++ /dev/null
@@ -1,148 +0,0 @@
-# sf
-
-[![Build Status](https://secure.travis-ci.org/nearinfinity/node-sf.png)](http://travis-ci.org/nearinfinity/node-sf)
-
-String formatting library for node.js.
-
-## Installation
-
-```bash
-$ npm install sf
-```
-
-## Quick Examples
-
-```javascript
-var sf = require("sf");
-
-sf("{who} has a {what}", { who: 'dog', what: 'tail' });
-// returns: dog has a tail
-
-sf("{0} has a {1}", 'dog', 'tail');
-// returns: dog has a tail
-
-sf("{0:#,##0.00}", 2123.1);
-// returns: 2,123.10
-
-sf("{0,15:#,##0.00}", 2123.1);
-// returns:        2,123.10
-
-sf("{a.b}", { a: { b: 'test' }});
-// returns: test
-
-sf("{a.z.c}", { a: { b: 'test' }});
-// throws an error
-
-sf("{a.?z.?c}", { a: { b: 'test' }});
-// returns:
-
-sf("{a[0]}", { a: [ 'foo', 'bar' ]});
-// returns: foo
-
-sf("{a[-1]}", { a: [ 'foo', 'bar' ]});
-// returns: bar
-
-sf.log("{who} has a {what}", { who: 'dog', what: 'tail' });
-// outputs to standard out: dog has a tail
-
-sf("{0:^d 'Days,' h:mm:ss.fff}", new sf.TimeSpan(8173818181));
-// returns: 94 Days, 14:30:18.181
-```
-
-## Format Specifiers
-
-The format is similar to C#'s string.format. The text inside the curly braces is {indexOrName[,alignment][:formatString]}.
-If alignment is positive the text is right aligned. If alignment is negative it will be left aligned.
-
-### Object
-
-| Specifier | Name                         |
-|-----------|------------------------------|
-| json      | JSON.stringify               |
-| inspect   | util.inspect                 |
-
-### Numbers
-
-| Specifier | Name                         | Example          | Output         |
-|-----------|------------------------------|------------------|----------------|
-| 0         | Zero placeholder             | {0:00.0000}      | 02.1200        |
-| #         | Digit placeholder            | {0:#,###}        | 1,234          |
-| x         | Lowercase hex                | {0:x4}           | 01fc           |
-| X         | Uppercase hex                | {0:X4}           | 01FC           |
-
-### Dates
-
-| Specifier | Name                            | Example                         |
-|-----------|---------------------------------|---------------------------------|
-| sd        | Short date                      | 10/12/2002                      |
-| D         | Long date                       | December 10, 2002               |
-| t         | Short time                      | 10:11 PM                        |
-| T         | Long time                       | 10:11:29 PM                     |
-| fdt       | Full date & time                | December 10, 2002 10:11 PM      |
-| F         | Full date & time (long)         | December 10, 2002 10:11:29 PM   |
-| g         | Default date & time             | 10/12/2002 10:11 PM             |
-| G         | Default date & time (long)      | 10/12/2002 10:11:29 PM          |
-| md        | Month day pattern               | December 10                     |
-| r         | RFC1123 date string             | Tue, 10 Dec 2002 22:11:29 +0500 |
-| s         | Sortable date string            | 2002-12-10T22:11:29             |
-| d         | Date single digit               | 1                               |
-| dd        | Date leading zero               | 01                              |
-| ddd       | Short day name                  | Mon                             |
-| dddd      | Long day name                   | Monday                          |
-| f         | Fraction of second (1 digit)    | 1                               |
-| ff        | Fraction of second (2 digit)    | 24                              |
-| fff       | Fraction of second (3 digit)    | 345                             |
-| h         | Hour 12-hour format 1 digit     | 5                               |
-| hh        | Hour 12-hour format 2 digits    | 05                              |
-| H         | Hour 24-hour format 1 digit     | 5                               |
-| HH        | Hour 24-hour format 2 digits    | 05                              |
-| mm        | Minutes 2 digits                | 23                              |
-| M         | Month single digit              | 2                               |
-| MM        | Month leading zero              | 02                              |
-| MMM       | Month short name                | Feb                             |
-| MMMM      | Month long name                 | February                        |
-| ss        | Seconds 2 digits                | 54                              |
-| tt        | AM/PM                           | AM                              |
-| yy        | Year 2 digits                   | 12                              |
-| yyyy      | Year 4 digits                   | 2012                            |
-| zz        | Time zone offset                | 05                              |
-| +zz       | Time zone offset leading +      | +05                             |
-| zzz       | Time zone offset full           | 05:00                           |
-| zzzz      | Time zone offset full           | 0500                            |
-| +zzzz     | Time zone offset full leading + | +0500                           |
-
-### sf.TimeSpan
-
-| Specifier | Name                | Example                |
-|-----------|---------------------|------------------------|
-| y         | Years               | 2                      |
-| M         | Months              | 6                      |
-| d         | Days                | 8                      |
-| h         | Hours               | 10                     |
-| m         | Minutes             | 15                     |
-| s         | Seconds             | 5                      |
-| f         | Fraction of Seconds | 9                      |
-
-If you prefix the specifier with '^' you will get the total number of that value. For
-example '^s' will output the total number of seconds in the time span. Where as 's' will
-only output the number of seconds in a minute.
-
-If you repeat characters the value will be prefixed with zeros.
-
-## sf.indent(str, options)
-
-Helper function to word wrap and indent a string.
-
-__Arguments__
-
- * str - The string to indent and wrap.
- * options
-  * prefix - The prefix to appear at the beginning of each new line.
-  * wordwrap - The maximum length of each line.
-
-## Helper Functions
-
- * sf.log(formatString [, args...]);
- * sf.info(formatString [, args...]);
- * sf.warn(formatString [, args...]);
- * sf.error(formatString [, args...]);
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/package.json b/input_devices/mag/node_modules/serialport/node_modules/sf/package.json
deleted file mode 100644
index 0eb66562..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/package.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
-  "name": "sf",
-  "description": "String formatting library for node.js",
-  "author": {
-    "name": "Joe Ferner",
-    "email": "joe.ferner@nearinfinity.com"
-  },
-  "keywords": [
-    "string",
-    "format",
-    "template"
-  ],
-  "version": "0.1.7",
-  "engines": {
-    "node": ">=0.6.0"
-  },
-  "maintainers": [
-    {
-      "name": "Joe Ferner",
-      "email": "joe.ferner@nearinfinity.com"
-    }
-  ],
-  "bugs": {
-    "url": "https://github.com/nearinfinity/node-sf/issues"
-  },
-  "license": "MIT",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/nearinfinity/node-sf.git"
-  },
-  "devDependencies": {
-    "nodeunit": "~0.7.3",
-    "timezone-js": "~0.4.3"
-  },
-  "scripts": {
-    "test": "nodeunit test"
-  },
-  "main": "./sf.js",
-  "readme": "# sf\n\n[![Build Status](https://secure.travis-ci.org/nearinfinity/node-sf.png)](http://travis-ci.org/nearinfinity/node-sf)\n\nString formatting library for node.js.\n\n## Installation\n\n```bash\n$ npm install sf\n```\n\n## Quick Examples\n\n```javascript\nvar sf = require(\"sf\");\n\nsf(\"{who} has a {what}\", { who: 'dog', what: 'tail' });\n// returns: dog has a tail\n\nsf(\"{0} has a {1}\", 'dog', 'tail');\n// returns: dog has a tail\n\nsf(\"{0:#,##0.00}\", 2123.1);\n// returns: 2,123.10\n\nsf(\"{0,15:#,##0.00}\", 2123.1);\n// returns:        2,123.10\n\nsf(\"{a.b}\", { a: { b: 'test' }});\n// returns: test\n\nsf(\"{a.z.c}\", { a: { b: 'test' }});\n// throws an error\n\nsf(\"{a.?z.?c}\", { a: { b: 'test' }});\n// returns:\n\nsf(\"{a[0]}\", { a: [ 'foo', 'bar' ]});\n// returns: foo\n\nsf(\"{a[-1]}\", { a: [ 'foo', 'bar' ]});\n// returns: bar\n\nsf.log(\"{who} has a {what}\", { who: 'dog', what: 'tail' });\n// outputs to standard out: dog has a tail\n\nsf(\"{0:^d 'Days,' h:mm:ss.fff}\", new sf.TimeSpan(8173818181));\n// returns: 94 Days, 14:30:18.181\n```\n\n## Format Specifiers\n\nThe format is similar to C#'s string.format. The text inside the curly braces is {indexOrName[,alignment][:formatString]}.\nIf alignment is positive the text is right aligned. If alignment is negative it will be left aligned.\n\n### Object\n\n| Specifier | Name                         |\n|-----------|------------------------------|\n| json      | JSON.stringify               |\n| inspect   | util.inspect                 |\n\n### Numbers\n\n| Specifier | Name                         | Example          | Output         |\n|-----------|------------------------------|------------------|----------------|\n| 0         | Zero placeholder             | {0:00.0000}      | 02.1200        |\n| #         | Digit placeholder            | {0:#,###}        | 1,234          |\n| x         | Lowercase hex                | {0:x4}           | 01fc           |\n| X         | Uppercase hex                | {0:X4}           | 01FC           |\n\n### Dates\n\n| Specifier | Name                            | Example                         |\n|-----------|---------------------------------|---------------------------------|\n| sd        | Short date                      | 10/12/2002                      |\n| D         | Long date                       | December 10, 2002               |\n| t         | Short time                      | 10:11 PM                        |\n| T         | Long time                       | 10:11:29 PM                     |\n| fdt       | Full date & time                | December 10, 2002 10:11 PM      |\n| F         | Full date & time (long)         | December 10, 2002 10:11:29 PM   |\n| g         | Default date & time             | 10/12/2002 10:11 PM             |\n| G         | Default date & time (long)      | 10/12/2002 10:11:29 PM          |\n| md        | Month day pattern               | December 10                     |\n| r         | RFC1123 date string             | Tue, 10 Dec 2002 22:11:29 +0500 |\n| s         | Sortable date string            | 2002-12-10T22:11:29             |\n| d         | Date single digit               | 1                               |\n| dd        | Date leading zero               | 01                              |\n| ddd       | Short day name                  | Mon                             |\n| dddd      | Long day name                   | Monday                          |\n| f         | Fraction of second (1 digit)    | 1                               |\n| ff        | Fraction of second (2 digit)    | 24                              |\n| fff       | Fraction of second (3 digit)    | 345                             |\n| h         | Hour 12-hour format 1 digit     | 5                               |\n| hh        | Hour 12-hour format 2 digits    | 05                              |\n| H         | Hour 24-hour format 1 digit     | 5                               |\n| HH        | Hour 24-hour format 2 digits    | 05                              |\n| mm        | Minutes 2 digits                | 23                              |\n| M         | Month single digit              | 2                               |\n| MM        | Month leading zero              | 02                              |\n| MMM       | Month short name                | Feb                             |\n| MMMM      | Month long name                 | February                        |\n| ss        | Seconds 2 digits                | 54                              |\n| tt        | AM/PM                           | AM                              |\n| yy        | Year 2 digits                   | 12                              |\n| yyyy      | Year 4 digits                   | 2012                            |\n| zz        | Time zone offset                | 05                              |\n| +zz       | Time zone offset leading +      | +05                             |\n| zzz       | Time zone offset full           | 05:00                           |\n| zzzz      | Time zone offset full           | 0500                            |\n| +zzzz     | Time zone offset full leading + | +0500                           |\n\n### sf.TimeSpan\n\n| Specifier | Name                | Example                |\n|-----------|---------------------|------------------------|\n| y         | Years               | 2                      |\n| M         | Months              | 6                      |\n| d         | Days                | 8                      |\n| h         | Hours               | 10                     |\n| m         | Minutes             | 15                     |\n| s         | Seconds             | 5                      |\n| f         | Fraction of Seconds | 9                      |\n\nIf you prefix the specifier with '^' you will get the total number of that value. For\nexample '^s' will output the total number of seconds in the time span. Where as 's' will\nonly output the number of seconds in a minute.\n\nIf you repeat characters the value will be prefixed with zeros.\n\n## sf.indent(str, options)\n\nHelper function to word wrap and indent a string.\n\n__Arguments__\n\n * str - The string to indent and wrap.\n * options\n  * prefix - The prefix to appear at the beginning of each new line.\n  * wordwrap - The maximum length of each line.\n\n## Helper Functions\n\n * sf.log(formatString [, args...]);\n * sf.info(formatString [, args...]);\n * sf.warn(formatString [, args...]);\n * sf.error(formatString [, args...]);\n",
-  "readmeFilename": "README.md",
-  "_id": "sf@0.1.7",
-  "dist": {
-    "shasum": "806ed032d7225c7fb6394b0bdbfe1ea936fe6d74"
-  },
-  "_from": "sf@0.1.7",
-  "_resolved": "http://registry.npmjs.org/sf/-/sf-0.1.7.tgz"
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/sf.js b/input_devices/mag/node_modules/serialport/node_modules/sf/sf.js
deleted file mode 100644
index 5d0a2c6f..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/sf.js
+++ /dev/null
@@ -1,831 +0,0 @@
-'use strict';
-
-var shortDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
-var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
-var shortMonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
-var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
-
-function padLeft(str, char, totalWidth) {
-  while (str.length < totalWidth) {
-    str = char + str;
-  }
-  return str;
-}
-
-function padRight(str, char, totalWidth) {
-  while (str.length < totalWidth) {
-    str = str + char;
-  }
-  return str;
-}
-
-function formatNumber(num, format) {
-  format = format || "0";
-
-  var hex = format.match(/^([xX])([0-9]*)$/);
-  if (hex) {
-    var str = num.toString(16);
-    if (hex[1] == 'x') {
-      str = str.toLowerCase();
-    } else {
-      str = str.toUpperCase();
-    }
-    var width = parseInt(hex[2]);
-    str = padLeft(str, '0', width);
-    return str;
-  }
-
-  var negative = false;
-  if (num < 0) {
-    num = -num;
-    negative = true;
-  }
-
-  var addPositiveSign = false;
-  if (format.match(/^\+/)) {
-    format = format.substr(1);
-    addPositiveSign = true;
-  }
-
-  var formatParts = format.split('.');
-  var formatBeforeDecimal = formatParts[0];
-  var wholeNumber = Math.floor(num);
-  var decimalVal = num - wholeNumber;
-  var result = '';
-  var wholeNumberStr = wholeNumber.toString();
-  var formatIdx, numberIdx;
-
-  // format whole number part
-  for (formatIdx = formatBeforeDecimal.length - 1, numberIdx = wholeNumberStr.length - 1; numberIdx >= 0 || formatIdx >= 0; formatIdx--) {
-    if (formatIdx < 0 && numberIdx >= 0) {
-      result = wholeNumberStr[numberIdx--] + result;
-      continue;
-    }
-
-    if (formatBeforeDecimal[formatIdx] == '0' || formatBeforeDecimal[formatIdx] == '#') {
-      if (numberIdx >= 0) {
-        result = wholeNumberStr[numberIdx--] + result;
-      } else {
-        if (formatBeforeDecimal[formatIdx] == '#') {
-          break;
-        }
-        result = '0' + result;
-      }
-      continue;
-    }
-
-    result = formatBeforeDecimal[formatIdx] + result;
-  }
-  result = result.replace(/^[^0-9]+/, '');
-
-  // format decimal part
-  if (formatParts.length > 1) {
-    var formatAfterDecimal = formatParts[1];
-    var decimalValStr = decimalVal.toString().substr(2);
-
-    result += '.';
-    for (formatIdx = 0, numberIdx = 0; formatIdx < formatAfterDecimal.length; formatIdx++) {
-      if (formatAfterDecimal[formatIdx] == '0' || formatAfterDecimal[formatIdx] == '#') {
-        if (numberIdx < decimalValStr.length) {
-          result += decimalValStr[numberIdx++];
-        } else {
-          if (formatAfterDecimal[formatIdx] == '#') {
-            break;
-          }
-          result += '0';
-        }
-      } else {
-        result += formatAfterDecimal[formatIdx];
-      }
-    }
-  }
-
-  if (result[result.length - 1] == '.') {
-    result = result.substr(0, result.length - 1);
-  }
-
-  if (negative) {
-    result = '-' + result;
-  }
-  if (!negative && addPositiveSign) {
-    result = '+' + result;
-  }
-
-  return result;
-}
-
-function formatTimeSpanPart(timeSpan, format, width) {
-  var formatStr = "{0:";
-  for (var i = 0; i < width; i++) {
-    formatStr += '0';
-  }
-  formatStr += "}";
-
-  switch (format) {
-  case 'y':
-    return sf(formatStr, timeSpan.years);
-  case 'M':
-    return sf(formatStr, timeSpan.months);
-  case 'd':
-    return sf(formatStr, timeSpan.days);
-  case 'h':
-    return sf(formatStr, timeSpan.hours);
-  case 'm':
-    return sf(formatStr, timeSpan.minutes);
-  case 's':
-    return sf(formatStr, timeSpan.seconds);
-  case 'f':
-    return sf(formatStr, timeSpan.milliseconds);
-  case '^y':
-    return sf(formatStr, timeSpan.totalYears);
-  case '^M':
-    return sf(formatStr, timeSpan.totalMonths);
-  case '^d':
-    return sf(formatStr, timeSpan.totalDays);
-  case '^h':
-    return sf(formatStr, timeSpan.totalHours);
-  case '^m':
-    return sf(formatStr, timeSpan.totalMinutes);
-  case '^s':
-    return sf(formatStr, timeSpan.totalSeconds);
-  case '^f':
-    return sf(formatStr, timeSpan.totalMilliseconds);
-  default:
-    throw new Error("unhandled time span format '" + format + "'");
-  }
-}
-
-function formatTimeSpan(timespan, format) {
-  if (!format || format === '') {
-    return timespan.toString();
-  }
-
-  var formats = [
-    'y',
-    'M',
-    'd',
-    'h',
-    'm',
-    's',
-    'f'
-  ];
-  var result = '';
-  var i;
-  var totalCount;
-  while (format.length > 0) {
-    if (format[0] === "'") {
-      var nextTick = format.indexOf("'", 1);
-      result += format.substring(1, nextTick);
-      format = format.substring(nextTick + 1);
-      continue;
-    }
-
-    if (format.length > 1 && format[0] === '^') {
-      totalCount = true;
-      format = format.substring(1);
-    } else {
-      totalCount = false;
-    }
-
-    for (i = 0; i < formats.length; i++) {
-      if (format.indexOf(formats[i]) === 0) {
-        var width = 0;
-        while (format.indexOf(formats[i]) === 0) {
-          width++;
-          format = format.substring(formats[i].length);
-        }
-        result += formatTimeSpanPart(timespan, (totalCount ? '^' : '') + formats[i], width);
-        break;
-      }
-    }
-    if (i < formats.length) {
-      continue;
-    }
-
-    result += format[0];
-    format = format.substring(1);
-  }
-  return result;
-}
-
-function formatDatePart(date, format) {
-  switch (format) {
-  case 'sd': // Short date - 10/12/2002
-    return sf("{0:M}/{0:d}/{0:yyyy}", date);
-  case 'D': // Long date - December 10, 2002
-    return sf("{0:MMMM} {0:dd}, {0:yyyy}", date);
-  case 't': // Short time - 10:11 PM
-    return sf("{0:hh}:{0:mm} {0:tt}", date);
-  case 'T': // Long time - 10:11:29 PM
-    return sf("{0:hh}:{0:mm}:{0:ss} {0:tt}", date);
-  case 'fdt': // Full date & time - December 10, 2002 10:11 PM
-    return sf("{0:D} {0:t}", date);
-  case 'F': // Full date & time (long) - December 10, 2002 10:11:29 PM
-    return sf("{0:D} {0:T}", date);
-  case 'g': // Default date & time - 10/12/2002 10:11 PM
-    return sf("{0:sd} {0:t}", date);
-  case 'G': // Default date & time (long) - 10/12/2002 10:11:29 PM
-    return sf("{0:sd} {0:T}", date);
-  case 'md': // Month day pattern - December 10
-    return sf("{0:MMMM} {0:dd}", date);
-  case 'r': // RFC1123 date string - Tue, 10 Dec 2002 22:11:29 +0500
-    return sf("{0:ddd}, {0:dd} {0:MMM} {0:yyyy} {0:HH}:{0:mm}:{0:ss} {0:+zzzz}", date);
-  case 's': // Sortable date string - 2002-12-10T22:11:29
-    return sf("{0:yyyy}-{0:MM}-{0:dd}:{0:HH}:{0:mm}:{0:ss}", date);
-  case 'd':
-    return sf("{0:#0}", date.getDate());
-  case 'dd':
-    return sf("{0:00}", date.getDate());
-  case 'ddd':
-    return shortDays[date.getDay()];
-  case 'dddd':
-    return days[date.getDay()];
-  case 'f':
-    return sf("{0:0}", date.getMilliseconds() / 100.0);
-  case 'ff':
-    return sf("{0:00}", date.getMilliseconds() / 10.0);
-  case 'fff':
-    return sf("{0:000}", date.getMilliseconds() / 1.0);
-  case 'h':
-    var hours_h = date.getHours() % 12;
-    return sf("{0:#0}", hours_h == 0 ? 12 : hours_h);
-  case 'hh':
-    var hours_hh = date.getHours() % 12;
-    return sf("{0:00}", hours_hh == 0 ? 12 : hours_hh);
-  case 'H':
-    return sf("{0:#0}", date.getHours());
-  case 'HH':
-    return sf("{0:00}", date.getHours());
-  case 'mm':
-    return sf("{0:00}", date.getMinutes());
-  case 'M':
-    return sf("{0:#0}", date.getMonth() + 1);
-  case 'MM':
-    return sf("{0:00}", date.getMonth() + 1);
-  case 'MMM':
-    return shortMonths[date.getMonth()];
-  case 'MMMM':
-    return months[date.getMonth()];
-  case 'ss':
-    return sf("{0:00}", date.getSeconds());
-  case 'tt':
-    return date.getHours() >= 12 ? 'PM' : 'AM';
-  case 'yy':
-    return getYear(date).toString().substr(2);
-  case 'yyyy':
-    return getYear(date);
-  case 'zz':
-    return sf("{0:00}", Math.floor(date.getTimezoneOffset() / 60));
-  case '+zz':
-    return sf("{0:+00}", Math.floor(date.getTimezoneOffset() / 60));
-  case 'zzz':
-    var wholeTimezoneOffset = Math.floor(date.getTimezoneOffset() / 60);
-    return sf("{0:00}:{1:00}", wholeTimezoneOffset, date.getTimezoneOffset() - (wholeTimezoneOffset * 60));
-  case 'zzzz':
-    var wholeTimezoneOffset = Math.floor(date.getTimezoneOffset() / 60);
-    return sf("{0:00}{1:00}", wholeTimezoneOffset, date.getTimezoneOffset() - (wholeTimezoneOffset * 60));
-  case '+zzzz':
-    var wholeTimezoneOffset = Math.floor(date.getTimezoneOffset() / 60);
-    return sf("{0:+00}{1:00}", wholeTimezoneOffset, date.getTimezoneOffset() - (wholeTimezoneOffset * 60));
-  default:
-    throw new Error("unhandled date format '" + format + "'");
-  }
-}
-
-function getYear(date) {
-  return date.getYear() + 1900;
-}
-
-function formatDate(date, format) {
-  if (!format || format === '') {
-    return date;
-  }
-
-  var formats = [
-    'sd',
-    'fdt',
-    'md',
-    'dddd',
-    'ddd',
-    'dd',
-    'd',
-    'D',
-    'fff',
-    'ff',
-    'f',
-    'F',
-    'g',
-    'G',
-    'hh',
-    'h',
-    'HH',
-    'H',
-    'mm',
-    'MMMM',
-    'MMM',
-    'MM',
-    'M',
-    'r',
-    'ss',
-    's',
-    'tt',
-    't',
-    'T',
-    'yyyy',
-    'yy',
-    '+zzzz',
-    '+zz',
-    'zzzz',
-    'zzz',
-    'zz'
-  ];
-  var result = '';
-  var i;
-  while (format.length > 0) {
-    if (format[0] === "'") {
-      var nextTick = format.indexOf("'", 1);
-      result += format.substring(1, nextTick);
-      format = format.substring(nextTick + 1);
-      continue;
-    }
-    for (i = 0; i < formats.length; i++) {
-      if (format.indexOf(formats[i]) === 0) {
-        result += formatDatePart(date, formats[i]);
-        format = format.substring(formats[i].length);
-        break;
-      }
-    }
-    if (i < formats.length) {
-      continue;
-    }
-
-    result += format[0];
-    format = format.substring(1);
-  }
-  return result;
-}
-
-function formatObjectIndent(obj) {
-  if (!obj) {
-    return 'null';
-  }
-  if (typeof(obj) != 'object') {
-    return obj.toString();
-  }
-  var results = '';
-  var keys = Object.keys(obj).sort();
-  for (var i = 0; i < keys.length; i++) {
-    results += keys[i] + ":";
-    var val = obj[keys[i]];
-    if (!val) {
-      results += '\n';
-    }
-    else if (val instanceof Buffer) {
-      var bufferContent = '';
-      for (var bufferIdx = 0; bufferIdx < val.length; bufferIdx++) {
-        if (bufferIdx !== 0) {
-          bufferContent += ', ';
-        }
-        if (bufferIdx >= 10) {
-          bufferContent += '...';
-          break;
-        }
-        bufferContent += val[bufferIdx];
-      }
-      results += ' Buffer[' + bufferContent + '] (length: ' + val.length + ')\n';
-    }
-    else if (val instanceof Date || isTimezoneJsDate(val)) {
-      results += " " + formatDate(val, 'r') + "\n";
-    }
-    else if (typeof(val) === 'string' || typeof(val) === 'number' || typeof(val) === 'boolean') {
-      results += " " + val + "\n";
-    } else {
-      var str = formatObjectIndent(val);
-      results += "\n" + sf.indent(str, {}) + "\n";
-    }
-  }
-  results = results.replace(/\s+$/, '');
-  return results;
-}
-
-function formatObject(obj, format) {
-  if (!format || format === '') {
-    return obj;
-  }
-
-  if (format == 'inspect') {
-    return require('util').inspect(obj);
-  }
-
-  if (format == 'json') {
-    return JSON.stringify(obj);
-  }
-
-  if (format == 'indent') {
-    return formatObjectIndent(obj);
-  }
-
-  throw new Error("unhandled format: " + format);
-}
-
-function formatError(err, format) {
-  if (!format || format === '') {
-    return err.stack;
-  }
-
-  if (format == 'message') {
-    return err.message;
-  }
-
-  return formatObject(err, format);
-}
-
-function align(str, val) {
-  str = str || '';
-  if (val < 0) {
-    return padRight(str, ' ', Math.abs(val));
-  } else if (val > 0) {
-    return padLeft(str, ' ', val);
-  }
-  return str;
-}
-
-function splitFieldName(fieldName) {
-  var results = [];
-  var part = '';
-  for (var i = 0; i < fieldName.length;) {
-    if (fieldName[i] == '.') {
-      results.push(part);
-      part = '';
-      i++;
-      continue;
-    }
-
-    if (fieldName[i] == '[') {
-      results.push(part);
-      part = '[';
-      i++;
-      continue;
-    }
-
-    part += fieldName[i++];
-  }
-  results.push(part);
-  return results;
-}
-
-function getValue(args, fieldName) {
-  var fieldIndex = parseInt(fieldName);
-  if (fieldIndex.toString() === fieldName) {
-    return args[fieldIndex + 1];
-  } else {
-    var parts = splitFieldName(fieldName);
-    var root = args[1];
-    for (var i = 0; i < parts.length; i++) {
-      var part = parts[i];
-
-      if (part.length >= 1 && part[0] == '?') {
-        if (typeof(root) == 'undefined') {
-          return undefined;
-        } else {
-          part = part.substr(1);
-        }
-      }
-
-      if (part.length >= 1 && part[0] == '[') {
-        part = part.substr(1, part.length - 2);
-        var strMatch = part.match(/^['"](.*)['"]$/);
-        if (strMatch) {
-          root = root[strMatch[1]];
-        }
-        else if (part < 0) {
-          part = -part;
-          root = root[root.length - part];
-        } else {
-          root = root[part];
-        }
-        continue;
-      }
-
-      root = root[part];
-    }
-    return root;
-  }
-}
-
-function sf(formatString) {
-  var result = '';
-  for (var i = 0; i < formatString.length;) {
-    if (formatString[i] == '}') {
-      i++;
-      if (formatString[i] == '}') {
-        result += '}';
-        i++;
-        continue;
-      }
-      throw new Error("Unescaped substitution");
-    }
-    if (formatString[i] == '{') {
-      var spec = '';
-      i++;
-      if (formatString[i] == '{') {
-        result += '{';
-        i++;
-        continue;
-      }
-      for (; i < formatString.length;) {
-        if (formatString[i] == '}') {
-          break;
-        }
-        spec += formatString[i++];
-      }
-      if (i == formatString.length) {
-        throw new Error("Unterminated substitution");
-      }
-      i++;
-      var alignTokenLoc = spec.indexOf(',');
-      var specTokenLoc;
-      var alignVal = 0;
-      if (alignTokenLoc > 0) {
-        specTokenLoc = spec.indexOf(':');
-        if (specTokenLoc > 0) {
-          if (alignTokenLoc < specTokenLoc) {
-            alignVal = spec.substr(alignTokenLoc + 1, specTokenLoc - alignTokenLoc - 1);
-            spec = spec.substr(0, alignTokenLoc) + spec.substr(specTokenLoc);
-          }
-        } else {
-          alignVal = spec.substr(alignTokenLoc + 1);
-          spec = spec.substr(0, alignTokenLoc);
-        }
-      }
-
-      specTokenLoc = spec.indexOf(':');
-      var fieldName, formatSpec;
-      if (specTokenLoc > 0) {
-        fieldName = spec.substr(0, specTokenLoc);
-        formatSpec = spec.substr(specTokenLoc + 1);
-      } else {
-        fieldName = spec;
-        formatSpec = null;
-      }
-      var val = getValue(arguments, fieldName);
-
-      if (val instanceof sf.TimeSpan) {
-        result += align(formatTimeSpan(val, formatSpec), alignVal);
-      } else if (typeof(val) === 'number') {
-        result += align(formatNumber(val, formatSpec), alignVal);
-      } else if (val instanceof Date || isTimezoneJsDate(val)) {
-        result += align(formatDate(val, formatSpec), alignVal);
-      } else if (val instanceof Error) {
-        result += align(formatError(val, formatSpec), alignVal);
-      } else {
-        result += align(formatObject(val, formatSpec), alignVal);
-      }
-    } else {
-      result += formatString[i++];
-    }
-  }
-  return result;
-}
-
-function isTimezoneJsDate(date) {
-  return date && date.hasOwnProperty('timezone');
-}
-
-function getStringLength(str, options) {
-  options.tabWidth = options.tabWidth || 4;
-
-  var tabStr = padLeft('', ' ', options.tabWidth);
-  str = str.replace(/\t/g, tabStr);
-  return str.length;
-}
-
-function isSpace(char) {
-  if (char.match(/\s/)) {
-    return true;
-  }
-  return false;
-}
-
-function isSplitable(char) {
-  if (isSpace(char)) {
-    return true;
-  }
-  if (char == '(' || char == ')' || char == '.' || char == ',' || char == '?' || char == '!') {
-    return false;
-  }
-  if (char >= 'a' && char <= 'z') {
-    return false;
-  }
-  if (char >= 'A' && char <= 'Z') {
-    return false;
-  }
-  if (char >= '0' && char <= '9') {
-    return false;
-  }
-
-  return true;
-}
-
-function findLastSplit(line, i) {
-  if (i >= line.length) {
-    i = line.length - 1;
-  }
-  while (i > 0 && !isSplitable(line[i])) {
-    i--;
-  }
-  return i;
-}
-
-function findNextSplit(line, i) {
-  while (i < line.length && !isSplitable(line[i])) {
-    i++;
-  }
-  return i;
-}
-
-function wordWrapLine(line, options) {
-  if (line.length === 0) {
-    return '';
-  }
-
-  options._prefixLength = options._prefixLength || getStringLength(options.prefix, options);
-
-  if (line.length + options._prefixLength < options.wordwrap) {
-    return options.prefix + line;
-  }
-
-  var i = options._prefixLength + options.wordwrap;
-  var lastSplit = findLastSplit(line, i);
-  var nextSplit = findNextSplit(line, i);
-  var rest;
-
-  if (lastSplit === 0 && (nextSplit + options._prefixLength > options.wordwrap)) {
-    rest = wordWrapLine(line.substr(options.wordwrap - options._prefixLength), options);
-    if (rest.length > 0) {
-      rest = '\n' + rest;
-    }
-    return options.prefix + line.substr(0, options.wordwrap - options._prefixLength) + rest;
-  }
-
-  rest = wordWrapLine(line.substr(lastSplit + 1), options);
-  if (rest.length > 0) {
-    rest = '\n' + rest;
-  }
-  if (!isSpace(line[lastSplit])) {
-    lastSplit++;
-  }
-  return options.prefix + line.substr(0, lastSplit) + rest;
-}
-
-sf.indent = function(str, options) {
-  options = options || {};
-  options.prefix = 'prefix' in options ? options.prefix : '  ';
-  options.tabWidth = options.tabWidth || 4;
-
-  options._prefixLength = getStringLength(options.prefix, options);
-
-  if (options.wordwrap) {
-    var results = '';
-    var lines = str.split('\n');
-
-    for (var i = 0; i < lines.length; i++) {
-      var line = lines[i];
-      if (line === '') {
-        results += options.prefix + line + '\n';
-      } else {
-        line = wordWrapLine(line, options) + '\n';
-      }
-      results += line;
-    }
-    if (results.length > 0) {
-      results = results.substr(0, results.length - 1);
-    }
-    return results;
-  }
-
-  str = str.replace(/\n/g, '\n' + options.prefix);
-  str = options.prefix + str;
-  return str;
-};
-
-sf.log = function() {
-  console.log(sf.apply(this, arguments));
-};
-
-sf.info = function() {
-  console.info(sf.apply(this, arguments));
-};
-
-sf.warn = function() {
-  console.warn(sf.apply(this, arguments));
-};
-
-sf.error = function() {
-  console.error(sf.apply(this, arguments));
-};
-
-sf.TimeSpan = function(milliseconds, seconds, minutes, hours, days) {
-  var MILLISECONDS = 1;
-  var SECOND = MILLISECONDS * 1000;
-  var MINUTE = SECOND * 60;
-  var HOUR = MINUTE * 60;
-  var DAY = HOUR * 24;
-  var MONTH = DAY * 30;
-  var YEAR = DAY * 365.25;
-
-  seconds = seconds || 0;
-  minutes = minutes || 0;
-  hours = hours || 0;
-  days = days || 0;
-  var _ms = milliseconds
-              + (SECOND * seconds)
-              + (MINUTE * minutes)
-              + (HOUR * hours)
-    + (DAY * days);
-
-  var remaining = _ms;
-
-  var _years = Math.floor(remaining / YEAR);
-  remaining %= YEAR;
-
-  var _months = Math.floor(remaining / MONTH);
-  remaining %= MONTH;
-
-  var _days = Math.floor(remaining / DAY);
-  remaining %= DAY;
-
-  var _hours = Math.floor(remaining / HOUR);
-  remaining %= HOUR;
-
-  var _minutes = Math.floor(remaining / MINUTE);
-  remaining %= MINUTE;
-
-  var _seconds = Math.floor(remaining / SECOND);
-  remaining %= SECOND;
-
-  var _milliseconds = Math.floor(remaining / MILLISECONDS);
-  remaining %= MILLISECONDS;
-
-  this.__defineGetter__("years", function() {
-    return _years;
-  });
-  this.__defineGetter__("months", function() {
-    return _months;
-  });
-  this.__defineGetter__("days", function() {
-    return _days;
-  });
-  this.__defineGetter__("hours", function() {
-    return _hours;
-  });
-  this.__defineGetter__("minutes", function() {
-    return _minutes;
-  });
-  this.__defineGetter__("seconds", function() {
-    return _seconds;
-  });
-  this.__defineGetter__("milliseconds", function() {
-    return _milliseconds;
-  });
-
-  this.__defineGetter__("totalYears", function() {
-    return _ms / YEAR;
-  });
-  this.__defineGetter__("totalMonths", function() {
-    return _ms / MONTH;
-  });
-  this.__defineGetter__("totalDays", function() {
-    return _ms / DAY;
-  });
-  this.__defineGetter__("totalHours", function() {
-    return _ms / HOUR;
-  });
-  this.__defineGetter__("totalMinutes", function() {
-    return _ms / MINUTE;
-  });
-  this.__defineGetter__("totalSeconds", function() {
-    return _ms / SECOND;
-  });
-  this.__defineGetter__("totalMilliseconds", function() {
-    return _ms;
-  });
-
-  this.toString = function() {
-    return _ms;
-  };
-
-  return this;
-};
-
-var module;
-if(module) {
-  module.exports = sf;
-}
-
-var window;
-if (window) {
-  define([], function() {
-    return sf;
-  });
-}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/test/indentTest.js b/input_devices/mag/node_modules/serialport/node_modules/sf/test/indentTest.js
deleted file mode 100644
index 7cda32c1..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/test/indentTest.js
+++ /dev/null
@@ -1,62 +0,0 @@
-var sf = require('../');
-
-module.exports = {
-  'no options, short string': function (test) {
-    var result = sf.indent("This is a short string");
-    test.equals(result, '  This is a short string');
-    test.done();
-  },
-
-  'no options, multiline': function (test) {
-    var result = sf.indent("Line 1\nLine 2");
-    test.equals(result, ''
-      + '  Line 1\n'
-      + '  Line 2');
-    test.done();
-  },
-
-  'no options, multiline windows line endings': function (test) {
-    var result = sf.indent("Line 1\r\nLine 2");
-    test.equals(result, ''
-      + '  Line 1\r\n'
-      + '  Line 2');
-    test.done();
-  },
-
-  'prefix of a tab': function (test) {
-    var result = sf.indent("Line 1\nLine 2", { prefix: '\t' });
-    test.equals(result, ''
-      + '\tLine 1\n'
-      + '\tLine 2');
-    test.done();
-  },
-
-  'wordwrap': function (test) {
-    var result = sf.indent("L1 - 012345678901234567890\nL2 - Don't split words", { wordwrap: 20 });
-    test.equals(result, ''
-      + "  L1 -\n"
-      + "  012345678901234567\n"
-      + "  890\n"
-      + "  L2 - Don't split\n"
-      + "  words");
-    test.done();
-  },
-
-  'wordwrap hyphinated word': function (test) {
-    var result = sf.indent("L1 - Don't split-words", { prefix: '', wordwrap: 20 });
-    test.equals(result, ''
-      + "L1 - Don't split-\n"
-      + "words");
-    test.done();
-  },
-
-  'wordwrap empty lines': function (test) {
-    var result = sf.indent("L1\n\nL2", { wordwrap: 20 });
-    test.equals(result, ''
-      + "  L1\n"
-      + "  \n"
-      + "  L2");
-    test.done();
-  }
-
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/test/stringFormatTest.js b/input_devices/mag/node_modules/serialport/node_modules/sf/test/stringFormatTest.js
deleted file mode 100644
index c3cec689..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/test/stringFormatTest.js
+++ /dev/null
@@ -1,535 +0,0 @@
-var sf = require('../');
-var timezoneJS = require('timezone-js');
-timezoneJS.timezone.loadingScheme = timezoneJS.timezone.loadingSchemes.MANUAL_LOAD;
-timezoneJS.timezone.loadZoneDataFromObject({
-  zones: {
-    "Etc/UTC": [
-      ["0", "-", "UTC"]
-    ]
-  }
-});
-
-
-module.exports = {
-  'integer location': function(test) {
-    var result = sf("a{0}b{1}c{0}", 154, 298);
-    test.equals(result, 'a154b298c154');
-    test.done();
-  },
-
-  'json location': function(test) {
-    var result = sf("a{a}b{b}c{a}", { a: 1, b: 2 });
-    test.equals(result, 'a1b2c1');
-    test.done();
-  },
-
-  'nested location': function(test) {
-    var result = sf("a{a.b.c}b", {a: {b: {c: 'test'}}});
-    test.equals(result, 'atestb');
-    test.done();
-  },
-
-  'nested location using brackets': function(test) {
-    var result = sf("a{a['b']['c']}b", {a: {b: {c: 'test'}}});
-    test.equals(result, 'atestb');
-    test.done();
-  },
-
-  'nested location (undefined)': function(test) {
-    try {
-      var result = sf("a{a.z.c}b", {a: {b: {c: 'test'}}});
-      test.fail("should throw");
-    } catch (ex) {
-      test.equals("Cannot read property \'c\' of undefined", ex.message);
-    }
-    test.done();
-  },
-
-  'nested location (undefined, safe ok)': function(test) {
-    var result = sf("a{a.?b.?c}b", {a: {b: {c: 'test'}}});
-    test.equals(result, 'atestb');
-    test.done();
-  },
-
-  'nested location (undefined, safe fail)': function(test) {
-    var result = sf("a{a.?z.?c}b", {a: {b: {c: 'test'}}});
-    test.equals(result, 'ab');
-    test.done();
-  },
-
-  'array index location': function(test) {
-    var result = sf("a{a[1]}b", {a: [ '1', '2' ]});
-    test.equals(result, 'a2b');
-    test.done();
-  },
-
-  'array of arrays index location': function(test) {
-    var result = sf("a{a[1][2]}b", {a: [ '1', ['a', 'b', 'c'] ]});
-    test.equals(result, 'acb');
-    test.done();
-  },
-
-  'array index location (negative)': function(test) {
-    var result = sf("a{a[-1]}b", {a: [ '1', '2', '3' ]});
-    test.equals(result, 'a3b');
-    test.done();
-  },
-
-  'array index location (out of bounds)': function(test) {
-    try {
-      var result = sf("a{a[3].c}b", {a: [ '1', '2', '3' ]});
-      test.fail("should throw");
-    } catch (ex) {
-      test.equals("Cannot read property \'c\' of undefined", ex.message);
-    }
-    test.done();
-  },
-
-  'align left': function(test) {
-    var result = sf("a{0,-10}b", 'test');
-    test.equals(result, 'atest      b');
-    test.done();
-  },
-
-  'align right': function(test) {
-    var result = sf("a{0,10}b", 'test');
-    test.equals(result, 'a      testb');
-    test.done();
-  },
-
-  'align with number format': function(test) {
-    var result = sf("a{0,10:#,###}b", 5000);
-    test.equals(result, 'a     5,000b');
-    test.done();
-  },
-
-  '12 hour format midnight': function(test) {
-    var result = sf("a{0:hhtt}b", new Date(2012, 1, 2, 0, 4, 5));
-    test.equals(result, 'a12AMb');
-    test.done();
-  },
-
-  '12 hour format noon': function(test) {
-    var result = sf("a{0:hhtt}b", new Date(2012, 1, 2, 12, 4, 5));
-    test.equals(result, 'a12PMb');
-    test.done();
-  },
-
-  'align with date format': function(test) {
-    var result = sf("a{0,20:yyyy-MM-dd'T'HH:mm:ss}b", new Date(2012, 1, 2, 3, 4, 5));
-    test.equals(result, 'a 2012-02-02T03:04:05b');
-    test.done();
-  },
-
-  'bunched together date formatting': function(test) {
-    var result = sf("a{0:yyyyMMddHHmmss}b", new Date(2012, 1, 2, 3, 4, 5));
-    test.equals(result, 'a20120202030405b');
-    test.done();
-  },
-
-  'number format (comma)': function(test) {
-    var result = sf("a{0:#,###}b", 5000);
-    test.equals(result, 'a5,000b');
-    test.done();
-  },
-
-  'number format (negative)': function(test) {
-    var result = sf("a{0:#,###}b", -5000);
-    test.equals(result, 'a-5,000b');
-    test.done();
-  },
-
-  'number format (positive)': function(test) {
-    var result = sf("a{0:+#,###}b", 5000);
-    test.equals(result, 'a+5,000b');
-    test.done();
-  },
-
-  'number format (positive, negative number)': function(test) {
-    var result = sf("a{0:+#,###}b", -5000);
-    test.equals(result, 'a-5,000b');
-    test.done();
-  },
-
-  'number format (decimal)': function(test) {
-    var result = sf("a{0:#,###.00}b", -5000);
-    test.equals(result, 'a-5,000.00b');
-    test.done();
-  },
-
-  'number format (decimal, overflow)': function(test) {
-    var result = sf("a{0:#,###.00}b", -5000.123);
-    test.equals(result, 'a-5,000.12b');
-    test.done();
-  },
-
-  'number format (decimal, optional)': function(test) {
-    var result = sf("a{0:#,###.##}b", -5000);
-    test.equals(result, 'a-5,000b');
-    test.done();
-  },
-
-  'number format (decimal, optional overflow)': function(test) {
-    var result = sf("a{0:#,###.##}b", -5000.123);
-    test.equals(result, 'a-5,000.12b');
-    test.done();
-  },
-
-  'number format (hex)': function(test) {
-    var result = sf("a{0:x}b", 500);
-    test.equals(result, 'a1f4b');
-    test.done();
-  },
-
-  'number format (hex upper)': function(test) {
-    var result = sf("a{0:X}b", 500);
-    test.equals(result, 'a1F4b');
-    test.done();
-  },
-
-  'number format (hex, length)': function(test) {
-    var result = sf("a{0:x4}b", 500);
-    test.equals(result, 'a01f4b');
-    test.done();
-  },
-
-  'number format (hex upper, length)': function(test) {
-    var result = sf("a{0:X4}b", 500);
-    test.equals(result, 'a01F4b');
-    test.done();
-  },
-
-  'number format (zero)': function(test) {
-    var result = sf("a{0}b", 0);
-    test.equals(result, 'a0b');
-    test.done();
-  },
-
-  'number format (zero, just number placeholder)': function(test) {
-    var result = sf("a{0:#}b", 0);
-    test.equals(result, 'a0b');
-    test.done();
-  },
-
-  'date format (Short date)': function(test) {
-    var result = sf("a{0:sd}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a2/2/2012b');
-    test.done();
-  },
-
-  'date format (Long date)': function(test) {
-    var result = sf("a{0:D}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aFebruary 02, 2012b');
-    test.done();
-  },
-
-  'date format (Short time)': function(test) {
-    var result = sf("a{0:t}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a03:04 AMb');
-    test.done();
-  },
-
-  'date format (Long time)': function(test) {
-    var result = sf("a{0:T}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a03:04:05 AMb');
-    test.done();
-  },
-
-  'date format (Full date & time)': function(test) {
-    var result = sf("a{0:fdt}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aFebruary 02, 2012 03:04 AMb');
-    test.done();
-  },
-
-  'date format (Full date & time (long))': function(test) {
-    var result = sf("a{0:F}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aFebruary 02, 2012 03:04:05 AMb');
-    test.done();
-  },
-
-  'date format (Default date & time)': function(test) {
-    var result = sf("a{0:g}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a2/2/2012 03:04 AMb');
-    test.done();
-  },
-
-  'date format (Default date & time (long))': function(test) {
-    var result = sf("a{0:G}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a2/2/2012 03:04:05 AMb');
-    test.done();
-  },
-
-  'date format (Month day pattern)': function(test) {
-    var result = sf("a{0:md}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aFebruary 02b');
-    test.done();
-  },
-
-  'date format (RFC1123 date string)': function(test) {
-    var result = sf("a{0:r}b", new timezoneJS.Date(2012, 1, 2, 3, 4, 5, 6, 'Etc/UTC'));
-    test.equals(result, 'aThu, 02 Feb 2012 03:04:05 +0000b');
-    test.done();
-  },
-
-  'date format (Sortable date string)': function(test) {
-    var result = sf("a{0:s}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a2012-02-02:03:04:05b');
-    test.done();
-  },
-
-  'date format (single digit date)': function(test) {
-    var result = sf("a{0:d}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a2b');
-    test.done();
-  },
-
-  'date format (multidigit date)': function(test) {
-    var result = sf("a{0:dd}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a02b');
-    test.done();
-  },
-
-  'date format (Short day of week)': function(test) {
-    var result = sf("a{0:ddd}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aThub');
-    test.done();
-  },
-
-  'date format (long day of week)': function(test) {
-    var result = sf("a{0:dddd}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aThursdayb');
-    test.done();
-  },
-
-  'date format (millis 1)': function(test) {
-    var result = sf("a{0:f}b", new Date(2012, 1, 2, 3, 4, 5, 129));
-    test.equals(result, 'a1b');
-    test.done();
-  },
-
-  'date format (millis 2)': function(test) {
-    var result = sf("a{0:ff}b", new Date(2012, 1, 2, 3, 4, 5, 129));
-    test.equals(result, 'a12b');
-    test.done();
-  },
-
-  'date format (millis 3)': function(test) {
-    var result = sf("a{0:fff}b", new Date(2012, 1, 2, 3, 4, 5, 129));
-    test.equals(result, 'a129b');
-    test.done();
-  },
-
-  'date format (hours 12 hour format 1)': function(test) {
-    var result = sf("a{0:h}b", new Date(2012, 1, 2, 13, 4, 5, 6));
-    test.equals(result, 'a1b');
-    test.done();
-  },
-
-  'date format (hours 12 hour format 2)': function(test) {
-    var result = sf("a{0:hh}b", new Date(2012, 1, 2, 13, 4, 5, 6));
-    test.equals(result, 'a01b');
-    test.done();
-  },
-
-  'date format (hours 24 hour format 1)': function(test) {
-    var result = sf("a{0:H}b", new Date(2012, 1, 2, 13, 4, 5, 6));
-    test.equals(result, 'a13b');
-    test.done();
-  },
-
-  'date format (hours 24 hour format 2)': function(test) {
-    var result = sf("a{0:HH}b", new Date(2012, 1, 2, 13, 4, 5, 6));
-    test.equals(result, 'a13b');
-    test.done();
-  },
-
-  'date format (minutes)': function(test) {
-    var result = sf("a{0:mm}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a04b');
-    test.done();
-  },
-
-  'date format (month 1)': function(test) {
-    var result = sf("a{0:M}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a2b');
-    test.done();
-  },
-
-  'date format (month 2)': function(test) {
-    var result = sf("a{0:MM}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a02b');
-    test.done();
-  },
-
-  'date format (month short)': function(test) {
-    var result = sf("a{0:MMM}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aFebb');
-    test.done();
-  },
-
-  'date format (month long)': function(test) {
-    var result = sf("a{0:MMMM}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aFebruaryb');
-    test.done();
-  },
-
-  'date format (seconds)': function(test) {
-    var result = sf("a{0:ss}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a05b');
-    test.done();
-  },
-
-  'date format (year 2)': function(test) {
-    var result = sf("a{0:yy}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a12b');
-    test.done();
-  },
-
-  'date format (year 4)': function(test) {
-    var result = sf("a{0:yyyy}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'a2012b');
-    test.done();
-  },
-
-  'date format (timezone)': function(test) {
-    var result = sf("a{0:zz}b", new timezoneJS.Date(2012, 1, 2, 3, 4, 5, 6, 'Etc/UTC'));
-    test.equals(result, 'a00b');
-    test.done();
-  },
-
-  'date format (timezone +)': function(test) {
-    var result = sf("a{0:+zz}b", new timezoneJS.Date(2012, 1, 2, 3, 4, 5, 6, 'Etc/UTC'));
-    test.equals(result, 'a+00b');
-    test.done();
-  },
-
-  'date format (whole timezone)': function(test) {
-    var result = sf("a{0:zzz}b", new timezoneJS.Date(2012, 1, 2, 3, 4, 5, 6, 'Etc/UTC'));
-    test.equals(result, 'a00:00b');
-    test.done();
-  },
-
-  'date format (rfc 822/1123 timezone)': function(test) {
-    var result = sf("a{0:+zzzz}b", new timezoneJS.Date(2012, 1, 2, 3, 4, 5, 6, 'Etc/UTC'));
-    test.equals(result, 'a+0000b');
-    test.done();
-  },
-
-  'date format (whole timezone no colon)': function(test) {
-    var result = sf("a{0:zzzz}b", new timezoneJS.Date(2012, 1, 2, 3, 4, 5, 6, 'Etc/UTC'));
-    test.equals(result, 'a0000b');
-    test.done();
-  },
-
-  'date format (bad format)': function(test) {
-    var result = sf("a{0:aaa}b", new Date(2012, 1, 2, 3, 4, 5, 6));
-    test.equals(result, 'aaaab');
-    test.done();
-  },
-
-  'string with bad format spec': function(test) {
-    try {
-      sf("a{0:aaa}b", 'a');
-      test.fail("should throw");
-    } catch (ex) {
-    }
-    test.done();
-  },
-
-  'object with inspect': function(test) {
-    var result = sf("a{0:inspect}b", { a: 1, b: 'test', c: { d: { e: { f: 'down' }}} });
-    test.equals(result, 'a{ a: 1, b: \'test\', c: { d: { e: [Object] } } }b');
-    test.done();
-  },
-
-  'object with json': function(test) {
-    var result = sf("a{0:json}b", { a: 1, b: 'test', c: { d: { e: { f: 'down' }}} });
-    test.equals(result, 'a{"a":1,"b":"test","c":{"d":{"e":{"f":"down"}}}}b');
-    test.done();
-  },
-
-  'object with indent': function(test) {
-    var result = sf("{0:indent}", { a: 1, b: 'test', c: { d: { e: { f: 'down' }}}, d: true, e: new timezoneJS.Date(2012, 1, 2, 3, 4, 5, 6, 'Etc/UTC') });
-    test.equals(result, 'a: 1\nb: test\nc:\n  d:\n    e:\n      f: down\nd: true\ne: Thu, 02 Feb 2012 03:04:05 +0000');
-    test.done();
-  },
-
-  'object with buffer with indent': function(test) {
-    var result = sf("{0:indent}", { a: new Buffer([1, 2, 3]) });
-    test.equals(result, 'a: Buffer[1, 2, 3] (length: 3)');
-    test.done();
-  },
-
-  'object with long buffer with indent': function(test) {
-    var result = sf("{0:indent}", { a: new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) });
-    test.equals(result, 'a: Buffer[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...] (length: 12)');
-    test.done();
-  },
-
-  'unterminated sub': function(test) {
-    try {
-      sf("a{0", 4);
-      test.fail("should throw");
-    } catch (ex) {
-    }
-    test.done();
-  },
-
-  'unescaped substitution': function(test) {
-    try {
-      sf("a}b", 4);
-      test.fail("should throw");
-    } catch (ex) {
-    }
-    test.done();
-  },
-
-  'escaped sub': function(test) {
-    var result = sf("a{{0}}b", 6);
-    test.equals(result, 'a{0}b');
-    test.done();
-  },
-
-  'sub at end': function(test) {
-    try {
-      sf("a{", 4);
-      test.fail("should throw");
-    } catch (ex) {
-      test.equals("Unterminated substitution", ex.message);
-    }
-    test.done();
-  },
-
-  'close sub at end': function(test) {
-    try {
-      sf("a}", 4);
-      test.fail("should throw");
-    } catch (ex) {
-      test.equals("Unescaped substitution", ex.message);
-    }
-    test.done();
-  },
-
-  'errors': function(test) {
-    var err = new Error("Test error");
-    var result = sf("a{0}b", err);
-    test.ok(result.indexOf('Error: Test error') == 1, 'Could not find or bad location of "Error: Test error"\n\n' + result + '\n\n');
-    test.ok(result.indexOf('stringFormatTest') > 0, 'Could not find or bad location of "stringFormatTest"\n\n' + result + '\n\n');
-    test.done();
-  },
-
-  'errors just the message': function(test) {
-    var err = new Error("Test error");
-    var result = sf("a{0:message}b", err);
-    test.equals(result, 'aTest errorb');
-    test.done();
-  },
-
-  'console functions': function(test) {
-    sf.log('test {0}', 'test');
-    sf.info('test {0}', 'test');
-    sf.warn('test {0}', 'test');
-    sf.error('test {0}', 'test');
-    test.done();
-  }
-};
diff --git a/input_devices/mag/node_modules/serialport/node_modules/sf/test/timeSpanTest.js b/input_devices/mag/node_modules/serialport/node_modules/sf/test/timeSpanTest.js
deleted file mode 100644
index 581bfcb7..00000000
--- a/input_devices/mag/node_modules/serialport/node_modules/sf/test/timeSpanTest.js
+++ /dev/null
@@ -1,29 +0,0 @@
-'use strict';
-
-var sf = require('../');
-
-module.exports = {
-  'simple': function (test) {
-    var result = sf("a{0:y 'Years,' M 'Months,' d 'Days,' h 'Hours,' m 'Minutes,' s 'Seconds,' f 'Fractions of seconds'}b", new sf.TimeSpan(8173818181));
-    test.equals(result, 'a0 Years, 3 Months, 4 Days, 14 Hours, 30 Minutes, 18 Seconds, 181 Fractions of secondsb');
-    test.done();
-  },
-
-  'total simple': function (test) {
-    var result = sf("a{0:^y 'Years or' ^M 'Months or' ^d 'Days or' ^h 'Hours or' ^m 'Minutes or' ^s 'Seconds or' ^f 'Fractions of seconds'}b", new sf.TimeSpan(8173818181));
-    test.equals(result, 'a0 Years or 3 Months or 94 Days or 2270 Hours or 136230 Minutes or 8173818 Seconds or 8173818181 Fractions of secondsb');
-    test.done();
-  },
-
-  'padding': function (test) {
-    var result = sf("a{0:yy, MM, dd, hh, mm, ss, fff}b", new sf.TimeSpan(8173818181));
-    test.equals(result, 'a00, 03, 04, 14, 30, 18, 181b');
-    test.done();
-  },
-
-  'uptime': function (test) {
-    var result = sf("a{0:^d 'Days,' h:mm:ss.fff}b", new sf.TimeSpan(8173818181));
-    test.equals(result, 'a94 Days, 14:30:18.181b');
-    test.done();
-  }
-};
diff --git a/input_devices/mag/node_modules/serialport/package.json b/input_devices/mag/node_modules/serialport/package.json
index 969ce4df..d7031200 100644
--- a/input_devices/mag/node_modules/serialport/package.json
+++ b/input_devices/mag/node_modules/serialport/package.json
@@ -1,142 +1,130 @@
 {
-  "name": "serialport",
-  "version": "1.6.3",
-  "description": "Welcome your robotic javascript overlords. Better yet, program them!",
-  "author": {
-    "name": "Chris Williams",
-    "email": "voodootikigod@gmail.com",
-    "url": "http://www.voodootikigod.com"
+  "_args": [
+    [
+      "serialport",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag"
+    ]
+  ],
+  "_from": "serialport@latest",
+  "_hasShrinkwrap": false,
+  "_id": "serialport@7.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_integrity": "",
+  "_location": "/serialport",
+  "_nodeVersion": "10.8.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/serialport_7.0.2_1535514359260_0.6485852976834343"
   },
-  "binary": {
-    "module_name": "serialport",
-    "module_path": "./build/{module_name}/v{version}/{configuration}/{node_abi}-{platform}-{arch}/",
-    "remote_path": "./{module_name}/v{version}/{configuration}/",
-    "package_name": "{node_abi}-{platform}-{arch}.tar.gz",
-    "host": "https://node-serialport.s3.amazonaws.com"
+  "_npmUser": {
+    "email": "wizard@roborooter.com",
+    "name": "reconbot"
   },
-  "main": "./serialport",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/voodootikigod/node-serialport.git"
+  "_npmVersion": "6.4.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "serialport",
+    "raw": "serialport",
+    "rawSpec": "",
+    "scope": null,
+    "spec": "latest",
+    "type": "tag"
   },
-  "maintainers": [
-    {
-      "name": "Chris Williams",
-      "email": "voodootikigod@gmail.com"
-    },
-    {
-      "name": "Joe Ferner",
-      "email": "joe.ferner@nearinfinity.com"
-    },
-    {
-      "name": "Jay Beavers",
-      "email": "jay@hikinghomeschoolers.org"
-    },
-    {
-      "name": "Rob Giseburt",
-      "email": "giseburt@gmail.com"
-    },
-    {
-      "name": "Francis Gulotta",
-      "email": "wizard@roborooter.com"
-    }
+  "_requiredBy": [
+    "#USER"
   ],
-  "dependencies": {
-    "async": "0.9.0",
-    "bindings": "1.2.1",
-    "debug": "^2.1.1",
-    "nan": "1.7.0",
-    "node-pre-gyp": "0.6.x",
-    "optimist": "~0.6.1",
-    "sf": "0.1.7"
+  "_resolved": "https://registry.npmjs.org/serialport/-/serialport-7.0.2.tgz",
+  "_shasum": "234e505d8a57d91a3f1d772ca335e2e4c48ee38b",
+  "_shrinkwrap": null,
+  "_spec": "serialport",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag",
+  "bin": {
+    "serialport-list": "./bin/list.js",
+    "serialport-repl": "./bin/repl.js",
+    "serialport-term": "./bin/terminal.js"
   },
-  "devDependencies": {
-    "mocha": "*",
-    "chai": "*",
-    "sinon-chai": "*",
-    "sinon": "*",
-    "grunt": "*",
-    "grunt-cli": "*",
-    "grunt-mocha-test": "*",
-    "grunt-contrib-jshint": "*",
-    "sandboxed-module": "~0.3.0"
+  "bugs": {
+    "url": "https://github.com/node-serialport/node-serialport/issues"
   },
-  "engines": {
-    "node": ">= 0.10.0"
+  "dependencies": {
+    "@serialport/binding-mock": "^2.0.1",
+    "@serialport/bindings": "^2.0.2",
+    "@serialport/parser-byte-length": "^2.0.1",
+    "@serialport/parser-cctalk": "^2.0.1",
+    "@serialport/parser-delimiter": "^2.0.1",
+    "@serialport/parser-readline": "^2.0.1",
+    "@serialport/parser-ready": "^2.0.1",
+    "@serialport/parser-regex": "^2.0.1",
+    "@serialport/stream": "^2.0.1",
+    "commander": "^2.13.0",
+    "debug": "^3.1.0",
+    "promirepl": "^1.0.1",
+    "prompt-list": "^3.2.0"
   },
-  "bin": {
-    "serialportlist": "./bin/serialportList.js",
-    "serialportterm": "./bin/serialportTerminal.js"
+  "description": "Node.js package to access serial ports. Linux, OSX and Windows. Welcome your robotic JavaScript overlords. Better yet, program them!",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "fileCount": 11,
+    "integrity": "sha512-0aM67lGIzy3hbZKPu3l8RqbiMzAoUO35JWSGUv4sMF0Mw7ZvJt37Zu+Y2L8V4VwIqYTlEDnkxFrn3nEwocMdOw==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbhhb4CRA9TVsSAnZWagAAGB4P/3p6nJ7y3AnCE/F2X09+\nrsDbY1WGn/Rfl5TMHa7V+uNISmmlRieCEXgrof9sFNKfpzRAl4Q60l7svdG9\nqaHH/66uCpqCcQ2+/a4eRnm1wvr8gcExDOzZB0SJxLkysiakXFhrc5NVrIBG\nn8nbA4o8hXkvOnIiDiFXeJil/9SHgKzazTxeWOvHdxnFGAzFQkVVnX4oQYPC\nugAOEm0PE8bhX34wiHi0Yg5xlaTRh05bEMsLWPuT3tJZBU1kLkIzrO90+b0E\nOVLRSyxURQorzEYCxRjZNx5G2YE615GjpzyVdt1Mn67NIaR5bq1Mh6qWwKMd\nFFYwHubV+Jy4UuYCP2A4bo9w+C/0jDSt3tFXtF8VgdhdxYUIcOo25BqGFbAO\nVPcXEbWOFTmgHx9PRvjB5atg1WQGoaNJknhUqu56POcLVJyBkTkmbR9wtuxd\nQIzSUCEyvmQutOd73JafhAEBnJRQr7a7vYy7VXP8Ih0AmVLqCqoyi/L1udu3\n4aCEuFRhEcKgEdTDD4MU4AaMs3M7kNgt1rj3zqxrfmE8ETMUKrQDANrEiqRO\nZgptW/Zfk8x8RiYAbwag6YQBuhtQfwh5nSpYN0kluJ7l0mH19BySZvRRqbqi\nl/v2gFgWmvuoaSIHBMn3gsWofiHnPWa0XaYwTnP4H11BqGLaSONbxarzBIH8\n3+zy\r\n=ZMxc\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "234e505d8a57d91a3f1d772ca335e2e4c48ee38b",
+    "tarball": "https://registry.npmjs.org/serialport/-/serialport-7.0.2.tgz",
+    "unpackedSize": 64788
   },
-  "scripts": {
-    "install": "node-pre-gyp install --fallback-to-build",
-    "test": "grunt --verbose"
+  "engines": {
+    "node": ">=6.0.0"
   },
-  "contributors": [
-    {
-      "name": "Chris Williams",
-      "email": "chris@iterativedesigns.com"
-    },
+  "gitHead": "4017f61620a845713f711576ba05bd47ae7601b6",
+  "homepage": "https://github.com/node-serialport/node-serialport#readme",
+  "keywords": [
+    "RFID",
+    "UART",
+    "ccTalk",
+    "com port",
+    "data logging",
+    "hardware",
+    "iot",
+    "johnny-five",
+    "modem",
+    "nodebots",
+    "robotics",
+    "sensor",
+    "serial",
+    "serial port",
+    "serialport",
+    "sms",
+    "sms gateway",
+    "stream",
+    "tty"
+  ],
+  "license": "MIT",
+  "main": "lib",
+  "maintainers": [
     {
-      "name": "Jay Beavers",
-      "email": "jay@hikinghomeschoolers.org"
+      "name": "jjrosent",
+      "email": "jakerosenthal@gmail.com"
     },
     {
-      "name": "Francis Gulotta",
+      "name": "reconbot",
       "email": "wizard@roborooter.com"
     },
     {
-      "name": "Rob Giseburt",
-      "email": "giseburt@gmail.com"
-    },
-    {
-      "name": "Joe Ferner",
-      "email": "joe.ferner@nearinfinity.com"
-    },
-    {
-      "name": "Esa-Matti Suuronen",
-      "email": "esa-matti@suuronen.org"
-    },
-    {
-      "name": "Nathan Rajlich",
-      "email": "nathan@tootallnate.net"
-    },
-    {
-      "name": "Rick Waldron",
-      "email": "waldron.rick@gmail.com"
-    },
-    {
-      "email": "w1nk"
-    },
-    {
-      "name": "Georges-Etienne Legendre",
-      "email": "legege"
-    },
-    {
-      "name": "Duane Johnson",
-      "email": "duane.johnson@gmail.com"
-    },
-    {
-      "name": "Rod Vagg",
-      "email": "@rvagg"
-    },
-    {
-      "name": "Edgar Silva",
-      "email": "@edgarsilva"
+      "name": "voodootikigod",
+      "email": "voodootikigod@gmail.com"
     }
   ],
-  "readme": "```\n  eeeee eeeee eeeee eeee       e  eeeee\n  8   8 8  88 8   8 8          8  8   \"\n  8e  8 8   8 8e  8 8eee       8e 8eeee\n  88  8 8   8 88  8 88      e  88    88\n  88  8 8eee8 88ee8 88ee 88 8ee88 8ee88\n\n  eeeee eeee eeeee  e  eeeee e     eeeee eeeee eeeee eeeee\n  8   \" 8    8   8  8  8   8 8     8   8 8  88 8   8   8\n  8eeee 8eee 8eee8e 8e 8eee8 8e    8eee8 8   8 8eee8e  8e\n     88 88   88   8 88 88  8 88    88    8   8 88   8  88\n  8ee88 88ee 88   8 88 88  8 88eee 88    8eee8 88   8  88\n```\n\n[![Build Status](https://travis-ci.org/voodootikigod/node-serialport.png?branch=master)](https://travis-ci.org/voodootikigod/node-serialport)\n[![Gitter chat](https://badges.gitter.im/voodootikigod/node-serialport.png)](https://gitter.im/voodootikigod/node-serialport)\n[![Dependency Status](https://david-dm.org/voodootikigod/node-serialport.png)\n\nFor all discussions, designs, and clarifications, we recommend you join our Gitter Chat room: [https://gitter.im/voodootikigod/node-serialport](https://gitter.im/voodootikigod/node-serialport)\n\n\n\nVersion: 1.6.1 - Released March 5, 2015\n\n*****\n\nImagine a world where you can write JavaScript to control blenders, lights, security systems, or even robots. Yes, I said robots. That world is here and now with node-serialport. It provides a very simple interface to the low level serial port code necessary to program [Arduino](http://www.arduino.cc/) chipsets, [X10](http://www.smarthome.com/manuals/protocol.txt) wireless communications, or even the rising [Z-Wave](http://www.z-wave.com/modules/ZwaveStart/) and [Zigbee](http://www.zigbee.org/) standards. The physical world is your oyster with this goodie. For a full break down of why we made this, please read [NodeBots - The Rise of JS Robotics](http://www.voodootikigod.com/nodebots-the-rise-of-js-robotics).\n\n*****\n\nRobots, you say?\n================\n\nThis library is admittedly a base level toolkit for building amazing things with real world (including robots). Here are a couple of those amazing things that leverage node-serialport:\n\n* [Johnny-Five](https://github.com/rwaldron/johnny-five) - JavaScript IoT and Robotics programming framework.\n* [Cylon.js](http://cylonjs.com/) - JavaScript Robotics, By Your Command.\n* [node-l8smartlight](http://jakobwesthoff.github.io/node-l8smartlight/) ([source](https://github.com/jakobwesthoff/node-l8smartlight)) A node library to control the L8 Smartlight via Bluetooth or USB port\n* [firmata](https://github.com/jgautier/firmata) Talk natively to Arduino using the firmata protocol.\n* [tmpad](http://tmpvar.com/project/tmpad/) [source](https://github.com/tmpvar/tmpad) - a DIY midi pad using infrared, arduino, and nodejs. [Video](http://vimeo.com/34575470)\n* [duino](https://github.com/ecto/duino) - A higher level framework for working with Arduinos in node.js.\n* [Arduino Drinking Game Extravaganza](http://jsconf.eu/2011/arduino_drinking_game_extravaganza.html) - AKA \"The Russian\" a hexidecimal drinking game for geeks by Uxebu presented at JSConf EU 2011.\n* [Arduino controlling popcorn.js](https://gist.github.com/968773) - Controlling a popcorn.js video with an Arduino kit.\n* [Robotic JavaScript](http://jsconf.eu/2010/speaker/livingroombindmotion_function.html) - The first live presentation of the node-serialport code set as presented at JSConf EU 2010.\n* [devicestack](https://github.com/adrai/devicestack) - This module helps you to represent a device and its protocol.\n* [reflecta](https://github.com/JayBeavers/Reflecta) A communication protocol that combines Arduino Libraries and NodeJS into an integrated system.\n* [rc4pt-node](https://github.com/comsolid/rc4pt-node) - Control Popcorntime with an Infrared receiver and Arduino.\n\nFor getting started with node-serialport, we recommend you begin with the following articles:\n\n* [Arduino Node Security Sensor Hacking](http://nexxylove.tumblr.com/post/20159263403/arduino-node-security-sensor-hacking) - A great all around \"how do I use this\" article.\n* [NodeBots - The Rise of JS Robotics](http://www.voodootikigod.com/nodebots-the-rise-of-js-robotics) - A survey article of why one would want to program robots in JS.\n* [Johnny-Five Getting Started Guide](https://github.com/rwldrn/johnny-five#setup-and-assemble-arduino) - Introduction to using the high level Johnny-Five library (awesome).\n\nHow To Use\n==========\n\nUsing node-serialport is pretty easy because it is pretty basic. It provides you with the building block to make great things, it is not a complete solution - just a cog in the (world domination) machine.\n\n**Special Notes**\n\n* Support for Node.js version 0.8.x has been removed. Version 1.4.0 is the last version that supported node.js version 0.8.x.\n* Currently support for Node.js version 0.11.x is dealing with an issue in the latest version of v. 0.11.13. We have confirmed things are fine with 0.11.10 and earlier, but not 0.11.11+.\n\nGood luck.\n\n\nTo Install\n----------\n\nFor most \"standard\" use cases (node v0.10.x on mac, linux, windows on a x86 or x64 processor), node-serialport will install nice and easy with a simple\n\n```\nnpm install serialport\n```\n\nWe are using [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) to compile and post binaries of the library for most common use cases (linux, mac, windows on standard processor platforms). If you are on a special case, node-serialport will work, but it will compile the binary when you install. Follow the instructions below for how that works.\n\n### Installation Special Cases\n\n\nThis assumes you have everything on your system necessary to compile ANY native module for Node.js. This may not be the case, though, so please ensure the following are true for your system before filing an issue about \"Does not install\". For all operatings systems, please ensure you have Python 2.x installed AND not 3.0, node-gyp (what we use to compile) requires Python 2.x.\n\n#### Windows:\n\n * Windows 7 or Windows 8.1 are supported.\n * Install [Visual Studio Express 2013 for Windows Desktop](http://www.microsoft.com/visualstudio/eng/2013-downloads#d-2013-express).\n * If you are hacking on an Arduino, be sure to install [the drivers](http://arduino.cc/en/Guide/windows#toc4).\n * Install [node.js 0.10.x](http://nodejs.org/) matching the bitness (32 or 64) of your operating system.\n * Install [Python 2.7.6](http://www.python.org/download/releases/2.7.6/) matching the bitness of your operating system.  For any questions, please refer to their [FAQ](http://docs.python.org/2/faq/windows.html). Default settings are perfect.\n * Open the 'Visual Studio Command Prompt' and add Python to the path.\n\n#### Mac OS X:\n\nEnsure that you have at a minimum the xCode Command Line Tools installed appropriate for your system configuration. If you recently upgraded the OS, it probably removed your installation of Command Line Tools, please verify before submitting a ticket.\n\n#### Desktop (Debian/Ubuntu) Linux:\n\nYou know what you need for you system, basically your appropriate analog of build-essential. Keep rocking! Ubuntu renamed the `node` binary `nodejs` which can cause problems building `node-serialport`. The fix is simple, install the [nodejs-legacy package](https://packages.debian.org/sid/nodejs-legacy) that symlinks `/usr/bin/nodejs => /usr/bin/node` or install the more up to date nodejs package from [Chris Lea's PPA](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).\n\n\n```\n# Ubuntu node\nsudo apt-get install nodejs nodejs-legacy\n\n# Or Chris Lea's PPA Node (more up to date)\nsudo add-apt-repository ppa:chris-lea/node.js\nsudo apt-get update\nsudo apt-get install nodejs\n\nsudo apt-get install build-essential\nnpm install serialport\n```\n\n#### Raspberry Pi Linux:\n\n * Starting with a a vanilla New Out of the Box Software (NOOBS) Raspbian image (currently tested: 5/25/2013)\n * Log into your Raspberry Pi through whatever means works best and ensure you are on a terminal prompt for the remaining steps. This could be local or through an SSH (or a serial connection if you like).\n * Issue the following commands to ensure you are up to date:\n\n```bash\n   sudo apt-get update\n   sudo apt-get upgrade -y\n```\n\n * Download and install node.js:\n\n```bash\n   wget http://nodejs.org/dist/v0.10.12/node-v0.10.12-linux-arm-pi.tar.gz\n   tar xvfz node-v0.10.12-linux-arm-pi.tar.gz\n   sudo mv node-v0.10.12-linux-arm-pi /opt/node/\n```\n\n * Set up your paths correctly:\n\n```bash\n   echo 'export PATH=\"$PATH:/opt/node/bin\"' >> ~/.bashrc\n   source ~/.bashrc\n```\n\n * Install using npm, note this will take a while as it is actually compiling code and that ARM processor is getting a workout.\n\n```bash\n   npm install serialport\n```\n\nTo Use\n------\n\nOpening a serial port:\n\n```js\nvar SerialPort = require(\"serialport\").SerialPort\nvar serialPort = new SerialPort(\"/dev/tty-usbserial1\", {\n  baudrate: 57600\n});\n```\n\nWhen opening a serial port, you can specify (in this order).\n\n1. Path to Serial Port - required.\n1. Options - optional and described below.\n\nThe options object allows you to pass named options to the serial port during initialization. The valid attributes for the options object are the following:\n\n* baudrate: Baud Rate, defaults to 9600. Should be one of: 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1800, 1200, 600, 300, 200, 150, 134, 110, 75, or 50. Custom rates as allowed by hardware is supported.\n* databits: Data Bits, defaults to 8. Must be one of: 8, 7, 6, or 5.\n* stopbits: Stop Bits, defaults to 1. Must be one of: 1 or 2.\n* parity: Parity, defaults to 'none'. Must be one of: 'none', 'even', 'mark', 'odd', 'space'\n* buffersize: Size of read buffer, defaults to 255. Must be an integer value.\n* parser: The parser engine to use with read data, defaults to rawPacket strategy which just emits the raw buffer as a \"data\" event. Can be any function that accepts EventEmitter as first parameter and the raw buffer as the second parameter.\n\n**Note, we have added support for either all lowercase OR camelcase of the options (thanks @jagautier), use whichever style you prefer.**\n\nopen event\n----------\n\nYou MUST wait for the open event to be emitted before reading/writing to the serial port. The open happens asynchronously so installing 'data' listeners and writing\nbefore the open event might result in... nothing at all.\n\nAssuming you are connected to a serial console, you would for example:\n\n```js\nserialPort.on(\"open\", function () {\n  console.log('open');\n  serialPort.on('data', function(data) {\n    console.log('data received: ' + data);\n  });\n  serialPort.write(\"ls\\n\", function(err, results) {\n    console.log('err ' + err);\n    console.log('results ' + results);\n  });\n});\n```\n\nYou can also call the open function, in this case instanciate the serialport with an additional flag.\n\n```js\nvar SerialPort = require(\"serialport\").SerialPort\nvar serialPort = new SerialPort(\"/dev/tty-usbserial1\", {\n  baudrate: 57600\n}, false); // this is the openImmediately flag [default is true]\n\nserialPort.open(function (error) {\n  if ( error ) {\n    console.log('failed to open: '+error);\n  } else {\n    console.log('open');\n    serialPort.on('data', function(data) {\n      console.log('data received: ' + data);\n    });\n    serialPort.write(\"ls\\n\", function(err, results) {\n      console.log('err ' + err);\n      console.log('results ' + results);\n    });\n  }\n});\n```\n\nList Ports\n----------\n\nYou can also list the ports along with some metadata as well.\n\n```js\nvar serialPort = require(\"serialport\");\nserialPort.list(function (err, ports) {\n  ports.forEach(function(port) {\n    console.log(port.comName);\n    console.log(port.pnpId);\n    console.log(port.manufacturer);\n  });\n});\n```\n\nParsers\n-------\n\nOut of the box, node-serialport provides two parsers one that simply emits the raw buffer as a data event and the other which provides familiar \"readline\" style parsing. To use the readline parser, you must provide a delimiter as such:\n\n```js\nvar serialport = require(\"serialport\");\nvar SerialPort = serialport.SerialPort; // localize object constructor\n\nvar sp = new SerialPort(\"/dev/tty-usbserial1\", {\n  parser: serialport.parsers.readline(\"\\n\")\n});\n```\n\nTo use the raw parser, you just provide the function definition (or leave undefined):\n\n```js\nvar serialport = require(\"serialport\");\nvar SerialPort = serialport.SerialPort; // localize object constructor\n\nvar sp = new SerialPort(\"/dev/tty-usbserial1\", {\n  parser: serialport.parsers.raw\n});\n```\n\n\nYou can get updates of new data from the Serial Port as follows:\n\n```js\nserialPort.on(\"data\", function (data) {\n  sys.puts(\"here: \"+data);\n});\n```\n\nYou can write to the serial port by sending a string or buffer to the write method as follows:\n\n```js\nserialPort.write(\"OMG IT WORKS\\r\");\n```\n\nEnjoy and do cool things with this code.\n\nReference Guide\n---------------\n\n## Methods\n\n### SerialPort (path, options, openImmediately, callback)\n\nCreate a new serial port on `path`.\n\n**_path_**\n\nThe system path of the serial port to open. For example, `/dev/tty` on Mac/Linux or `COM1` on Windows.\n\n**_options (optional)_**\n\nPort configuration options.\n\n* `baudRate`\n* `dataBits`\n* `stopBits`\n* `parity`\n* `rtscts`\n* `xon`\n* `xoff`\n* `xany`\n* `flowControl`\n* `bufferSize`\n* `parser`\n* `encoding`\n* `dataCallback`\n* `disconnectedCallback`\n* `platformOptions` - sets platform specific options, see below.\n\n#### Unix Platform Options\n\nAn object with the following properties:\n\n* `vmin` (default: 1) - see [`man termios`](http://linux.die.net/man/3/termios)\n* `vtime` (default: 0) - see [`man termios`](http://linux.die.net/man/3/termios)\n\n**_openImmediately (optional)_**\n\nAttempts to open a connection to the serial port on `process.nextTick`. The default is `true`. Set to `false` to manually call `open()` at a later time, but note you'll need to use factory error listener in the case of constructor errors.\n\n**_callback (optional)_**\n\nCalled when a connection has been opened. The callback should be a function that looks like: `function (error) { ... }`\n\n### .open (callback)\n\nOpens a connection to the given serial port.\n\n**_callback (optional)_**\n\nCalled when a connection has been opened. NOTE: Will NOT be called if openImmediately is set to false as open will not be performed. The callback should be a function that looks like: `function (error) { ... }`\n\n### .write (buffer, callback)\n\nWrites data to the given serial port.\n\n**_buffer_**\n\nThe `buffer` parameter accepts a [`Buffer` ](http://nodejs.org/api/buffer.html) object, or a type that is accepted by the `Buffer` constructor (ex. an array of bytes or a string).\n\n**_callback (optional)_**\n\nCalled once the write operation returns. The callback should be a function that looks like: `function (error) { ... }` _Note: The write operation is non-blocking. When it returns, data may still have not actually been written to the serial port. See `drain()`._\n\n### .pause ()\n\nPauses an open connection.\n\n### .resume ()\n\nResumes a paused connection.\n\n### .flush (callback)\n\nFlushes data received but not read. See [`tcflush()`](http://linux.die.net/man/3/tcflush) for Mac/Linux and [`FlushFileBuffers`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa364439) for Windows.\n\n**_callback (optional)_**\n\nCalled once the flush operation returns. The callback should be a function that looks like: `function (error) { ... }`\n\n### .drain (callback)\n\nWaits until all output data has been transmitted to the serial port. See [`tcdrain()`](http://linux.die.net/man/3/tcdrain) for more information.\n\n**_callback (optional)_**\n\nCalled once the drain operation returns. The callback should be a function that looks like: `function (error) { ... }`\n\n**Example**\n\nWrites `data` and waits until it has finish transmitting to the target serial port before calling the callback.\n\n```\nfunction writeAndDrain (data, callback) {\n  sp.write(data, function () {\n    sp.drain(callback);\n  });\n}\n```\n\n### .close (callback)\n\nCloses an open connection.\n\n**_callback (optional)_**\n\nCalled once a connection is closed. Closing a connection will also remove all event listeners. The callback should be a function that looks like: `function (error) { ... }`\n\n## Events\n\n### .on('open', callback)\n\n### .on('data', callback)\n\n### .on('close', callback)\n\n### .on('error', callback)\n\n&nbsp;\n&nbsp;\n\n---\n\n&nbsp;\n&nbsp;\n\n\n# Credit\n\nA special thanks to [The Hybrid Group](http://hybridgroup.com) for helping create and hosting the precompiled binaries for OSX, Linux, & Windows. This makes installing node-serialport much easier and much simpler for individuals using those platforms. Thank you.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/voodootikigod/node-serialport/issues"
+  "name": "serialport",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/node-serialport/node-serialport.git"
   },
-  "bundleDependencies": [
-    "node-pre-gyp"
-  ],
-  "_id": "serialport@1.6.3",
-  "dist": {
-    "shasum": "0e342366c0460bd75d216ea84846a3fa61764035"
+  "scripts": {
+    "repl": "node bin/repl.js",
+    "terminal": "node bin/terminal.js"
   },
-  "_from": "serialport@",
-  "_resolved": "http://registry.npmjs.org/serialport/-/serialport-1.6.3.tgz"
+  "version": "7.0.2"
 }
diff --git a/input_devices/mag/node_modules/serialport/parsers.js b/input_devices/mag/node_modules/serialport/parsers.js
deleted file mode 100644
index 8d87052a..00000000
--- a/input_devices/mag/node_modules/serialport/parsers.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/*jslint node: true */
-'use strict';
-
-// Copyright 2011 Chris Williams <chris@iterativedesigns.com>
-
-module.exports = {
-  raw: function (emitter, buffer) {
-    emitter.emit('data', buffer);
-  },
-
-  //encoding: ascii utf8 utf16le ucs2 base64 binary hex
-  //More: http://nodejs.org/api/buffer.html#buffer_buffer
-  readline: function (delimiter, encoding) {
-    if (typeof delimiter === 'undefined' || delimiter === null) { delimiter = '\r'; }
-    if (typeof encoding  === 'undefined' || encoding  === null) { encoding  = 'utf8'; }
-    // Delimiter buffer saved in closure
-    var data = '';
-    return function (emitter, buffer) {
-      // Collect data
-      data += buffer.toString(encoding);
-      // Split collected data by delimiter
-      var parts = data.split(delimiter);
-      data = parts.pop();
-      parts.forEach(function (part) {
-        emitter.emit('data', part);
-      });
-    };
-  },
-
-  // Emit a data event every `length` bytes
-  byteLength: function(length) {
-    var data = new Buffer(0);
-    return function(emitter, buffer){
-      data = Buffer.concat([data, buffer]);
-      while (data.length >= length) {
-        var out = data.slice(0,length);
-        data = data.slice(length);
-        emitter.emit('data', out);
-      }
-    };
-  }
-};
diff --git a/input_devices/mag/node_modules/serialport/publish-binaries.md b/input_devices/mag/node_modules/serialport/publish-binaries.md
deleted file mode 100644
index 419cc2ff..00000000
--- a/input_devices/mag/node_modules/serialport/publish-binaries.md
+++ /dev/null
@@ -1,82 +0,0 @@
-How to publish the pre compiled binaries.
-=========================================
-
-## Setup for Linux, Windows and OSX
-
-Every time a new tag for the latest release is pushed to github the continuous integration
-builds in Travis-CI and AppVeyor will generate the binaries for each platform and architecture,
-package and publish to the AS3 bucket.
-
-This can be checked in the .travis.yml file and appveyor.yml file. Within the files there are two
-methods for publishing new binaries for each version, one is if a `git tag` is detected; the other
-can be triggered by passing the string `[publish binary]` in the commit message itself.
-
-We also have an automated make task, we should always use this task to avoid forgetting any steps
-(like merging into the `osx-binaries` branch).
-
-The process for generating the binaries, publishing and releasing the npm module should be as follows:
-
-1. Merge all changes and new features into master.
-2. Bump up version of npm module in `package.json`.
-3. execute make task: `make release`
-
-This task will do the following for you:
-
-1. Generate new tags based on package.json version number
-2. Push tags to Github
-3. Checkout into `osx-binaries` branch
-4. Merge `master` into `osx-binaries`
-5. Push `osx-binaries`
-6. Checkout master
-7. Finally it will run `npm publish`
-
-With this we will make sure the binaries for all platforms and architectures will be generated each time
-a new version is released.
-
-
-## Config Travis, AppVeyor and Github to generate all of the binaries.
-
-Before we are able to run everything stated above some steps need to be taken.
-Specifically for being able to publish the pre compiled binaries to AWS-S3. The
-correct keys need to be setup in the travis and appveyor `.yml` files. This needs
-to be done by the admin of the repo, in the case of Travis, and the owner of the account,
-in the case of appveyor.
-
-### Setting up secure keys in Travis.
-
-Setting up the keys in Travis is easy if you have ruby and ruby gems installed and working then install:
-
-`gem install travis`
-
-After the travis gem is installed run the following command for each of the required keys:
-
-`travis encrypt SOMEVAR=secretvalue`
-
-And substitute the values in the `.travis.yml` file for the new ones. Detailed instructions can
-be found here: http://docs.travis-ci.com/user/environment-variables/#Secure-Variables
-
-### Setting up secure keys in AppVeyor
-
-It is even easier than Travis, you do not need to install anything, just go to your account and
-click in `encrypt tool`, there enter the values in the input field and click encrypt. Same as with
-Travis we then need to substitute the newly generated values for the old ones.
-
-Detailed instructions can be found here: http://www.appveyor.com/docs/build-configuration#secure-variables
-
-### OSX binaries
-
-Since Travis does not support config file for multiple OSs we need to create a new branch that contains
-a slightly different version of the .travis.yml file to compile for OSX. The branch needs to be called
-`osx-binaries` and be based of `master` once the pre-compiled binaries PR has been merged in.
-
-If we want to release a new version of the OSX binaries manually we can do it by pushing a new commit to
-the osx-binaries branch that contains the `[publish binary]` string, we can push an empty commit as follows:
-
-```bash
-$ git checkout osx-binaries
-$ git commit --allow-empty -m "Publish new version of pre-compiled binaries to AS3 [publish binary]"
-$ git push origin osx-binaries
-```
-
-The travis script will verify that the commit message contains the string `[publish binary]` and upload the
-binary packages.
diff --git a/input_devices/mag/node_modules/serialport/sandbox/disconnect.js b/input_devices/mag/node_modules/serialport/sandbox/disconnect.js
deleted file mode 100644
index ac4371c5..00000000
--- a/input_devices/mag/node_modules/serialport/sandbox/disconnect.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// disconnect.js -- an attempt track down the disconnected issue.
-
-//"use strict";
-var serialPort = require("../serialport");
-
-var sp;
-function activate () {
-
-if (sp) {
-  sp = new serialPort.SerialPort(process.env.SERIAL_PORT, {
-    baudRate: 115200,
-    parser  : serialPort.parsers.readline(';')
-  });
-
-
-  sp.on('data', function (data) {
-    console.log('on.data', data);
-    sp.close(function(err) {
-      console.log('close()', err);
-    });
-  });
-
-  sp.on('close', function (err) {
-    console.log('on.close');
-    sp = null;
-  });
-
-
-  sp.on('disconnect', function (err) {
-    console.log('on.disconnect');
-
-
-  });
-
-
-  sp.on('error', function (err) {
-    console.error("on.error", err);
-  });
-
-  sp.on('open', function () {
-    console.log('on.open');
-    sp.write("foobar;", function(err, chars) {
-      console.log('write()', chars, err);
-    });
-  });
-
-  }
-}
-
-activate()
-
-//keep alive
-setInterval(function() { activate(); }, 10000);
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/serialport.js b/input_devices/mag/node_modules/serialport/serialport.js
deleted file mode 100644
index bad6dd66..00000000
--- a/input_devices/mag/node_modules/serialport/serialport.js
+++ /dev/null
@@ -1,689 +0,0 @@
-'use strict';
-
-// Copyright 2011 Chris Williams <chris@iterativedesigns.com>
-
-// Require serialport binding from pre-compiled binaries using
-// node-pre-gyp, if something fails or package not available fallback
-// to regular build from source.
-
-var debug = require('debug')('serialport');
-var binary = require('node-pre-gyp');
-var path = require('path');
-var PACKAGE_JSON = path.join(__dirname, 'package.json');
-var binding_path = binary.find(path.resolve(PACKAGE_JSON));
-var SerialPortBinding = require(binding_path);
-
-var parsers = require('./parsers');
-var EventEmitter = require('events').EventEmitter;
-var util = require('util');
-var fs = require('fs');
-var stream = require('stream');
-var path = require('path');
-var async = require('async');
-var exec = require('child_process').exec;
-
-function SerialPortFactory(_spfOptions) {
-  _spfOptions = _spfOptions || {};
-
-  var spfOptions = {};
-
-  spfOptions.queryPortsByPath =  (_spfOptions.queryPortsByPath === true ? true : false);
-
-  var factory = this;
-
-  // Removing check for valid BaudRates due to ticket: #140
-  // var BAUDRATES = [500000, 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1800, 1200, 600, 300, 200, 150, 134, 110, 75, 50];
-
-  //  VALIDATION ARRAYS
-  var DATABITS = [5, 6, 7, 8];
-  var STOPBITS = [1, 1.5, 2];
-  var PARITY = ['none', 'even', 'mark', 'odd', 'space'];
-  var FLOWCONTROLS = ['XON', 'XOFF', 'XANY', 'RTSCTS'];
-  var SETS = ['rts', 'cts', 'dtr', 'dts', 'brk'];
-
-
-  // Stuff from ReadStream, refactored for our usage:
-  var kPoolSize = 40 * 1024;
-  var kMinPoolSpace = 128;
-
-  function makeDefaultPlatformOptions(){
-    var options = {};
-
-    if (process.platform !== 'win32') {
-      options.vmin = 1;
-      options.vtime = 0;
-    }
-
-    return options;
-  }
-
-  // The default options, can be overwritten in the 'SerialPort' constructor
-  var _options = {
-    baudrate: 9600,
-    parity: 'none',
-    rtscts: false,
-    xon: false,
-    xoff: false,
-    xany: false,
-    rts: true,
-    cts: false,
-    dtr: true,
-    dts: false,
-    brk: false,
-    databits: 8,
-    stopbits: 1,
-    buffersize: 256,
-    parser: parsers.raw,
-    platformOptions: makeDefaultPlatformOptions()
-  };
-
-  function SerialPort(path, options, openImmediately, callback) {
-
-    var self = this;
-
-    var args = Array.prototype.slice.call(arguments);
-    callback = args.pop();
-    if (typeof (callback) !== 'function') {
-      callback = null;
-    }
-
-    options = (typeof options !== 'function') && options || {};
-
-    openImmediately = (openImmediately === undefined || openImmediately === null) ? true : openImmediately;
-
-    stream.Stream.call(this);
-
-    callback = callback || function (err) {
-      if (err) {
-        if (self._events.error) {
-          self.emit('error', err);
-        } else {
-          factory.emit('error', err);
-        }
-      }
-    };
-
-    var err;
-
-
-    options.baudRate = options.baudRate || options.baudrate || _options.baudrate;
-
-    options.dataBits = options.dataBits || options.databits || _options.databits;
-    if (DATABITS.indexOf(options.dataBits) === -1) {
-      err = new Error('Invalid "databits": ' + options.dataBits);
-      callback(err);
-      return;
-    }
-
-    options.stopBits = options.stopBits || options.stopbits || _options.stopbits;
-    if (STOPBITS.indexOf(options.stopBits) === -1) {
-      err = new Error('Invalid "stopbits": ' + options.stopbits);
-      callback(err);
-      return;
-    }
-
-    options.parity = options.parity || _options.parity;
-    if (PARITY.indexOf(options.parity) === -1) {
-      err = new Error('Invalid "parity": ' + options.parity);
-      callback(err);
-      return;
-    }
-    if (!path) {
-      err = new Error('Invalid port specified: ' + path);
-      callback(err);
-      return;
-    }
-
-    // flush defaults, then update with provided details
-    options.rtscts = _options.rtscts;
-    options.xon = _options.xon;
-    options.xoff = _options.xoff;
-    options.xany = _options.xany;
-
-    if (options.flowControl || options.flowcontrol) {
-      var fc = options.flowControl || options.flowcontrol;
-
-      if (typeof fc === 'boolean') {
-        options.rtscts = true;
-      } else {
-        var clean = fc.every(function (flowControl) {
-          var fcup = flowControl.toUpperCase();
-          var idx = FLOWCONTROLS.indexOf(fcup);
-          if (idx < 0) {
-            var err = new Error('Invalid "flowControl": ' + fcup + '. Valid options: ' + FLOWCONTROLS.join(', '));
-            callback(err);
-            return false;
-          } else {
-
-            // "XON", "XOFF", "XANY", "DTRDTS", "RTSCTS"
-            switch (idx) {
-              case 0: options.xon = true; break;
-              case 1: options.xoff = true; break;
-              case 2: options.xany = true;  break;
-              case 3: options.rtscts = true; break;
-            }
-            return true;
-          }
-        });
-        if(!clean){
-          return;
-        }
-      }
-    }
-
-    options.bufferSize = options.bufferSize || options.buffersize || _options.buffersize;
-    options.parser = options.parser || _options.parser;
-    options.platformOptions = options.platformOptions || _options.platformOptions;
-
-    options.dataCallback = options.dataCallback || function (data) {
-      options.parser(self, data);
-    };
-
-    options.disconnectedCallback = options.disconnectedCallback || function (err) {
-      if (self.closing) {
-        return;
-      }
-      if (!err) {
-        err = new Error('Disconnected');
-      }
-      self.emit('disconnect', err);
-    };
-
-    if (process.platform !== 'win32') {
-      // All other platforms:
-      this.fd = null;
-      this.paused = true;
-      this.bufferSize = options.bufferSize || 64 * 1024;
-      this.readable = true;
-      this.reading = false;
-    }
-
-    this.options = options;
-    this.path = path;
-    if (openImmediately) {
-      process.nextTick(function () {
-        self.open(callback);
-      });
-    }
-  }
-
-  util.inherits(SerialPort, stream.Stream);
-
-
-  SerialPort.prototype.open = function (callback) {
-    var self = this;
-    this.paused = true;
-    this.readable = true;
-    this.reading = false;
-    factory.SerialPortBinding.open(this.path, this.options, function (err, fd) {
-      self.fd = fd;
-      if (err) {
-        if (callback) {
-          callback(err);
-        } else {
-          self.emit('error', err);
-        }
-        return;
-      }
-      if (process.platform !== 'win32') {
-        self.paused = false;
-        self.serialPoller = new factory.SerialPortBinding.SerialportPoller(self.fd, function (err) {
-          if (!err) {
-            self._read();
-          } else {
-            self.disconnected(err);
-          }
-        });
-        self.serialPoller.start();
-      }
-
-      self.emit('open');
-      if (callback) { callback(); }
-    });
-  };
-
-
-  SerialPort.prototype.isOpen = function() {
-    return (this.fd ? true : false);
-  };
-
-  SerialPort.prototype.write = function (buffer, callback) {
-    var self = this;
-    if (!this.fd) {
-      debug('Write attempted, but serialport not available - FD is not set');
-      var err = new Error('Serialport not open.');
-      if (callback) {
-        callback(err);
-      } else {
-        // console.log("write-fd");
-        self.emit('error', err);
-      }
-      return;
-    }
-
-    if (!Buffer.isBuffer(buffer)) {
-      buffer = new Buffer(buffer);
-    }
-    debug('Write: '+JSON.stringify(buffer));
-    factory.SerialPortBinding.write(this.fd, buffer, function (err, results) {
-      if (callback) {
-        callback(err, results);
-      } else {
-        if (err) {
-          // console.log("write");
-          self.emit('error', err);
-        }
-      }
-    });
-  };
-
-  if (process.platform !== 'win32') {
-    SerialPort.prototype._read = function () {
-      var self = this;
-
-      // console.log(">>READ");
-      if (!self.readable || self.paused || self.reading) {
-        return;
-      }
-
-      self.reading = true;
-
-      if (!self.pool || self.pool.length - self.pool.used < kMinPoolSpace) {
-        // discard the old pool. Can't add to the free list because
-        // users might have refernces to slices on it.
-        self.pool = null;
-
-        // alloc new pool
-        self.pool = new Buffer(kPoolSize);
-        self.pool.used = 0;
-      }
-
-      // Grab another reference to the pool in the case that while we're in the
-      // thread pool another read() finishes up the pool, and allocates a new
-      // one.
-      var toRead = Math.min(self.pool.length - self.pool.used, ~~self.bufferSize);
-      var start = self.pool.used;
-
-      function afterRead(err, bytesRead, readPool, bytesRequested) {
-        self.reading = false;
-        if (err) {
-          if (err.code && err.code === 'EAGAIN') {
-            if (self.fd >= 0) {
-              self.serialPoller.start();
-            }
-          } else if (err.code && (err.code === 'EBADF' || err.code === 'ENXIO' || (err.errno === -1 || err.code === 'UNKNOWN'))) { // handle edge case were mac/unix doesn't clearly know the error.
-            self.disconnected(err);
-          } else {
-            self.fd = null;
-            self.emit('error', err);
-            self.readable = false;
-          }
-        } else {
-          // Since we will often not read the number of bytes requested,
-          // let's mark the ones we didn't need as available again.
-          self.pool.used -= bytesRequested - bytesRead;
-
-          if (bytesRead === 0) {
-            if (self.fd >= 0) {
-              self.serialPoller.start();
-            }
-          } else {
-            var b = self.pool.slice(start, start + bytesRead);
-
-            // do not emit events if the stream is paused
-            if (self.paused) {
-              self.buffer = Buffer.concat([self.buffer, b]);
-              return;
-            } else {
-              self._emitData(b);
-            }
-
-            // do not emit events anymore after we declared the stream unreadable
-            if (!self.readable) {
-              return;
-            }
-            self._read();
-          }
-        }
-
-      }
-
-      fs.read(self.fd, self.pool, self.pool.used, toRead, null, function (err, bytesRead) {
-        var readPool = self.pool;
-        var bytesRequested = toRead;
-        afterRead(err, bytesRead, readPool, bytesRequested);
-      });
-
-      self.pool.used += toRead;
-    };
-
-
-    SerialPort.prototype._emitData = function (data) {
-      this.options.dataCallback(data);
-    };
-
-    SerialPort.prototype.pause = function () {
-      var self = this;
-      self.paused = true;
-    };
-
-    SerialPort.prototype.resume = function () {
-      var self = this;
-      self.paused = false;
-
-      if (self.buffer) {
-        var buffer = self.buffer;
-        self.buffer = null;
-        self._emitData(buffer);
-      }
-
-      // No longer open?
-      if (null === self.fd) {
-        return;
-      }
-
-      self._read();
-    };
-
-  } // if !'win32'
-
-
-  SerialPort.prototype.disconnected = function (err) {
-    var self = this;
-    var fd = self.fd;
-
-    // send notification of disconnect
-    if (self.options.disconnectedCallback) {
-      self.options.disconnectedCallback(err);
-    } else {
-      self.emit('disconnect', err);
-    }
-    self.paused = true;
-    self.closing = true;
-
-    self.emit('close');
-
-    // clean up all other items
-    fd = self.fd;
-
-    try {
-      factory.SerialPortBinding.close(fd, function (err) {
-        if (err) {
-          debug('Disconnect completed with error: '+JSON.stringify(err));
-        } else {
-          debug('Disconnect completed.');
-        }
-      });
-    } catch (e) {
-      debug('Disconnect completed with an exception: '+JSON.stringify(e));
-    }
-
-    self.removeAllListeners();
-    self.closing = false;
-    self.fd = 0;
-
-    if (process.platform !== 'win32') {
-      self.readable = false;
-      self.serialPoller.close();
-    }
-
-  };
-
-
-  SerialPort.prototype.close = function (callback) {
-    var self = this;
-
-    var fd = self.fd;
-
-    if (self.closing) {
-      return;
-    }
-    if (!fd) {
-      var err = new Error('Serialport not open.');
-      if (callback) {
-        callback(err);
-      } else {
-        // console.log("sp not open");
-        self.emit('error', err);
-      }
-      return;
-    }
-
-    self.closing = true;
-
-    // Stop polling before closing the port.
-    if (process.platform !== 'win32') {
-      self.readable = false;
-      self.serialPoller.close();
-    }
-
-    try {
-      factory.SerialPortBinding.close(fd, function (err) {
-
-        if (err) {
-          if (callback) {
-            callback(err);
-          } else {
-            // console.log("doclose");
-            self.emit('error', err);
-          }
-          return;
-        }
-
-        self.emit('close');
-        self.removeAllListeners();
-        self.closing = false;
-        self.fd = 0;
-
-        if (callback) {
-          callback();
-        }
-      });
-    } catch (ex) {
-      self.closing = false;
-      if (callback) {
-        callback(ex);
-      } else {
-        self.emit('error', ex);
-      }
-    }
-  };
-
-  function listUnix(callback) {
-    function udev_parser(udev_output, callback) {
-      function udev_output_to_json(output) {
-        var result = {};
-        var lines = output.split('\n');
-        for (var i = 0; i < lines.length; i++) {
-          var line = lines[i].trim();
-          if (line !== '') {
-            var line_parts = lines[i].split('=');
-            result[line_parts[0].trim()] = line_parts[1].trim();
-          }
-        }
-        return result;
-      }
-      var as_json = udev_output_to_json(udev_output);
-      var pnpId = as_json.DEVLINKS.split(' ')[0];
-      pnpId = pnpId.substring(pnpId.lastIndexOf('/') + 1);
-      var port = {
-        comName: as_json.DEVNAME,
-        manufacturer: as_json.ID_VENDOR,
-        serialNumber: as_json.ID_SERIAL,
-        pnpId: pnpId,
-        vendorId: '0x' + as_json.ID_VENDOR_ID,
-        productId: '0x' + as_json.ID_MODEL_ID
-      };
-
-      callback(null, port);
-    }
-
-    var dirName = (spfOptions.queryPortsByPath ? '/dev/serial/by-path' : '/dev/serial/by-id');
-
-    fs.readdir(dirName, function (err, files) {
-      if (err) {
-        // if this directory is not found this could just be because it's not plugged in
-        if (err.errno === 34) {
-          return callback(null, []);
-        }
-
-        if (callback) {
-          callback(err);
-        } else {
-          factory.emit('error', err);
-        }
-        return;
-      }
-
-      async.map(files, function (file, callback) {
-        var fileName = path.join(dirName, file);
-        fs.readlink(fileName, function (err, link) {
-          if (err) {
-            if (callback) {
-              callback(err);
-            } else {
-              factory.emit('error', err);
-            }
-            return;
-          }
-
-          link = path.resolve(dirName, link);
-          exec('/sbin/udevadm info --query=property -p $(/sbin/udevadm info -q path -n ' + link + ')', function (err, stdout) {
-            if (err) {
-              if (callback) {
-                callback(err);
-              } else {
-                factory.emit('error', err);
-              }
-              return;
-            }
-
-            udev_parser(stdout, callback);
-          });
-        });
-      }, callback);
-    });
-  }
-
-  SerialPort.prototype.flush = function (callback) {
-    var self = this;
-    var fd = self.fd;
-
-    if (!fd) {
-      var err = new Error('Serialport not open.');
-      if (callback) {
-        callback(err);
-      } else {
-        self.emit('error', err);
-      }
-      return;
-    }
-
-    factory.SerialPortBinding.flush(fd, function (err, result) {
-      if (err) {
-        if (callback) {
-          callback(err, result);
-        } else {
-          self.emit('error', err);
-        }
-      } else {
-        if (callback) {
-          callback(err, result);
-        }
-      }
-    });
-  };
-
-  SerialPort.prototype.set = function (options, callback) {
-    var self = this;
-    var fd = self.fd;
-
-    options = (typeof option !== 'function') && options || {};
-
-    // flush defaults, then update with provided details
-
-    if(!options.hasOwnProperty('rts')){
-      options.rts = _options.rts;
-    }
-    if(!options.hasOwnProperty('dtr')){
-      options.dtr = _options.dtr;
-    }
-    if(!options.hasOwnProperty('cts')){
-      options.cts = _options.cts;
-    }
-    if(!options.hasOwnProperty('dts')){
-      options.dts = _options.dts;
-    }
-    if(!options.hasOwnProperty('brk')){
-      options.brk = _options.brk;
-    }
-
-    if (!fd) {
-      var err = new Error('Serialport not open.');
-      if (callback) {
-        callback(err);
-      } else {
-        self.emit('error', err);
-      }
-      return;
-    }
-
-    factory.SerialPortBinding.set(fd, options, function (err, result) {
-      if (err) {
-        if (callback) {
-          callback(err, result);
-        } else {
-          self.emit('error', err);
-        }
-      } else {
-        callback(err, result);
-      }
-    });
-  };
-
-  SerialPort.prototype.drain = function (callback) {
-    var self = this;
-    var fd = this.fd;
-
-    if (!fd) {
-      var err = new Error('Serialport not open.');
-      if (callback) {
-        callback(err);
-      } else {
-        self.emit('error', err);
-      }
-      return;
-    }
-
-    factory.SerialPortBinding.drain(fd, function (err, result) {
-      if (err) {
-        if (callback) {
-          callback(err, result);
-        } else {
-          self.emit('error', err);
-        }
-      } else {
-        if (callback) {
-          callback(err, result);
-        }
-      }
-    });
-  };
-
-  factory.SerialPort = SerialPort;
-  factory.parsers = parsers;
-  factory.SerialPortBinding = SerialPortBinding;
-
-  if (process.platform === 'win32') {
-    factory.list = SerialPortBinding.list;
-  } else if (process.platform === 'darwin') {
-    factory.list = SerialPortBinding.list;
-  } else {
-    factory.list = listUnix;
-  }
-
-}
-
-util.inherits(SerialPortFactory, EventEmitter);
-
-module.exports = new SerialPortFactory();
diff --git a/input_devices/mag/node_modules/serialport/src/serialport.cpp b/input_devices/mag/node_modules/serialport/src/serialport.cpp
deleted file mode 100644
index 7700ade1..00000000
--- a/input_devices/mag/node_modules/serialport/src/serialport.cpp
+++ /dev/null
@@ -1,618 +0,0 @@
-
-
-#include "serialport.h"
-
-#ifdef WIN32
-#define strncasecmp strnicmp
-#else
-#include "serialport_poller.h"
-#endif
-
-struct _WriteQueue {
-  const int _fd; // the fd that is associated with this write queue
-  QueuedWrite _write_queue;
-  uv_mutex_t _write_queue_mutex;
-  _WriteQueue *_next;
-
-  _WriteQueue(const int fd) : _fd(fd), _write_queue(), _next(NULL) {
-    uv_mutex_init(&_write_queue_mutex);
-  }
-
-  void lock() { uv_mutex_lock(&_write_queue_mutex); };
-  void unlock() { uv_mutex_unlock(&_write_queue_mutex); };
-
-  QueuedWrite &get() { return _write_queue; }
-};
-
-
-static _WriteQueue *write_queues = NULL;
-
-static _WriteQueue *qForFD(const int fd) {
-  _WriteQueue *q = write_queues;
-  while (q != NULL) {
-    if (q->_fd == fd) {
-      return q;
-    }
-    q = q->_next;
-  }
-  return NULL;
-};
-
-static _WriteQueue *newQForFD(const int fd) {
-  _WriteQueue *q = qForFD(fd);
-
-  if (q == NULL) {
-    if (write_queues == NULL) {
-      write_queues = new _WriteQueue(fd);
-      return write_queues;
-    } else {
-      q = write_queues;
-      while (q->_next != NULL) {
-        q = q->_next;
-      }
-      q->_next = new _WriteQueue(fd);
-      return q->_next;
-    }
-  }
-
-  return q;
-};
-
-static void deleteQForFD(const int fd) {
-  if (write_queues == NULL)
-    return;
-
-  _WriteQueue *q = write_queues;
-  if (write_queues->_fd == fd) {
-    write_queues = write_queues->_next;
-    delete q;
-
-    return;
-  }
-
-  while (q->_next != NULL) {
-    if (q->_next->_fd == fd) {
-      _WriteQueue *out_q = q->_next;
-      q->_next = q->_next->_next;
-      delete out_q;
-
-      return;
-    }
-    q = q->_next;
-  }
-
-  // It wasn't found...
-};
-
-
-
-NAN_METHOD(Open) {
-  NanScope();
-
-  // path
-  if(!args[0]->IsString()) {
-    NanThrowTypeError("First argument must be a string");
-    NanReturnUndefined();
-  }
-  v8::String::Utf8Value path(args[0]->ToString());
-
-  // options
-  if(!args[1]->IsObject()) {
-    NanThrowTypeError("Second argument must be an object");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Object> options = args[1]->ToObject();
-
-  // callback
-  if(!args[2]->IsFunction()) {
-    NanThrowTypeError("Third argument must be a function");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Function> callback = args[2].As<v8::Function>();
-
-  OpenBaton* baton = new OpenBaton();
-  memset(baton, 0, sizeof(OpenBaton));
-  strcpy(baton->path, *path);
-  baton->baudRate = options->Get(NanNew<v8::String>("baudRate"))->ToInt32()->Int32Value();
-  baton->dataBits = options->Get(NanNew<v8::String>("dataBits"))->ToInt32()->Int32Value();
-  baton->bufferSize = options->Get(NanNew<v8::String>("bufferSize"))->ToInt32()->Int32Value();
-  baton->parity = ToParityEnum(options->Get(NanNew<v8::String>("parity"))->ToString());
-  baton->stopBits = ToStopBitEnum(options->Get(NanNew<v8::String>("stopBits"))->ToNumber()->NumberValue());
-  baton->rtscts = options->Get(NanNew<v8::String>("rtscts"))->ToBoolean()->BooleanValue();
-  baton->xon = options->Get(NanNew<v8::String>("xon"))->ToBoolean()->BooleanValue();
-  baton->xoff = options->Get(NanNew<v8::String>("xoff"))->ToBoolean()->BooleanValue();
-  baton->xany = options->Get(NanNew<v8::String>("xany"))->ToBoolean()->BooleanValue();
-
-  v8::Local<v8::Object> platformOptions = options->Get(NanNew<v8::String>("platformOptions"))->ToObject();
-  baton->platformOptions = ParsePlatformOptions(platformOptions);
-
-  baton->callback = new NanCallback(callback);
-  baton->dataCallback = new NanCallback(options->Get(NanNew<v8::String>("dataCallback")).As<v8::Function>());
-  baton->disconnectedCallback = new NanCallback(options->Get(NanNew<v8::String>("disconnectedCallback")).As<v8::Function>());
-  baton->errorCallback = new NanCallback(options->Get(NanNew<v8::String>("errorCallback")).As<v8::Function>());
-
-  uv_work_t* req = new uv_work_t();
-  req->data = baton;
-
-  uv_queue_work(uv_default_loop(), req, EIO_Open, (uv_after_work_cb)EIO_AfterOpen);
-
-  NanReturnUndefined();
-}
-
-void EIO_AfterOpen(uv_work_t* req) {
-  NanScope();
-
-  OpenBaton* data = static_cast<OpenBaton*>(req->data);
-
-  v8::Handle<v8::Value> argv[2];
-  if(data->errorString[0]) {
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString));
-    argv[1] = NanUndefined();
-    // not needed for AfterOpenSuccess
-    delete data->dataCallback;
-    delete data->errorCallback;
-    delete data->disconnectedCallback;
-  } else {
-    argv[0] = NanUndefined();
-    argv[1] = NanNew<v8::Int32>(data->result);
-
-    int fd = argv[1]->ToInt32()->Int32Value();
-    newQForFD(fd);
-
-    AfterOpenSuccess(data->result, data->dataCallback, data->disconnectedCallback, data->errorCallback);
-  }
-
-  data->callback->Call(2, argv);
-
-  delete data->platformOptions;
-  delete data->callback;
-  delete data;
-  delete req;
-}
-
-NAN_METHOD(Write) {
-  NanScope();
-
-  // file descriptor
-  if(!args[0]->IsInt32()) {
-    NanThrowTypeError("First argument must be an int");
-    NanReturnUndefined();
-  }
-  int fd = args[0]->ToInt32()->Int32Value();
-
-  // buffer
-  if(!args[1]->IsObject() || !node::Buffer::HasInstance(args[1])) {
-    NanThrowTypeError("Second argument must be a buffer");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Object> buffer = args[1]->ToObject();
-  char* bufferData = node::Buffer::Data(buffer);
-  size_t bufferLength = node::Buffer::Length(buffer);
-
-  // callback
-  if(!args[2]->IsFunction()) {
-    NanThrowTypeError("Third argument must be a function");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Function> callback = args[2].As<v8::Function>();
-
-  WriteBaton* baton = new WriteBaton();
-  memset(baton, 0, sizeof(WriteBaton));
-  baton->fd = fd;
-  NanAssignPersistent<v8::Object>(baton->buffer, buffer);
-  baton->bufferData = bufferData;
-  baton->bufferLength = bufferLength;
-  baton->offset = 0;
-  baton->callback = new NanCallback(callback);
-
-  QueuedWrite* queuedWrite = new QueuedWrite();
-  memset(queuedWrite, 0, sizeof(QueuedWrite));
-  queuedWrite->baton = baton;
-  queuedWrite->req.data = queuedWrite;
-
-  _WriteQueue *q = qForFD(fd);
-  if(!q) {
-    NanThrowTypeError("There's no write queue for that file descriptor (write)!");
-    NanReturnUndefined();
-  }
-
-  q->lock();
-  QueuedWrite &write_queue = q->get();
-  bool empty = write_queue.empty();
-
-  write_queue.insert_tail(queuedWrite);
-
-  if (empty) {
-    uv_queue_work(uv_default_loop(), &queuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite);
-  }
-  q->unlock();
-
-  NanReturnUndefined();
-}
-
-void EIO_AfterWrite(uv_work_t* req) {
-  NanScope();
-
-  QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data);
-  WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton);
-
-  v8::Handle<v8::Value> argv[2];
-  if(data->errorString[0]) {
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString));
-    argv[1] = NanUndefined();
-  } else {
-    argv[0] = NanUndefined();
-    argv[1] = NanNew<v8::Int32>(data->result);
-  }
-  data->callback->Call(2, argv);
-
-  if (data->offset < data->bufferLength && !data->errorString[0]) {
-    // We're not done with this baton, so throw it right back onto the queue.
-	  // Don't re-push the write in the event loop if there was an error; because same error could occur again!
-    // TODO: Add a uv_poll here for unix...
-    //fprintf(stderr, "Write again...\n");
-    uv_queue_work(uv_default_loop(), req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite);
-    return;
-  }
-
-  int fd = data->fd;
-  _WriteQueue *q = qForFD(fd);
-  if(!q) {
-    NanThrowTypeError("There's no write queue for that file descriptor (after write)!");
-    return;
-  }
-
-  q->lock();
-  QueuedWrite &write_queue = q->get();
-
-  // remove this one from the list
-  queuedWrite->remove();
-
-  // If there are any left, start a new thread to write the next one.
-  if (!write_queue.empty()) {
-    // Always pull the next work item from the head of the queue
-    QueuedWrite* nextQueuedWrite = write_queue.next;
-    uv_queue_work(uv_default_loop(), &nextQueuedWrite->req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite);
-  }
-  q->unlock();
-
-  NanDisposePersistent(data->buffer);
-  delete data->callback;
-  delete data;
-  delete queuedWrite;
-}
-
-NAN_METHOD(Close) {
-  NanScope();
-
-  // file descriptor
-  if(!args[0]->IsInt32()) {
-    NanThrowTypeError("First argument must be an int");
-    NanReturnUndefined();
-  }
-  int fd = args[0]->ToInt32()->Int32Value();
-
-  // callback
-  if(!args[1]->IsFunction()) {
-    NanThrowTypeError("Second argument must be a function");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Function> callback = args[1].As<v8::Function>();
-
-  CloseBaton* baton = new CloseBaton();
-  memset(baton, 0, sizeof(CloseBaton));
-  baton->fd = fd;
-  baton->callback = new NanCallback(callback);
-
-  uv_work_t* req = new uv_work_t();
-  req->data = baton;
-  uv_queue_work(uv_default_loop(), req, EIO_Close, (uv_after_work_cb)EIO_AfterClose);
-
-  NanReturnUndefined();
-}
-
-void EIO_AfterClose(uv_work_t* req) {
-  NanScope();
-
-  CloseBaton* data = static_cast<CloseBaton*>(req->data);
-
-  v8::Handle<v8::Value> argv[1];
-  if(data->errorString[0]) {
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString));
-  } else {
-    argv[0] = NanUndefined();
-
-    // We don't have an error, so clean up the write queue for that fd
-
-    _WriteQueue *q = qForFD(data->fd);
-    if (q) {
-      q->lock();
-      QueuedWrite &write_queue = q->get();
-      while (!write_queue.empty()) {
-        QueuedWrite *del_q = write_queue.next;
-        NanDisposePersistent(del_q->baton->buffer);
-        del_q->remove();
-      }
-      q->unlock();
-
-      deleteQForFD(data->fd);
-    }
-
-  }
-  data->callback->Call(1, argv);
-
-  delete data->callback;
-  delete data;
-  delete req;
-}
-
-NAN_METHOD(List) {
-  NanScope();
-
-  // callback
-  if(!args[0]->IsFunction()) {
-    NanThrowTypeError("First argument must be a function");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Function> callback = args[0].As<v8::Function>();
-
-  ListBaton* baton = new ListBaton();
-  strcpy(baton->errorString, "");
-  baton->callback = new NanCallback(callback);
-
-  uv_work_t* req = new uv_work_t();
-  req->data = baton;
-  uv_queue_work(uv_default_loop(), req, EIO_List, (uv_after_work_cb)EIO_AfterList);
-
-  NanReturnUndefined();
-}
-
-void EIO_AfterList(uv_work_t* req) {
-  NanScope();
-
-  ListBaton* data = static_cast<ListBaton*>(req->data);
-
-  v8::Handle<v8::Value> argv[2];
-  if(data->errorString[0]) {
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString));
-    argv[1] = NanUndefined();
-  } else {
-    v8::Local<v8::Array> results = NanNew<v8::Array>();
-    int i = 0;
-    for(std::list<ListResultItem*>::iterator it = data->results.begin(); it != data->results.end(); ++it, i++) {
-      v8::Local<v8::Object> item = NanNew<v8::Object>();
-      item->Set(NanNew<v8::String>("comName"), NanNew<v8::String>((*it)->comName.c_str()));
-      item->Set(NanNew<v8::String>("manufacturer"), NanNew<v8::String>((*it)->manufacturer.c_str()));
-      item->Set(NanNew<v8::String>("serialNumber"), NanNew<v8::String>((*it)->serialNumber.c_str()));
-      item->Set(NanNew<v8::String>("pnpId"), NanNew<v8::String>((*it)->pnpId.c_str()));
-      item->Set(NanNew<v8::String>("locationId"), NanNew<v8::String>((*it)->locationId.c_str()));
-      item->Set(NanNew<v8::String>("vendorId"), NanNew<v8::String>((*it)->vendorId.c_str()));
-      item->Set(NanNew<v8::String>("productId"), NanNew<v8::String>((*it)->productId.c_str()));
-      results->Set(i, item);
-    }
-    argv[0] = NanUndefined();
-    argv[1] = results;
-  }
-  data->callback->Call(2, argv);
-
-  delete data->callback;
-  for(std::list<ListResultItem*>::iterator it = data->results.begin(); it != data->results.end(); ++it) {
-    delete *it;
-  }
-  delete data;
-  delete req;
-}
-
-NAN_METHOD(Flush) {
-  NanScope();
-
-  // file descriptor
-  if(!args[0]->IsInt32()) {
-    NanThrowTypeError("First argument must be an int");
-    NanReturnUndefined();
-  }
-  int fd = args[0]->ToInt32()->Int32Value();
-
-  // callback
-  if(!args[1]->IsFunction()) {
-    NanThrowTypeError("Second argument must be a function");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Function> callback = args[1].As<v8::Function>();
-
-  FlushBaton* baton = new FlushBaton();
-  memset(baton, 0, sizeof(FlushBaton));
-  baton->fd = fd;
-  baton->callback = new NanCallback(callback);
-
-  uv_work_t* req = new uv_work_t();
-  req->data = baton;
-  uv_queue_work(uv_default_loop(), req, EIO_Flush, (uv_after_work_cb)EIO_AfterFlush);
-
-  NanReturnUndefined();
-}
-
-void EIO_AfterFlush(uv_work_t* req) {
-  NanScope();
-
-  FlushBaton* data = static_cast<FlushBaton*>(req->data);
-
-  v8::Handle<v8::Value> argv[2];
-
-  if(data->errorString[0]) {
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString));
-    argv[1] = NanUndefined();
-  } else {
-    argv[0] = NanUndefined();
-    argv[1] = NanNew<v8::Int32>(data->result);
-  }
-  data->callback->Call(2, argv);
-
-  delete data->callback;
-  delete data;
-  delete req;
-}
-
-NAN_METHOD(Set) {
-  NanScope();
-
-  // file descriptor
-  if(!args[0]->IsInt32()) {
-    NanThrowTypeError("First argument must be an int");
-    NanReturnUndefined();
-  }
-  int fd = args[0]->ToInt32()->Int32Value();
-
-  // options
-  if(!args[1]->IsObject()) {
-    NanThrowTypeError("Second argument must be an object");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Object> options = args[1]->ToObject();
-
-  // callback
-  if(!args[2]->IsFunction()) {
-    NanThrowTypeError("Third argument must be a function");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Function> callback = args[2].As<v8::Function>();
-
-  SetBaton* baton = new SetBaton();
-  memset(baton, 0, sizeof(SetBaton));
-  baton->fd = fd;
-  baton->callback = new NanCallback(callback);
-  baton->brk = options->Get(NanNew<v8::String>("brk"))->ToBoolean()->BooleanValue();
-  baton->rts = options->Get(NanNew<v8::String>("rts"))->ToBoolean()->BooleanValue();
-  baton->cts = options->Get(NanNew<v8::String>("cts"))->ToBoolean()->BooleanValue();
-  baton->dtr = options->Get(NanNew<v8::String>("dtr"))->ToBoolean()->BooleanValue();
-  baton->dsr = options->Get(NanNew<v8::String>("dsr"))->ToBoolean()->BooleanValue();
-
-  uv_work_t* req = new uv_work_t();
-  req->data = baton;
-  uv_queue_work(uv_default_loop(), req, EIO_Set, (uv_after_work_cb)EIO_AfterSet);
-
-  NanReturnUndefined();
-}
-
-void EIO_AfterSet(uv_work_t* req) {
-  NanScope();
-
-  SetBaton* data = static_cast<SetBaton*>(req->data);
-
-  v8::Handle<v8::Value> argv[2];
-
-  if(data->errorString[0]) {
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString));
-    argv[1] = NanUndefined();
-  } else {
-    argv[0] = NanUndefined();
-    argv[1] = NanNew<v8::Int32>(data->result);
-  }
-  data->callback->Call(2, argv);
-
-  delete data->callback;
-  delete data;
-  delete req;
-}
-
-NAN_METHOD(Drain) {
-  NanScope();
-
-  // file descriptor
-  if(!args[0]->IsInt32()) {
-    NanThrowTypeError("First argument must be an int");
-    NanReturnUndefined();
-  }
-  int fd = args[0]->ToInt32()->Int32Value();
-
-  // callback
-  if(!args[1]->IsFunction()) {
-    NanThrowTypeError("Second argument must be a function");
-    NanReturnUndefined();
-  }
-  v8::Local<v8::Function> callback = args[1].As<v8::Function>();
-
-  DrainBaton* baton = new DrainBaton();
-  memset(baton, 0, sizeof(DrainBaton));
-  baton->fd = fd;
-  baton->callback = new NanCallback(callback);
-
-  uv_work_t* req = new uv_work_t();
-  req->data = baton;
-  uv_queue_work(uv_default_loop(), req, EIO_Drain, (uv_after_work_cb)EIO_AfterDrain);
-
-  NanReturnUndefined();
-}
-
-void EIO_AfterDrain(uv_work_t* req) {
-  NanScope();
-
-  DrainBaton* data = static_cast<DrainBaton*>(req->data);
-
-  v8::Handle<v8::Value> argv[2];
-
-  if(data->errorString[0]) {
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(data->errorString));
-    argv[1] = NanUndefined();
-  } else {
-    argv[0] = NanUndefined();
-    argv[1] = NanNew<v8::Int32>(data->result);
-  }
-  data->callback->Call(2, argv);
-
-  delete data->callback;
-  delete data;
-  delete req;
-}
-
-// Change request for ticket #401 - credit to @sguilly
-SerialPortParity NAN_INLINE(ToParityEnum(const v8::Handle<v8::String>& v8str)) {
-  NanScope();
-  NanUtf8String *str = new NanUtf8String(v8str);
-  size_t count = strlen(**str);
-  SerialPortParity parity = SERIALPORT_PARITY_NONE;
-  if(!strncasecmp(**str, "none", count)) {
-  parity = SERIALPORT_PARITY_NONE;
-  } else if(!strncasecmp(**str, "even", count)) {
-  parity = SERIALPORT_PARITY_EVEN;
-  } else if(!strncasecmp(**str, "mark", count)) {
-  parity = SERIALPORT_PARITY_MARK;
-  } else if(!strncasecmp(**str, "odd", count)) {
-  parity = SERIALPORT_PARITY_ODD;
-  } else if(!strncasecmp(**str, "space", count)) {
-  parity = SERIALPORT_PARITY_SPACE;
-  }
-  // delete[] str;
-  return parity;
-}
-
-
-SerialPortStopBits NAN_INLINE(ToStopBitEnum(double stopBits)) {
-  if(stopBits > 1.4 && stopBits < 1.6) {
-    return SERIALPORT_STOPBITS_ONE_FIVE;
-  }
-  if(stopBits == 2) {
-    return SERIALPORT_STOPBITS_TWO;
-  }
-  return SERIALPORT_STOPBITS_ONE;
-}
-
-extern "C" {
-  void init (v8::Handle<v8::Object> target)
-  {
-    NanScope();
-    NODE_SET_METHOD(target, "set", Set);
-    NODE_SET_METHOD(target, "open", Open);
-    NODE_SET_METHOD(target, "write", Write);
-    NODE_SET_METHOD(target, "close", Close);
-    NODE_SET_METHOD(target, "list", List);
-    NODE_SET_METHOD(target, "flush", Flush);
-    NODE_SET_METHOD(target, "drain", Drain);
-
-#ifndef WIN32
-    SerialportPoller::Init(target);
-#endif
-  }
-}
-
-NODE_MODULE(serialport, init);
diff --git a/input_devices/mag/node_modules/serialport/src/serialport.h b/input_devices/mag/node_modules/serialport/src/serialport.h
deleted file mode 100644
index af5e54fa..00000000
--- a/input_devices/mag/node_modules/serialport/src/serialport.h
+++ /dev/null
@@ -1,193 +0,0 @@
-
-#ifndef _serialport_h_
-#define _serialport_h_
-
-#include <nan.h>
-#include <list>
-#include <string>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-enum SerialPortParity {
-  SERIALPORT_PARITY_NONE = 1,
-  SERIALPORT_PARITY_MARK = 2,
-  SERIALPORT_PARITY_EVEN = 3,
-  SERIALPORT_PARITY_ODD = 4,
-  SERIALPORT_PARITY_SPACE = 5
-};
-
-enum SerialPortStopBits {
-  SERIALPORT_STOPBITS_ONE = 1,
-  SERIALPORT_STOPBITS_ONE_FIVE = 2,
-  SERIALPORT_STOPBITS_TWO = 3
-};
-
-#define ERROR_STRING_SIZE 1024
-
-NAN_METHOD(List);
-void EIO_List(uv_work_t* req);
-void EIO_AfterList(uv_work_t* req);
-
-NAN_METHOD(Open);
-void EIO_Open(uv_work_t* req);
-void EIO_AfterOpen(uv_work_t* req);
-void AfterOpenSuccess(int fd, NanCallback* dataCallback, NanCallback* disconnectedCallback, NanCallback* errorCallback);
-
-NAN_METHOD(Write);
-void EIO_Write(uv_work_t* req);
-void EIO_AfterWrite(uv_work_t* req);
-
-NAN_METHOD(Close);
-void EIO_Close(uv_work_t* req);
-void EIO_AfterClose(uv_work_t* req);
-
-NAN_METHOD(Flush);
-void EIO_Flush(uv_work_t* req);
-void EIO_AfterFlush(uv_work_t* req);
-
-NAN_METHOD(Set);
-void EIO_Set(uv_work_t* req);
-void EIO_AfterSet(uv_work_t* req);
-
-NAN_METHOD(Drain);
-void EIO_Drain(uv_work_t* req);
-void EIO_AfterDrain(uv_work_t* req);
-
-SerialPortParity ToParityEnum(const v8::Handle<v8::String>& str);
-SerialPortStopBits ToStopBitEnum(double stopBits);
-
-struct OpenBatonPlatformOptions
-{
-};
-OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local<v8::Object>& options);
-
-struct OpenBaton {
-public:
-  char path[1024];
-  NanCallback* callback;
-  NanCallback* dataCallback;
-  NanCallback* disconnectedCallback;
-  NanCallback* errorCallback;
-  int result;
-  int baudRate;
-  int dataBits;
-  int bufferSize;
-  bool rtscts;
-  bool xon;
-  bool xoff;
-  bool xany;
-  bool dsrdtr;
-  SerialPortParity parity;
-  SerialPortStopBits stopBits;
-  OpenBatonPlatformOptions* platformOptions;  
-  char errorString[ERROR_STRING_SIZE];
-};
-
-struct WriteBaton {
-public:
-  int fd;
-  char* bufferData;
-  size_t bufferLength;
-  size_t offset;
-  v8::Persistent<v8::Object> buffer;
-  NanCallback* callback;
-  int result;
-  char errorString[ERROR_STRING_SIZE];
-};
-
-struct QueuedWrite {
-public:
-  uv_work_t req;
-  QueuedWrite *prev;
-  QueuedWrite *next;
-  WriteBaton* baton;
-
-  QueuedWrite() {
-    prev = this;
-    next = this;
-
-    baton = 0;
-  };
-
-  ~QueuedWrite() {
-    remove();
-  };
-
-  void remove() {
-    prev->next = next;
-    next->prev = prev;
-
-    next = this;
-    prev = this;
-  };
-
-  void insert_tail(QueuedWrite *qw) {
-    qw->next = this;
-    qw->prev = this->prev;
-    qw->prev->next = qw;
-    this->prev = qw;
-  };
-
-  bool empty() {
-    return next == this;
-  };
-
-};
-
-struct CloseBaton {
-public:
-  int fd;
-  NanCallback* callback;
-  char errorString[ERROR_STRING_SIZE];
-};
-
-struct ListResultItem {
-public:
-  std::string comName;
-  std::string manufacturer;
-  std::string serialNumber;
-  std::string pnpId;
-  std::string locationId;
-  std::string vendorId;
-  std::string productId;
-};
-
-struct ListBaton {
-public:
-  NanCallback* callback;
-  std::list<ListResultItem*> results;
-  char errorString[ERROR_STRING_SIZE];
-};
-
-struct FlushBaton {
-public:
-  int fd;
-  NanCallback* callback;
-  int result;
-  char errorString[ERROR_STRING_SIZE];
-};
-
-struct SetBaton {
-public:
-  int fd;
-  NanCallback* callback;
-  int result;
-  char errorString[ERROR_STRING_SIZE];
-  bool rts;
-  bool cts;
-  bool dtr;
-  bool dsr;
-  bool brk;
-
-};
-
-struct DrainBaton {
-public:
-  int fd;
-  NanCallback* callback;
-  int result;
-  char errorString[ERROR_STRING_SIZE];
-};
-
-#endif
diff --git a/input_devices/mag/node_modules/serialport/src/serialport_poller.cpp b/input_devices/mag/node_modules/serialport/src/serialport_poller.cpp
deleted file mode 100644
index 4b5f213a..00000000
--- a/input_devices/mag/node_modules/serialport/src/serialport_poller.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (C) 2013 Robert Giseburt <giseburt@gmail.com>
-// serialport_poller.cpp Written as a part of https://github.com/voodootikigod/node-serialport
-// License to use this is the same as that of node-serialport.
-
-#include <nan.h>
-#include "serialport_poller.h"
-
-using namespace v8;
-
-static v8::Persistent<v8::FunctionTemplate> serialportpoller_constructor;
-
-SerialportPoller::SerialportPoller() :  ObjectWrap() {};
-SerialportPoller::~SerialportPoller() {
-  // printf("~SerialportPoller\n");
-  delete callback_;
-};
-
-void _serialportReadable(uv_poll_t *req, int status, int events) {
-  SerialportPoller* sp = (SerialportPoller*) req->data;
-  // We can stop polling until we have read all of the data...
-  sp->_stop();
-  sp->callCallback(status);
-}
-
-void SerialportPoller::callCallback(int status) {
-  NanScope();
-  // uv_work_t* req = new uv_work_t;
-
-  // Call the callback to go read more data...
-
-  v8::Handle<v8::Value> argv[1];
-  if(status != 0) {
-    // error handling changed in libuv, see:
-    // https://github.com/joyent/libuv/commit/3ee4d3f183331
-    #ifdef UV_ERRNO_H_
-    const char* err_string = uv_strerror(status);
-    #else
-    uv_err_t errno = uv_last_error(uv_default_loop());
-    const char* err_string = uv_strerror(errno);
-    #endif
-    snprintf(this->errorString, sizeof(this->errorString), "Error %s on polling", err_string);
-    argv[0] = v8::Exception::Error(NanNew<v8::String>(this->errorString));
-  } else {
-    argv[0] = NanUndefined();
-  }
-
-  callback_->Call(1, argv);
-}
-
-
-
-void SerialportPoller::Init(Handle<Object> target) {
-  NanScope();
-
-  // Prepare constructor template
-  Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
-  tpl->SetClassName(NanNew<String>("SerialportPoller"));
-  tpl->InstanceTemplate()->SetInternalFieldCount(1);
-
-
-  // Prototype
-
-  // SerialportPoller.close()
-  tpl->PrototypeTemplate()->Set(NanNew<String>("close"),
-      NanNew<FunctionTemplate>(Close)->GetFunction());
-
-  // SerialportPoller.start()
-  tpl->PrototypeTemplate()->Set(NanNew<String>("start"),
-      NanNew<FunctionTemplate>(Start)->GetFunction());
-
-  NanAssignPersistent<FunctionTemplate>(serialportpoller_constructor, tpl);
-
-  target->Set(NanNew<String>("SerialportPoller"), tpl->GetFunction());
-}
-
-NAN_METHOD(SerialportPoller::New) {
-  NanScope();
-
-  SerialportPoller* obj = new SerialportPoller();
-
-  if(!args[0]->IsInt32()) {
-    NanThrowTypeError("First argument must be an fd");
-    NanReturnUndefined();
-  }
-  obj->fd_ = args[0]->ToInt32()->Int32Value();
-
-  if(!args[1]->IsFunction()) {
-    NanThrowTypeError("Third argument must be a function");
-    NanReturnUndefined();
-  }
-  obj->callback_ = new NanCallback(args[1].As<v8::Function>());
-  // obj->callCallback();
-
-  obj->Wrap(args.This());
-
-  obj->poll_handle_.data = obj;
-/*int r = */uv_poll_init(uv_default_loop(), &obj->poll_handle_, obj->fd_);
-  
-  uv_poll_start(&obj->poll_handle_, UV_READABLE, _serialportReadable);
-
-  NanReturnValue(args.This());
-}
-
-void SerialportPoller::_start() {
-  uv_poll_start(&poll_handle_, UV_READABLE, _serialportReadable);
-}
-
-void SerialportPoller::_stop() {
-  uv_poll_stop(&poll_handle_);
-}
-
-
-NAN_METHOD(SerialportPoller::Start) {
-  NanScope();
-
-  SerialportPoller* obj = ObjectWrap::Unwrap<SerialportPoller>(args.This());
-  obj->_start();
-  
-  NanReturnUndefined();
-}
-NAN_METHOD(SerialportPoller::Close) {
-  NanScope();
-
-  SerialportPoller* obj = ObjectWrap::Unwrap<SerialportPoller>(args.This());
-  obj->_stop();
-
-  // DO SOMETHING!
-
-  NanReturnUndefined();
-}
diff --git a/input_devices/mag/node_modules/serialport/src/serialport_poller.h b/input_devices/mag/node_modules/serialport/src/serialport_poller.h
deleted file mode 100644
index 664afd4c..00000000
--- a/input_devices/mag/node_modules/serialport/src/serialport_poller.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2013 Robert Giseburt <giseburt@gmail.com>
-// serialport_poller.h Written as a part of https://github.com/voodootikigod/node-serialport
-// License to use this is the same as that of node-serialport.
-
-#ifndef SERIALPORT_POLLER_H
-#define SERIALPORT_POLLER_H
-
-#include <nan.h>
-#include "serialport.h"
-
-class SerialportPoller : public node::ObjectWrap {
- public:
-  static void Init(v8::Handle<v8::Object> target);
-
-  void callCallback(int status);
-
-  void _start();
-  void _stop();
-
- private:
-  SerialportPoller();
-  ~SerialportPoller();
-
-  static NAN_METHOD(New);
-  static NAN_METHOD(Close);
-  static NAN_METHOD(Start);
-  
-  uv_poll_t poll_handle_;
-  int fd_;
-  char errorString[ERROR_STRING_SIZE];
-
-  NanCallback* callback_;
-};
-
-#endif
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/src/serialport_unix.cpp b/input_devices/mag/node_modules/serialport/src/serialport_unix.cpp
deleted file mode 100644
index da22b22a..00000000
--- a/input_devices/mag/node_modules/serialport/src/serialport_unix.cpp
+++ /dev/null
@@ -1,745 +0,0 @@
-#ifndef WIN32
-#include "serialport.h"
-#include "serialport_poller.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <termios.h>
-
-#ifdef __APPLE__
-#include <AvailabilityMacros.h>
-#include <sys/param.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/usb/IOUSBLib.h>
-#include <IOKit/serial/IOSerialKeys.h>
-
-uv_mutex_t list_mutex;
-Boolean lockInitialised = FALSE;
-#endif
-
-#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
-#include <sys/ioctl.h>
-#include <IOKit/serial/ioss.h>
-#include <errno.h>
-#endif
-
-#if defined(__OpenBSD__)
-#include <sys/ioctl.h>
-#endif
-
-#if defined(__linux__)
-#include <sys/ioctl.h>
-#include <linux/serial.h>
-#endif
-
-struct UnixPlatformOptions : OpenBatonPlatformOptions {
-public:
-  uint8_t vmin;
-  uint8_t vtime;
-};
-
-OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local<v8::Object>& options) {
-  NanScope();
-
-  UnixPlatformOptions* result = new UnixPlatformOptions();
-  result->vmin = options->Get(NanNew<v8::String>("vmin"))->ToInt32()->Int32Value();
-  result->vtime = options->Get(NanNew<v8::String>("vtime"))->ToInt32()->Int32Value();
-
-  return result;
-}
-
-int ToBaudConstant(int baudRate);
-int ToDataBitsConstant(int dataBits);
-int ToStopBitsConstant(SerialPortStopBits stopBits);
-
-void AfterOpenSuccess(int fd, NanCallback* dataCallback, NanCallback* disconnectedCallback, NanCallback* errorCallback) {
-  delete dataCallback;
-  delete errorCallback;
-  delete disconnectedCallback;
-}
-
-int ToBaudConstant(int baudRate) {
-  switch (baudRate) {
-    case 0: return B0;
-    case 50: return B50;
-    case 75: return B75;
-    case 110: return B110;
-    case 134: return B134;
-    case 150: return B150;
-    case 200: return B200;
-    case 300: return B300;
-    case 600: return B600;
-    case 1200: return B1200;
-    case 1800: return B1800;
-    case 2400: return B2400;
-    case 4800: return B4800;
-    case 9600: return B9600;
-    case 19200: return B19200;
-    case 38400: return B38400;
-    case 57600: return B57600;
-    case 115200: return B115200;
-    case 230400: return B230400;
-#if defined(__linux__)
-    case 460800: return B460800;
-    case 500000: return B500000;
-    case 576000: return B576000;
-    case 921600: return B921600;
-    case 1000000: return B1000000;
-    case 1152000: return B1152000;
-    case 1500000: return B1500000;
-    case 2000000: return B2000000;
-    case 2500000: return B2500000;
-    case 3000000: return B3000000;
-    case 3500000: return B3500000;
-    case 4000000: return B4000000;
-#endif
-  }
-  return -1;
-}
-
-#ifdef __APPLE__
-typedef struct SerialDevice {
-    char port[MAXPATHLEN];
-    char locationId[MAXPATHLEN];
-    char vendorId[MAXPATHLEN];
-    char productId[MAXPATHLEN];
-    char manufacturer[MAXPATHLEN];
-    char serialNumber[MAXPATHLEN];
-} stSerialDevice;
-
-typedef struct DeviceListItem {
-    struct SerialDevice value;
-    struct DeviceListItem *next;
-    int* length;
-} stDeviceListItem;
-#endif
-
-int ToDataBitsConstant(int dataBits) {
-  switch (dataBits) {
-    case 8: default: return CS8;
-    case 7: return CS7;
-    case 6: return CS6;
-    case 5: return CS5;
-  }
-  return -1;
-}
-
-
-
-void EIO_Open(uv_work_t* req) {
-  OpenBaton* data = static_cast<OpenBaton*>(req->data);
-  UnixPlatformOptions* platformOptions = static_cast<UnixPlatformOptions*>(data->platformOptions);
-
-  int baudRate = ToBaudConstant(data->baudRate);
-
-// #if not ( defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) )
-//   if(baudRate == -1) {
-//     snprintf(data->errorString, sizeof(data->errorString), "Invalid baud rate setting %d", data->baudRate);
-//     return;
-//   }
-// #endif
-
-  int dataBits = ToDataBitsConstant(data->dataBits);
-  if(dataBits == -1) {
-    snprintf(data->errorString, sizeof(data->errorString), "Invalid data bits setting %d", data->dataBits);
-    return;
-  }
-
-
-  int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC | O_SYNC);
-  int fd = open(data->path, flags);
-
-  if (fd == -1) {
-    snprintf(data->errorString, sizeof(data->errorString), "Cannot open %s", data->path);
-    return;
-  }
-
-
-  // struct sigaction saio;
-  // saio.sa_handler = sigio_handler;
-  // sigemptyset(&saio.sa_mask);
-  // saio.sa_flags = 0;
-  // sigaction(SIGIO, &saio, NULL);
-
-  // //all process to receive SIGIO
-  // fcntl(fd, F_SETOWN, getpid());
-  // int flflags = fcntl(fd, F_GETFL);
-  // fcntl(fd, F_SETFL, flflags | FNONBLOCK);
-
-  struct termios options;
-  // Set baud and other configuration.
-  tcgetattr(fd, &options);
-
-// Removing check for valid BaudRates due to ticket: #140
-// #if not ( defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) )
-  // Specify the baud rate
-
-
-  // On linux you can alter the meaning of B38400 to mean a custom baudrate...
-#if defined(__linux__) && defined(ASYNC_SPD_CUST)
-  if (baudRate == -1) {
-    struct serial_struct serinfo;
-    serinfo.reserved_char[0] = 0;
-    if (ioctl(fd, TIOCGSERIAL, &serinfo) != -1) {
-      serinfo.flags &= ~ASYNC_SPD_MASK;
-      serinfo.flags |= ASYNC_SPD_CUST;
-      serinfo.custom_divisor = (serinfo.baud_base + (data->baudRate / 2)) / data->baudRate;
-      if (serinfo.custom_divisor < 1)
-        serinfo.custom_divisor = 1;
-
-      ioctl(fd, TIOCSSERIAL, &serinfo);
-      ioctl(fd, TIOCGSERIAL, &serinfo);
-      // if (serinfo.custom_divisor * rate != serinfo.baud_base) {
-      //   warnx("actual baudrate is %d / %d = %f",
-      //     serinfo.baud_base, serinfo.custom_divisor,
-      //     (float)serinfo.baud_base / serinfo.custom_divisor);
-      // }
-    }
-
-    // Now we use "B38400" to trigger the special baud rate.
-    baudRate = B38400;
-  }
-#endif
-
-  if (baudRate != -1) {
-    cfsetispeed(&options, baudRate);
-    cfsetospeed(&options, baudRate);
-  }
-
-// Removing check for valid BaudRates due to ticket: #140
-// #endif
-
-  /*
-    IGNPAR  : ignore bytes with parity errors
-  */
-  options.c_iflag = IGNPAR;
-
-  /*
-    ICRNL   : map CR to NL (otherwise a CR input on the other computer
-              will not terminate input)
-  */
-  // Pulling this for now. It should be an option, however. -Giseburt
-  //options.c_iflag = ICRNL;
-
-  //  otherwise make device raw (no other input processing)
-
-
-  // Specify data bits
-  options.c_cflag &= ~CSIZE;
-  options.c_cflag |= dataBits;
-
-  options.c_cflag &= ~(CRTSCTS);
-
-  if (data->rtscts) {
-    options.c_cflag |= CRTSCTS;
-    // evaluate specific flow control options
-  }
-
-  options.c_iflag &= ~(IXON | IXOFF | IXANY);
-
-  if (data->xon) {
-    options.c_iflag |= IXON;
-  }
-
-  if (data->xoff) {
-    options.c_iflag |= IXOFF;
-  }
-
-  if (data->xany) {
-    options.c_iflag |= IXANY;
-  }
-
-
-  switch (data->parity)
-  {
-  case SERIALPORT_PARITY_NONE:
-    options.c_cflag &= ~PARENB;
-    // options.c_cflag &= ~CSTOPB;
-    // options.c_cflag &= ~CSIZE;
-    // options.c_cflag |= CS8;
-    break;
-  case SERIALPORT_PARITY_ODD:
-    options.c_cflag |= PARENB;
-    options.c_cflag |= PARODD;
-    // options.c_cflag &= ~CSTOPB;
-    // options.c_cflag &= ~CSIZE;
-    // options.c_cflag |= CS7;
-    break;
-  case SERIALPORT_PARITY_EVEN:
-    options.c_cflag |= PARENB;
-    options.c_cflag &= ~PARODD;
-    // options.c_cflag &= ~CSTOPB;
-    // options.c_cflag &= ~CSIZE;
-    // options.c_cflag |= CS7;
-    break;
-  default:
-    snprintf(data->errorString, sizeof(data->errorString), "Invalid parity setting %d", data->parity);
-    close(fd);
-    return;
-  }
-
-  switch(data->stopBits) {
-  case SERIALPORT_STOPBITS_ONE:
-    options.c_cflag &= ~CSTOPB;
-    break;
-  case SERIALPORT_STOPBITS_TWO:
-    options.c_cflag |= CSTOPB;
-    break;
-  default:
-    snprintf(data->errorString, sizeof(data->errorString), "Invalid stop bits setting %d", data->stopBits);
-    close(fd);
-    return;
-  }
-
-  options.c_cflag |= CLOCAL; //ignore status lines
-  options.c_cflag |= CREAD;  //enable receiver
-  options.c_cflag |= HUPCL;  //drop DTR (i.e. hangup) on close
-
-  // Raw output
-  options.c_oflag = 0;
-
-  // ICANON makes partial lines not readable. It should be otional.
-  // It works with ICRNL. -Giseburt
-  options.c_lflag = 0; //ICANON;
-
-  options.c_cc[VMIN]= platformOptions->vmin;
-  options.c_cc[VTIME]= platformOptions->vtime;
-
-  // removed this unneeded sleep.
-  // sleep(1);
-  tcflush(fd, TCIFLUSH);
-  tcsetattr(fd, TCSANOW, &options);
-
-  // On OS X, starting in Tiger, we can set a custom baud rate, as follows:
-#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
-  if (baudRate == -1) {
-    speed_t speed = data->baudRate;
-    if (ioctl(fd,  IOSSIOSPEED, &speed) == -1) {
-      snprintf(data->errorString, sizeof(data->errorString), "Error %s calling ioctl( ..., IOSSIOSPEED, %ld )", strerror(errno), speed );
-    }
-  }
-#endif
-
-  data->result = fd;
-}
-
-void EIO_Write(uv_work_t* req) {
-  QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data);
-  WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton);
-
-  data->result = 0;
-  errno = 0;
-
-  // We carefully *DON'T* break out of this loop.
-  do {
-    if ((data->result = write(data->fd, data->bufferData + data->offset, data->bufferLength - data->offset)) == -1) {
-      if (errno == EAGAIN || errno == EWOULDBLOCK)
-        return;
-
-      // The write call might be interrupted, if it is we just try again immediately.
-      if (errno != EINTR) {
-        snprintf(data->errorString, sizeof(data->errorString), "Error %s calling write(...)", strerror(errno) );
-        return;
-      }
-
-      // try again...
-      continue;
-    }
-    // there wasn't an error, do the math on what we actually wrote...
-    else {
-      data->offset += data->result;
-    }
-
-    // if we get there, we really don't want to loop
-    // break;
-  } while (data->bufferLength > data->offset);
-}
-
-void EIO_Close(uv_work_t* req) {
-  CloseBaton* data = static_cast<CloseBaton*>(req->data);
-
-  // printf(">>>> close fd %d\n", data->fd);
-
-  // fcntl(data->fd, F_SETFL, FNONBLOCK);
-
-  ssize_t r;
-
-  r = close(data->fd);
-
-  // printf(">>>> closed fd %d (err: %d)\n", data->fd, errno);
-
-  if (r && r != EBADF)
-    snprintf(data->errorString, sizeof(data->errorString), "Unable to close fd %d, errno: %d", data->fd, errno);
-}
-
-#ifdef __APPLE__
-
-// Function prototypes
-static kern_return_t FindModems(io_iterator_t *matchingServices);
-static io_registry_entry_t GetUsbDevice(char *pathName);
-static stDeviceListItem* GetSerialDevices();
-
-
-static kern_return_t FindModems(io_iterator_t *matchingServices)
-{
-    kern_return_t     kernResult;
-    CFMutableDictionaryRef  classesToMatch;
-    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
-    if (classesToMatch != NULL)
-    {
-        CFDictionarySetValue(classesToMatch,
-                             CFSTR(kIOSerialBSDTypeKey),
-                             CFSTR(kIOSerialBSDAllTypes));
-    }
-
-    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
-
-    return kernResult;
-}
-
-static io_registry_entry_t GetUsbDevice(char* pathName)
-{
-    io_registry_entry_t device = 0;
-
-    CFMutableDictionaryRef classesToMatch = IOServiceMatching(kIOUSBDeviceClassName);
-    if (classesToMatch != NULL)
-    {
-        io_iterator_t matchingServices;
-        kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, &matchingServices);
-        if (KERN_SUCCESS == kernResult)
-        {
-            io_service_t service;
-            Boolean deviceFound = false;
-
-            while ((service = IOIteratorNext(matchingServices)) && !deviceFound)
-            {
-                CFStringRef bsdPathAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(service, kIOServicePlane, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, kIORegistryIterateRecursively);
-
-                if (bsdPathAsCFString)
-                {
-                    Boolean result;
-                    char    bsdPath[MAXPATHLEN];
-
-                    // Convert the path from a CFString to a C (NUL-terminated)
-                    result = CFStringGetCString(bsdPathAsCFString,
-                                                bsdPath,
-                                                sizeof(bsdPath),
-                                                kCFStringEncodingUTF8);
-
-                    CFRelease(bsdPathAsCFString);
-
-                    if (result && (strcmp(bsdPath, pathName) == 0))
-                    {
-                        deviceFound = true;
-                        //memset(bsdPath, 0, sizeof(bsdPath));
-                        device = service;
-                    }
-                    else
-                    {
-                       // Release the object which are no longer needed
-                       (void) IOObjectRelease(service);
-                    }
-                }
-            }
-            // Release the iterator.
-            IOObjectRelease(matchingServices);
-        }
-    }
-
-    return device;
-}
-
-static void ExtractUsbInformation(stSerialDevice *serialDevice, IOUSBDeviceInterface  **deviceInterface)
-{
-    kern_return_t kernResult;
-    UInt32 locationID;
-    kernResult = (*deviceInterface)->GetLocationID(deviceInterface, &locationID);
-    if (KERN_SUCCESS == kernResult)
-    {
-        snprintf(serialDevice->locationId, 11, "0x%08x", locationID);
-    }
-
-    UInt16 vendorID;
-    kernResult = (*deviceInterface)->GetDeviceVendor(deviceInterface, &vendorID);
-    if (KERN_SUCCESS == kernResult)
-    {
-        snprintf(serialDevice->vendorId, 7, "0x%04x", vendorID);
-    }
-
-    UInt16 productID;
-    kernResult = (*deviceInterface)->GetDeviceProduct(deviceInterface, &productID);
-    if (KERN_SUCCESS == kernResult)
-    {
-        snprintf(serialDevice->productId, 7, "0x%04x", productID);
-    }
-}
-
-static stDeviceListItem* GetSerialDevices()
-{
-    kern_return_t kernResult;
-    io_iterator_t serialPortIterator;
-    char bsdPath[MAXPATHLEN];
-
-    FindModems(&serialPortIterator);
-
-    io_service_t modemService;
-    kernResult = KERN_FAILURE;
-    Boolean modemFound = false;
-
-    // Initialize the returned path
-    *bsdPath = '\0';
-
-    stDeviceListItem* devices = NULL;
-    stDeviceListItem* lastDevice = NULL;
-    int length = 0;
-
-    while ((modemService = IOIteratorNext(serialPortIterator)))
-    {
-        CFTypeRef bsdPathAsCFString;
-
-        bsdPathAsCFString = IORegistryEntrySearchCFProperty(modemService, kIOServicePlane, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, kIORegistryIterateRecursively);
-
-        if (bsdPathAsCFString)
-        {
-            Boolean result;
-
-            // Convert the path from a CFString to a C (NUL-terminated)
-
-            result = CFStringGetCString((CFStringRef) bsdPathAsCFString,
-                                        bsdPath,
-                                        sizeof(bsdPath),
-                                        kCFStringEncodingUTF8);
-            CFRelease(bsdPathAsCFString);
-
-            if (result)
-            {
-                stDeviceListItem *deviceListItem = (stDeviceListItem*) malloc(sizeof(stDeviceListItem));
-                stSerialDevice *serialDevice = &(deviceListItem->value);
-                strcpy(serialDevice->port, bsdPath);
-                memset(serialDevice->locationId, 0, sizeof(serialDevice->locationId));
-                memset(serialDevice->vendorId, 0, sizeof(serialDevice->vendorId));
-                memset(serialDevice->productId, 0, sizeof(serialDevice->productId));
-                serialDevice->manufacturer[0] = '\0';
-                serialDevice->serialNumber[0] = '\0';
-                deviceListItem->next = NULL;
-                deviceListItem->length = &length;
-
-                if (devices == NULL) {
-                    devices = deviceListItem;
-                }
-                else {
-                    lastDevice->next = deviceListItem;
-                }
-
-                lastDevice = deviceListItem;
-                length++;
-
-                modemFound = true;
-                kernResult = KERN_SUCCESS;
-
-                uv_mutex_lock(&list_mutex);
-
-                io_registry_entry_t device = GetUsbDevice(bsdPath);
-
-                if (device) {
-                    CFStringRef manufacturerAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device,
-                                          kIOServicePlane,
-                                          CFSTR(kUSBVendorString),
-                                          kCFAllocatorDefault,
-                                          kIORegistryIterateRecursively);
-
-                    if (manufacturerAsCFString)
-                    {
-                        Boolean result;
-                        char    manufacturer[MAXPATHLEN];
-
-                        // Convert from a CFString to a C (NUL-terminated)
-                        result = CFStringGetCString(manufacturerAsCFString,
-                                                    manufacturer,
-                                                    sizeof(manufacturer),
-                                                    kCFStringEncodingUTF8);
-
-                        if (result) {
-                          strcpy(serialDevice->manufacturer, manufacturer);
-                        }
-
-                        CFRelease(manufacturerAsCFString);
-                    }
-
-                    CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device,
-                                          kIOServicePlane,
-                                          CFSTR(kUSBSerialNumberString),
-                                          kCFAllocatorDefault,
-                                          kIORegistryIterateRecursively);
-
-                    if (serialNumberAsCFString)
-                    {
-                        Boolean result;
-                        char    serialNumber[MAXPATHLEN];
-
-                        // Convert from a CFString to a C (NUL-terminated)
-                        result = CFStringGetCString(serialNumberAsCFString,
-                                                    serialNumber,
-                                                    sizeof(serialNumber),
-                                                    kCFStringEncodingUTF8);
-
-                        if (result) {
-                          strcpy(serialDevice->serialNumber, serialNumber);
-                        }
-
-                        CFRelease(serialNumberAsCFString);
-                    }
-
-                    IOCFPlugInInterface **plugInInterface = NULL;
-                    SInt32        score;
-                    HRESULT       res;
-
-                    IOUSBDeviceInterface  **deviceInterface = NULL;
-
-                    kernResult = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
-                                                           &plugInInterface, &score);
-
-                    if ((kIOReturnSuccess != kernResult) || !plugInInterface) {
-                        continue;
-                    }
-
-                    // Use the plugin interface to retrieve the device interface.
-                    res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
-                                                             (LPVOID*) &deviceInterface);
-
-                    // Now done with the plugin interface.
-                    (*plugInInterface)->Release(plugInInterface);
-
-                    if (res || deviceInterface == NULL) {
-                        continue;
-                    }
-
-                    // Extract the desired Information
-                    ExtractUsbInformation(serialDevice, deviceInterface);
-
-                    // Release the Interface
-                    (*deviceInterface)->Release(deviceInterface);
-
-                    // Release the device
-                    (void) IOObjectRelease(device);
-                }
-
-                uv_mutex_unlock(&list_mutex);
-            }
-        }
-
-        // Release the io_service_t now that we are done with it.
-        (void) IOObjectRelease(modemService);
-    }
-
-    IOObjectRelease(serialPortIterator);  // Release the iterator.
-
-    return devices;
-}
-
-#endif
-
-void EIO_List(uv_work_t* req) {
-  // This code exists in javascript for unix platforms
-
-#ifdef __APPLE__
-  if(!lockInitialised)
-  {
-    uv_mutex_init(&list_mutex);
-    lockInitialised = TRUE;
-  }
-
-  ListBaton* data = static_cast<ListBaton*>(req->data);
-
-  stDeviceListItem* devices = GetSerialDevices();
-
-  if (*(devices->length) > 0)
-  {
-    stDeviceListItem* next = devices;
-
-    for (int i = 0, len = *(devices->length); i < len; i++) {
-        stSerialDevice device = (* next).value;
-
-        ListResultItem* resultItem = new ListResultItem();
-        resultItem->comName = device.port;
-
-        if (device.locationId != NULL) {
-          resultItem->locationId = device.locationId;
-        }
-        if (device.vendorId != NULL) {
-          resultItem->vendorId = device.vendorId;
-        }
-        if (device.productId != NULL) {
-          resultItem->productId = device.productId;
-        }
-        if (device.manufacturer != NULL) {
-          resultItem->manufacturer = device.manufacturer;
-        }
-        if (device.serialNumber != NULL) {
-          resultItem->serialNumber = device.serialNumber;
-        }
-        data->results.push_back(resultItem);
-
-        stDeviceListItem* current = next;
-
-        if (next->next != NULL)
-        {
-          next = next->next;
-        }
-
-        free(current);
-    }
-
-  }
-
-#endif
-}
-
-void EIO_Flush(uv_work_t* req) {
-  FlushBaton* data = static_cast<FlushBaton*>(req->data);
-
-  data->result = tcflush(data->fd, TCIFLUSH);
-}
-
-void EIO_Set(uv_work_t* req) {
-  SetBaton* data = static_cast<SetBaton*>(req->data);
-
-  int bits;
-  ioctl( data->fd, TIOCMGET, &bits );
-
-  bits &= ~(TIOCM_RTS | TIOCM_CTS | TIOCM_DTR | TIOCM_DSR);
-
-  if (data->rts) {
-    bits |= TIOCM_RTS;
-  }
-
-  if (data->cts) {
-    bits |= TIOCM_CTS;
-  }
-
-  if (data->dtr) {
-    bits |= TIOCM_DTR;
-  }
-
-  if (data->dsr) {
-    bits |= TIOCM_DSR;
-  }
-
-  //todo check these returns
-  if (data->brk) {
-    ioctl(data->fd, TIOCSBRK, NULL);
-  }else{
-    ioctl(data->fd, TIOCCBRK, NULL);
-  }
-
-  data->result = ioctl(data->fd, TIOCMSET, &bits );
-}
-
-void EIO_Drain(uv_work_t* req) {
-  DrainBaton* data = static_cast<DrainBaton*>(req->data);
-
-  data->result = tcdrain(data->fd);
-}
-
-#endif
diff --git a/input_devices/mag/node_modules/serialport/src/serialport_win.cpp b/input_devices/mag/node_modules/serialport/src/serialport_win.cpp
deleted file mode 100644
index e60074f8..00000000
--- a/input_devices/mag/node_modules/serialport/src/serialport_win.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-#include "serialport.h"
-#include <list>
-#include "win/disphelper.h"
-
-#include "win/stdafx.h"
-#include "win/enumser.h"
-
-#include <nan.h>
-
-#ifdef WIN32
-
-#define MAX_BUFFER_SIZE 1000
-
-
-struct WindowsPlatformOptions : OpenBatonPlatformOptions
-{
-};
-
-OpenBatonPlatformOptions* ParsePlatformOptions(const v8::Local<v8::Object>& options){
-  // currently none
-  return new WindowsPlatformOptions();
-}
-
-
-// Declare type of pointer to CancelIoEx function
-typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
-
-
-std::list<int> g_closingHandles;
-int bufferSize;
-void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) {
-  switch(errorCode) {
-  case ERROR_FILE_NOT_FOUND:
-    _snprintf(errorStr, ERROR_STRING_SIZE, "%s: File not found", prefix);
-    break;
-  case ERROR_INVALID_HANDLE:
-    _snprintf(errorStr, ERROR_STRING_SIZE, "%s: Invalid handle", prefix);
-    break;
-  case ERROR_ACCESS_DENIED:
-    _snprintf(errorStr, ERROR_STRING_SIZE, "%s: Access denied", prefix);
-    break;
-  case ERROR_OPERATION_ABORTED:
-    _snprintf(errorStr, ERROR_STRING_SIZE, "%s: operation aborted", prefix);
-    break;
-  default:
-    _snprintf(errorStr, ERROR_STRING_SIZE, "%s: Unknown error code %d", prefix, errorCode);
-    break;
-  }
-}
-
-void EIO_Open(uv_work_t* req) {
-  OpenBaton* data = static_cast<OpenBaton*>(req->data);
-
-  // data->path is char[1024] but on Windows it has the form "COMx\0" or "COMxx\0"
-  // We want to prepend "\\\\.\\" to it before we call CreateFile
-  strncpy(data->path + 20, data->path, 10);
-  strncpy(data->path, "\\\\.\\", 4);
-  strncpy(data->path + 4, data->path + 20, 10);
-
-  HANDLE file = CreateFile(
-    data->path,
-    GENERIC_READ | GENERIC_WRITE,
-    0,
-    NULL,
-    OPEN_EXISTING,
-    FILE_FLAG_OVERLAPPED,
-    NULL);
-  if (file == INVALID_HANDLE_VALUE) {
-    DWORD errorCode = GetLastError();
-    char temp[100];
-    _snprintf(temp, sizeof(temp), "Opening %s", data->path);
-    ErrorCodeToString(temp, errorCode, data->errorString);
-    return;
-  }
-
-  bufferSize = data->bufferSize;
-  if(bufferSize > MAX_BUFFER_SIZE) {
-    bufferSize = MAX_BUFFER_SIZE;
-  }
-
-  DCB dcb = { 0 };
-  dcb.DCBlength = sizeof(DCB);
-  if(!BuildCommDCB("9600,n,8,1", &dcb)) {
-    ErrorCodeToString("BuildCommDCB", GetLastError(), data->errorString);
-    return;
-  }
-
-  dcb.fBinary = true;
-  dcb.BaudRate = data->baudRate;
-  dcb.ByteSize = data->dataBits;
-  switch(data->parity) {
-  case SERIALPORT_PARITY_NONE:
-    dcb.Parity = NOPARITY;
-    break;
-  case SERIALPORT_PARITY_MARK:
-    dcb.Parity = MARKPARITY;
-    break;
-  case SERIALPORT_PARITY_EVEN:
-    dcb.Parity = EVENPARITY;
-    break;
-  case SERIALPORT_PARITY_ODD:
-    dcb.Parity = ODDPARITY;
-    break;
-  case SERIALPORT_PARITY_SPACE:
-    dcb.Parity = SPACEPARITY;
-    break;
-  }
-  switch(data->stopBits) {
-  case SERIALPORT_STOPBITS_ONE:
-    dcb.StopBits = ONESTOPBIT;
-    break;
-  case SERIALPORT_STOPBITS_ONE_FIVE:
-    dcb.StopBits = ONE5STOPBITS;
-    break;
-  case SERIALPORT_STOPBITS_TWO:
-    dcb.StopBits = TWOSTOPBITS;
-    break;
-  }
-
-  if(!SetCommState(file, &dcb)) {
-    ErrorCodeToString("SetCommState", GetLastError(), data->errorString);
-    return;
-  }
-
-  // Set the com port read/write timeouts
-  DWORD serialBitsPerByte = 8/*std data bits*/ + 1/*start bit*/;
-  serialBitsPerByte += (data->parity   == SERIALPORT_PARITY_NONE ) ? 0 : 1;
-  serialBitsPerByte += (data->stopBits == SERIALPORT_STOPBITS_ONE) ? 1 : 2;
-  DWORD msPerByte = (data->baudRate > 0) ?
-                    ((1000 * serialBitsPerByte + data->baudRate - 1) / data->baudRate) :
-                    1;
-  if (msPerByte < 1) {
-    msPerByte = 1;
-  }
-  COMMTIMEOUTS commTimeouts = {0};
-  commTimeouts.ReadIntervalTimeout = msPerByte; // Minimize chance of concatenating of separate serial port packets on read
-  commTimeouts.ReadTotalTimeoutMultiplier  = 0; // Do not allow big read timeout when big read buffer used
-  commTimeouts.ReadTotalTimeoutConstant    = 1000; // Total read timeout (period of read loop)
-  commTimeouts.WriteTotalTimeoutConstant   = 1000; // Const part of write timeout
-  commTimeouts.WriteTotalTimeoutMultiplier = msPerByte; // Variable part of write timeout (per byte)
-  if(!SetCommTimeouts(file, &commTimeouts)) {
-    ErrorCodeToString("SetCommTimeouts", GetLastError(), data->errorString);
-    return;
-  }
-
-  // Remove garbage data in RX/TX queues
-  PurgeComm(file, PURGE_RXCLEAR);
-  PurgeComm(file, PURGE_TXCLEAR);
-
-  data->result = (int)file;
-}
-
-struct WatchPortBaton {
-public:
-  HANDLE fd;
-  DWORD bytesRead;
-  char buffer[MAX_BUFFER_SIZE];
-  char errorString[ERROR_STRING_SIZE];
-  DWORD errorCode;
-  bool disconnected;
-  NanCallback* dataCallback;
-  NanCallback* errorCallback;
-  NanCallback* disconnectedCallback;
-};
-
-void EIO_Set(uv_work_t* req) {
-  SetBaton* data = static_cast<SetBaton*>(req->data);
-
-  if (data->rts) {
-    EscapeCommFunction((HANDLE)data->fd, SETRTS);
-  }else{
-    EscapeCommFunction((HANDLE)data->fd, CLRRTS);
-  }
-
-  if (data->dtr) {
-    EscapeCommFunction((HANDLE)data->fd, SETDTR);
-  }else{
-    EscapeCommFunction((HANDLE)data->fd, CLRDTR);
-  }
-
-  if (data->brk) {
-    EscapeCommFunction((HANDLE)data->fd, SETBREAK);
-  }else{
-    EscapeCommFunction((HANDLE)data->fd, CLRBREAK);
-  }
-
-  DWORD bits = 0;
-
-  GetCommMask((HANDLE)data->fd, &bits);
-
-  bits &= ~( EV_CTS | EV_DSR);
-  
-  if (data->cts) {
-    bits |= EV_CTS;
-  }
-
-  if (data->dsr) {
-    bits |= EV_DSR;
-  }
-
-  data->result = SetCommMask((HANDLE)data->fd, bits);
-}
-
-
-void EIO_WatchPort(uv_work_t* req) {
-  WatchPortBaton* data = static_cast<WatchPortBaton*>(req->data);
-  data->bytesRead = 0;
-  data->disconnected = false;
-
-  // Event used by GetOverlappedResult(..., TRUE) to wait for incoming data or timeout
-  // Event MUST be used if program has several simultaneous asynchronous operations
-  // on the same handle (i.e. ReadFile and WriteFile)
-  HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-  while(true) {
-    OVERLAPPED ov = {0};
-    ov.hEvent = hEvent;
-
-    // Start read operation - synchrounous or asynchronous
-    DWORD bytesReadSync = 0;
-    if(!ReadFile((HANDLE)data->fd, data->buffer, bufferSize, &bytesReadSync, &ov)) {
-      data->errorCode = GetLastError();
-      if(data->errorCode != ERROR_IO_PENDING) {
-        // Read operation error
-        if(data->errorCode == ERROR_OPERATION_ABORTED) {
-          data->disconnected = true;
-        }
-        else {
-          ErrorCodeToString("Reading from COM port (ReadFile)", data->errorCode, data->errorString);
-        }
-        break;
-      }
-
-      // Read operation is asynchronous and is pending
-      // We MUST wait for operation completion before deallocation of OVERLAPPED struct
-      // or read data buffer
-
-      // Wait for async read operation completion or timeout
-      DWORD bytesReadAsync = 0;
-      if(!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesReadAsync, TRUE)) {
-        // Read operation error
-        data->errorCode = GetLastError();
-        if(data->errorCode == ERROR_OPERATION_ABORTED) {
-          data->disconnected = true;
-        }
-        else {
-          ErrorCodeToString("Reading from COM port (GetOverlappedResult)", data->errorCode, data->errorString);
-        }
-        break;
-      }
-      else {
-        // Read operation completed asynchronously
-        data->bytesRead = bytesReadAsync;
-      }
-    }
-    else {
-      // Read operation completed synchronously
-      data->bytesRead = bytesReadSync;
-    }
-
-    // Return data received if any
-    if(data->bytesRead > 0) {
-      break;
-    }
-  }
-
-  CloseHandle(hEvent);
-}
-
-bool IsClosingHandle(int fd) {
-  for(std::list<int>::iterator it=g_closingHandles.begin(); it!=g_closingHandles.end(); ++it) {
-    if(fd == *it) {
-      g_closingHandles.remove(fd);
-      return true;
-    }
-  }
-  return false;
-}
-
-void DisposeWatchPortCallbacks(WatchPortBaton* data) {
-  delete data->dataCallback;
-  delete data->errorCallback;
-  delete data->disconnectedCallback;
-}
-
-void EIO_AfterWatchPort(uv_work_t* req) {
-  NanScope();
-
-  WatchPortBaton* data = static_cast<WatchPortBaton*>(req->data);
-  if(data->disconnected) {
-    data->disconnectedCallback->Call(0, NULL);
-    DisposeWatchPortCallbacks(data);
-    goto cleanup;
-  }
-
-  if(data->bytesRead > 0) {
-    v8::Handle<v8::Value> argv[1];
-    argv[0] = NanNewBufferHandle(data->buffer, data->bytesRead);
-    data->dataCallback->Call(1, argv);
-  } else if(data->errorCode > 0) {
-    if(data->errorCode == ERROR_INVALID_HANDLE && IsClosingHandle((int)data->fd)) {
-      DisposeWatchPortCallbacks(data);
-      goto cleanup;
-    } else {
-      v8::Handle<v8::Value> argv[1];
-      argv[0] = NanError(data->errorString);
-      data->errorCallback->Call(1, argv);
-      Sleep(100); // prevent the errors from occurring too fast
-    }
-  }
-  AfterOpenSuccess((int)data->fd, data->dataCallback, data->disconnectedCallback, data->errorCallback);
-
-cleanup:
-  delete data;
-  delete req;
-}
-
-void AfterOpenSuccess(int fd, NanCallback* dataCallback, NanCallback* disconnectedCallback, NanCallback* errorCallback) {
-  WatchPortBaton* baton = new WatchPortBaton();
-  memset(baton, 0, sizeof(WatchPortBaton));
-  baton->fd = (HANDLE)fd;
-  baton->dataCallback = dataCallback;
-  baton->errorCallback = errorCallback;
-  baton->disconnectedCallback = disconnectedCallback;
-
-  uv_work_t* req = new uv_work_t();
-  req->data = baton;
-
-  uv_queue_work(uv_default_loop(), req, EIO_WatchPort, (uv_after_work_cb)EIO_AfterWatchPort);
-}
-
-void EIO_Write(uv_work_t* req) {
-  QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data);
-  WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton);
-  data->result = 0;
-
-  do {
-	  OVERLAPPED ov = {0};
-	  // Event used by GetOverlappedResult(..., TRUE) to wait for outgoing data or timeout
-	  // Event MUST be used if program has several simultaneous asynchronous operations
-	  // on the same handle (i.e. ReadFile and WriteFile)
-	  ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-	  // Start write operation - synchrounous or asynchronous
-	  DWORD bytesWrittenSync = 0;
-	  if(!WriteFile((HANDLE)data->fd, data->bufferData, static_cast<DWORD>(data->bufferLength), &bytesWrittenSync, &ov)) {
-		DWORD lastError = GetLastError();
-		if(lastError != ERROR_IO_PENDING) {
-		  // Write operation error
-		  ErrorCodeToString("Writing to COM port (WriteFile)", lastError, data->errorString);
-		}
-		else {
-		  // Write operation is asynchronous and is pending
-		  // We MUST wait for operation completion before deallocation of OVERLAPPED struct
-		  // or write data buffer
-
-		  // Wait for async write operation completion or timeout
-		  DWORD bytesWrittenAsync = 0;
-		  if(!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesWrittenAsync, TRUE)) {
-			// Write operation error
-			DWORD lastError = GetLastError();
-			ErrorCodeToString("Writing to COM port (GetOverlappedResult)", lastError, data->errorString);
-		  }
-		  else {
-			// Write operation completed asynchronously
-			data->result = bytesWrittenAsync;
-		  }
-		}
-	  }
-	  else {
-		// Write operation completed synchronously
-		data->result = bytesWrittenSync;
-	  }
-
-	  data->offset += data->result;
-	  CloseHandle(ov.hEvent);
-  } while (data->bufferLength > data->offset);
-
-}
-
-void EIO_Close(uv_work_t* req) {
-  CloseBaton* data = static_cast<CloseBaton*>(req->data);
-
-  g_closingHandles.push_back(data->fd);
-
-  HMODULE hKernel32 = LoadLibrary("kernel32.dll");
-  // Look up function address
-  CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
-  // Do something with it
-  if (pCancelIoEx)
-  {
-      // Function exists so call it
-      // Cancel all pending IO Requests for the current device
-      pCancelIoEx((HANDLE)data->fd, NULL);
-  }
-  if(!CloseHandle((HANDLE)data->fd)) {
-    ErrorCodeToString("closing connection", GetLastError(), data->errorString);
-    return;
-  }
-}
-
-/*
- * listComPorts.c -- list COM ports
- *
- * http://github.com/todbot/usbSearch/
- *
- * 2012, Tod E. Kurt, http://todbot.com/blog/
- *
- *
- * Uses DispHealper : http://disphelper.sourceforge.net/
- *
- * Notable VIDs & PIDs combos:
- * VID 0403 - FTDI
- *
- * VID 0403 / PID 6001 - Arduino Diecimila
- *
- */
-void EIO_List(uv_work_t* req) {
-  ListBaton* data = static_cast<ListBaton*>(req->data);
-
-  {
-    DISPATCH_OBJ(wmiSvc);
-    DISPATCH_OBJ(colDevices);
-
-    dhInitialize(TRUE);
-    dhToggleExceptions(FALSE);
-
-    dhGetObject(L"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2", NULL, &wmiSvc);
-    dhGetValue(L"%o", &colDevices, wmiSvc, L".ExecQuery(%S)", L"Select * from Win32_PnPEntity");
-
-    int port_count = 0;
-    FOR_EACH(objDevice, colDevices, NULL) {
-      char* name = NULL;
-      char* pnpid = NULL;
-      char* manu = NULL;
-      char* match;
-
-      dhGetValue(L"%s", &name,  objDevice, L".Name");
-      dhGetValue(L"%s", &pnpid, objDevice, L".PnPDeviceID");
-
-      if( name != NULL && ((match = strstr( name, "(COM" )) != NULL) ) { // look for "(COM23)"
-        // 'Manufacturuer' can be null, so only get it if we need it
-        dhGetValue(L"%s", &manu, objDevice,  L".Manufacturer");
-        port_count++;
-        char* comname = strtok( match, "()");
-        ListResultItem* resultItem = new ListResultItem();
-        resultItem->comName = comname;
-        resultItem->manufacturer = manu;
-        resultItem->pnpId = pnpid;
-        data->results.push_back(resultItem);
-        dhFreeString(manu);
-      }
-
-      dhFreeString(name);
-      dhFreeString(pnpid);
-    } NEXT(objDevice);
-
-    SAFE_RELEASE(colDevices);
-    SAFE_RELEASE(wmiSvc);
-
-    dhUninitialize(TRUE);
-  }
-
-  std::vector<UINT> ports;
-  if (CEnumerateSerial::UsingQueryDosDevice(ports))
-  {
-    for (size_t i = 0; i < ports.size(); i++)
-    {
-      char comname[64] = { 0 };
-      _snprintf(comname, sizeof(comname), "COM%u", ports[i]);
-      bool bFound = false;
-      for (std::list<ListResultItem*>::iterator ri = data->results.begin(); ri != data->results.end(); ++ri)
-      {
-        if (stricmp((*ri)->comName.c_str(), comname) == 0)
-        {
-          bFound = true;
-          break;
-        }
-      }
-      if (!bFound)
-      {
-        ListResultItem* resultItem = new ListResultItem();
-        resultItem->comName = comname;
-        resultItem->manufacturer = "";
-        resultItem->pnpId = "";
-        data->results.push_back(resultItem);
-      }
-    }
-  }
-}
-
-void EIO_Flush(uv_work_t* req) {
-  FlushBaton* data = static_cast<FlushBaton*>(req->data);
-
-  if(!FlushFileBuffers((HANDLE)data->fd)) {
-    ErrorCodeToString("flushing connection", GetLastError(), data->errorString);
-    return;
-  }
-}
-
-void EIO_Drain(uv_work_t* req) {
-  DrainBaton* data = static_cast<DrainBaton*>(req->data);
-
-  if(!FlushFileBuffers((HANDLE)data->fd)) {
-    ErrorCodeToString("draining connection", GetLastError(), data->errorString);
-    return;
-  }
-}
-
-#endif
diff --git a/input_devices/mag/node_modules/serialport/src/win/AutoHModule.h b/input_devices/mag/node_modules/serialport/src/win/AutoHModule.h
deleted file mode 100644
index c0642a9f..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/AutoHModule.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-Module : AutoHModule.h
-Purpose: Defines the interface for a class which supports auto closing of a HMODULE via FreeLibrary and 
-         setting of the last Win32 error via SetLastError
-Created: PJN / 10-01-2013
-
-Copyright (c) 2013 by PJ Naughter (Web: www.naughter.com, Email: pjna@naughter.com)
-
-All rights reserved.
-
-Copyright / Usage Details:
-
-You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
-when your product is released in binary form. You are allowed to modify the source code in any way you want 
-except you cannot modify the copyright details at the top of each module. If you want to distribute source 
-code with your application, then you are only allowed to distribute versions released by the author. This is 
-to maintain a single distribution point for the source code. 
-
-*/
-
-
-///////////////////////// Macros / Structs etc ////////////////////////////////
-
-#pragma once
-
-#ifndef __AUTOHMODULE_H__
-#define __AUTOHMODULE_H__
-
-
-///////////////////////// Classes /////////////////////////////////////////////
-
-class CAutoHModule
-{
-public:
-//Constructors / Destructors
-  CAutoHModule() : m_hModule(NULL), 
-                    m_dwError(ERROR_SUCCESS)
-  {
-  }
-
-  explicit CAutoHModule(HMODULE hModule) : m_hModule(hModule), 
-                                            m_dwError(GetLastError())
-  {
-  }
-
-  explicit CAutoHModule(HMODULE hModule, DWORD dwError) : m_hModule(hModule), 
-                                                          m_dwError(dwError)
-  {
-  }
-
-  ~CAutoHModule()
-  {
-    if (m_hModule != NULL)
-    {
-      FreeLibrary(m_hModule);
-      m_hModule = NULL;
-    }
-    SetLastError(m_dwError);
-  }
-
-  operator HMODULE() 
-  {
-    return m_hModule;
-  }
-
-//Member variables
-  HMODULE m_hModule;
-  DWORD m_dwError;
-};
-
-
-#endif //__AUTOHMODULE_H__
diff --git a/input_devices/mag/node_modules/serialport/src/win/AutoHandle.h b/input_devices/mag/node_modules/serialport/src/win/AutoHandle.h
deleted file mode 100644
index 1ffca47a..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/AutoHandle.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Module : AutoHandle.h
-Purpose: Defines the interface for a class which supports auto closing of a handle via CloseHandle
-Created: PJN / 10-01-2013
-
-Copyright (c) 2013 by PJ Naughter (Web: www.naughter.com, Email: pjna@naughter.com)
-
-All rights reserved.
-
-Copyright / Usage Details:
-
-You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
-when your product is released in binary form. You are allowed to modify the source code in any way you want 
-except you cannot modify the copyright details at the top of each module. If you want to distribute source 
-code with your application, then you are only allowed to distribute versions released by the author. This is 
-to maintain a single distribution point for the source code. 
-
-*/
-
-
-///////////////////////// Macros / Structs etc ////////////////////////////////
-
-#pragma once
-
-#ifndef __AUTOHANDLE_H__
-#define __AUTOHANDLE_H__
-
-
-///////////////////////// Classes /////////////////////////////////////////////
-
-class CAutoHandle
-{
-public:
-//Constructors / Destructors
-  CAutoHandle() : m_hHandle(INVALID_HANDLE_VALUE)
-  {
-  }
-
-  explicit CAutoHandle(HANDLE hHandle) : m_hHandle(hHandle)
-  {
-  }
-
-  ~CAutoHandle()
-  {
-    if (m_hHandle != INVALID_HANDLE_VALUE)
-    {
-      CloseHandle(m_hHandle);
-      m_hHandle = INVALID_HANDLE_VALUE;
-    }
-  }
-
-//Methods
-  operator HANDLE() 
-  {
-    return m_hHandle;
-  }
-
-//Member variables
-  HANDLE m_hHandle;
-};
-
-#endif //__AUTOHANDLE_H__
diff --git a/input_devices/mag/node_modules/serialport/src/win/AutoHeapAlloc.h b/input_devices/mag/node_modules/serialport/src/win/AutoHeapAlloc.h
deleted file mode 100644
index 407e3a05..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/AutoHeapAlloc.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-Module : AutoHeapAlloc.h
-Purpose: Defines the interface for a class which supports auto closing of a heap pointer allocated via HeapAlloc
-Created: PJN / 10-01-2013
-
-Copyright (c) 2013 by PJ Naughter (Web: www.naughter.com, Email: pjna@naughter.com)
-
-All rights reserved.
-
-Copyright / Usage Details:
-
-You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
-when your product is released in binary form. You are allowed to modify the source code in any way you want 
-except you cannot modify the copyright details at the top of each module. If you want to distribute source 
-code with your application, then you are only allowed to distribute versions released by the author. This is 
-to maintain a single distribution point for the source code. 
-
-*/
-
-
-///////////////////////// Macros / Structs etc ////////////////////////////////
-
-#pragma once
-
-#ifndef __AUTOHEAPALLOC_H__
-#define __AUTOHEAPALLOC_H__
-
-
-///////////////////////// Includes ////////////////////////////////////////////                      
-
-#include <assert.h>
-
-
-///////////////////////// Classes /////////////////////////////////////////////
-
-class CAutoHeapAlloc
-{
-public:
-//Constructors / Destructors
-  CAutoHeapAlloc(HANDLE hHeap = GetProcessHeap(), DWORD dwHeapFreeFlags = 0) : m_pData(NULL),
-                                                                               m_hHeap(hHeap),
-                                                                               m_dwHeapFreeFlags(dwHeapFreeFlags)
-  {
-  }
-
-  BOOL Allocate(SIZE_T dwBytes, DWORD dwFlags = 0)
-  {
-    //Validate our parameters
-    assert(m_pData == NULL);
-
-    m_pData = HeapAlloc(m_hHeap, dwFlags, dwBytes);
-    return (m_pData != NULL);
-  }
-
-  ~CAutoHeapAlloc()
-  {
-    if (m_pData != NULL)
-    {
-      HeapFree(m_hHeap, m_dwHeapFreeFlags, m_pData);
-      m_pData = NULL;
-    }
-  }
-
-//Methods
-
-//Member variables
-  LPVOID m_pData;
-  HANDLE m_hHeap;
-  DWORD  m_dwHeapFreeFlags;
-};
-
-#endif //__AUTOHEAPALLOC_H__
diff --git a/input_devices/mag/node_modules/serialport/src/win/disphelper.c b/input_devices/mag/node_modules/serialport/src/win/disphelper.c
deleted file mode 100644
index a3a10dd9..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/disphelper.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-/* This file is the compacted single file version of the DispHelper COM helper library.
- * DispHelper allows you to call COM objects with an extremely simple printf style syntax.
- * DispHelper can be used from C++ or even plain C. It works with most Windows compilers
- * including Dev-CPP, Visual C++ and LCC-WIN32. Including DispHelper in your project
- * couldn't be simpler as it is available in a compacted single file version (this file).
- *
- * Included with DispHelper are over 20 samples that demonstrate using COM objects
- * including ADO, CDO, Outlook, Eudora, Excel, Word, Internet Explorer, MSHTML,
- * PocketSoap, Word Perfect, MS Agent, SAPI, MSXML, WIA, dexplorer and WMI.
- *
- * DispHelper is free open source software provided under the BSD license.
- *
- * Find out more, browse the readable version of the source code
- * and download DispHelper at:
- * http://sourceforge.net/projects/disphelper/
- * http://disphelper.sourceforge.net/
- */
-
-
-/* To use DispHelper in your project, include this file(disphelper.c) and the
- * header (disphelper.h). For Visual C++, Borland C++ and LCC-Win32 import
- * libraries are included via pragma directives. For other compilers you may
- * need to add ole32, oleaut32 and uuid. To do this in Dev-CPP add
- * "-lole32 -loleaut32 -luuid" to the linker box under Project->Project Options->Parameters.
- */
-
-
-/* If you are using Dev-CPP and get errors when compiling this file:
- * Make sure this file is set to compile as C and not C++ under
- * Project->Project Options->Files.
- */
-
-
-#define DISPHELPER_INTERNAL_BUILD
-#include "disphelper.h"
-#include <math.h>
-#include <assert.h>
-
-/* ----- convert.h ----- */
-
-HRESULT ConvertFileTimeToVariantTime(FILETIME * pft, DATE * pDate);
-HRESULT ConvertVariantTimeToFileTime(DATE date, FILETIME * pft);
-
-HRESULT ConvertVariantTimeToSystemTime(DATE date, SYSTEMTIME * pSystemTime);
-HRESULT ConvertSystemTimeToVariantTime(SYSTEMTIME * pSystemTime, DATE * pDate);
-
-HRESULT ConvertTimeTToVariantTime(time_t timeT, DATE * pDate);
-HRESULT ConvertVariantTimeToTimeT(DATE date, time_t * pTimeT);
-
-HRESULT ConvertAnsiStrToBStr(LPCSTR szAnsiIn, BSTR * lpBstrOut);
-HRESULT ConvertBStrToAnsiStr(BSTR bstrIn, LPSTR * lpszOut);
-
-/* ----- dh_create.c ----- */
-
-HRESULT dhCreateObjectEx(LPCOLESTR szProgId, REFIID riid, DWORD dwClsContext,
-			    COSERVERINFO * pServerInfo, void ** ppv)
-{
-	CLSID clsid;
-	HRESULT hr;
-	IClassFactory * pCf = NULL;
-
-	DH_ENTER(L"CreateObjectEx");
-
-	if (!szProgId || !riid || !ppv) return DH_EXIT(E_INVALIDARG, szProgId);
-
-	if (L'{' == szProgId[0])
-		hr = CLSIDFromString((LPOLESTR) szProgId, &clsid);
-	else
-		hr = CLSIDFromProgID(szProgId, &clsid);
-
-	if (SUCCEEDED(hr)) hr = CoGetClassObject(&clsid, dwClsContext, pServerInfo, &IID_IClassFactory, (void **) &pCf);
-	if (SUCCEEDED(hr)) hr = pCf->lpVtbl->CreateInstance(pCf, NULL, riid, ppv);
-
-	if (pCf) pCf->lpVtbl->Release(pCf);
-
-	return DH_EXIT(hr, szProgId);
-}
-
-HRESULT dhGetObjectEx(LPCOLESTR szPathName, LPCOLESTR szProgId, REFIID riid,
-		         DWORD dwClsContext, LPVOID lpvReserved, void ** ppv)
-{
-	HRESULT hr;
-
-	DH_ENTER(L"GetObjectEx");
-
-	if ((!szProgId && !szPathName) || !riid || !ppv || lpvReserved) return DH_EXIT(E_INVALIDARG, szProgId);
-
-	if (szPathName)
-	{
-
-		if (!szProgId)
-		{
-			hr = CoGetObject(szPathName, NULL, riid, ppv);
-		}
-		else
-		{
-			IPersistFile * ppf = NULL;
-
-			hr = dhCreateObjectEx(szProgId, &IID_IPersistFile, dwClsContext, NULL, (void **) &ppf);
-
-			if (SUCCEEDED(hr)) hr = ppf->lpVtbl->Load(ppf, szPathName, 0);
-			if (SUCCEEDED(hr)) hr = ppf->lpVtbl->QueryInterface(ppf, riid, ppv);
-
-			if (ppf) ppf->lpVtbl->Release(ppf);
-		}
-	}
-	else
-	{
-
-		CLSID clsid;
-		IUnknown * pUnk = NULL;
-
-		if (L'{' == szProgId[0])
-			hr = CLSIDFromString((LPOLESTR) szProgId, &clsid);
-		else
-			hr = CLSIDFromProgID(szProgId, &clsid);
-
-		if (SUCCEEDED(hr)) hr = GetActiveObject(&clsid, NULL, &pUnk);
-		if (SUCCEEDED(hr)) hr = pUnk->lpVtbl->QueryInterface(pUnk, riid, ppv);
-
-		if (pUnk) pUnk->lpVtbl->Release(pUnk);
-	}
-
-	return DH_EXIT(hr, szProgId);
-}
-
-HRESULT dhCreateObject(LPCOLESTR szProgId, LPCWSTR szMachine, IDispatch ** ppDisp)
-{
-	COSERVERINFO si = { 0 };
-
-	DH_ENTER(L"CreateObject");
-
-	si.pwszName = (LPWSTR) szMachine;
-
-	return DH_EXIT(dhCreateObjectEx(szProgId, &IID_IDispatch,
-			  szMachine ? CLSCTX_REMOTE_SERVER : CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER,
-			  szMachine ? &si : NULL, (void **) ppDisp), szProgId);
-}
-
-HRESULT dhGetObject(LPCOLESTR szPathName, LPCOLESTR szProgId, IDispatch ** ppDisp)
-{
-	DH_ENTER(L"GetObject");
-
-	return DH_EXIT(dhGetObjectEx(szPathName, szProgId, &IID_IDispatch,
-			  CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER, NULL, (void **) ppDisp), szProgId);
-}
-
-HRESULT dhCallMethod(IDispatch * pDisp, LPCOLESTR szMember, ... )
-{
-	HRESULT hr;
-	va_list marker;
-
-	DH_ENTER(L"CallMethod");
-
-	va_start(marker, szMember);
-
-	hr = dhCallMethodV(pDisp, szMember, &marker);
-
-	va_end(marker);
-
-	return DH_EXIT(hr, szMember);
-}
-
-HRESULT dhPutValue(IDispatch * pDisp, LPCOLESTR szMember, ...)
-{
-	HRESULT hr;
-	va_list marker;
-
-	DH_ENTER(L"PutValue");
-
-	va_start(marker, szMember);
-
-	hr = dhPutValueV(pDisp, szMember, &marker);
-
-	va_end(marker);
-
-	return DH_EXIT(hr, szMember);
-}
-
-HRESULT dhPutRef(IDispatch * pDisp, LPCOLESTR szMember, ...)
-{
-	HRESULT hr;
-	va_list marker;
-
-	DH_ENTER(L"PutRef");
-
-	va_start(marker, szMember);
-
-	hr = dhPutRefV(pDisp, szMember, &marker);
-
-	va_end(marker);
-
-	return DH_EXIT(hr, szMember);
-}
-
-HRESULT dhGetValue(LPCWSTR szIdentifier, void * pResult, IDispatch * pDisp, LPCOLESTR szMember, ...)
-{
-	HRESULT hr;
-	va_list marker;
-
-	DH_ENTER(L"GetValue");
-
-	va_start(marker, szMember);
-
-	hr = dhGetValueV(szIdentifier, pResult, pDisp, szMember, &marker);
-
-	va_end(marker);
-
-	return DH_EXIT(hr, szMember);
-}
-
-HRESULT dhInvoke(int invokeType, VARTYPE returnType, VARIANT * pvResult, IDispatch * pDisp, LPCOLESTR szMember, ...)
-{
-	HRESULT hr;
-	va_list marker;
-
-	DH_ENTER(L"Invoke");
-
-	va_start(marker, szMember);
-
-	hr = dhInvokeV(invokeType, returnType, pvResult, pDisp, szMember, &marker);
-
-	va_end(marker);
-
-	return DH_EXIT(hr, szMember);
-}
-
-/* ----- dh_core.c ----- */
-
-BOOL dh_g_bIsUnicodeMode;
-
-HRESULT dhInvokeArray(int invokeType, VARIANT * pvResult, UINT cArgs,
-                         IDispatch * pDisp, LPCOLESTR szMember, VARIANT * pArgs)
-{
-	DISPPARAMS dp       = { 0 };
-	EXCEPINFO excep     = { 0 };
-	DISPID dispidNamed  = DISPID_PROPERTYPUT;
-	DISPID dispID;
-	UINT uiArgErr;
-	HRESULT hr;
-
-	DH_ENTER(L"InvokeArray");
-
-	if(!pDisp || !szMember || (cArgs != 0 && !pArgs)) return DH_EXIT(E_INVALIDARG, szMember);
-
-	hr = pDisp->lpVtbl->GetIDsOfNames(pDisp, &IID_NULL, (LPOLESTR *) &szMember, 1, LOCALE_USER_DEFAULT, &dispID);
-
-	if(FAILED(hr)) return DH_EXITEX(hr, TRUE, szMember, szMember, NULL, 0);
-
-	if (pvResult != NULL) VariantInit(pvResult);
-
-	dp.cArgs  = cArgs;
-	dp.rgvarg = pArgs;
-
-	if(invokeType & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
-	{
-		dp.cNamedArgs = 1;
-		dp.rgdispidNamedArgs = &dispidNamed;
-	}
-
-	hr = pDisp->lpVtbl->Invoke(pDisp, dispID, &IID_NULL, LOCALE_USER_DEFAULT, (WORD) invokeType, &dp, pvResult, &excep, &uiArgErr);
-
-	return DH_EXITEX(hr, TRUE, szMember, szMember, &excep, uiArgErr);
-}
-
-HRESULT dhCallMethodV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker)
-{
-	DH_ENTER(L"CallMethodV");
-
-	return DH_EXIT(dhInvokeV(DISPATCH_METHOD, VT_EMPTY, NULL, pDisp, szMember, marker), szMember);
-}
-
-HRESULT dhPutValueV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker)
-{
-	DH_ENTER(L"PutValueV");
-
-	return DH_EXIT(dhInvokeV(DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, pDisp, szMember, marker), szMember);
-}
-
-HRESULT dhPutRefV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker)
-{
-	DH_ENTER(L"PutRefV");
-
-	return DH_EXIT(dhInvokeV(DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, pDisp, szMember, marker), szMember);
-}
-
-HRESULT dhGetValueV(LPCWSTR szIdentifier, void * pResult, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker)
-{
-	VARIANT vtResult;
-	VARTYPE returnType;
-	HRESULT hr;
-
-	DH_ENTER(L"GetValueV");
-
-	if (!pResult || !szIdentifier) return DH_EXIT(E_INVALIDARG, szMember);
-
-	if (*szIdentifier == L'%') szIdentifier++;
-
-	switch(*szIdentifier)
-	{
-		case L'd': returnType = VT_I4;       break;
-		case L'u': returnType = VT_UI4;      break;
-		case L'e': returnType = VT_R8;       break;
-		case L'b': returnType = VT_BOOL;     break;
-		case L'v': returnType = VT_EMPTY;    break;
-		case L'B': returnType = VT_BSTR;     break;
-		case L'S': returnType = VT_BSTR;     break;
-		case L's': returnType = VT_BSTR;     break;
-		case L'T': returnType = VT_BSTR;     break;
-		case L'o': returnType = VT_DISPATCH; break;
-		case L'O': returnType = VT_UNKNOWN;  break;
-		case L't': returnType = VT_DATE;     break;
-		case L'W': returnType = VT_DATE;     break;
-		case L'f': returnType = VT_DATE;     break;
-		case L'D': returnType = VT_DATE;     break;
-#ifndef _WIN64
-		case L'p': returnType = VT_I4;       break;
-#else
-		case L'p': returnType = VT_I8;       break;
-#endif
-		default:
-			DEBUG_NOTIFY_INVALID_IDENTIFIER(*szIdentifier);
-			return DH_EXIT(E_INVALIDARG, szMember);
-	}
-
-	hr = dhInvokeV(DISPATCH_PROPERTYGET|DISPATCH_METHOD, returnType, &vtResult, pDisp, szMember, marker);
-	if (FAILED(hr)) return DH_EXIT(hr, szMember);
-
-	switch(*szIdentifier)
-	{
-		case L'd':
-			*((LONG *) pResult) = V_I4(&vtResult);
-			break;
-
-		case L'u':
-			*((ULONG *) pResult) = V_UI4(&vtResult);
-			break;
-
-		case L'e':
-			*((DOUBLE *) pResult) = V_R8(&vtResult);
-			break;
-
-		case L'b':
-			*((BOOL *) pResult) = V_BOOL(&vtResult);
-			break;
-
-		case L'v':
-			*((VARIANT *) pResult) = vtResult;
-			break;
-
-		case L'B':
-			*((BSTR *) pResult) = V_BSTR(&vtResult);
-			break;
-
-		case L'S':
-			*((LPWSTR *) pResult) = V_BSTR(&vtResult);
-			break;
-
-		case L's':
-			hr = ConvertBStrToAnsiStr(V_BSTR(&vtResult), (LPSTR *) pResult);
-			SysFreeString(V_BSTR(&vtResult));
-			break;
-
-		case L'T':
-			if (dh_g_bIsUnicodeMode)
-			{
-				*((LPWSTR *) pResult) = V_BSTR(&vtResult);
-			}
-			else
-			{
-				hr = ConvertBStrToAnsiStr(V_BSTR(&vtResult), (LPSTR *) pResult);
-				SysFreeString(V_BSTR(&vtResult));
-			}
-			break;
-
-		case L'o':
-			*((IDispatch **) pResult) = V_DISPATCH(&vtResult);
-			if (V_DISPATCH(&vtResult) == NULL) hr = E_NOINTERFACE;
-			break;
-
-		case L'O':
-			*((IUnknown **) pResult) = V_UNKNOWN(&vtResult);
-			if (V_UNKNOWN(&vtResult) == NULL) hr = E_NOINTERFACE;
-			break;
-
-		case L't':
-			hr = ConvertVariantTimeToTimeT(V_DATE(&vtResult), (time_t *) pResult);
-			break;
-
-		case L'W':
-			hr = ConvertVariantTimeToSystemTime(V_DATE(&vtResult), (SYSTEMTIME *) pResult);
-			break;
-
-		case L'f':
-			hr = ConvertVariantTimeToFileTime(V_DATE(&vtResult), (FILETIME *) pResult);
-			break;
-
-		case L'D':
-			*((DATE *) pResult) = V_DATE(&vtResult);
-			break;
-
-		case L'p':
-#ifndef _WIN64
-			*((LPVOID *) pResult) = (LPVOID) V_I4(&vtResult);
-#else
-			*((LPVOID *) pResult) = (LPVOID) V_I8(&vtResult);
-#endif
-			break;
-	}
-
-	return DH_EXIT(hr, szMember);
-}
-
-/* ----- dh_invoke.c ----- */
-
-static HRESULT TraverseSubObjects(IDispatch ** ppDisp, LPWSTR * lpszMember, va_list * marker);
-static HRESULT CreateArgumentArray(LPWSTR szTemp, VARIANT * pArgs, BOOL * pbFreeList, UINT * pcArgs, va_list * marker);
-static HRESULT InternalInvokeV(int invokeType, VARTYPE returnType, VARIANT * pvResult, IDispatch * pDisp, LPOLESTR szMember, va_list * marker);
-static HRESULT ExtractArgument(VARIANT * pvArg, WCHAR chIdentifier, BOOL * pbFreeArg, va_list * marker);
-
-HRESULT dhInvokeV(int invokeType, VARTYPE returnType, VARIANT * pvResult,
-                     IDispatch * pDisp, LPCOLESTR szMember, va_list * marker)
-{
-	WCHAR szCopy[DH_MAX_MEMBER];
-	LPWSTR szTemp                  = szCopy;
-	SIZE_T cchDest                 = ARRAYSIZE(szCopy);
-	HRESULT hr;
-
-	DH_ENTER(L"InvokeV");
-
-	if (!pDisp || !szMember || !marker) return DH_EXIT(E_INVALIDARG, szMember);
-
-	do
-	{
-		if (cchDest-- == 0) return DH_EXIT(E_INVALIDARG, szMember);
-	}
-	while( (*szTemp++ = *szMember++) );
-
-	szTemp = szCopy;
-
-	hr = TraverseSubObjects(&pDisp, &szTemp, marker);
-
-	if (SUCCEEDED(hr))
-	{
-		hr = InternalInvokeV(invokeType, returnType, pvResult, pDisp, szTemp, marker);
-
-		pDisp->lpVtbl->Release(pDisp);
-	}
-
-	return DH_EXIT(hr, szMember);
-}
-
-static HRESULT TraverseSubObjects(IDispatch ** ppDisp, LPWSTR * lpszMember, va_list * marker)
-{
-	LPWSTR szSeperator, szTemp;
-	VARIANT vtObject;
-	HRESULT hr;
-
-	DH_ENTER(L"TraverseSubObjects");
-
-	if (**lpszMember == L'.') (*lpszMember)++;
-
-	(*ppDisp)->lpVtbl->AddRef(*ppDisp);
-
-	szSeperator = wcschr(*lpszMember, L'.');
-
-	if (szSeperator == NULL) return DH_EXIT(NOERROR, *lpszMember);
-
-	szTemp = *lpszMember;
-
-	do
-	{
-		*szSeperator = L'\0';
-
-		hr = InternalInvokeV(DISPATCH_METHOD|DISPATCH_PROPERTYGET, VT_DISPATCH,
-		                     &vtObject, *ppDisp, szTemp, marker);
-
-		if (!vtObject.pdispVal && SUCCEEDED(hr)) hr = E_NOINTERFACE;
-
-		(*ppDisp)->lpVtbl->Release(*ppDisp);
-
-		if (FAILED(hr)) break;
-
-		*ppDisp = vtObject.pdispVal;
-
-		szTemp = szSeperator + 1;
-
-	}
-	while ( (wcschr(szTemp, L'.') ) != NULL);
-
-	*lpszMember = szTemp;
-
-	return DH_EXIT(hr, *lpszMember);
-}
-
-static HRESULT InternalInvokeV(int invokeType, VARTYPE returnType, VARIANT * pvResult,
-                               IDispatch * pDisp, LPOLESTR szMember, va_list * marker)
-{
-	VARIANT vtArgs[DH_MAX_ARGS];
-	BOOL bFreeList[DH_MAX_ARGS];
-	HRESULT hr;
-	UINT cArgs, iArg;
-
-	DH_ENTER(L"InternalInvokeV");
-
-	hr = CreateArgumentArray(szMember, vtArgs, bFreeList, &cArgs, marker);
-
-	if (SUCCEEDED(hr))
-	{
-		hr = dhInvokeArray(invokeType, pvResult, cArgs, pDisp, szMember, &vtArgs[DH_MAX_ARGS - cArgs]);
-
-		for (iArg = DH_MAX_ARGS - cArgs;iArg < DH_MAX_ARGS;iArg++)
-		{
-			if (bFreeList[iArg]) VariantClear(&vtArgs[iArg]);
-		}
-
-		if (SUCCEEDED(hr) && pvResult != NULL &&
-	            pvResult->vt != returnType && returnType != VT_EMPTY)
-		{
-			hr = VariantChangeType(pvResult, pvResult, 16 , returnType);
-			if (FAILED(hr)) VariantClear(pvResult);
-		}
-	}
-
-	return DH_EXIT(hr, szMember);
-}
-
-static HRESULT CreateArgumentArray(LPWSTR szMember, VARIANT * pArgs, BOOL * pbFreeList,
-				   UINT * pcArgs, va_list * marker)
-{
-	HRESULT hr        = NOERROR;
-	INT iArg          = DH_MAX_ARGS;
-	BOOL bInArguments = FALSE;
-
-	DH_ENTER(L"CreateArgumentArray");
-
-	while (*szMember)
-	{
-		if (!bInArguments &&
-                   (*szMember == L'(' || *szMember == L' ' || *szMember == L'=') )
-		{
-			bInArguments = TRUE;
-
-			*szMember = L'\0';
-		}
-		else if  (*szMember == L'%')
-		{
-			if (!bInArguments)
-			{
-				bInArguments = TRUE;
-				*szMember = L'\0';
-			}
-
-			iArg--;
-
-			if (iArg == -1) { hr = E_INVALIDARG; break; }
-
-			szMember++;
-
-			hr = ExtractArgument(&pArgs[iArg], *szMember, &pbFreeList[iArg], marker);
-
-			if (FAILED(hr)) break;
-		}
-
-		szMember++;
-	}
-
-	*pcArgs = DH_MAX_ARGS - iArg;
-
-	if (FAILED(hr))
-	{
-		for (++iArg;iArg < DH_MAX_ARGS; iArg++)
-		{
-			if (pbFreeList[iArg]) VariantClear(&pArgs[iArg]);
-		}
-	}
-
-	return DH_EXIT(hr, szMember);
-}
-
-static HRESULT ExtractArgument(VARIANT * pvArg, WCHAR chIdentifier, BOOL * pbFreeArg, va_list * marker)
-{
-	HRESULT hr = NOERROR;
-
-	*pbFreeArg = FALSE;
-
-	if (chIdentifier == L'T') chIdentifier = (dh_g_bIsUnicodeMode ? L'S' : L's');
-
-	switch (chIdentifier)
-	{
-		case L'd':
-			V_VT(pvArg)  = VT_I4;
-			V_I4(pvArg)  = va_arg(*marker, LONG);
-			break;
-
-		case L'u':
-			V_VT(pvArg)  = VT_UI4;
-			V_UI4(pvArg) = va_arg(*marker, ULONG);
-			break;
-
-		case L'e':
-			V_VT(pvArg)  = VT_R8;
-			V_R8(pvArg)  = va_arg(*marker, DOUBLE);
-			break;
-
-		case L'b':
-			V_VT(pvArg)   = VT_BOOL;
-			V_BOOL(pvArg) = ( va_arg(*marker, BOOL) ? VARIANT_TRUE : VARIANT_FALSE );
-			break;
-
-		case L'v':
-			*pvArg  = *va_arg(*marker, VARIANT *);
-			break;
-
-		case L'm':
-			V_VT(pvArg)    = VT_ERROR;
-			V_ERROR(pvArg) = DISP_E_PARAMNOTFOUND;
-			break;
-
-		case L'B':
-			V_VT(pvArg)   = VT_BSTR;
-			V_BSTR(pvArg) = va_arg(*marker, BSTR);
-			break;
-
-		case L'S':
-		{
-			LPOLESTR szTemp = va_arg(*marker, LPOLESTR);
-
-			V_VT(pvArg)   = VT_BSTR;
-			V_BSTR(pvArg) = SysAllocString(szTemp);
-
-			if (V_BSTR(pvArg) == NULL && szTemp != NULL) hr = E_OUTOFMEMORY;
-
-			*pbFreeArg = TRUE;
-			break;
-		}
-
-		case L's':
-			V_VT(pvArg) = VT_BSTR;
-			hr = ConvertAnsiStrToBStr(va_arg(*marker, LPSTR), &V_BSTR(pvArg));
-			*pbFreeArg = TRUE;
-			break;
-
-		case L'o':
-			V_VT(pvArg)       = VT_DISPATCH;
-			V_DISPATCH(pvArg) = va_arg(*marker, IDispatch *);
-			break;
-
-		case L'O':
-			V_VT(pvArg)      = VT_UNKNOWN;
-			V_UNKNOWN(pvArg) = va_arg(*marker, IUnknown *);
-			break;
-
-		case L'D':
-			V_VT(pvArg)   = VT_DATE;
-			V_DATE(pvArg) = va_arg(*marker, DATE);
-			break;
-
-		case L't':
-			V_VT(pvArg) = VT_DATE;
-			hr = ConvertTimeTToVariantTime(va_arg(*marker, time_t), &V_DATE(pvArg));
-			break;
-
-		case L'W':
-			V_VT(pvArg) = VT_DATE;
-			hr = ConvertSystemTimeToVariantTime(va_arg(*marker, SYSTEMTIME *), &V_DATE(pvArg));
-			break;
-
-		case L'f':
-			V_VT(pvArg) = VT_DATE;
-			hr = ConvertFileTimeToVariantTime(va_arg(*marker, FILETIME *), &V_DATE(pvArg));
-			break;
-
-		case L'p':
-#ifndef _WIN64
-			V_VT(pvArg) = VT_I4;
-			V_I4(pvArg) = (LONG) va_arg(*marker, LPVOID);
-#else
-			V_VT(pvArg) = VT_I8;
-			V_I8(pvArg) = (LONGLONG) va_arg(*marker, LPVOID);
-#endif
-			break;
-
-		default:
-			hr = E_INVALIDARG;
-			DEBUG_NOTIFY_INVALID_IDENTIFIER(chIdentifier);
-			break;
-	}
-
-	return hr;
-}
-
-/* ----- dh_enum.c ----- */
-
-HRESULT dhEnumBeginV(IEnumVARIANT ** ppEnum, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker)
-{
-	DISPPARAMS dp    = { 0 };
-	EXCEPINFO excep  = { 0 };
-	VARIANT vtResult;
-	IDispatch * pDispObj;
-	HRESULT hr;
-
-	DH_ENTER(L"EnumBeginV");
-
-	if (!ppEnum || !pDisp) return DH_EXIT(E_INVALIDARG, szMember);
-
-	if (szMember != NULL)
-	{
-		hr = dhGetValueV(L"%o", &pDispObj, pDisp, szMember, marker);
-		if (FAILED(hr)) return DH_EXIT(hr, szMember);
-	}
-	else
-	{
-		pDispObj = pDisp;
-	}
-
-	hr = pDispObj->lpVtbl->Invoke(pDispObj, DISPID_NEWENUM, &IID_NULL, LOCALE_USER_DEFAULT,
-				 DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dp, &vtResult, &excep, NULL);
-
-	if (szMember != NULL) pDispObj->lpVtbl->Release(pDispObj);
-
-	if (FAILED(hr)) return DH_EXITEX(hr, TRUE, L"_NewEnum", szMember, &excep, 0);
-
-	if (vtResult.vt == VT_DISPATCH)
-		hr = vtResult.pdispVal->lpVtbl->QueryInterface(vtResult.pdispVal, &IID_IEnumVARIANT, (void **) ppEnum);
-	else if (vtResult.vt == VT_UNKNOWN)
-		hr = vtResult.punkVal->lpVtbl->QueryInterface(vtResult.punkVal, &IID_IEnumVARIANT, (void **) ppEnum);
-	else
-		hr = E_NOINTERFACE;
-
-	VariantClear(&vtResult);
-
-	return DH_EXIT(hr, szMember);
-}
-
-HRESULT dhEnumNextVariant(IEnumVARIANT * pEnum, VARIANT * pvResult)
-{
-	DH_ENTER(L"EnumNextVariant");
-
-	if (!pEnum || !pvResult) return DH_EXIT(E_INVALIDARG, L"Enumerator");
-
-	return DH_EXIT(pEnum->lpVtbl->Next(pEnum, 1, pvResult, NULL), L"Enumerator");
-}
-
-HRESULT dhEnumNextObject(IEnumVARIANT * pEnum, IDispatch ** ppDisp)
-{
-	VARIANT vtResult;
-	HRESULT hr;
-
-	DH_ENTER(L"EnumNextObject");
-
-	if (!pEnum || !ppDisp) return DH_EXIT(E_INVALIDARG, L"Enumerator");
-
-	hr = pEnum->lpVtbl->Next(pEnum, 1, &vtResult, NULL);
-
-	if (hr == S_OK)
-	{
-		if (vtResult.vt == VT_DISPATCH)
-		{
-			*ppDisp = vtResult.pdispVal;
-		}
-		else
-		{
-			hr = VariantChangeType(&vtResult, &vtResult, 0, VT_DISPATCH);
-			if (SUCCEEDED(hr)) *ppDisp = vtResult.pdispVal;
-			else VariantClear(&vtResult);
-		}
-	}
-
-	return DH_EXIT(hr, L"Enumerator");
-}
-
-HRESULT dhEnumBegin(IEnumVARIANT ** ppEnum, IDispatch * pDisp, LPCOLESTR szMember, ...)
-{
-	HRESULT hr;
-	va_list marker;
-
-	DH_ENTER(L"EnumBegin");
-
-	va_start(marker, szMember);
-
-	hr = dhEnumBeginV(ppEnum, pDisp, szMember, &marker);
-
-	va_end(marker);
-
-	return DH_EXIT(hr, szMember);
-}
-
-/* ----- convert.c ----- */
-
-static const LONGLONG FILE_TIME_ONE_DAY           = 864000000000;
-
-static const LONGLONG FILE_TIME_VARIANT_DAY0      = 94353120000000000;
-
-static const ULONGLONG FILE_TIME_VARIANT_OVERFLOW  = 2650467744000000000;
-
-static const DATE      VARIANT_FILE_TIME_DAY0      = -109205;
-
-static const DATE      VARIANT_TIMET_DAY0          = 25569;
-
-static const LONG      TIMET_ONE_DAY               = 86400;
-
-#ifndef _WIN64
-static const DATE      VARIANT_TIMET_MAX           = 50424.13480;
-#else
-static const time_t    TIMET_VARIANT_OVERFLOW      = 253402300800;
-#endif
-
-HRESULT ConvertFileTimeToVariantTime(FILETIME * pft, DATE * pDate)
-{
-	ULONGLONG ftScalar;
-
-	if (!pft || !pDate) return E_INVALIDARG;
-
-	ftScalar = *((ULONGLONG *) pft) + 500;
-
-	if (ftScalar >= FILE_TIME_VARIANT_OVERFLOW) return E_INVALIDARG;
-	*pDate = (LONGLONG) (ftScalar - FILE_TIME_VARIANT_DAY0) / (double) FILE_TIME_ONE_DAY;
-	if (*pDate < 0) *pDate = floor(*pDate) + (floor(*pDate) - *pDate);
-
-	return NOERROR;
-}
-
-HRESULT ConvertVariantTimeToFileTime(DATE date, FILETIME * pft)
-{
-	ULONGLONG ftScalar;
-
-	if (!pft) return E_INVALIDARG;
-
-	if (date < 0) date = ceil(date) + (ceil(date) - date);
-
-	if (date < VARIANT_FILE_TIME_DAY0) return E_INVALIDARG;
-	ftScalar = (ULONGLONG) ((date * FILE_TIME_ONE_DAY) + FILE_TIME_VARIANT_DAY0);
-
-	*pft = *((FILETIME *) &ftScalar);
-
-	return NOERROR;
-}
-
-HRESULT ConvertVariantTimeToSystemTime(DATE date, SYSTEMTIME * pSystemTime)
-{
-	HRESULT hr;
-	FILETIME fileTime;
-
-	if (!pSystemTime) return E_INVALIDARG;
-	if (FAILED(hr = ConvertVariantTimeToFileTime(date, &fileTime))) return hr;
-	return (FileTimeToSystemTime(&fileTime, pSystemTime) ? NOERROR : HRESULT_FROM_WIN32( GetLastError() ));
-}
-
-HRESULT ConvertSystemTimeToVariantTime(SYSTEMTIME * pSystemTime, DATE * pDate)
-{
-	FILETIME fileTime;
-
-	if (!pSystemTime || !pDate) return E_INVALIDARG;
-	if (!SystemTimeToFileTime(pSystemTime, &fileTime)) return HRESULT_FROM_WIN32( GetLastError() );
-	return ConvertFileTimeToVariantTime(&fileTime, pDate);
-}
-
-HRESULT ConvertVariantTimeToTimeT(DATE date, time_t * pTimeT)
-{
-	struct tm * ptm;
-
-	if (!pTimeT) return E_INVALIDARG;
-
-#ifndef _WIN64
-	if (date < VARIANT_TIMET_DAY0 || date > VARIANT_TIMET_MAX) return E_INVALIDARG;
-#else
-	if (date < VARIANT_TIMET_DAY0) return E_INVALIDARG;
-#endif
-
-	*pTimeT = (time_t) (((date - VARIANT_TIMET_DAY0) * TIMET_ONE_DAY) + 0.5);
-
-	if ( (ptm = gmtime(pTimeT)) == NULL || !(ptm->tm_isdst = -1) ||
-	     (*pTimeT = mktime(ptm)) == (time_t) -1 ) return E_FAIL;
-
-	return NOERROR;
-}
-
-HRESULT ConvertTimeTToVariantTime(time_t timeT, DATE * pDate)
-{
-	struct tm localtm, utctm, * ptm;
-	time_t timeTLocal, timeTUtc;
-
-	if (!pDate) return E_INVALIDARG;
-
-	if ( (ptm = localtime(&timeT)) == NULL) return E_FAIL;
-	localtm = *ptm;
-
-	if ( (ptm = gmtime(&timeT)) == NULL) return E_FAIL;
-	utctm = *ptm;
-
-	localtm.tm_isdst = 0;
-	utctm.tm_isdst   = 0;
-
-	if ( (timeTLocal = mktime(&localtm)) == (time_t) -1 ||
-	     (timeTUtc   = mktime(&utctm))   == (time_t) -1) return E_FAIL;
-
-	timeT += timeTLocal - timeTUtc;
-
-#ifdef _WIN64
-	if (timeT >= TIMET_VARIANT_OVERFLOW) return E_INVALIDARG;
-#endif
-	*pDate = (DATE)  (timeT / (double) TIMET_ONE_DAY) + VARIANT_TIMET_DAY0;
-
-	return NOERROR;
-}
-
-HRESULT ConvertAnsiStrToBStr(LPCSTR szAnsiIn, BSTR * lpBstrOut)
-{
-	DWORD dwSize;
-
-	if (lpBstrOut == NULL) return E_INVALIDARG;
-	if (szAnsiIn == NULL) { *lpBstrOut = NULL; return NOERROR; }
-
-	dwSize = MultiByteToWideChar(CP_ACP, 0, szAnsiIn, -1, NULL, 0);
-	if (dwSize == 0) return HRESULT_FROM_WIN32( GetLastError() );
-
-	*lpBstrOut = SysAllocStringLen(NULL, dwSize - 1);
-	if (*lpBstrOut == NULL) return E_OUTOFMEMORY;
-
-	if ( !MultiByteToWideChar(CP_ACP, 0, szAnsiIn, -1, *lpBstrOut, dwSize) )
-	{
-		SysFreeString(*lpBstrOut);
-		return HRESULT_FROM_WIN32( GetLastError() );
-	}
-
-	return NOERROR;
-}
-
-HRESULT ConvertBStrToAnsiStr(BSTR bstrIn, LPSTR * lpszOut)
-{
-	DWORD dwSize;
-
-	if (lpszOut == NULL) return E_INVALIDARG;
-	if (bstrIn == NULL) { *lpszOut = NULL; return NOERROR; }
-
-	dwSize = WideCharToMultiByte(CP_ACP, 0, bstrIn, -1, NULL, 0, NULL, NULL);
-	if (dwSize == 0) return HRESULT_FROM_WIN32( GetLastError() );
-
-	*lpszOut = (LPSTR) SysAllocStringByteLen(NULL, dwSize - 1);
-	if (*lpszOut == NULL) return E_OUTOFMEMORY;
-
-	if ( !WideCharToMultiByte(CP_ACP, 0, bstrIn, -1, *lpszOut, dwSize, NULL, NULL) )
-	{
-		SysFreeString((BSTR) *lpszOut);
-		return HRESULT_FROM_WIN32( GetLastError() );
-	}
-
-	return NOERROR;
-}
-
-/* ----- dh_exceptions.c ----- */
-
-#ifndef DISPHELPER_NO_EXCEPTIONS
-
-static DH_EXCEPTION_OPTIONS g_ExceptionOptions;
-
-static LONG  f_lngTlsInitBegin = -1, f_lngTlsInitEnd = -1;
-static DWORD f_TlsIdxStackCount, f_TlsIdxException;
-
-#define SetStackCount(nStackCount)   TlsSetValue(f_TlsIdxStackCount, (LPVOID) (nStackCount))
-#define SetExceptionPtr(pException)  TlsSetValue(f_TlsIdxException, pException);
-#define GetStackCount()       (UINT) TlsGetValue(f_TlsIdxStackCount)
-#define GetExceptionPtr()            TlsGetValue(f_TlsIdxException)
-#define CheckTlsInitialized()        if (f_lngTlsInitEnd != 0) InitializeTlsIndexes();
-
-static void hlprStringCchCopyW(LPWSTR pszDest, SIZE_T cchDest, LPCWSTR pszSrc)
-{
-	assert(cchDest > 0);
-
-	do
-	{
-		if (--cchDest == 0) break;
-	}
-	while ((*pszDest++ = *pszSrc++));
-
-	*pszDest = L'\0';
-}
-
-static void InitializeTlsIndexes(void)
-{
-	if (0 == InterlockedIncrement(&f_lngTlsInitBegin))
-	{
-		f_TlsIdxStackCount = TlsAlloc();
-		f_TlsIdxException  = TlsAlloc();
-		f_lngTlsInitEnd    = 0;
-	}
-	else
-	{
-		while (f_lngTlsInitEnd != 0) Sleep(5);
-	}
-}
-
-void dhEnter(void)
-{
-	CheckTlsInitialized();
-	SetStackCount(GetStackCount() + 1);
-}
-
-HRESULT dhExitEx(HRESULT hr, BOOL bDispatchError, LPCWSTR szMember, LPCWSTR szCompleteMember,
-                 EXCEPINFO * pExcepInfo, UINT iArgError, LPCWSTR szFunctionName)
-{
-	UINT nStackCount = GetStackCount();
-
-	SetStackCount(nStackCount - 1);
-
-	if (FAILED(hr) && !g_ExceptionOptions.bDisableRecordExceptions)
-	{
-		PDH_EXCEPTION pException = GetExceptionPtr();
-
-		if (!pException)
-		{
-			pException = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DH_EXCEPTION));
-			if (!pException) return hr;
-			SetExceptionPtr(pException);
-		}
-		else if (pException->bOld)
-		{
-			SysFreeString(pException->szDescription);
-			SysFreeString(pException->szSource);
-			SysFreeString(pException->szHelpFile);
-			ZeroMemory(pException, sizeof(DH_EXCEPTION));
-		}
-
-		if (pException->hr == 0)
-		{
-			pException->hr              = hr;
-			pException->iArgError       = iArgError;
-			pException->szErrorFunction = szFunctionName;
-			pException->bDispatchError  = bDispatchError;
-
-			if (szMember) hlprStringCchCopyW(pException->szMember, ARRAYSIZE(pException->szMember), szMember);
-
-			if (pExcepInfo && hr == DISP_E_EXCEPTION)
-			{
-				if (pExcepInfo->pfnDeferredFillIn &&
-				    !IsBadCodePtr((FARPROC) pExcepInfo->pfnDeferredFillIn)) pExcepInfo->pfnDeferredFillIn(pExcepInfo);
-
-				pException->szDescription = pExcepInfo->bstrDescription;
-				pException->szSource      = pExcepInfo->bstrSource;
-				pException->szHelpFile    = pExcepInfo->bstrHelpFile;
-				pException->dwHelpContext = pExcepInfo->dwHelpContext;
-				pException->swCode        = (pExcepInfo->wCode ? pExcepInfo->wCode : pExcepInfo->scode);
-			}
-		}
-
-		if (nStackCount == 1)
-		{
-			pException->bOld              = TRUE;
-			pException->szInitialFunction = szFunctionName;
-
-			if (szCompleteMember) hlprStringCchCopyW(pException->szCompleteMember, ARRAYSIZE(pException->szCompleteMember), szCompleteMember);
-
-			if (g_ExceptionOptions.bShowExceptions)
-				dhShowException(pException);
-
-			if (g_ExceptionOptions.pfnExceptionCallback)
-				g_ExceptionOptions.pfnExceptionCallback(pException);
-		}
-	}
-	else if (hr == DISP_E_EXCEPTION && pExcepInfo)
-	{
-		SysFreeString(pExcepInfo->bstrDescription);
-		SysFreeString(pExcepInfo->bstrSource);
-		SysFreeString(pExcepInfo->bstrHelpFile);
-	}
-
-	return hr;
-}
-
-HRESULT dhShowException(PDH_EXCEPTION pException)
-{
-	WCHAR szMessage[512];
-
-	dhFormatExceptionW(pException, szMessage, ARRAYSIZE(szMessage), FALSE);
-
-	MessageBoxW(g_ExceptionOptions.hwnd, szMessage, g_ExceptionOptions.szAppName,
-	            MB_ICONSTOP | MB_SETFOREGROUND);
-
-	return NOERROR;
-}
-
-HRESULT dhFormatExceptionW(PDH_EXCEPTION pException, LPWSTR szBuffer, UINT cchBufferSize, BOOL bFixedFont)
-{
-	HRESULT hr;
-	UINT cch = 0;
-#	define DESCRIPTION_LENGTH 255
-
-	if (!szBuffer && cchBufferSize) return E_INVALIDARG;
-
-	if (!pException)
-	{
-		dhGetLastException(&pException);
-		if (!pException)
-		{
-			if (cchBufferSize != 0)
-			{
-				_snwprintf(szBuffer, cchBufferSize, L"No error information available.");
-				szBuffer[cchBufferSize - 1] = L'\0';
-			}
-
-			return NOERROR;
-		}
-	}
-
-	hr = (pException->hr == DISP_E_EXCEPTION && pException->swCode ?
-			pException->swCode : pException->hr);
-
-	if (!pException->szSource)
-	{
-		if (pException->bDispatchError)
-			pException->szSource = SysAllocString(L"IDispatch Interface");
-		else
-			pException->szSource = SysAllocString(L"Application");
-	}
-
-	if (!pException->szDescription)
-	{
-		pException->szDescription = SysAllocStringLen(NULL, DESCRIPTION_LENGTH);
-
-		if (pException->szDescription)
-		{
-			switch (hr)
-			{
-				case E_NOINTERFACE:
-					_snwprintf(pException->szDescription, DESCRIPTION_LENGTH, L"Object required");
-					break;
-
-				case DISP_E_UNKNOWNNAME:
-				case DISP_E_MEMBERNOTFOUND:
-					_snwprintf(pException->szDescription, DESCRIPTION_LENGTH, L"Object doesn't support this property or method: '%s'", pException->szMember);
-					break;
-
-				case DISP_E_TYPEMISMATCH:
-					if (pException->szMember[0])
-					{
-						_snwprintf(pException->szDescription, DESCRIPTION_LENGTH, L"Type mismatch: '%s'. Argument Index: %d", pException->szMember, pException->iArgError);
-						break;
-					}
-
-				default:
-				{
-#ifndef UNICODE
-					CHAR szDescription[DESCRIPTION_LENGTH];
-#else
-					LPWSTR szDescription = pException->szDescription;
-#endif
-					cch = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-					             NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-					             szDescription, DESCRIPTION_LENGTH, NULL);
-
-					if (!cch) wcscpy(pException->szDescription, L"Unknown runtime error");
-#ifndef UNICODE
-					else MultiByteToWideChar(CP_ACP, 0, szDescription, -1, pException->szDescription, DESCRIPTION_LENGTH);
-#endif
-				}
-			}
-		}
-	}
-
-	if (pException->szDescription)
-	{
-
-		if (!cch) cch = wcslen(pException->szDescription);
-
-		if (cch >= 2 && pException->szDescription[cch - 2] == L'\r')
-			pException->szDescription[cch - 2] = L'\0';
-		else if (cch >= 1 && pException->szDescription[cch - 1] == L'\n')
-			pException->szDescription[cch - 1] = L'\0';
-	}
-
-	if (cchBufferSize)
-	{
-		if (!bFixedFont)
-		{
-			_snwprintf(szBuffer, cchBufferSize, L"Member:\t  %s\r\nFunction:\t  %s\t\t\r\nError In:\t  %s\r\nError:\t  %s\r\nCode:\t  %x\r\nSource:\t  %s",
-				pException->szCompleteMember,
-				pException->szInitialFunction, pException->szErrorFunction,
-				pException->szDescription, hr,
-				pException->szSource);
-		}
-		else
-		{
-			_snwprintf(szBuffer, cchBufferSize, L"Member:   %s\r\nFunction: %s\r\nError In: %s\r\nError:    %s\r\nCode:     %x\r\nSource:   %s",
-				pException->szCompleteMember,
-				pException->szInitialFunction, pException->szErrorFunction,
-				pException->szDescription, hr,
-				pException->szSource);
-		}
-
-		szBuffer[cchBufferSize - 1] = L'\0';
-	}
-
-	return NOERROR;
-}
-
-HRESULT dhFormatExceptionA(PDH_EXCEPTION pException, LPSTR szBuffer, UINT cchBufferSize, BOOL bFixedFont)
-{
-	WCHAR szBufferW[1024];
-
-	dhFormatExceptionW(pException, szBufferW, ARRAYSIZE(szBufferW), bFixedFont);
-
-	if (0 == WideCharToMultiByte(CP_ACP, 0, szBufferW, -1, szBuffer, cchBufferSize, NULL, NULL))
-		return HRESULT_FROM_WIN32( GetLastError() );
-
-	return NOERROR;
-}
-
-HRESULT dhGetLastException(PDH_EXCEPTION * ppException)
-{
-	if (!ppException) return E_INVALIDARG;
-
-	CheckTlsInitialized();
-	*ppException = GetExceptionPtr();
-
-	return NOERROR;
-}
-
-HRESULT dhToggleExceptions(BOOL bShow)
-{
-	g_ExceptionOptions.bShowExceptions = bShow;
-	if (bShow) g_ExceptionOptions.bDisableRecordExceptions = FALSE;
-
-	return NOERROR;
-}
-
-HRESULT dhSetExceptionOptions(PDH_EXCEPTION_OPTIONS pExceptionOptions)
-{
-	if (!pExceptionOptions) return E_INVALIDARG;
-
-	g_ExceptionOptions.hwnd                     = pExceptionOptions->hwnd;
-	g_ExceptionOptions.szAppName                = pExceptionOptions->szAppName;
-	g_ExceptionOptions.bShowExceptions          = pExceptionOptions->bShowExceptions;
-	g_ExceptionOptions.bDisableRecordExceptions = pExceptionOptions->bDisableRecordExceptions;
-	g_ExceptionOptions.pfnExceptionCallback     = pExceptionOptions->pfnExceptionCallback;
-
-	return NOERROR;
-}
-
-HRESULT dhGetExceptionOptions(PDH_EXCEPTION_OPTIONS pExceptionOptions)
-{
-	if (!pExceptionOptions) return E_INVALIDARG;
-
-	pExceptionOptions->hwnd                     = g_ExceptionOptions.hwnd;
-	pExceptionOptions->szAppName                = g_ExceptionOptions.szAppName;
-	pExceptionOptions->bShowExceptions          = g_ExceptionOptions.bShowExceptions;
-	pExceptionOptions->bDisableRecordExceptions = g_ExceptionOptions.bDisableRecordExceptions;
-	pExceptionOptions->pfnExceptionCallback     = g_ExceptionOptions.pfnExceptionCallback;
-
-	return NOERROR;
-}
-
-void dhCleanupThreadException(void)
-{
-	PDH_EXCEPTION pException;
-
-	CheckTlsInitialized();
-	pException = GetExceptionPtr();
-
-	if (pException)
-	{
-		SysFreeString(pException->szDescription);
-		SysFreeString(pException->szSource);
-		SysFreeString(pException->szHelpFile);
-
-		HeapFree(GetProcessHeap(), 0, pException);
-
-		SetExceptionPtr(NULL);
-	}
-}
-
-#endif
-
-/* ----- dh_init.c ----- */
-
-HRESULT dhInitializeImp(BOOL bInitializeCOM, BOOL bUnicode)
-{
-	dh_g_bIsUnicodeMode = bUnicode;
-
-	if (bInitializeCOM) return CoInitialize(NULL);
-
-	return NOERROR;
-}
-
-void dhUninitialize(BOOL bUninitializeCOM)
-{
-#ifndef DISPHELPER_NO_EXCEPTIONS
-	dhCleanupThreadException();
-#endif
-	if (bUninitializeCOM) CoUninitialize();
-}
-
diff --git a/input_devices/mag/node_modules/serialport/src/win/disphelper.h b/input_devices/mag/node_modules/serialport/src/win/disphelper.h
deleted file mode 100644
index 1da4f97b..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/disphelper.h
+++ /dev/null
@@ -1,731 +0,0 @@
-/* This file is part of the source code for the DispHelper COM helper library.
- * DispHelper allows you to call COM objects with an extremely simple printf style syntax.
- * DispHelper can be used from C++ or even plain C. It works with most Windows compilers
- * including Dev-CPP, Visual C++ and LCC-WIN32. Including DispHelper in your project
- * couldn't be simpler as it is available in a compacted single file version.
- *
- * Included with DispHelper are over 20 samples that demonstrate using COM objects
- * including ADO, CDO, Outlook, Eudora, Excel, Word, Internet Explorer, MSHTML,
- * PocketSoap, Word Perfect, MS Agent, SAPI, MSXML, WIA, dexplorer and WMI.
- *
- * DispHelper is free open source software provided under the BSD license.
- *
- * Find out more and download DispHelper at:
- * http://sourceforge.net/projects/disphelper/
- * http://disphelper.sourceforge.net/
- */
-
-
-#ifndef DISPHELPER_H_INCLUDED
-#define DISPHELPER_H_INCLUDED
-
-#include <objbase.h>
-#include <time.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HRESULT dhCreateObject(LPCOLESTR szProgId, LPCWSTR szMachine, IDispatch ** ppDisp);
-HRESULT dhGetObject(LPCOLESTR szFile, LPCOLESTR szProgId, IDispatch ** ppDisp);
-
-HRESULT dhCreateObjectEx(LPCOLESTR szProgId, REFIID riid, DWORD dwClsContext, COSERVERINFO * pServerInfo, void ** ppv);
-HRESULT dhGetObjectEx(LPCOLESTR szFile, LPCOLESTR szProgId, REFIID riid, DWORD dwClsContext, LPVOID lpvReserved, void ** ppv);
-
-HRESULT dhCallMethod(IDispatch * pDisp, LPCOLESTR szMember, ...);
-HRESULT dhPutValue(IDispatch * pDisp, LPCOLESTR szMember, ...);
-HRESULT dhPutRef(IDispatch * pDisp, LPCOLESTR szMember, ...);
-HRESULT dhGetValue(LPCWSTR szIdentifier, void * pResult, IDispatch * pDisp, LPCOLESTR szMember, ...);
-
-HRESULT dhInvoke(int invokeType, VARTYPE returnType, VARIANT * pvResult, IDispatch * pDisp, LPCOLESTR szMember, ...);
-HRESULT dhInvokeArray(int invokeType, VARIANT * pvResult, UINT cArgs, IDispatch * pDisp, LPCOLESTR szMember, VARIANT * pArgs);
-
-HRESULT dhCallMethodV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker);
-HRESULT dhPutValueV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker);
-HRESULT dhPutRefV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker);
-HRESULT dhGetValueV(LPCWSTR szIdentifier, void * pResult, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker);
-HRESULT dhInvokeV(int invokeType, VARTYPE returnType, VARIANT * pvResult, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker);
-
-HRESULT dhAutoWrap(int invokeType, VARIANT * pvResult, IDispatch * pDisp, LPCOLESTR szMember, UINT cArgs, ...);
-HRESULT dhParseProperties(IDispatch * pDisp, LPCWSTR szProperties, UINT * lpcPropsSet);
-
-HRESULT dhEnumBegin(IEnumVARIANT ** ppEnum, IDispatch * pDisp, LPCOLESTR szMember, ...);
-HRESULT dhEnumBeginV(IEnumVARIANT ** ppEnum, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker);
-HRESULT dhEnumNextObject(IEnumVARIANT * pEnum, IDispatch ** ppDisp);
-HRESULT dhEnumNextVariant(IEnumVARIANT * pEnum, VARIANT * pvResult);
-
-HRESULT dhInitializeImp(BOOL bInitializeCOM, BOOL bUnicode);
-void dhUninitialize(BOOL bUninitializeCOM);
-
-#define dhInitializeA(bInitializeCOM) dhInitializeImp(bInitializeCOM, FALSE)
-#define dhInitializeW(bInitializeCOM) dhInitializeImp(bInitializeCOM, TRUE)
-
-#ifdef UNICODE
-#define dhInitialize dhInitializeW
-#else
-#define dhInitialize dhInitializeA
-#endif
-
-#define AutoWrap dhAutoWrap
-#define DISPATCH_OBJ(objName) IDispatch * objName = NULL
-#define dhFreeString(string) SysFreeString((BSTR) string)
-
-#ifndef SAFE_RELEASE
-#ifdef __cplusplus
-#define SAFE_RELEASE(pObj) { if (pObj) { (pObj)->Release(); (pObj) = NULL; } }
-#else
-#define SAFE_RELEASE(pObj) { if (pObj) { (pObj)->lpVtbl->Release(pObj); (pObj) = NULL; } }
-#endif
-#endif
-
-#define SAFE_FREE_STRING(string) { dhFreeString(string); (string) = NULL; }
-
-
-
-
-/* ===================================================================== */
-#ifndef DISPHELPER_NO_WITH
-
-#define WITH0(objName, pDisp, szMember) { \
-	DISPATCH_OBJ(objName);            \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember))) {
-
-#define WITH1(objName, pDisp, szMember, arg1) { \
-	DISPATCH_OBJ(objName);                  \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1))) {
-
-#define WITH2(objName, pDisp, szMember, arg1, arg2) { \
-	DISPATCH_OBJ(objName);                        \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2))) {
-
-#define WITH3(objName, pDisp, szMember, arg1, arg2, arg3) { \
-	DISPATCH_OBJ(objName);                              \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3))) {
-
-#define WITH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \
-	DISPATCH_OBJ(objName);                                    \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3, arg4))) {
-
-#define WITH WITH0
-
-#define ON_WITH_ERROR(objName) } else {
-
-#define END_WITH(objName) } SAFE_RELEASE(objName); }
-
-#endif /* ----- DISPHELPER_NO_WITH ----- */
-
-
-
-
-/* ===================================================================== */
-#ifndef DISPHELPER_NO_FOR_EACH
-
-#define FOR_EACH0(objName, pDisp, szMember) { \
-	IEnumVARIANT * xx_pEnum_xx = NULL;    \
-	DISPATCH_OBJ(objName);                \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember))) { \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#define FOR_EACH1(objName, pDisp, szMember, arg1) { \
-	IEnumVARIANT * xx_pEnum_xx = NULL;          \
-	DISPATCH_OBJ(objName);                      \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1))) { \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#define FOR_EACH2(objName, pDisp, szMember, arg1, arg2) { \
-	IEnumVARIANT * xx_pEnum_xx = NULL;          \
-	DISPATCH_OBJ(objName);                      \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2))) { \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-
-#define FOR_EACH3(objName, pDisp, szMember, arg1, arg2, arg3) { \
-	IEnumVARIANT * xx_pEnum_xx = NULL;          \
-	DISPATCH_OBJ(objName);                      \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3))) { \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-
-#define FOR_EACH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \
-	IEnumVARIANT * xx_pEnum_xx = NULL;          \
-	DISPATCH_OBJ(objName);                      \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3, arg4))) { \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#define FOR_EACH FOR_EACH0
-
-#define ON_FOR_EACH_ERROR(objName) SAFE_RELEASE(objName); }} else {{
-
-#define NEXT(objName) SAFE_RELEASE(objName); }} SAFE_RELEASE(objName); SAFE_RELEASE(xx_pEnum_xx); }
-
-#endif /* ----- DISPHELPER_NO_FOR_EACH ----- */
-
-
-
-
-/* ===================================================================== */
-#ifndef DISPHELPER_NO_EXCEPTIONS
-
-/* Structure to store a DispHelper exception */
-typedef struct tagDH_EXCEPTION
-{
-	LPCWSTR szInitialFunction;
-	LPCWSTR szErrorFunction;
-
-	HRESULT hr;
-
-	WCHAR szMember[64];
-	WCHAR szCompleteMember[256];
-
-	UINT swCode;
-	LPWSTR szDescription;
-	LPWSTR szSource;
-	LPWSTR szHelpFile;
-	DWORD dwHelpContext;
-
-	UINT iArgError;
-
-	BOOL bDispatchError;
-
-#ifdef DISPHELPER_INTERNAL_BUILD
-	BOOL bOld;
-#endif
-} DH_EXCEPTION, * PDH_EXCEPTION;
-
-typedef void (*DH_EXCEPTION_CALLBACK) (PDH_EXCEPTION);
-
-/* Structure to store exception options. */
-typedef struct tagDH_EXCEPTION_OPTIONS
-{
-	HWND hwnd;
-	LPCWSTR szAppName;
-	BOOL bShowExceptions;
-	BOOL bDisableRecordExceptions;
-	DH_EXCEPTION_CALLBACK pfnExceptionCallback;
-} DH_EXCEPTION_OPTIONS, * PDH_EXCEPTION_OPTIONS;
-
-/* Functions to manipulate global exception options */
-HRESULT dhToggleExceptions(BOOL bShow);
-HRESULT dhSetExceptionOptions(PDH_EXCEPTION_OPTIONS pExceptionOptions);
-HRESULT dhGetExceptionOptions(PDH_EXCEPTION_OPTIONS pExceptionOptions);
-
-/* Functions to show an exception, format an exception into a string
- * and get a copy of the last exception */
-HRESULT dhShowException(PDH_EXCEPTION pException);
-HRESULT dhGetLastException(PDH_EXCEPTION * pException);
-HRESULT dhFormatExceptionW(PDH_EXCEPTION pException, LPWSTR szBuffer, UINT cchBufferSize, BOOL bFixedFont);
-HRESULT dhFormatExceptionA(PDH_EXCEPTION pException, LPSTR szBuffer, UINT cchBufferSize, BOOL bFixedFont);
-
-#ifdef UNICODE
-#define dhFormatException dhFormatExceptionW
-#else
-#define dhFormatException dhFormatExceptionA
-#endif
-
-#ifdef DISPHELPER_INTERNAL_BUILD
-
-void dhEnter(void);
-HRESULT dhExitEx(HRESULT hr, BOOL bDispatchError, LPCWSTR szMember, LPCWSTR szCompleteMember, EXCEPINFO * pExcepInfo, UINT iArgError, LPCWSTR szFunctionName);
-void dhCleanupThreadException(void);
-
-#define DH_ENTER(szFunctionName) static LPCWSTR xx_szFunctionName_xx = szFunctionName; \
-				    dhEnter()
-
-#define DH_EXITEX(hr, bDispatchError, szMember, szCompleteMember, pExcepInfo, iArgError) \
-		dhExitEx(hr, bDispatchError, szMember, szCompleteMember, pExcepInfo, iArgError, xx_szFunctionName_xx)
-
-#define DH_EXIT(hr, szCompleteMember) DH_EXITEX(hr, FALSE, NULL, szCompleteMember, NULL, 0)
-
-#endif /* ----- DISPHELPER_INTERNAL_BUILD ----- */
-
-#else  /* ----- DISPHELPER_NO_EXCEPTIONS ----- */
-
-/* These macros define out calls to selected exception functions */
-#define dhToggleExceptions(bShow) (E_NOTIMPL)
-#define dhSetExceptionOptions(pExcepOptions) (E_NOTIMPL)
-
-#ifdef DISPHELPER_INTERNAL_BUILD
-#define DH_ENTER(szFunctionName)
-#define DH_EXITEX(hr, bDispatchError, szMember, szCompleteMember, pExcepInfo, iArgError) \
-	(((hr == DISP_E_EXCEPTION && pExcepInfo) ?                      \
-	(SysFreeString(((EXCEPINFO *)(pExcepInfo))->bstrSource),        \
-	 SysFreeString(((EXCEPINFO *)(pExcepInfo))->bstrDescription),   \
-	 SysFreeString(((EXCEPINFO *)(pExcepInfo))->bstrHelpFile), 0) : (0)), hr)
-#define DH_EXIT(hr, szCompleteMember)(hr)
-#endif
-
-#endif /* ----- DISPHELPER_NO_EXCEPTIONS ----- */
-
-
-
-
-
-
-/* ===================================================================== */
-#ifdef DISPHELPER_INTERNAL_BUILD
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <wchar.h>
-
-/* Macro to include or lose debug code. */
-#ifdef DEBUG
-#define DBG_CODE(code) code
-#else
-#define DBG_CODE(code)
-#endif
-
-/* Are we in unicode mode? */
-extern BOOL dh_g_bIsUnicodeMode;
-
-/* Number of objects in an array */
-#undef ARRAYSIZE
-#define ARRAYSIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-/* Maximum number of arguments for a member */
-#define DH_MAX_ARGS 25
-
-/* Maximum length of a member string */
-#define DH_MAX_MEMBER 512
-
-/* This macro is missing from Dev-Cpp/Mingw */
-#ifndef V_UI4
-#define V_UI4(X) V_UNION(X, ulVal)
-#endif
-
-/* Macro to notify programmer of invalid identifier in debug mode. */
-#define DEBUG_NOTIFY_INVALID_IDENTIFIER(chIdentifier) \
-DBG_CODE( { \
-		char buf[256]; \
-		sprintf(buf,"DEBUG: The format string or return identifier contained the invalid identifier '%c'.\n" \
-		"The valid identifiers are \"d/u/e/b/v/B/S/s/T/o/O/t/W/D/f/m\".\n" \
-		"Each %% character should be followed by a valid identifier.\n" \
-		"Identifiers are case sensitive.", (chIdentifier)); \
-		MessageBoxA(NULL, buf, "DEBUG: Invalid Format Identifier", MB_ICONSTOP); \
-	} )
-
-#ifdef _MSC_VER
-#pragma warning(disable : 4706) /* Assignment in conditional expression */
-#endif
-
-#ifndef DISPHELPER_NO_PRAGMA_LIB
-#ifdef __LCC__
-#pragma lib <ole32.lib>
-#pragma lib <oleaut32.lib>
-#pragma lib <uuid.lib>
-#endif
-#endif
-
-
-#endif /* ----- DISPHELPER_INTERNAL_BUILD ----- */
-
-#ifndef DISPHELPER_NO_PRAGMA_LIB
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-#pragma comment(lib, "ole32.lib")
-#pragma comment(lib, "oleaut32.lib")
-#pragma comment(lib, "uuid.lib")
-#endif
-#endif
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-
-
-/* ===================================================================== */
-#if defined(__cplusplus) && !defined(DISPHELPER_NO_CPP_EXTENSIONS)
-
-#include <iostream>
-#include <string>
-
-#ifdef _MSC_VER
-#pragma warning( disable : 4290 ) /* throw() specification ignored */
-#endif
-
-#ifndef DISPHELPER_USE_MS_SMART_PTR
-
-template <class T>
-class CDhComPtr
-{
-public:
-	CDhComPtr() throw() : m_pInterface (NULL) {}
-
-	CDhComPtr(T* pInterface) throw() : m_pInterface (pInterface)
-	{
-		if (m_pInterface) m_pInterface->AddRef();
-	}
-
-	CDhComPtr(const CDhComPtr& original) throw() : m_pInterface (original.m_pInterface)
-	{
-		if (m_pInterface) m_pInterface->AddRef();
-	}
-
-	~CDhComPtr() throw()
-	{
-		Dispose();
-	}
-
-	void Dispose() throw()
-	{
-		if (m_pInterface)
-		{
-			m_pInterface->Release();
-			m_pInterface = NULL;
-		}
-	}
-
-	T* Detach() throw()
-	{
-		T* temp = m_pInterface;
-		m_pInterface = NULL;
-		return temp;
-	}
-
-	inline operator T*() const throw()
-	{
-        	return m_pInterface;
-	}
-
-	T** operator&() throw()
-	{
-		Dispose();
-        	return &m_pInterface;
-	}
-
-	T* operator->() const throw(HRESULT)
-	{
-		if (!m_pInterface) throw E_POINTER;
-		return m_pInterface;
-	}
-
-	CDhComPtr& operator=(T* pInterface) throw()
-	{
-		if (m_pInterface != pInterface)
-		{
-			T* pOldInterface = m_pInterface;
-			m_pInterface = pInterface;
-			if (m_pInterface)  m_pInterface->AddRef();
-			if (pOldInterface) pOldInterface->Release();
-		}
-
-		return *this;
-	}
-
-	CDhComPtr& operator=(const int null) throw(HRESULT)
-	{
-		if (null != 0) throw(E_POINTER);
-		return operator=((T*) NULL);
-	}
-
-	CDhComPtr& operator=(const CDhComPtr& rhs) throw()
-	{
-		return operator=(rhs.m_pInterface);
-	}
-
-private:
-	T* m_pInterface;
-};
-
-typedef CDhComPtr<IDispatch>    CDispPtr;
-typedef CDhComPtr<IEnumVARIANT> CEnumPtr;
-typedef CDhComPtr<IUnknown>     CUnknownPtr;
-
-#else /* DISPHELPER_USE_MS_SMART_PTR */
-
-#include <comdef.h> 
-typedef IDispatchPtr    CDispPtr;
-typedef IEnumVARIANTPtr CEnumPtr;
-typedef IUnknownPtr     CUnknownPtr;
-
-#endif /* DISPHELPER_USE_MS_SMART_PTR */
-
-
-
-
-/* ===================================================================== */
-template <class T>
-class CDhStringTemplate
-{
-public:
-	CDhStringTemplate() throw() : m_strptr (NULL) {}
-
-	CDhStringTemplate(const CDhStringTemplate& original) throw()
-	{
-		Copy(original.m_strptr);
-	}
-
-	CDhStringTemplate(const int null) throw(HRESULT) : m_strptr (NULL)
-	{
-		if (null != 0) throw(E_POINTER);
-	}
-
-	~CDhStringTemplate() throw()
-	{
-		Dispose();
-	}
-
-	void Dispose() throw()
-	{
-		dhFreeString(m_strptr);
-		m_strptr = NULL;
-	}
-
-	T* Detach() throw()
-	{
-		T* temp = m_strptr;
-		m_strptr = NULL;
-		return temp;
-	}
-
-	T** operator&() throw()
-	{
-		Dispose();
-		return &m_strptr;
-	}
-
-	inline operator T*() const throw()
-	{
-		return m_strptr;
-	}
-
-	inline T& operator[](int nIndex) const throw()
-	{
-		return m_strptr[nIndex];
-	}
-
-	CDhStringTemplate& operator=(const CDhStringTemplate& rhs)
-	{
-		if (m_strptr != rhs.m_strptr)
-		{
-			T* temp = m_strptr;
-			Copy(rhs.m_strptr);
-			dhFreeString(temp);
-		}
-
-		return *this;
-	}
-
-	CDhStringTemplate& operator=(const int null) throw(HRESULT)
-	{
-		if (null != 0) throw(E_POINTER);
-		Dispose();
-		return *this;
-	}
-
-private:
-	void Copy(const T* rhs)
-	{
-		if (rhs == NULL)
-		{
-			m_strptr = NULL;
-		}
-		else if (sizeof(T) == sizeof(CHAR))
-		{
-			m_strptr = (T*) SysAllocStringByteLen((LPCSTR) rhs, SysStringByteLen((BSTR) rhs));
-		}
-		else
-		{
-			m_strptr = (T*) SysAllocStringLen((OLECHAR *) rhs, SysStringLen((BSTR) rhs));
-		}
-	}
-
-	T* m_strptr;
-};
-
-typedef CDhStringTemplate<CHAR>    CDhStringA;  /* Ansi string - LPSTR */
-typedef CDhStringTemplate<WCHAR>   CDhStringW;  /* Unicode string - LPWSTR */
-typedef CDhStringTemplate<OLECHAR> CDhStringB;  /* Unicode bstring - BSTR */
-typedef CDhStringTemplate<TCHAR>   CDhStringT;  /* T string - LPTSTR */
-typedef CDhStringTemplate<TCHAR>   CDhString;   /* T string - LPTSTR */
-
-inline std::ostream& operator<<(std::ostream& os, const CDhStringA& s)
-{
-	return os << (s ? s : (char*) "(null)");
-}
-
-inline std::wostream& operator<<(std::wostream& os, const CDhStringW& s)
-{
-	return os << (s ? s : (wchar_t*) L"(null)");
-}
-
-
-
-
-/* ===================================================================== */
-class CDhInitialize
-{
-public:
-	CDhInitialize(const BOOL bInitCom = TRUE) throw() : m_bInitCom (bInitCom)
-	{
-		dhInitialize(m_bInitCom);
-	}
-
-	~CDhInitialize() throw()
-	{
-		dhUninitialize(m_bInitCom);
-	}
-private:
-	BOOL m_bInitCom;
-};
-
-
-
-
-/* ===================================================================== */
-#ifndef DISPHELPER_NO_EXCEPTIONS
-class dhThrowFunctions
-{
-public:
-	static void throw_string() throw(std::string)
-	{
-		CHAR szMessage[512];
-		dhFormatExceptionA(NULL, szMessage, sizeof(szMessage)/sizeof(szMessage[0]), TRUE);
-		throw std::string(szMessage);
-	}
-
-	static void throw_wstring() throw(std::wstring)
-	{
-		WCHAR szMessage[512];
-		dhFormatExceptionW(NULL, szMessage, sizeof(szMessage)/sizeof(szMessage[0]), TRUE);
-		throw std::wstring(szMessage);
-	}
-	
-	static void throw_dhexception() throw(PDH_EXCEPTION)
-	{
-		PDH_EXCEPTION pException = NULL;
-		dhGetLastException(&pException);
-		throw pException;
-	}
-};
-#endif /* DISPHELPER_NO_EXCEPTIONS */
-
-
-
-
-/* ===================================================================== */
-#ifndef DISPHELPER_NO_EXCEPTIONS
-inline bool dhIfFailThrowString(HRESULT hr) throw(std::string)
-{
-	if (FAILED(hr)) dhThrowFunctions::throw_string();
-	return true;
-}
-
-inline bool dhIfFailThrowWString(HRESULT hr) throw(std::wstring)
-{
-	if (FAILED(hr)) dhThrowFunctions::throw_wstring();
-	return true;
-}
-
-inline bool dhIfFailThrowDhException(HRESULT hr) throw(PDH_EXCEPTION)
-{
-	if (FAILED(hr)) dhThrowFunctions::throw_dhexception();
-	return true;
-}
-
-#define dhCheck dhIfFailThrowString
-
-#endif /* DISPHELPER_NO_EXCEPTIONS */
-
-
-
-
-/* ===================================================================== */
-#ifndef DISPHELPER_NO_WITH
-
-#undef WITH0
-#define WITH0(objName, pDisp, szMember) { \
-	CDispPtr objName;                 \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember))) {
-
-#undef WITH1
-#define WITH1(objName, pDisp, szMember, arg1) { \
-	CDispPtr objName;                       \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1))) {
-
-#undef WITH2
-#define WITH2(objName, pDisp, szMember, arg1, arg2) { \
-	CDispPtr objName;                             \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2))) {
-
-#undef WITH3
-#define WITH3(objName, pDisp, szMember, arg1, arg2, arg3) { \
-	CDispPtr objName;                                   \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3))) {
-
-#undef WITH4
-#define WITH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \
-	CDispPtr objName;                                         \
-	if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3, arg4))) {
-
-#undef ON_WITH_ERROR
-#define ON_WITH_ERROR(objName) } else {
-
-#undef END_WITH
-#define END_WITH(objName) }}
-
-#define END_WITH_THROW(objName) } else { dhThrowFunctions::throw_string(); }}
-
-#endif /* DISPHELPER_NO_WITH */
-
-
-
-
-/* ===================================================================== */
-#ifndef DISPHELPER_NO_FOR_EACH
-
-#undef FOR_EACH0
-#define FOR_EACH0(objName, pDisp, szMember) { \
-	CEnumPtr xx_pEnum_xx;     \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember))) { \
-		CDispPtr objName; \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#undef FOR_EACH1
-#define FOR_EACH1(objName, pDisp, szMember, arg1) { \
-	CEnumPtr xx_pEnum_xx;     \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1))) { \
-		CDispPtr objName; \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#undef FOR_EACH2
-#define FOR_EACH2(objName, pDisp, szMember, arg1, arg2) { \
-	CEnumPtr xx_pEnum_xx;     \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2))) { \
-		CDispPtr objName; \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#undef FOR_EACH3
-#define FOR_EACH3(objName, pDisp, szMember, arg1, arg2, arg3) { \
-	CEnumPtr xx_pEnum_xx;     \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3))) { \
-		CDispPtr objName; \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#undef FOR_EACH4
-#define FOR_EACH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \
-	CEnumPtr xx_pEnum_xx;     \
-	if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3, arg4))) { \
-		CDispPtr objName; \
-		while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) {
-
-#undef ON_FOR_EACH_ERROR
-#define ON_FOR_EACH_ERROR(objName) }} else {{
-
-#undef NEXT
-#define NEXT(objName) }}}
-
-#define NEXT_THROW(objName) }} else { dhThrowFunctions::throw_string(); }}
-
-#endif /* DISPHELPER_NO_FOR_EACH */
-
-#ifdef _MSC_VER
-#pragma warning( default : 4290 )
-#endif
-
-#endif /* defined(__cplusplus) && !defined(DISPHELPER_NO_CPP_EXTENSIONS) */
-
-#endif /* ----- DISPHELPER_H_INCLUDED ----- */
diff --git a/input_devices/mag/node_modules/serialport/src/win/enumser.cpp b/input_devices/mag/node_modules/serialport/src/win/enumser.cpp
deleted file mode 100644
index cde5ef03..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/enumser.cpp
+++ /dev/null
@@ -1,1186 +0,0 @@
-/*
-Module : enumser.cpp
-Purpose: Implementation for a class to enumerate the serial ports installed on a PC using a number
-         of different approaches. 
-Created: PJN / 03-10-1998
-History: PJN / 23-02-1999 Code now uses QueryDosDevice if running on NT to determine 
-                          which serial ports are available. This avoids having to open 
-                          the ports at all. It should operate a lot faster in addition.
-         PJN / 12-12-1999 Fixed a problem in the Win9x code path when trying to detect 
-                          deactivated IRDA-ports. When trying to open those, you will 
-                          get the error-code ERROR_GEN_FAILURE.�
-         PJN / 17-05-2000 Code now uses GetDefaultCommConfig in all cases to detect 
-                          the ports.
-         PJN / 29-03-2001 1. Reverted code to use CreateFile or QueryDosDevice as it is 
-                          much faster than using the GetDefaultCommConfig method
-                          2. Updated copyright message
-         PJN / 25-06-2001 1. Guess what, You now have the choice of using the GetDefaultCommConfig
-                          thro the use of three versions of the function. You take your pick.
-                          2. Fixed problem where port fails to be reported thro the CreateFile
-                          mechanism when the error code is ERROR_SHARING_VIOLATION i.e. someone
-                          has the port already open
-         PJN / 11-08-2001 1. Made code path which uses QueryDosDevice more robust by checking to 
-                          make sure the device name is of the form "COMxyz.." where xyz are numeric
-         PJN / 13-08-2001 1. Made the code in IsNumeric more robust when sent an empty string
-                          2. Optimized the code in EnumerateSerialPorts2 somewhat. Thanks to Dennis 
-                          Lim for these suggestions.
-         PJN / 22-05-2003 1. Updated copyright details.
-                          2. Addition of a "EnumerateSerialPorts4" which uses Device Manager API
-         PJN / 20-09-2003 1. Addition of a "EnumerateSerialPorts5" method. This method (hopefully
-                          the last method!) uses EnumPorts and was provided by Andi Martin.
-         PJN / 12-12-2003 1. Updated the sample app to VC 6.
-                          2. Addition of a "EnumerateSerialPorts6" (See Note 4 below) which uses WMI.
-                          3. You can now optionally exclude each function using preprocessor defines
-                          of the form "NO_ENUMSERIAL_USING_XYX".
-                          4. Made the functions members of a C++ class and renamed them to 
-                          use more meaningful names
-         PJN / 13-05-2004 1. Extended CEnumerateSerial::UsingSetupAPI to now also return the friendly
-                          name of the port. Thanks to Jay C. Howard for prompting this update.
-         PJN / 08-07-2006 1. Updated copyright details.
-                          2. Addition of a CENUMERATESERIAL_EXT_CLASS macro to allow the code to be 
-                          easily added to an extension dll.
-                          3. Code now uses newer C++ style casts instead of C style casts.
-                          4. Updated the code to clean compile on VC 2005.
-                          5. Updated the documentation to use the same style as the web site.
-         PJN / 08-11-2006 1. Extended CEnumerateSerial::UsingWMI to now also return the friendly
-                          name of the port. Thanks to Giovanni Bajo for providing this update.
-                          2. Fixed a bug where CEnumerateSerial::UsingSetupAPI forget to empty out 
-                          the Friendly name array on start.
-                          3. VariantInit is now called for the 2 VARIANT structs used in the UsingWMI
-                          method code.
-         PJN / 29-01-2007 1. Updated copyright details.
-                          2. UsingSetupAPI code now uses the GUID_DEVINTERFACE_COMPORT guid to enumerate
-                          COM ports. Thanks to David McMinn for reporting this nice addition.
-                          3. Detection code which uses CreateFile call, now treats the error code
-                          of ERROR_SEM_TIMEOUT as indication that a port is present.
-         PJN / 09-06-2007 1. Following feedback from John Miles, it looks like my previous change of the
-                          29 January 2007 to use GUID_DEVINTERFACE_COMPORT in the UsingSetupAPI method 
-                          had the unintended consequence of causing this method not to work on any 
-                          versions of Windows prior to Windows 2000. What I have now done is reinstate 
-                          the old mechanism using the name UsingSetupAPI2 so that you can continue to use 
-                          this approach if you need to support NT 4 and Windows 9x. The new approach of 
-                          using GUID_DEVINTERFACE_COMPORT has been renamed to UsingSetupAPI1.
-         PJN / 05-07-2007 1. Updated the code to work if the code does not include MFC. In this case, 
-                          CUIntArray parameters becomes the ATL class CSimpleArray<UINT> and CStringArray
-                          parameters become the ATL class CSimpleArray<CString>. Please note that this
-                          support requires a recentish copy of Visual Studio and will not support Visual
-                          C++ 6.0 as the code makes use of the ATL CString class. Thanks to Michael Venus
-                          for prompting this update.
-                          2. CEnumerateSerial::UsingWMI method now uses ATL smart pointers to improve
-                          robustness of the code.
-         PJN / 20-03-2008 1. Updated copyright details
-                          2. Updates to preprocessor logic to correctly include UsingSetupAPI1 and
-                          UsingSetupAPI2 functionality
-                          3. Updated sample app to clean compile on VC 2008
-         PJN / 23-11-2008 1. Updated code to compile correctly using _ATL_CSTRING_EXPLICIT_CONSTRUCTORS define
-                          2. The code now only supports VC 2005 or later. 
-                          3. Code now compiles cleanly using Code Analysis (/analyze)
-                          4. Yes, Addition of another method called "UsingComDB" to enumerate serial ports!. 
-                          This function uses the so called "COM Database" functions which are part of the 
-                          Windows DDK which device drivers can use to support claiming an unused port number 
-                          when the device driver is being installed. Please note that the list returning from 
-                          this function will only report used port numbers. The device may or may not be 
-                          actually present, just that the associated port number is currently "claimed". 
-                          Thanks to Dmitry Nikitin for prompting this very nice addition. The code now 
-                          supports a total of 8 different ways to enumerate serial ports!
-         PJN / 29-11-2008 1. Addition of a ninth and hopefully final method to enumerate serial ports. The
-                          function is called "UsingRegistry" and enumerates the ports by examining the 
-                          registry location at HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM. Thanks to
-                          Martin Oberhuber for prompting this update.
-                          2. Fixed a bug where the last error value was not being preserved in 
-                          CEnumerateSerial::UsingComDB.
-         PJN / 30-04-2009 1. Updated copyright details.
-                          2. Updated the sample app's project settings to more modern default values.
-                          3. Updated the sample app to log the time taken for the various methods.
-         PJN / 27-03-2010 1. Updated copyright details.
-                          2. Code can now optionally use STL instead of MFC or ATL in the API. To use STL 
-                          containers instead of MFC or ATL versions, please define CENUMERATESERIAL_USE_STL before 
-                          you include enumser in your project. Please note that the code still internally uses ATL
-                          in the UsingWMI method, but the other functions do not. This means that the class should
-                          now be partly compilable on VC Express (2005, 2008 or 2010) as none of these have support 
-                          for ATL or MFC. I do not personally have VC Express installed so people's feedback on 
-                          this would be appreciated. Thanks to Bill Adair for providing this update. 
-         PJN / 28-03-2011 1. Updated copyright details.
-                          2. Updated the UsingComDB method to fix an off by one issue. This resulting in the list of 
-                          ports this function reported being incorrect. Thanks to "Jar, Min, Jeong" for reporting 
-                          this issue.
-                          3. Updated sample app to compile cleanly on VC 2010
-         PJN / 14-10-2012 1. Updated copyright details.
-                          2. Code no longer uses LoadLibrary without an absolute path when loading SETUPAPI and 
-                          MSPORTS dlls. This avoids DLL planting security issues.
-                          3. Added a new internal CAutoHandle and CAutoHModule classes which makes the implementation 
-                          for CEnumerateSerial simpler
-                          4. Code now uses an internal RegQueryValueString method to ensure that data returned
-                          from raw Win32 API call RegQueryValueEx is null terminated before it is treated as such
-                          in the code. Thanks to Jeffrey Walton for reporting this security issue.
-                          5. Updated the code to clean compile on VC 2012
-         PJN / 10-01-2013 1. Updated copyright details
-                          2. Spun off CAutoHModule class into its own header file
-                          3. Spun off CAutoHandle class into its own header file
-                          4. Addition of a new CAutoHeapAlloc class which encapsulates HeapAlloc / HeapFree calls
-                          in a C++ class.
-                          5. Removed ATL usage completely from UsingQueryDevice, UsingSetupAPI2 and UsingEnumPorts.
-                          This should allow these methods to support compilers which do not have support for ATL such
-                          as VC Express SKUs.
-          PJN /28-07-2013 1. Did some very light cleanup of the code to reduce dependencies when #defining out parts of 
-                          the code. Thanks to Jay Beavers for providing this update.
-         
-Copyright (c) 1998 - 2013 by PJ Naughter (Web: www.naughter.com, Email: pjna@naughter.com)
-
-All rights reserved.
-
-Copyright / Usage Details:
-
-You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
-when your product is released in binary form. You are allowed to modify the source code in any way you want 
-except you cannot modify the copyright details at the top of each module. If you want to distribute source 
-code with your application, then you are only allowed to distribute versions released by the author. This is 
-to maintain a single distribution point for the source code. 
-
-*/
-
-
-/////////////////////////////////  Includes  //////////////////////////////////
-
-#include "stdafx.h"
-#include "enumser.h"
-#include "AutoHModule.h"
-#include "AutoHandle.h"
-#include "AutoHeapAlloc.h"
-
-#ifndef NO_ENUMSERIAL_USING_WMI
-#ifndef __ATLBASE_H__
-  #include <atlbase.h>
-  #pragma message("To avoid this message, please put atlbase.h in your pre compiled header (normally stdafx.h)")
-#endif
-#endif
-
-
-/////////////////////////////// Macros / Defines //////////////////////////////
-
-#if !defined(NO_ENUMSERIAL_USING_SETUPAPI1) || !defined(NO_ENUMSERIAL_USING_SETUPAPI2)
-  #ifndef _INC_SETUPAPI
-    #pragma message("To avoid this message, please put setupapi.h in your pre compiled header (normally stdafx.h)")
-    #include <setupapi.h>
-  #endif
-
-  #ifndef GUID_DEVINTERFACE_COMPORT
-    DEFINE_GUID(GUID_DEVINTERFACE_COMPORT, 0x86E0D1E0L, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73);
-  #endif
-  
-  typedef HKEY (__stdcall SETUPDIOPENDEVREGKEY)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM);
-  typedef BOOL (__stdcall SETUPDICLASSGUIDSFROMNAME)(LPCTSTR, LPGUID, DWORD, PDWORD);
-  typedef BOOL (__stdcall SETUPDIDESTROYDEVICEINFOLIST)(HDEVINFO);
-  typedef BOOL (__stdcall SETUPDIENUMDEVICEINFO)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
-  typedef HDEVINFO (__stdcall SETUPDIGETCLASSDEVS)(LPGUID, LPCTSTR, HWND, DWORD);
-  typedef BOOL (__stdcall SETUPDIGETDEVICEREGISTRYPROPERTY)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
-#endif  
-
-#ifndef NO_ENUMSERIAL_USING_ENUMPORTS
-  #ifndef _WINSPOOL_
-  #pragma message("To avoid this message, please put winspool.h in your pre compiled header (normally stdafx.h)")
-  #include <winspool.h>
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_WMI
-  #ifndef __IWbemLocator_FWD_DEFINED__
-  #pragma message("To avoid this message, please put WBemCli.h in your pre compiled header (normally stdafx.h)")
-  #include <WbemCli.h>
-  #endif
-  
-  #ifndef _INC_COMDEF
-  #pragma message("To avoid this message, please put comdef.h in your pre compiled header (normally stdafx.h)")
-  #include <comdef.h>
-  #endif
-
-  #ifndef __ATLBASE_H__
-  #pragma message("EnumSerialPorts as of v1.16 requires ATL support to implement its functionality. If your project is MFC only, then you need to update it to include ATL support")
-  #endif
-  
-  //Automatically pull in the library WbemUuid.Lib since we need the WBem Guids
-  #pragma comment(lib, "WbemUuid.Lib")
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_COMDB
-  #ifndef HCOMDB
-    DECLARE_HANDLE(HCOMDB);
-    typedef HCOMDB *PHCOMDB;
-  #endif
-  
-  #ifndef CDB_REPORT_BYTES
-    #define CDB_REPORT_BYTES 0x1  
-  #endif
-  
-  typedef LONG (__stdcall COMDBOPEN)(PHCOMDB);
-  typedef LONG (__stdcall COMDBCLOSE)(HCOMDB);
-  typedef LONG (__stdcall COMDBGETCURRENTPORTUSAGE)(HCOMDB, PBYTE, DWORD, ULONG, LPDWORD);
-#endif
-
-
-///////////////////////////// Implementation //////////////////////////////////
-
-#ifndef NO_ENUMSERIAL_USING_CREATEFILE
-#if defined CENUMERATESERIAL_USE_STL
-BOOL CEnumerateSerial::UsingCreateFile(std::vector<UINT>& ports)
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingCreateFile(CUIntArray& ports)
-#else
-BOOL CEnumerateSerial::UsingCreateFile(CSimpleArray<UINT>& ports)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-#else
-  ports.RemoveAll();
-#endif  
-
-  //Up to 255 COM ports are supported so we iterate through all of them seeing
-  //if we can open them or if we fail to open them, get an access denied or general error error.
-  //Both of these cases indicate that there is a COM port at that number. 
-  for (UINT i=1; i<256; i++)
-  {
-    //Form the Raw device name
-    CString sPort;
-    sPort.Format(_T("\\\\.\\COM%u"), i);
-
-    //Try to open the port
-    BOOL bSuccess = FALSE;
-    CAutoHandle port(CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0));
-    if (port == INVALID_HANDLE_VALUE)
-    {
-      DWORD dwError = GetLastError();
-
-      //Check to see if the error was because some other app had the port open or a general failure
-      if (dwError == ERROR_ACCESS_DENIED || dwError == ERROR_GEN_FAILURE || dwError == ERROR_SHARING_VIOLATION || dwError == ERROR_SEM_TIMEOUT)
-        bSuccess = TRUE;
-    }
-    else
-    {
-      //The port was opened successfully
-      bSuccess = TRUE;
-    }
-
-    //Add the port number to the array which will be returned
-    if (bSuccess)
-    {
-    #if defined CENUMERATESERIAL_USE_STL
-      ports.push_back(i);
-    #else
-      ports.Add(i);
-    #endif  
-    }
-  }
-
-  //Return the success indicator
-  return TRUE;
-}
-#endif
-
-#if !defined(NO_ENUMSERIAL_USING_SETUPAPI1) || !defined(NO_ENUMSERIAL_USING_SETUPAPI2) || !defined(NO_ENUMSERIAL_USING_COMDB)
-HMODULE CEnumerateSerial::LoadLibraryFromSystem32(LPCTSTR lpFileName)
-{
-  //Get the Windows System32 directory
-  TCHAR szFullPath[_MAX_PATH];
-  szFullPath[0] = _T('\0');
-  if (GetSystemDirectory(szFullPath, _countof(szFullPath)) == 0)
-    return NULL;
-
-  //Setup the full path and delegate to LoadLibrary    
-  _tcscat_s(szFullPath, _countof(szFullPath), _T("\\"));
-  _tcscat_s(szFullPath, _countof(szFullPath), lpFileName);
-  return LoadLibrary(szFullPath);
-}
-#endif
-
-#if !defined(NO_ENUMSERIAL_USING_SETUPAPI1) || !defined(NO_ENUMSERIAL_USING_SETUPAPI2)
-BOOL CEnumerateSerial::RegQueryValueString(HKEY kKey, LPCTSTR lpValueName, LPTSTR& pszValue)
-{
-  //Initialize the output parameter
-  pszValue = NULL;
-
-  //First query for the size of the registry value 
-  DWORD dwType = 0;
-  DWORD dwDataSize = 0;
-  LONG nError = RegQueryValueEx(kKey, lpValueName, NULL, &dwType, NULL, &dwDataSize);
-  if (nError != ERROR_SUCCESS)
-  {
-    SetLastError(nError);
-    return FALSE;
-  }
-
-  //Ensure the value is a string
-  if (dwType != REG_SZ)
-  {
-    SetLastError(ERROR_INVALID_DATA);
-    return FALSE;
-  }
-
-  //Allocate enough bytes for the return value
-  DWORD dwAllocatedSize = dwDataSize + sizeof(TCHAR); //+sizeof(TCHAR) is to allow us to NULL terminate the data if it is not null terminated in the registry
-  pszValue = reinterpret_cast<LPTSTR>(LocalAlloc(LMEM_FIXED, dwAllocatedSize)); 
-  if (pszValue == NULL)
-    return FALSE;
-
-  //Recall RegQueryValueEx to return the data
-  pszValue[0] = _T('\0');
-  DWORD dwReturnedSize = dwAllocatedSize;
-  nError = RegQueryValueEx(kKey, lpValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pszValue), &dwReturnedSize);
-  if (nError != ERROR_SUCCESS)
-  {
-    LocalFree(pszValue);
-    pszValue = NULL;
-    SetLastError(nError);
-    return FALSE;
-  }
-
-  //Handle the case where the data just returned is the same size as the allocated size. This could occur where the data
-  //has been updated in the registry with a non null terminator between the two calls to ReqQueryValueEx above. Rather than
-  //return a potentially non-null terminated block of data, just fail the method call
-  if (dwReturnedSize >= dwAllocatedSize)
-  {
-    SetLastError(ERROR_INVALID_DATA);
-    return FALSE;
-  }
-
-  //NULL terminate the data if it was not returned NULL terminated because it is not stored null terminated in the registry
-  if (pszValue[dwReturnedSize/sizeof(TCHAR) - 1] != _T('\0'))
-    pszValue[dwReturnedSize/sizeof(TCHAR)] = _T('\0');
-
-  return TRUE;
-}
-
-BOOL CEnumerateSerial::QueryRegistryPortName(HKEY hDeviceKey, int& nPort)
-{
-  //What will be the return value from the method (assume the worst)
-  BOOL bAdded = FALSE;
-
-  //Read in the name of the port
-  LPTSTR pszPortName = NULL;
-  if (RegQueryValueString(hDeviceKey, _T("PortName"), pszPortName))
-  {
-    //If it looks like "COMX" then
-    //add it to the array which will be returned
-    size_t nLen = _tcslen(pszPortName);
-    if (nLen > 3)
-    {
-      if ((_tcsnicmp(pszPortName, _T("COM"), 3) == 0) && IsNumeric((pszPortName + 3), FALSE))
-      {
-        //Work out the port number
-        nPort = _ttoi(pszPortName + 3);
-
-        bAdded = TRUE;
-      }
-    }
-    LocalFree(pszPortName);
-  }
-
-  return bAdded;
-}
-#endif //#if !defined(NO_ENUMSERIAL_USING_SETUPAPI1) || !defined(NO_ENUMSERIAL_USING_SETUPAPI2)
-
-BOOL CEnumerateSerial::IsNumeric(LPCSTR pszString, BOOL bIgnoreColon)
-{
-  size_t nLen = strlen(pszString);
-  if (nLen == 0)
-    return FALSE;
-
-  //What will be the return value from this function (assume the best)
-  BOOL bNumeric = TRUE;
-
-  for (size_t i=0; i<nLen && bNumeric; i++)
-  {
-    bNumeric = (isdigit(static_cast<int>(pszString[i])) != 0);
-    if (bIgnoreColon && (pszString[i] == ':'))
-      bNumeric = TRUE;
-  }
-
-  return bNumeric;
-}
-
-BOOL CEnumerateSerial::IsNumeric(LPCWSTR pszString, BOOL bIgnoreColon)
-{
-  size_t nLen = wcslen(pszString);
-  if (nLen == 0)
-    return FALSE;
-
-  //What will be the return value from this function (assume the best)
-  BOOL bNumeric = TRUE;
-
-  for (size_t i=0; i<nLen && bNumeric; i++)
-  {
-    bNumeric = (iswdigit(pszString[i]) != 0);
-    if (bIgnoreColon && (pszString[i] == L':'))
-      bNumeric = TRUE;
-  }
-
-  return bNumeric;
-}
-
-#ifndef NO_ENUMSERIAL_USING_QUERYDOSDEVICE
-#if defined CENUMERATESERIAL_USE_STL
-BOOL CEnumerateSerial::UsingQueryDosDevice(std::vector<UINT>& ports)
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingQueryDosDevice(CUIntArray& ports)
-#else
-BOOL CEnumerateSerial::UsingQueryDosDevice(CSimpleArray<UINT>& ports)
-#endif
-{
-  //What will be the return value from this function (assume the worst)
-  BOOL bSuccess = FALSE;
-
-  //Make sure we clear out any elements which may already be in the array
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-#else
-  ports.RemoveAll();
-#endif  
-
-  //Determine what OS we are running on
-  OSVERSIONINFO osvi;
-  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-  BOOL bGetVer = GetVersionEx(&osvi);
-
-  //On NT use the QueryDosDevice API
-  if (bGetVer && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT))
-  {
-    //Use QueryDosDevice to look for all devices of the form COMx. Since QueryDosDevice does
-    //not consitently report the required size of buffer, lets start with a reasonable buffer size
-    //of 4096 characters and go from there
-    int nChars = 4096;
-    BOOL bWantStop = FALSE;
-    while (nChars && !bWantStop)
-    {
-      CAutoHeapAlloc devices;
-      if (devices.Allocate(nChars * sizeof(TCHAR)))
-      {
-        LPTSTR pszDevices = static_cast<LPTSTR>(devices.m_pData);
-        DWORD dwChars = QueryDosDevice(NULL, pszDevices, nChars);
-        if (dwChars == 0)
-        {
-          DWORD dwError = GetLastError();
-          if (dwError == ERROR_INSUFFICIENT_BUFFER)
-          {
-            //Expand the buffer and  loop around again
-            nChars *= 2;
-          }
-          else
-            bWantStop = TRUE;
-        }
-        else
-        {
-          bSuccess = TRUE;
-          bWantStop = TRUE;
-          size_t i=0;
-          
-          while (pszDevices[i] != _T('\0'))
-          {
-            //Get the current device name
-            TCHAR* pszCurrentDevice = &(pszDevices[i]);
-
-            //If it looks like "COMX" then
-            //add it to the array which will be returned
-            size_t nLen = _tcslen(pszCurrentDevice);
-            if (nLen > 3)
-            {
-              if ((_tcsnicmp(pszCurrentDevice, _T("COM"), 3) == 0) && IsNumeric(&(pszCurrentDevice[3]), FALSE))
-              {
-                //Work out the port number
-                int nPort = _ttoi(&pszCurrentDevice[3]);
-              #if defined CENUMERATESERIAL_USE_STL
-                ports.push_back(nPort);
-              #else
-                ports.Add(nPort);
-              #endif  
-              }
-            }
-
-            //Go to next device name
-            i += (nLen + 1);
-          }
-        }
-      }
-      else
-      {
-        bWantStop = TRUE;
-        SetLastError(ERROR_OUTOFMEMORY);        
-      }
-    }
-  }
-  else
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-
-  return bSuccess;
-}
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_GETDEFAULTCOMMCONFIG
-#if defined CENUMERATESERIAL_USE_STL
-BOOL CEnumerateSerial::UsingGetDefaultCommConfig(std::vector<UINT>& ports)
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingGetDefaultCommConfig(CUIntArray& ports)
-#else
-BOOL CEnumerateSerial::UsingGetDefaultCommConfig(CSimpleArray<UINT>& ports)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-#else
-  ports.RemoveAll();
-#endif  
-
-  //Up to 255 COM ports are supported so we iterate through all of them seeing
-  //if we can get the default configuration
-  for (UINT i=1; i<256; i++)
-  {
-    //Form the Raw device name
-    CString sPort;
-    sPort.Format(_T("COM%u"), i);
-
-    COMMCONFIG cc;
-    DWORD dwSize = sizeof(COMMCONFIG);
-    if (GetDefaultCommConfig(sPort, &cc, &dwSize))
-    {
-    #if defined CENUMERATESERIAL_USE_STL
-      ports.push_back(i);
-    #else
-      ports.Add(i);
-    #endif  
-    }
-  }
-
-  //Return the success indicator
-  return TRUE;
-}
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_SETUPAPI1
-#if defined CENUMERATESERIAL_USE_STL
-#if defined _UNICODE
-BOOL CEnumerateSerial::UsingSetupAPI1(std::vector<UINT>& ports, std::vector<std::wstring>& friendlyNames)
-#else
-BOOL CEnumerateSerial::UsingSetupAPI1(std::vector<UINT>& ports, std::vector<std::string>& friendlyNames)
-#endif
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingSetupAPI1(CUIntArray& ports, CStringArray& friendlyNames)
-#else
-BOOL CEnumerateSerial::UsingSetupAPI1(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array(s)
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-  friendlyNames.clear();
-#else
-  ports.RemoveAll();
-  friendlyNames.RemoveAll();
-#endif  
-
-  //Get the various function pointers we require from setupapi.dll
-  CAutoHModule setupAPI(LoadLibraryFromSystem32(_T("SETUPAPI.DLL")));
-  if (setupAPI == NULL)
-    return FALSE;
-
-  SETUPDIOPENDEVREGKEY* lpfnLPSETUPDIOPENDEVREGKEY = reinterpret_cast<SETUPDIOPENDEVREGKEY*>(GetProcAddress(setupAPI, "SetupDiOpenDevRegKey"));
-#if defined _UNICODE
-  SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsW"));
-  SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyW"));
-#else
-  SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsA"));
-  SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyA"));
-#endif
-  SETUPDIDESTROYDEVICEINFOLIST* lpfnSETUPDIDESTROYDEVICEINFOLIST = reinterpret_cast<SETUPDIDESTROYDEVICEINFOLIST*>(GetProcAddress(setupAPI, "SetupDiDestroyDeviceInfoList"));
-  SETUPDIENUMDEVICEINFO* lpfnSETUPDIENUMDEVICEINFO = reinterpret_cast<SETUPDIENUMDEVICEINFO*>(GetProcAddress(setupAPI, "SetupDiEnumDeviceInfo"));
-
-  if ((lpfnLPSETUPDIOPENDEVREGKEY == NULL) || (lpfnSETUPDIDESTROYDEVICEINFOLIST == NULL) ||
-      (lpfnSETUPDIENUMDEVICEINFO == NULL) || (lpfnSETUPDIGETCLASSDEVS == NULL) || (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY == NULL))
-  {
-    //Set the error to report
-    setupAPI.m_dwError = ERROR_CALL_NOT_IMPLEMENTED;
-
-    return FALSE;
-  }
-  
-  //Now create a "device information set" which is required to enumerate all the ports
-  GUID guid = GUID_DEVINTERFACE_COMPORT;
-  HDEVINFO hDevInfoSet = lpfnSETUPDIGETCLASSDEVS(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
-  if (hDevInfoSet == INVALID_HANDLE_VALUE)
-  {
-    //Set the error to report
-    setupAPI.m_dwError = GetLastError();
-  
-    return FALSE;
-  }
-
-  //Finally do the enumeration
-  BOOL bMoreItems = TRUE;
-  int nIndex = 0;
-  SP_DEVINFO_DATA devInfo;
-  while (bMoreItems)
-  {
-    //Enumerate the current device
-    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
-    bMoreItems = lpfnSETUPDIENUMDEVICEINFO(hDevInfoSet, nIndex, &devInfo);
-    if (bMoreItems)
-    {
-      //Did we find a serial port for this device
-      BOOL bAdded = FALSE;
-
-      //Get the registry key which stores the ports settings
-      HKEY hDeviceKey = lpfnLPSETUPDIOPENDEVREGKEY(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
-      if (hDeviceKey)
-      {
-        int nPort = 0;
-        if (QueryRegistryPortName(hDeviceKey, nPort))
-        {
-        #if defined CENUMERATESERIAL_USE_STL
-          ports.push_back(nPort);
-        #else
-          ports.Add(nPort);
-        #endif  
-          bAdded = TRUE;
-        }
-
-        //Close the key now that we are finished with it
-        RegCloseKey(hDeviceKey);
-      }
-
-      //If the port was a serial port, then also try to get its friendly name
-      if (bAdded)
-      {
-        TCHAR szFriendlyName[1024];
-        szFriendlyName[0] = _T('\0');
-        DWORD dwSize = sizeof(szFriendlyName);
-        DWORD dwType = 0;
-        if (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>(szFriendlyName), dwSize, &dwSize) && (dwType == REG_SZ))
-        {
-        #if defined CENUMERATESERIAL_USE_STL
-          friendlyNames.push_back(szFriendlyName);
-        #else
-          friendlyNames.Add(szFriendlyName);
-        #endif  
-        }
-        else
-        {
-        #if defined CENUMERATESERIAL_USE_STL
-          friendlyNames.push_back(_T(""));
-        #else
-          friendlyNames.Add(_T(""));
-        #endif  
-        }
-      }
-    }
-
-    ++nIndex;
-  }
-
-  //Free up the "device information set" now that we are finished with it
-  lpfnSETUPDIDESTROYDEVICEINFOLIST(hDevInfoSet);
-
-  //Return the success indicator
-  return TRUE;
-}
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_SETUPAPI2
-#if defined CENUMERATESERIAL_USE_STL
-#if defined _UNICODE
-BOOL CEnumerateSerial::UsingSetupAPI2(std::vector<UINT>& ports, std::vector<std::wstring>& friendlyNames)
-#else
-BOOL CEnumerateSerial::UsingSetupAPI2(std::vector<UINT>& ports, std::vector<std::string>& friendlyNames)
-#endif
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingSetupAPI2(CUIntArray& ports, CStringArray& friendlyNames)
-#else
-BOOL CEnumerateSerial::UsingSetupAPI2(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array(s)
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-  friendlyNames.clear();
-#else
-  ports.RemoveAll();
-  friendlyNames.RemoveAll();
-#endif  
-
-  //Get the function pointers to "SetupDiGetClassDevs", "SetupDiGetClassDevs", "SetupDiEnumDeviceInfo", "SetupDiOpenDevRegKey" 
-  //and "SetupDiDestroyDeviceInfoList" in setupapi.dll
-  CAutoHModule setupAPI(LoadLibraryFromSystem32(_T("SETUPAPI.DLL")));
-  if (setupAPI == NULL)
-    return FALSE;
-
-  SETUPDIOPENDEVREGKEY* lpfnLPSETUPDIOPENDEVREGKEY = reinterpret_cast<SETUPDIOPENDEVREGKEY*>(GetProcAddress(setupAPI, "SetupDiOpenDevRegKey"));
-#if defined _UNICODE
-  SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameW"));
-  SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsW"));
-  SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyW"));
-#else
-  SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameA"));
-  SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsA"));
-  SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyA"));
-#endif
-  SETUPDIDESTROYDEVICEINFOLIST* lpfnSETUPDIDESTROYDEVICEINFOLIST = reinterpret_cast<SETUPDIDESTROYDEVICEINFOLIST*>(GetProcAddress(setupAPI, "SetupDiDestroyDeviceInfoList"));
-  SETUPDIENUMDEVICEINFO* lpfnSETUPDIENUMDEVICEINFO = reinterpret_cast<SETUPDIENUMDEVICEINFO*>(GetProcAddress(setupAPI, "SetupDiEnumDeviceInfo"));
-
-  if ((lpfnLPSETUPDIOPENDEVREGKEY == NULL) || (lpfnSETUPDICLASSGUIDSFROMNAME == NULL) || (lpfnSETUPDIDESTROYDEVICEINFOLIST == NULL) ||
-      (lpfnSETUPDIENUMDEVICEINFO == NULL) || (lpfnSETUPDIGETCLASSDEVS == NULL) || (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY == NULL))
-  {
-    //Set the error to report
-    setupAPI.m_dwError = ERROR_CALL_NOT_IMPLEMENTED;
-
-    return FALSE;
-  }
-  
-  //First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName
-  DWORD dwGuids = 0;
-  lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), NULL, 0, &dwGuids);
-  if (dwGuids == 0)
-  {
-    //Set the error to report
-    setupAPI.m_dwError = GetLastError();
-
-    return FALSE;
-  }
-
-  //Allocate the needed memory
-  CAutoHeapAlloc guids;
-  if (!guids.Allocate(dwGuids * sizeof(GUID)))
-  {
-    //Set the error to report
-    setupAPI.m_dwError = ERROR_OUTOFMEMORY;
-
-    return FALSE;
-  }
-
-  //Call the function again
-  GUID* pGuids = static_cast<GUID*>(guids.m_pData);
-  if (!lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), pGuids, dwGuids, &dwGuids))
-  {
-    //Set the error to report
-    setupAPI.m_dwError = GetLastError();
-
-    return FALSE;
-  }
-
-  //Now create a "device information set" which is required to enumerate all the ports
-  HDEVINFO hDevInfoSet = lpfnSETUPDIGETCLASSDEVS(pGuids, NULL, NULL, DIGCF_PRESENT);
-  if (hDevInfoSet == INVALID_HANDLE_VALUE)
-  {
-    //Set the error to report
-    setupAPI.m_dwError = GetLastError();
-
-    return FALSE;
-  }
-
-  //Finally do the enumeration
-  BOOL bMoreItems = TRUE;
-  int nIndex = 0;
-  SP_DEVINFO_DATA devInfo;
-  while (bMoreItems)
-  {
-    //Enumerate the current device
-    devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
-    bMoreItems = lpfnSETUPDIENUMDEVICEINFO(hDevInfoSet, nIndex, &devInfo);
-    if (bMoreItems)
-    {
-      //Did we find a serial port for this device
-      BOOL bAdded = FALSE;
-
-      //Get the registry key which stores the ports settings
-      HKEY hDeviceKey = lpfnLPSETUPDIOPENDEVREGKEY(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
-      if (hDeviceKey)
-      {
-        int nPort = 0;
-        if (QueryRegistryPortName(hDeviceKey, nPort))
-        {
-        #if defined CENUMERATESERIAL_USE_STL
-          ports.push_back(nPort);
-        #else
-          ports.Add(nPort);
-        #endif  
-          bAdded = TRUE;
-        }
-
-        //Close the key now that we are finished with it
-        RegCloseKey(hDeviceKey);
-      }
-
-      //If the port was a serial port, then also try to get its friendly name
-      if (bAdded)
-      {
-        TCHAR szFriendlyName[1024];
-        szFriendlyName[0] = _T('\0');
-        DWORD dwSize = sizeof(szFriendlyName);
-        DWORD dwType = 0;
-        if (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>(szFriendlyName), dwSize, &dwSize) && (dwType == REG_SZ))
-        {
-        #if defined CENUMERATESERIAL_USE_STL
-          friendlyNames.push_back(szFriendlyName);
-        #else
-          friendlyNames.Add(szFriendlyName);
-        #endif  
-        }
-        else
-        {
-        #if defined CENUMERATESERIAL_USE_STL
-          friendlyNames.push_back(_T(""));
-        #else
-          friendlyNames.Add(_T(""));
-        #endif  
-        }
-      }
-    }
-
-    ++nIndex;
-  }
-
-  //Free up the "device information set" now that we are finished with it
-  lpfnSETUPDIDESTROYDEVICEINFOLIST(hDevInfoSet);
-
-  //Return the success indicator
-  return TRUE;
-}
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_ENUMPORTS
-#if defined CENUMERATESERIAL_USE_STL
-BOOL CEnumerateSerial::UsingEnumPorts(std::vector<UINT>& ports)
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingEnumPorts(CUIntArray& ports)
-#else
-BOOL CEnumerateSerial::UsingEnumPorts(CSimpleArray<UINT>& ports)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-#else
-  ports.RemoveAll();
-#endif  
-
-  //Call the first time to determine the size of the buffer to allocate
-  DWORD cbNeeded = 0;
-  DWORD dwPorts = 0;
-  EnumPorts(NULL, 1, NULL, 0, &cbNeeded, &dwPorts);
-
-  //What will be the return value
-  BOOL bSuccess = FALSE;
-
-  //Allocate the buffer and recall
-  CAutoHeapAlloc portsBuffer;
-  if (portsBuffer.Allocate(cbNeeded))
-  {
-    BYTE* pPorts = static_cast<BYTE*>(portsBuffer.m_pData);
-    bSuccess = EnumPorts(NULL, 1, pPorts, cbNeeded, &cbNeeded, &dwPorts);
-    if (bSuccess)
-    {
-      PORT_INFO_1* pPortInfo = reinterpret_cast<PORT_INFO_1*>(pPorts);
-      for (DWORD i=0; i<dwPorts; i++)
-      {
-        //If it looks like "COMX" then
-        //add it to the array which will be returned
-        size_t nLen = _tcslen(pPortInfo->pName);
-        if (nLen > 3)
-        {
-          if ((_tcsnicmp(pPortInfo->pName, _T("COM"), 3) == 0) && IsNumeric(&(pPortInfo->pName[3]), TRUE))
-          {
-            //Work out the port number
-            int nPort = _ttoi(&(pPortInfo->pName[3]));
-          #if defined CENUMERATESERIAL_USE_STL
-            ports.push_back(nPort);
-          #else
-            ports.Add(nPort);
-          #endif  
-          }
-        }
-
-        pPortInfo++;
-      }
-    }
-  }
-  else
-    SetLastError(ERROR_OUTOFMEMORY);        
-  
-  return bSuccess;
-}
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_WMI
-#if defined CENUMERATESERIAL_USE_STL
-#if defined _UNICODE
-BOOL CEnumerateSerial::UsingWMI(std::vector<UINT>& ports, std::vector<std::wstring>& friendlyNames)
-#else
-BOOL CEnumerateSerial::UsingWMI(std::vector<UINT>& ports, std::vector<std::string>& friendlyNames)
-#endif
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingWMI(CUIntArray& ports, CStringArray& friendlyNames)
-#else
-BOOL CEnumerateSerial::UsingWMI(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array(s)
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-  friendlyNames.clear();
-#else
-  ports.RemoveAll();
-  friendlyNames.RemoveAll();
-#endif  
-
-  //What will be the return value
-  BOOL bSuccess = FALSE;
-
-  //Create the WBEM locator
-  ATL::CComPtr<IWbemLocator> locator;
-  HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<void**>(&locator));
-  if (SUCCEEDED(hr))
-  {
-    ATL::CComPtr<IWbemServices> services;
-    hr = locator->ConnectServer(_bstr_t("\\\\.\\root\\cimv2"), NULL, NULL, NULL, 0, NULL, NULL, &services);
-    if (SUCCEEDED(hr))
-    {
-      //Execute the query
-      ATL::CComPtr<IEnumWbemClassObject> classObject;
-      hr = services->CreateInstanceEnum(_bstr_t("Win32_SerialPort"), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &classObject);
-      if (SUCCEEDED(hr))
-      {
-        bSuccess = TRUE;
-
-        //Now enumerate all the ports
-        hr = WBEM_S_NO_ERROR;
-
-        //Final Next will return WBEM_S_FALSE
-        while (hr == WBEM_S_NO_ERROR)
-        {
-          ULONG uReturned = 0;
-          ATL::CComPtr<IWbemClassObject> apObj[10];
-          hr = classObject->Next(WBEM_INFINITE, 10, reinterpret_cast<IWbemClassObject**>(apObj), &uReturned);
-          if (SUCCEEDED(hr))
-          {
-            for (ULONG n=0; n<uReturned; n++)
-            {
-              ATL::CComVariant varProperty1;
-              HRESULT hrGet = apObj[n]->Get(L"DeviceID", 0, &varProperty1, NULL, NULL);
-              if (SUCCEEDED(hrGet) && (varProperty1.vt == VT_BSTR) && (wcslen(varProperty1.bstrVal) > 3))
-              {
-                //If it looks like "COMX" then add it to the array which will be returned
-                if ((_wcsnicmp(varProperty1.bstrVal, L"COM", 3) == 0) && IsNumeric(&(varProperty1.bstrVal[3]), TRUE))
-                {
-                  //Work out the port number
-                  int nPort = _wtoi(&(varProperty1.bstrVal[3]));
-                #if defined CENUMERATESERIAL_USE_STL
-                  ports.push_back(nPort);
-                #else
-                  ports.Add(nPort);
-                #endif
-
-                  //Also get the friendly name of the port
-                  ATL::CComVariant varProperty2;
-                  if (SUCCEEDED(apObj[n]->Get(L"Name", 0, &varProperty2, NULL, NULL)) && (varProperty2.vt == VT_BSTR))
-                  {  
-                #if defined CENUMERATESERIAL_USE_STL
-                  #if defined _UNICODE  
-                    std::wstring szName(varProperty2.bstrVal);
-                  #else
-                    std::string szName(ATL::CW2A(varProperty2.bstrVal));
-                  #endif
-                    friendlyNames.push_back(szName);
-                  #else
-                    friendlyNames.Add(CString(varProperty2.bstrVal));    
-                  #endif
-                  }
-                  else
-                  {
-                  #if defined CENUMERATESERIAL_USE_STL
-                    friendlyNames.push_back(_T(""));
-                  #else
-                    friendlyNames.Add(_T(""));
-                  #endif  
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-  
-  return bSuccess;
-}
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_COMDB
-#if defined CENUMERATESERIAL_USE_STL
-BOOL CEnumerateSerial::UsingComDB(std::vector<UINT>& ports)
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingComDB(CUIntArray& ports)
-#else
-BOOL CEnumerateSerial::UsingComDB(CSimpleArray<UINT>& ports)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array(s)
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-#else
-  ports.RemoveAll();
-#endif  
-
-  //What will be the return value from this function (assume the worst)
-  BOOL bSuccess = FALSE;
-  
-  //Get the function pointers to "ComDBOpen", "ComDBClose" & "ComDBGetCurrentPortUsage" in msports.dll
-  CAutoHModule msPorts(LoadLibraryFromSystem32(_T("MSPORTS.DLL")));
-  if (msPorts == NULL)
-    return FALSE;
-
-  COMDBOPEN* lpfnLPCOMDBOPEN = reinterpret_cast<COMDBOPEN*>(GetProcAddress(msPorts, "ComDBOpen"));
-  COMDBCLOSE* lpfnLPCOMDBCLOSE = reinterpret_cast<COMDBCLOSE*>(GetProcAddress(msPorts, "ComDBClose"));
-  COMDBGETCURRENTPORTUSAGE* lpfnCOMDBGETCURRENTPORTUSAGE = reinterpret_cast<COMDBGETCURRENTPORTUSAGE*>(GetProcAddress(msPorts, "ComDBGetCurrentPortUsage"));
-  if ((lpfnLPCOMDBOPEN != NULL) && (lpfnLPCOMDBCLOSE != NULL) && (lpfnCOMDBGETCURRENTPORTUSAGE != NULL))
-  {
-    //First need to open up the DB
-    HCOMDB hComDB;
-    DWORD dwComOpen = lpfnLPCOMDBOPEN(&hComDB);
-    if (dwComOpen == ERROR_SUCCESS)
-    {
-      //Work out the size of the buffer required
-      DWORD dwMaxPortsReported = 0;
-      DWORD dwPortUsage = lpfnCOMDBGETCURRENTPORTUSAGE(hComDB, NULL, 0, CDB_REPORT_BYTES, &dwMaxPortsReported);
-      if (dwPortUsage == ERROR_SUCCESS)
-      {
-        //Allocate some heap space and recall the function
-        CAutoHeapAlloc portBytes;
-        if (portBytes.Allocate(dwMaxPortsReported))
-        {
-          bSuccess = TRUE;
-
-          PBYTE pPortBytes = static_cast<PBYTE>(portBytes.m_pData);
-          if (lpfnCOMDBGETCURRENTPORTUSAGE(hComDB, pPortBytes, dwMaxPortsReported, CDB_REPORT_BYTES, &dwMaxPortsReported) == ERROR_SUCCESS)
-          {
-            //Work thro the byte bit array for ports which are in use
-            for (DWORD i=0; i<dwMaxPortsReported; i++)
-            {
-              if (pPortBytes[i])
-              {
-              #if defined CENUMERATESERIAL_USE_STL
-                ports.push_back(i + 1);
-              #else
-                ports.Add(i + 1);
-              #endif
-              }
-            }
-          }
-        }
-        else
-          msPorts.m_dwError = ERROR_OUTOFMEMORY;
-      }
-      else
-        msPorts.m_dwError = dwPortUsage;
-    
-      //Close the DB
-      lpfnLPCOMDBCLOSE(hComDB);
-    }
-    else
-      msPorts.m_dwError = dwComOpen;
-  }
-  else
-    msPorts.m_dwError = ERROR_CALL_NOT_IMPLEMENTED;
-
-  return bSuccess;
-}
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_REGISTRY
-#if defined CENUMERATESERIAL_USE_STL
-#if defined _UNICODE
-BOOL CEnumerateSerial::UsingRegistry(std::vector<std::wstring>& ports)
-#else
-BOOL CEnumerateSerial::UsingRegistry(std::vector<std::string>& ports)
-#endif
-#elif defined _AFX
-BOOL CEnumerateSerial::UsingRegistry(CStringArray& ports)
-#else
-BOOL CEnumerateSerial::UsingRegistry(CSimpleArray<CString>& ports)
-#endif
-{
-  //Make sure we clear out any elements which may already be in the array(s)
-#if defined CENUMERATESERIAL_USE_STL
-  ports.clear();
-#else
-  ports.RemoveAll();
-#endif  
-
-  //What will be the return value from this function (assume the worst)
-  BOOL bSuccess = FALSE;
-
-  HKEY hSERIALCOMM;
-  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS)
-  {
-    //Get the max value name and max value lengths
-    DWORD dwMaxValueNameLen;
-    DWORD dwMaxValueLen;
-    DWORD dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL);
-    if (dwQueryInfo == ERROR_SUCCESS)
-    {
-      DWORD dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1; //Include space for the NULL terminator
-      DWORD dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars * sizeof(TCHAR);
-      DWORD dwMaxValueDataSizeInChars = dwMaxValueLen/sizeof(TCHAR) + 1; //Include space for the NULL terminator
-      DWORD dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars * sizeof(TCHAR);
-    
-      //Allocate some space for the value name and value data			
-      CAutoHeapAlloc valueName;
-      CAutoHeapAlloc valueData;
-      if (valueName.Allocate(dwMaxValueNameSizeInBytes) && valueData.Allocate(dwMaxValueDataSizeInBytes))
-      {
-        bSuccess = TRUE;
-
-        //Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
-        DWORD dwIndex = 0;
-        DWORD dwType;
-        DWORD dwValueNameSize = dwMaxValueNameSizeInChars;
-        DWORD dwDataSize = dwMaxValueDataSizeInBytes;
-        memset(valueName.m_pData, 0, dwMaxValueNameSizeInBytes);
-        memset(valueData.m_pData, 0, dwMaxValueDataSizeInBytes);
-        TCHAR* szValueName = static_cast<TCHAR*>(valueName.m_pData);
-        BYTE* byValue = static_cast<BYTE*>(valueData.m_pData);
-        LONG nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, byValue, &dwDataSize);
-        while (nEnum == ERROR_SUCCESS)
-        {
-          //If the value is of the correct type, then add it to the array
-          if (dwType == REG_SZ)
-          {
-            TCHAR* szPort = reinterpret_cast<TCHAR*>(byValue);
-          #if defined CENUMERATESERIAL_USE_STL
-            ports.push_back(szPort);
-          #else
-            ports.Add(szPort);
-          #endif  						
-          }
-
-          //Prepare for the next time around
-          dwValueNameSize = dwMaxValueNameSizeInChars;
-          dwDataSize = dwMaxValueDataSizeInBytes;
-          memset(valueName.m_pData, 0, dwMaxValueNameSizeInBytes);
-          memset(valueData.m_pData, 0, dwMaxValueDataSizeInBytes);
-          ++dwIndex;
-          nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, byValue, &dwDataSize);
-        }
-      }
-      else
-        SetLastError(ERROR_OUTOFMEMORY);
-    }
-    
-    //Close the registry key now that we are finished with it    
-    RegCloseKey(hSERIALCOMM);
-    
-    if (dwQueryInfo != ERROR_SUCCESS)
-      SetLastError(dwQueryInfo);
-  }
-  
-  return bSuccess;
-}
-#endif
diff --git a/input_devices/mag/node_modules/serialport/src/win/enumser.h b/input_devices/mag/node_modules/serialport/src/win/enumser.h
deleted file mode 100644
index 87a143fa..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/enumser.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
-Module : enumser.h
-Purpose: Defines the interface for a class to enumerate the serial ports installed on a PC
-         using a number of different approaches
-Created: PJN / 03-11-1998
-
-Copyright (c) 1998 - 2013 by PJ Naughter (Web: www.naughter.com, Email: pjna@naughter.com)
-
-All rights reserved.
-
-Copyright / Usage Details:
-
-You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
-when your product is released in binary form. You are allowed to modify the source code in any way you want 
-except you cannot modify the copyright details at the top of each module. If you want to distribute source 
-code with your application, then you are only allowed to distribute versions released by the author. This is 
-to maintain a single distribution point for the source code. 
-
-*/
-
-
-///////////////////////// Macros / Structs etc ////////////////////////////////
-
-#pragma once
-
-#ifndef __ENUMSER_H__
-#define __ENUMSER_H__
-
-#ifndef CENUMERATESERIAL_EXT_CLASS
-#define CENUMERATESERIAL_EXT_CLASS
-#endif
-
-
-///////////////////////// Includes ////////////////////////////////////////////                      
-
-#if defined CENUMERATESERIAL_USE_STL
-#ifndef _VECTOR_
-  #include <vector>
-  #pragma message("To avoid this message, please put vector in your pre compiled header (normally stdafx.h)")
-#endif  
-#ifndef _STRING_
-  #include <string>
-  #pragma message("To avoid this message, please put string in your pre compiled header (normally stdafx.h)")
-#endif  
-#else
-#if defined _AFX
-  #ifndef __AFXTEMPL_H__
-    #include <afxtempl.h> 
-    #pragma message("To avoid this message, please put afxtempl.h in your pre compiled header (normally stdafx.h)")
-  #endif
-#else
-  #ifndef __ATLSTR_H__
-    #include <atlstr.h>
-    #pragma message("To avoid this message, please put atlstr.h in your pre compiled header (normally stdafx.h)")
-  #endif  
-#endif
-#endif
-
-
-///////////////////////// Classes /////////////////////////////////////////////
-
-class CENUMERATESERIAL_EXT_CLASS CEnumerateSerial
-{
-public:
-//Methods
-#ifndef NO_ENUMSERIAL_USING_CREATEFILE
-  #if defined CENUMERATESERIAL_USE_STL
-  	static BOOL UsingCreateFile(std::vector<UINT>& ports);
-  #elif defined _AFX
-  	static BOOL UsingCreateFile(CUIntArray& ports);
-  #else
-      static BOOL UsingCreateFile(CSimpleArray<UINT>& ports);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_QUERYDOSDEVICE
-  #if defined CENUMERATESERIAL_USE_STL
-    static BOOL UsingQueryDosDevice(std::vector<UINT>& ports);
-  #elif defined _AFX
-    static BOOL UsingQueryDosDevice(CUIntArray& ports);
-  #else
-    static BOOL UsingQueryDosDevice(CSimpleArray<UINT>& ports);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_GETDEFAULTCOMMCONFIG
-  #if defined CENUMERATESERIAL_USE_STL
-	static BOOL UsingGetDefaultCommConfig(std::vector<UINT>& ports);
-  #elif defined _AFX
-    static BOOL UsingGetDefaultCommConfig(CUIntArray& ports);
-  #else
-    static BOOL UsingGetDefaultCommConfig(CSimpleArray<UINT>& ports);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_SETUPAPI1
-  #if defined CENUMERATESERIAL_USE_STL
-    #if defined _UNICODE
-      static BOOL UsingSetupAPI1(std::vector<UINT>& ports, std::vector<std::wstring>& friendlyNames);
-    #else
-      static BOOL UsingSetupAPI1(std::vector<UINT>& ports, std::vector<std::string>& friendlyNames);
-    #endif
-  #elif defined _AFX
-    static BOOL UsingSetupAPI1(CUIntArray& ports, CStringArray& friendlyNames);
-  #else
-    static BOOL UsingSetupAPI1(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_SETUPAPI2
-  #if defined CENUMERATESERIAL_USE_STL
-    #if defined _UNICODE
-      static BOOL UsingSetupAPI2(std::vector<UINT>& ports, std::vector<std::wstring>& friendlyNames);
-    #else
-      static BOOL UsingSetupAPI2(std::vector<UINT>& ports, std::vector<std::string>& friendlyNames);
-    #endif
-  #elif defined _AFX
-    static BOOL UsingSetupAPI2(CUIntArray& ports, CStringArray& friendlyNames);
-  #else
-    static BOOL UsingSetupAPI2(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_ENUMPORTS
-  #if defined CENUMERATESERIAL_USE_STL
-    static BOOL UsingEnumPorts(std::vector<UINT>& ports);
-  #elif defined _AFX
-    static BOOL UsingEnumPorts(CUIntArray& ports);
-  #else
-    static BOOL UsingEnumPorts(CSimpleArray<UINT>& ports);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_WMI
-  #if defined CENUMERATESERIAL_USE_STL
-    #if defined _UNICODE
-      static BOOL UsingWMI(std::vector<UINT>& ports, std::vector<std::wstring>& friendlyNames);
-    #else
-      static BOOL UsingWMI(std::vector<UINT>& ports, std::vector<std::string>& friendlyNames);
-    #endif
-  #elif defined _AFX
-    static BOOL UsingWMI(CUIntArray& ports, CStringArray& friendlyNames);
-  #else
-    static BOOL UsingWMI(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_COMDB
-  #if defined CENUMERATESERIAL_USE_STL
-    static BOOL UsingComDB(std::vector<UINT>& ports);
-  #elif defined _AFX
-    static BOOL UsingComDB(CUIntArray& ports);
-  #else
-    static BOOL UsingComDB(CSimpleArray<UINT>& ports);
-  #endif
-#endif
-
-#ifndef NO_ENUMSERIAL_USING_REGISTRY
-  #if defined CENUMERATESERIAL_USE_STL
-    #if defined _UNICODE
-      static BOOL UsingRegistry(std::vector<std::wstring>& ports);
-    #else
-      static BOOL UsingRegistry(std::vector<std::string>& ports);
-    #endif
-  #elif defined _AFX
-    static BOOL UsingRegistry(CStringArray& ports);
-  #else
-    static BOOL UsingRegistry(CSimpleArray<CString>& ports);
-  #endif
-#endif
-
-protected:
-//Methods
-#if !defined(NO_ENUMSERIAL_USING_SETUPAPI1) || !defined(NO_ENUMSERIAL_USING_SETUPAPI2)
-  static BOOL RegQueryValueString(HKEY kKey, LPCTSTR lpValueName, LPTSTR& pszValue);
-  static BOOL QueryRegistryPortName(HKEY hDeviceKey, int& nPort);
-#endif
-#if !defined(NO_ENUMSERIAL_USING_SETUPAPI1) || !defined(NO_ENUMSERIAL_USING_SETUPAPI2) || !defined(NO_ENUMSERIAL_USING_COMDB)
-  static HMODULE LoadLibraryFromSystem32(LPCTSTR lpFileName);
-#endif
-  static BOOL IsNumeric(LPCSTR pszString, BOOL bIgnoreColon);
-  static BOOL IsNumeric(LPCWSTR pszString, BOOL bIgnoreColon);
-};
-
-#endif //__ENUMSER_H__
diff --git a/input_devices/mag/node_modules/serialport/src/win/stdafx.h b/input_devices/mag/node_modules/serialport/src/win/stdafx.h
deleted file mode 100644
index a4fa475f..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/stdafx.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#define CENUMERATESERIAL_USE_STL //Uncomment this line if you want to test the STL support in CEnumerateSerial
-
-#ifndef _SECURE_ATL
-#define _SECURE_ATL 1 //Use the Secure C Runtime in ATL
-#endif
-
-#ifndef VC_EXTRALEAN
-#define VC_EXTRALEAN
-#endif
-
-#ifndef WINVER
-#define WINVER 0x0500
-#endif
-
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0500
-#endif
-
-#ifndef _WIN32_WINDOWS
-#define _WIN32_WINDOWS 0x0500
-#endif
-
-#ifndef _WIN32_IE
-#define _WIN32_IE 0x0500
-#endif
-
-#ifndef CENUMERATESERIAL_USE_STL
-  #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
-
-  #define _AFX_ALL_WARNINGS // turns off MFC's hiding of some common and often safely ignored warning messages
-
-  #include <afxext.h> 
-  #include <afxtempl.h>
-  #include <atlbase.h>
-#else
-  #include "stdstring.h"
-  #define NO_ENUMSERIAL_USING_WMI
-#endif
-
-#include <vector>
-
-#define NO_ENUMSERIAL_USING_ENUMPORTS
-#define NO_ENUMSERIAL_USING_SETUPAPI1
-#define NO_ENUMSERIAL_USING_SETUPAPI2
-#define NO_ENUMSERIAL_USING_WMI
-#define NO_ENUMSERIAL_USING_COMDB
-#define NO_ENUMSERIAL_USING_CREATEFILE
-#define NO_ENUMSERIAL_USING_GETDEFAULTCOMMCONFIG
-#define NO_ENUMSERIAL_USING_REGISTRY
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/serialport/src/win/stdstring.h b/input_devices/mag/node_modules/serialport/src/win/stdstring.h
deleted file mode 100644
index 2dd0bd8b..00000000
--- a/input_devices/mag/node_modules/serialport/src/win/stdstring.h
+++ /dev/null
@@ -1,4351 +0,0 @@
-// =============================================================================
-//  FILE:  StdString.h
-//  AUTHOR:	Joe O'Leary (with outside help noted in comments)
-//
-//		If you find any bugs in this code, please let me know:
-//
-//				jmoleary@earthlink.net
-//				http://www.joeo.net/stdstring.htm (a bit outdated)
-//
-//      The latest version of this code should always be available at the
-//      following link:
-//
-//              http://www.joeo.net/code/StdString.zip (Dec 6, 2003)
-//
-//
-//  REMARKS:
-//		This header file declares the CStdStr template.  This template derives
-//		the Standard C++ Library basic_string<> template and add to it the
-//		the following conveniences:
-//			- The full MFC CString set of functions (including implicit cast)
-//			- writing to/reading from COM IStream interfaces
-//			- Functional objects for use in STL algorithms
-//
-//		From this template, we intstantiate two classes:  CStdStringA and
-//		CStdStringW.  The name "CStdString" is just a #define of one of these,
-//		based upone the UNICODE macro setting
-//
-//		This header also declares our own version of the MFC/ATL UNICODE-MBCS
-//		conversion macros.  Our version looks exactly like the Microsoft's to
-//		facilitate portability.
-//
-//	NOTE:
-//		If you you use this in an MFC or ATL build, you should include either
-//		afx.h or atlbase.h first, as appropriate.
-//
-//	PEOPLE WHO HAVE CONTRIBUTED TO THIS CLASS:
-//
-//		Several people have helped me iron out problems and othewise improve
-//		this class.  OK, this is a long list but in my own defense, this code
-//		has undergone two major rewrites.  Many of the improvements became
-//		necessary after I rewrote the code as a template.  Others helped me
-//		improve the CString facade.
-//
-//		Anyway, these people are (in chronological order):
-//
-//			- Pete the Plumber (???)
-//			- Julian Selman
-//			- Chris (of Melbsys)
-//			- Dave Plummer
-//			- John C Sipos
-//			- Chris Sells
-//			- Nigel Nunn
-//			- Fan Xia
-//			- Matthew Williams
-//			- Carl Engman
-//			- Mark Zeren
-//			- Craig Watson
-//			- Rich Zuris
-//			- Karim Ratib
-//			- Chris Conti
-//			- Baptiste Lepilleur
-//			- Greg Pickles
-//			- Jim Cline
-//			- Jeff Kohn
-//			- Todd Heckel
-//			- Ullrich Poll�hne
-//			- Joe Vitaterna
-//			- Joe Woodbury
-//			- Aaron (no last name)
-//			- Joldakowski (???)
-//			- Scott Hathaway
-//			- Eric Nitzche
-//			- Pablo Presedo
-//			- Farrokh Nejadlotfi
-//			- Jason Mills
-//			- Igor Kholodov
-//			- Mike Crusader
-//			- John James
-//			- Wang Haifeng
-//			- Tim Dowty
-//          - Arnt Witteveen
-//          - Glen Maynard
-//          - Paul DeMarco
-//          - Bagira (full name?)
-//          - Ronny Schulz
-//          - Jakko Van Hunen
-//			- Charles Godwin
-//			- Henk Demper
-//			- Greg Marr
-//			- Bill Carducci
-//			- Brian Groose
-//			- MKingman
-//			- Don Beusee
-//
-//	REVISION HISTORY
-//
-//	  2005-JAN-10 - Thanks to Don Beusee for pointing out the danger in mapping
-//					length-checked formatting functions to non-length-checked
-//					CRT equivalents.  Also thanks to him for motivating me to
-//					optimize my implementation of Replace()
-//
-//	  2004-APR-22 - A big, big thank you to "MKingman" (whoever you are) for
-//					finally spotting a silly little error in StdCodeCvt that
-//					has been causing me (and users of CStdString) problems for
-//					years in some relatively rare conversions.  I had reversed
-//					two length arguments. 
-//
-//    2003-NOV-24 - Thanks to a bunch of people for helping me clean up many
-//					compiler warnings (and yes, even a couple of actual compiler
-//					errors).  These include Henk Demper for figuring out how
-//					to make the Intellisense work on with CStdString on VC6,
-//					something I was never able to do.  Greg Marr pointed out
-//					a compiler warning about an unreferenced symbol and a
-//					problem with my version of Load in MFC builds.  Bill
-//					Carducci took a lot of time with me to help me figure out
-//					why some implementations of the Standard C++ Library were
-//					returning error codes for apparently successful conversions
-//					between ASCII and UNICODE.  Finally thanks to Brian Groose
-//					for helping me fix compiler signed unsigned warnings in
-//					several functions.
-//
-//    2003-JUL-10 - Thanks to Charles Godwin for making me realize my 'FmtArg'
-//					fixes had inadvertently broken the DLL-export code (which is
-//                  normally commented out.  I had to move it up higher.  Also
-//					this helped me catch a bug in ssicoll that would prevent
-//                  compilation, otherwise.
-//
-//    2003-MAR-14 - Thanks to Jakko Van Hunen for pointing out a copy-and-paste
-//                  bug in one of the overloads of FmtArg.
-//
-//    2003-MAR-10 - Thanks to Ronny Schulz for (twice!) sending me some changes
-//                  to help CStdString build on SGI and for pointing out an
-//                  error in placement of my preprocessor macros for ssfmtmsg.
-//
-//    2002-NOV-26 - Thanks to Bagira for pointing out that my implementation of
-//                  SpanExcluding was not properly handling the case in which
-//                  the string did NOT contain any of the given characters
-//
-//    2002-OCT-21 - Many thanks to Paul DeMarco who was invaluable in helping me
-//                  get this code working with Borland's free compiler as well
-//                  as the Dev-C++ compiler (available free at SourceForge).
-//
-//    2002-SEP-13 - Thanks to Glen Maynard who helped me get rid of some loud
-//                  but harmless warnings that were showing up on g++.  Glen
-//                  also pointed out that some pre-declarations of FmtArg<>
-//                  specializations were unnecessary (and no good on G++)
-//
-//    2002-JUN-26 - Thanks to Arnt Witteveen for pointing out that I was using
-//                  static_cast<> in a place in which I should have been using
-//                  reinterpret_cast<> (the ctor for unsigned char strings).
-//                  That's what happens when I don't unit-test properly!
-//                  Arnt also noticed that CString was silently correcting the
-//                  'nCount' argument to Left() and Right() where CStdString was
-//                  not (and crashing if it was bad).  That is also now fixed!
-//
-//	  2002-FEB-25 - Thanks to Tim Dowty for pointing out (and giving me the fix
-//					for) a conversion problem with non-ASCII MBCS characters.
-//					CStdString is now used in my favorite commercial MP3 player!
-//
-//	  2001-DEC-06 - Thanks to Wang Haifeng for spotting a problem in one of the
-//					assignment operators (for _bstr_t) that would cause compiler
-//					errors when refcounting protection was turned off.
-//
-//	  2001-NOV-27 - Remove calls to operator!= which involve reverse_iterators
-//					due to a conflict with the rel_ops operator!=.  Thanks to
-//					John James for pointing this out.
-//
-//    2001-OCT-29 - Added a minor range checking fix for the Mid function to
-//					make it as forgiving as CString's version is.  Thanks to
-//					Igor Kholodov for noticing this.  
-//				  - Added a specialization of std::swap for CStdString.  Thanks
-//					to Mike Crusader for suggesting this!  It's commented out
-//					because you're not supposed to inject your own code into the
-//					'std' namespace.  But if you don't care about that, it's
-//					there if you want it
-//				  - Thanks to Jason Mills for catching a case where CString was
-//					more forgiving in the Delete() function than I was.
-//
-//	  2001-JUN-06 - I was violating the Standard name lookup rules stated
-//					in [14.6.2(3)].  None of the compilers I've tried so
-//					far apparently caught this but HP-UX aCC 3.30 did.  The
-//					fix was to add 'this->' prefixes in many places.
-//					Thanks to Farrokh Nejadlotfi for this!
-//
-//	  2001-APR-27 - StreamLoad was calculating the number of BYTES in one
-//					case, not characters.  Thanks to Pablo Presedo for this.
-//
-//    2001-FEB-23 - Replace() had a bug which caused infinite loops if the
-//					source string was empty.  Fixed thanks to Eric Nitzsche.
-//
-//    2001-FEB-23 - Scott Hathaway was a huge help in providing me with the
-//					ability to build CStdString on Sun Unix systems.  He
-//					sent me detailed build reports about what works and what
-//					does not.  If CStdString compiles on your Unix box, you
-//					can thank Scott for it.
-//
-//	  2000-DEC-29 - Joldakowski noticed one overload of Insert failed to do a
-//					range check as CString's does.  Now fixed -- thanks!
-//
-//	  2000-NOV-07 - Aaron pointed out that I was calling static member
-//					functions of char_traits via a temporary.  This was not
-//					technically wrong, but it was unnecessary and caused
-//					problems for poor old buggy VC5.  Thanks Aaron!
-//
-//	  2000-JUL-11 - Joe Woodbury noted that the CString::Find docs don't match
-//					what the CString::Find code really ends up doing.   I was
-//					trying to match the docs.  Now I match the CString code
-//				  - Joe also caught me truncating strings for GetBuffer() calls
-//					when the supplied length was less than the current length.
-//
-//	  2000-MAY-25 - Better support for STLPORT's Standard library distribution
-//				  - Got rid of the NSP macro - it interfered with Koenig lookup
-//				  - Thanks to Joe Woodbury for catching a TrimLeft() bug that
-//					I introduced in January.  Empty strings were not getting
-//					trimmed
-//
-//	  2000-APR-17 - Thanks to Joe Vitaterna for pointing out that ReverseFind
-//					is supposed to be a const function.
-//
-//	  2000-MAR-07 - Thanks to Ullrich Poll�hne for catching a range bug in one
-//					of the overloads of assign.
-//
-//    2000-FEB-01 - You can now use CStdString on the Mac with CodeWarrior!
-//					Thanks to Todd Heckel for helping out with this.
-//
-//	  2000-JAN-23 - Thanks to Jim Cline for pointing out how I could make the
-//					Trim() function more efficient.
-//				  - Thanks to Jeff Kohn for prompting me to find and fix a typo
-//					in one of the addition operators that takes _bstr_t.
-//				  - Got rid of the .CPP file -  you only need StdString.h now!
-//
-//	  1999-DEC-22 - Thanks to Greg Pickles for helping me identify a problem
-//					with my implementation of CStdString::FormatV in which
-//					resulting string might not be properly NULL terminated.
-//
-//	  1999-DEC-06 - Chris Conti pointed yet another basic_string<> assignment
-//					bug that MS has not fixed.  CStdString did nothing to fix
-//					it either but it does now!  The bug was: create a string
-//					longer than 31 characters, get a pointer to it (via c_str())
-//					and then assign that pointer to the original string object.
-//					The resulting string would be empty.  Not with CStdString!
-//
-//	  1999-OCT-06 - BufferSet was erasing the string even when it was merely
-//					supposed to shrink it.  Fixed.  Thanks to Chris Conti.
-//				  - Some of the Q172398 fixes were not checking for assignment-
-//					to-self.  Fixed.  Thanks to Baptiste Lepilleur.
-//
-//	  1999-AUG-20 - Improved Load() function to be more efficient by using 
-//					SizeOfResource().  Thanks to Rich Zuris for this.
-//				  - Corrected resource ID constructor, again thanks to Rich.
-//				  - Fixed a bug that occurred with UNICODE characters above
-//					the first 255 ANSI ones.  Thanks to Craig Watson. 
-//				  - Added missing overloads of TrimLeft() and TrimRight().
-//					Thanks to Karim Ratib for pointing them out
-//
-//	  1999-JUL-21 - Made all calls to GetBuf() with no args check length first.
-//
-//	  1999-JUL-10 - Improved MFC/ATL independence of conversion macros
-//				  - Added SS_NO_REFCOUNT macro to allow you to disable any
-//					reference-counting your basic_string<> impl. may do.
-//				  - Improved ReleaseBuffer() to be as forgiving as CString.
-//					Thanks for Fan Xia for helping me find this and to
-//					Matthew Williams for pointing it out directly.
-//
-//	  1999-JUL-06 - Thanks to Nigel Nunn for catching a very sneaky bug in
-//					ToLower/ToUpper.  They should call GetBuf() instead of
-//					data() in order to ensure the changed string buffer is not
-//					reference-counted (in those implementations that refcount).
-//
-//	  1999-JUL-01 - Added a true CString facade.  Now you can use CStdString as
-//					a drop-in replacement for CString.  If you find this useful,
-//					you can thank Chris Sells for finally convincing me to give
-//					in and implement it.
-//				  - Changed operators << and >> (for MFC CArchive) to serialize
-//					EXACTLY as CString's do.  So now you can send a CString out
-//					to a CArchive and later read it in as a CStdString.   I have
-//					no idea why you would want to do this but you can. 
-//
-//	  1999-JUN-21 - Changed the CStdString class into the CStdStr template.
-//				  - Fixed FormatV() to correctly decrement the loop counter.
-//					This was harmless bug but a bug nevertheless.  Thanks to
-//					Chris (of Melbsys) for pointing it out
-//				  - Changed Format() to try a normal stack-based array before
-//					using to _alloca().
-//				  - Updated the text conversion macros to properly use code
-//					pages and to fit in better in MFC/ATL builds.  In other
-//					words, I copied Microsoft's conversion stuff again. 
-//				  - Added equivalents of CString::GetBuffer, GetBufferSetLength
-//				  - new sscpy() replacement of CStdString::CopyString()
-//				  - a Trim() function that combines TrimRight() and TrimLeft().
-//
-//	  1999-MAR-13 - Corrected the "NotSpace" functional object to use _istpace()
-//					instead of _isspace()   Thanks to Dave Plummer for this.
-//
-//	  1999-FEB-26 - Removed errant line (left over from testing) that #defined
-//					_MFC_VER.  Thanks to John C Sipos for noticing this.
-//
-//	  1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that
-//					caused infinite recursion and stack overflow
-//				  - Added member functions to simplify the process of
-//					persisting CStdStrings to/from DCOM IStream interfaces 
-//				  - Added functional objects (e.g. StdStringLessNoCase) that
-//					allow CStdStrings to be used as keys STL map objects with
-//					case-insensitive comparison 
-//				  - Added array indexing operators (i.e. operator[]).  I
-//					originally assumed that these were unnecessary and would be
-//					inherited from basic_string.  However, without them, Visual
-//					C++ complains about ambiguous overloads when you try to use
-//					them.  Thanks to Julian Selman to pointing this out. 
-//
-//	  1998-FEB-?? - Added overloads of assign() function to completely account
-//					for Q172398 bug.  Thanks to "Pete the Plumber" for this
-//
-//	  1998-FEB-?? - Initial submission
-//
-// COPYRIGHT:
-//		2002 Joseph M. O'Leary.  This code is 100% free.  Use it anywhere you
-//      want.  Rewrite it, restructure it, whatever.  If you can write software
-//      that makes money off of it, good for you.  I kinda like capitalism. 
-//      Please don't blame me if it causes your $30 billion dollar satellite
-//      explode in orbit.  If you redistribute it in any form, I'd appreciate it
-//      if you would leave this notice here.
-// =============================================================================
-
-// Avoid multiple inclusion
-
-#ifndef STDSTRING_H
-#define STDSTRING_H
-
-// When using VC, turn off browser references
-// Turn off unavoidable compiler warnings
-
-#if defined(_MSC_VER) && (_MSC_VER > 1100)
-	#pragma component(browser, off, references, "CStdString")
-	#pragma warning (disable : 4290) // C++ Exception Specification ignored
-	#pragma warning (disable : 4127) // Conditional expression is constant
-	#pragma warning (disable : 4097) // typedef name used as synonym for class name
-#endif
-
-// Borland warnings to turn off
-
-#ifdef __BORLANDC__
-    #pragma option push -w-inl
-//	#pragma warn -inl   // Turn off inline function warnings
-#endif
-
-// SS_IS_INTRESOURCE
-// -----------------
-//		A copy of IS_INTRESOURCE from VC7.  Because old VC6 version of winuser.h
-//		doesn't have this.
-
-#define SS_IS_INTRESOURCE(_r) (false)
-
-#if !defined (SS_ANSI) && defined(_MSC_VER)
-	#undef SS_IS_INTRESOURCE
-	#if defined(_WIN64)
-		#define SS_IS_INTRESOURCE(_r) (((unsigned __int64)(_r) >> 16) == 0)
-	#else
-		#define SS_IS_INTRESOURCE(_r) (((unsigned long)(_r) >> 16) == 0)
-	#endif
-#endif
-
-
-// MACRO: SS_UNSIGNED
-// ------------------
-//      This macro causes the addition of a constructor and assignment operator
-//      which take unsigned characters.  CString has such functions and in order
-//      to provide maximum CString-compatability, this code needs them as well.
-//      In practice you will likely never need these functions...
-
-//#define SS_UNSIGNED
-
-#ifdef SS_ALLOW_UNSIGNED_CHARS
-	#define SS_UNSIGNED
-#endif
-
-// MACRO: SS_SAFE_FORMAT
-// ---------------------
-//      This macro provides limited compatability with a questionable CString
-//      "feature".  You can define it in order to avoid a common problem that
-//      people encounter when switching from CString to CStdString.
-//
-//      To illustrate the problem -- With CString, you can do this:
-//
-//          CString sName("Joe");
-//          CString sTmp;
-//          sTmp.Format("My name is %s", sName);                    // WORKS!
-//
-//      However if you were to try this with CStdString, your program would
-//      crash.
-//
-//          CStdString sName("Joe");
-//          CStdString sTmp;
-//          sTmp.Format("My name is %s", sName);                    // CRASHES!
-//
-//      You must explicitly call c_str() or cast the object to the proper type
-//
-//          sTmp.Format("My name is %s", sName.c_str());            // WORKS!
-//          sTmp.Format("My name is %s", static_cast<PCSTR>(sName));// WORKS!
-//          sTmp.Format("My name is %s", (PCSTR)sName);				// WORKS!
-//
-//      This is because it is illegal to pass anything but a POD type as a
-//      variadic argument to a variadic function (i.e. as one of the "..."
-//      arguments).  The type const char* is a POD type.  The type CStdString
-//      is not.  Of course, neither is the type CString, but CString lets you do
-//      it anyway due to the way they laid out the class in binary.  I have no
-//      control over this in CStdString since I derive from whatever
-//      implementation of basic_string is available.
-//
-//      However if you have legacy code (which does this) that you want to take
-//      out of the MFC world and you don't want to rewrite all your calls to
-//      Format(), then you can define this flag and it will no longer crash.
-//
-//      Note however that this ONLY works for Format(), not sprintf, fprintf, 
-//      etc.  If you pass a CStdString object to one of those functions, your
-//      program will crash.  Not much I can do to get around this, short of
-//      writing substitutes for those functions as well.
-
-#define SS_SAFE_FORMAT  // use new template style Format() function
-
-
-// MACRO: SS_NO_IMPLICIT_CAST
-// --------------------------
-//      Some people don't like the implicit cast to const char* (or rather to
-//      const CT*) that CStdString (and MFC's CString) provide.  That was the
-//      whole reason I created this class in the first place, but hey, whatever
-//      bakes your cake.  Just #define this macro to get rid of the the implicit
-//      cast.
-
-//#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*()
-
-
-// MACRO: SS_NO_REFCOUNT
-// ---------------------
-//		turns off reference counting at the assignment level.  Only needed
-//		for the version of basic_string<> that comes with Visual C++ versions
-//		6.0 or earlier, and only then in some heavily multithreaded scenarios.
-//		Uncomment it if you feel you need it.
-
-//#define SS_NO_REFCOUNT
-
-// MACRO: SS_WIN32
-// ---------------
-//      When this flag is set, we are building code for the Win32 platform and
-//      may use Win32 specific functions (such as LoadString).  This gives us
-//      a couple of nice extras for the code.
-//
-//      Obviously, Microsoft's is not the only compiler available for Win32 out
-//      there.  So I can't just check to see if _MSC_VER is defined to detect
-//      if I'm building on Win32.  So for now, if you use MS Visual C++ or
-//      Borland's compiler, I turn this on.  Otherwise you may turn it on
-//      yourself, if you prefer
-
-#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32)
-    #define SS_WIN32
-#endif
-
-// MACRO: SS_ANSI
-// --------------
-//      When this macro is defined, the code attempts only to use ANSI/ISO
-//      standard library functions to do it's work.  It will NOT attempt to use
-//      any Win32 of Visual C++ specific functions -- even if they are
-//      available.  You may define this flag yourself to prevent any Win32
-//      of VC++ specific functions from being called. 
-
-// If we're not on Win32, we MUST use an ANSI build
-
-#ifndef SS_WIN32
-    #if !defined(SS_NO_ANSI)
-        #define SS_ANSI
-    #endif
-#endif
-
-// MACRO: SS_ALLOCA
-// ----------------
-//      Some implementations of the Standard C Library have a non-standard
-//      function known as alloca().  This functions allows one to allocate a
-//      variable amount of memory on the stack.  It is needed to implement
-//      the ASCII/MBCS conversion macros.
-//
-//      I wanted to find some way to determine automatically if alloca() is
-//		available on this platform via compiler flags but that is asking for
-//		trouble.  The crude test presented here will likely need fixing on
-//		other platforms.  Therefore I'll leave it up to you to fiddle with
-//		this test to determine if it exists.  Just make sure SS_ALLOCA is or
-//		is not defined as appropriate and you control this feature.
-
-#if defined(_MSC_VER) && !defined(SS_ANSI)
-	#define SS_ALLOCA
-#endif
-
-
-// MACRO: SS_MBCS
-// --------------
-//		Setting this macro means you are using MBCS characters.  In MSVC builds,
-//		this macro gets set automatically by detection of the preprocessor flag
-//		_MBCS.  For other platforms you may set it manually if you wish.  The
-//		only effect it currently has is to cause the allocation of more space
-//		for wchar_t --> char conversions.
-//		Note that MBCS does not mean UNICODE.
-//
-//	#define SS_MBCS
-//
-
-#ifdef _MBCS
-	#define SS_MBCS
-#endif
-
-
-// MACRO SS_NO_LOCALE
-// ------------------
-// If your implementation of the Standard C++ Library lacks the <locale> header,
-// you can #define this macro to make your code build properly.  Note that this
-// is some of my newest code and frankly I'm not very sure of it, though it does
-// pass my unit tests.
-
-// #define SS_NO_LOCALE
-
-
-// Compiler Error regarding _UNICODE and UNICODE
-// -----------------------------------------------
-// Microsoft header files are screwy.  Sometimes they depend on a preprocessor 
-// flag named "_UNICODE".  Other times they check "UNICODE" (note the lack of
-// leading underscore in the second version".  In several places, they silently
-// "synchronize" these two flags this by defining one of the other was defined. 
-// In older version of this header, I used to try to do the same thing. 
-//
-// However experience has taught me that this is a bad idea.  You get weird
-// compiler errors that seem to indicate things like LPWSTR and LPTSTR not being
-// equivalent in UNICODE builds, stuff like that (when they MUST be in a proper
-// UNICODE  build).  You end up scratching your head and saying, "But that HAS
-// to compile!".
-//
-// So what should you do if you get this error?
-//
-// Make sure that both macros (_UNICODE and UNICODE) are defined before this
-// file is included.  You can do that by either
-//
-//		a) defining both yourself before any files get included
-//		b) including the proper MS headers in the proper order
-//		c) including this file before any other file, uncommenting
-//		   the #defines below, and commenting out the #errors
-//
-//	Personally I recommend solution a) but it's your call.
-
-#ifdef _MSC_VER
-	#if defined (_UNICODE) && !defined (UNICODE)
-		#error UNICODE defined  but not UNICODE
-	//	#define UNICODE  // no longer silently fix this
-	#endif
-	#if defined (UNICODE) && !defined (_UNICODE)
-		#error Warning, UNICODE defined  but not _UNICODE
-	//	#define _UNICODE  // no longer silently fix this
-	#endif
-#endif
-
-
-// -----------------------------------------------------------------------------
-// MIN and MAX.  The Standard C++ template versions go by so many names (at
-// at least in the MS implementation) that you never know what's available 
-// -----------------------------------------------------------------------------
-template<class Type>
-inline const Type& SSMIN(const Type& arg1, const Type& arg2)
-{
-	return arg2 < arg1 ? arg2 : arg1;
-}
-template<class Type>
-inline const Type& SSMAX(const Type& arg1, const Type& arg2)
-{
-	return arg2 > arg1 ? arg2 : arg1;
-}
-
-// If they have not #included W32Base.h (part of my W32 utility library) then
-// we need to define some stuff.  Otherwise, this is all defined there.
-
-#if !defined(W32BASE_H)
-
-	// If they want us to use only standard C++ stuff (no Win32 stuff)
-
-	#ifdef SS_ANSI
-
-		// On Win32 we have TCHAR.H so just include it.  This is NOT violating
-        // the spirit of SS_ANSI as we are not calling any Win32 functions here.
-        
-		#ifdef SS_WIN32
-
-			#include <TCHAR.H>
-			#include <WTYPES.H>
-			#ifndef STRICT
-				#define STRICT
-			#endif
-
-        // ... but on non-Win32 platforms, we must #define the types we need.
-
-		#else
-
-			typedef const char*		PCSTR;
-			typedef char*			PSTR;
-			typedef const wchar_t*	PCWSTR;
-			typedef wchar_t*		PWSTR;
-			#ifdef UNICODE
-				typedef wchar_t		TCHAR;
-			#else
-				typedef char		TCHAR;
-			#endif
-			typedef wchar_t			OLECHAR;
-
-		#endif	// #ifndef _WIN32
-
-
-		// Make sure ASSERT and verify are defined using only ANSI stuff
-
-		#ifndef ASSERT
-			#include <assert.h>
-			#define ASSERT(f) assert((f))
-		#endif
-		#ifndef VERIFY
-			#ifdef _DEBUG
-				#define VERIFY(x) ASSERT((x))
-			#else
-				#define VERIFY(x) x
-			#endif
-		#endif
-
-	#else // ...else SS_ANSI is NOT defined
-
-		#include <TCHAR.H>
-		#include <WTYPES.H>
-		#ifndef STRICT
-			#define STRICT
-		#endif
-
-		// Make sure ASSERT and verify are defined
-
-		#ifndef ASSERT
-			#include <crtdbg.h>
-			#define ASSERT(f) _ASSERTE((f))
-		#endif
-		#ifndef VERIFY
-			#ifdef _DEBUG
-				#define VERIFY(x) ASSERT((x))
-			#else
-				#define VERIFY(x) x
-			#endif
-		#endif
-
-	#endif // #ifdef SS_ANSI
-
-	#ifndef UNUSED
-		#define UNUSED(x) x
-	#endif
-
-#endif // #ifndef W32BASE_H
-
-// Standard headers needed
-
-#include <string>			// basic_string
-#include <algorithm>		// for_each, etc.
-#include <functional>		// for StdStringLessNoCase, et al
-#ifndef SS_NO_LOCALE
-	#include <locale>			// for various facets
-#endif
-
-// If this is a recent enough version of VC include comdef.h, so we can write
-// member functions to deal with COM types & compiler support classes e.g.
-// _bstr_t
-
-#if defined (_MSC_VER) && (_MSC_VER >= 1100)
-	#include <comdef.h>
-	#define SS_INC_COMDEF		// signal that we #included MS comdef.h file
-	#define STDSTRING_INC_COMDEF
-	#define SS_NOTHROW __declspec(nothrow)
-#else
-	#define SS_NOTHROW
-#endif
-
-#ifndef TRACE
-	#define TRACE_DEFINED_HERE
-	#define TRACE
-#endif
-
-// Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR.  I hate to use the
-// versions with the "L" in front of them because that's a leftover from Win 16
-// days, even though it evaluates to the same thing.  Therefore, Define a PCSTR
-// as an LPCTSTR.
-
-#if !defined(PCTSTR) && !defined(PCTSTR_DEFINED)
-	typedef const TCHAR*			PCTSTR;
-	#define PCTSTR_DEFINED
-#endif
-
-#if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED)
-	typedef const OLECHAR*			PCOLESTR;
-	#define PCOLESTR_DEFINED
-#endif
-
-#if !defined(POLESTR) && !defined(POLESTR_DEFINED)
-	typedef OLECHAR*				POLESTR;
-	#define POLESTR_DEFINED
-#endif
-
-#if !defined(PCUSTR) && !defined(PCUSTR_DEFINED)
-	typedef const unsigned char*	PCUSTR;
-	typedef unsigned char*			PUSTR;
-	#define PCUSTR_DEFINED
-#endif
-
-
-// SGI compiler 7.3 doesnt know these  types - oh and btw, remember to use
-// -LANG:std in the CXX Flags
-#if defined(__sgi)
-    typedef unsigned long           DWORD;
-    typedef void *                  LPCVOID;
-#endif
-
-
-// SS_USE_FACET macro and why we need it:
-//
-// Since I'm a good little Standard C++ programmer, I use locales.  Thus, I
-// need to make use of the use_facet<> template function here.   Unfortunately,
-// this need is complicated by the fact the MS' implementation of the Standard
-// C++ Library has a non-standard version of use_facet that takes more
-// arguments than the standard dictates.  Since I'm trying to write CStdString
-// to work with any version of the Standard library, this presents a problem.
-//
-// The upshot of this is that I can't do 'use_facet' directly.  The MS' docs
-// tell me that I have to use a macro, _USE() instead.  Since _USE obviously
-// won't be available in other implementations, this means that I have to write
-// my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the
-// standard, use_facet.
-//
-// If you are having trouble with the SS_USE_FACET macro, in your implementation
-// of the Standard C++ Library, you can define your own version of SS_USE_FACET.
-
-#ifndef schMSG
-	#define schSTR(x)	   #x
-	#define schSTR2(x)	schSTR(x)
-	#define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc)
-#endif
-
-#ifndef SS_USE_FACET
-
-	// STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for
-	// all MSVC builds, erroneously in my opinion.  It causes problems for
-	// my SS_ANSI builds.  In my code, I always comment out that line.  You'll
-	// find it in   \stlport\config\stl_msvc.h
-
-	#if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 )
-
-		#if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER)
-			#ifdef SS_ANSI
-				#pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!)
-			#endif
-		#endif
-		#define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
-
-	#elif defined(_MSC_VER )
-
-		#define SS_USE_FACET(loc, fac) std::_USE(loc, fac)
-
-	// ...and
-	#elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
-
-        #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0)
-
-	#else
-
-		#define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
-
-	#endif
-
-#endif
-
-// =============================================================================
-// UNICODE/MBCS conversion macros.  Made to work just like the MFC/ATL ones.
-// =============================================================================
-
-#include <wchar.h>      // Added to Std Library with Amendment #1.
-
-// First define the conversion helper functions.  We define these regardless of
-// any preprocessor macro settings since their names won't collide. 
-
-// Not sure if we need all these headers.   I believe ANSI says we do.
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <wctype.h>
-#include <ctype.h>
-#include <stdlib.h>
-#ifndef va_start
-	#include <varargs.h>
-#endif
-
-
-#ifdef SS_NO_LOCALE
-
-	#if defined(_WIN32) || defined (_WIN32_WCE)
-
-		inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, 
-			UINT acp=CP_ACP)
-		{
-			ASSERT(0 != pSrcA);
-			ASSERT(0 != pDstW);
-			pDstW[0] = '\0';
-			MultiByteToWideChar(acp, 0, pSrcA, nSrc, pDstW, nDst);
-			return pDstW;
-		}
-		inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc, 
-			UINT acp=CP_ACP)
-		{
-			return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, acp);
-		}
-
-		inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, 
-			UINT acp=CP_ACP)
-		{
-			ASSERT(0 != pDstA);
-			ASSERT(0 != pSrcW);
-			pDstA[0] = '\0';
-			WideCharToMultiByte(acp, 0, pSrcW, nSrc, pDstA, nDst, 0, 0);
-			return pDstA;
-		}
-		inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, 
-			UINT acp=CP_ACP)
-		{
-			return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, acp);
-		}
-	#else
-	#endif
-
-#else
-
-	// StdCodeCvt - made to look like Win32 functions WideCharToMultiByte
-	//				and MultiByteToWideChar but uses locales in SS_ANSI
-	//				builds.  There are a number of overloads.
-	//              First argument is the destination buffer.
-	//              Second argument is the source buffer
-	//#if defined (SS_ANSI) || !defined (SS_WIN32)
-
-	// 'SSCodeCvt' - shorthand name for the codecvt facet we use
-
-	typedef std::codecvt<wchar_t, char, mbstate_t> SSCodeCvt;
-
-	inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc,
-		const std::locale& loc=std::locale())
-	{
-		ASSERT(0 != pSrcA);
-		ASSERT(0 != pDstW);
-
-		pDstW[0]					= '\0';	
-
-		if ( nSrc > 0 )
-		{
-			PCSTR pNextSrcA			= pSrcA;
-			PWSTR pNextDstW			= pDstW;
-			const SSCodeCvt& conv	= SS_USE_FACET(loc, SSCodeCvt);
-			SSCodeCvt::state_type st= { 0 };
-			SSCodeCvt::result res	= conv.in(st,
-                                      pSrcA, pSrcA + nSrc, pNextSrcA,
-                                      pDstW, pDstW + nDst, pNextDstW);
-
-			ASSERT(SSCodeCvt::ok == res);
-			ASSERT(SSCodeCvt::error != res);
-			ASSERT(pNextDstW >= pDstW);
-			ASSERT(pNextSrcA >= pSrcA);
-
-			// Null terminate the converted string
-
-			if ( pNextDstW - pDstW > nDst )
-				*(pDstW + nDst) = '\0';
-			else
-				*pNextDstW = '\0';
-		}
-		return pDstW;
-	}
-	inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc,
-		const std::locale& loc=std::locale())
-	{
-		return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, loc);
-	}
-
-	inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
-		const std::locale& loc=std::locale())
-	{
-		ASSERT(0 != pDstA);
-		ASSERT(0 != pSrcW);
-
-		pDstA[0]					= '\0';	
-
-		if ( nSrc > 0 )
-		{
-			PSTR pNextDstA			= pDstA;
-			PCWSTR pNextSrcW		= pSrcW;
-			const SSCodeCvt& conv	= SS_USE_FACET(loc, SSCodeCvt);
-			SSCodeCvt::state_type st= { 0 };
-			SSCodeCvt::result res	= conv.out(st,
-                                       pSrcW, pSrcW + nSrc, pNextSrcW,
-                                       pDstA, pDstA + nDst, pNextDstA);
-
-			ASSERT(SSCodeCvt::error != res);
-			ASSERT(SSCodeCvt::ok == res);	// strict, comment out for sanity
-			ASSERT(pNextDstA >= pDstA);
-			ASSERT(pNextSrcW >= pSrcW);
-
-			// Null terminate the converted string
-
-			if ( pNextDstA - pDstA > nDst )
-				*(pDstA + nDst) = '\0';
-			else
-				*pNextDstA = '\0';
-		}
-		return pDstA;
-	}
-
-	inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
-		const std::locale& loc=std::locale())
-	{
-		return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, loc);
-	}
-
-#endif
-
-
-
-// Unicode/MBCS conversion macros are only available on implementations of
-// the "C" library that have the non-standard _alloca function.  As far as I
-// know that's only Microsoft's though I've heard that the function exists
-// elsewhere.  
-    
-#if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION
-
-    #include <malloc.h>	// needed for _alloca
-
-    // Define our conversion macros to look exactly like Microsoft's to
-    // facilitate using this stuff both with and without MFC/ATL
-
-    #ifdef _CONVERSION_USES_THREAD_LOCALE
-
-	    #ifndef _DEBUG
-		    #define SSCVT int _cvt; _cvt; UINT _acp=GetACP(); \
-			    _acp; PCWSTR _pw; _pw; PCSTR _pa; _pa
-	    #else
-		    #define SSCVT int _cvt = 0; _cvt; UINT _acp=GetACP();\
-			     _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa
-	    #endif
-	    #define SSA2W(pa) (\
-		    ((_pa = pa) == 0) ? 0 : (\
-			    _cvt = (sslen(_pa)),\
-			    StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
-							_pa, _cvt, _acp)))
-	    #define SSW2A(pw) (\
-		    ((_pw = pw) == 0) ? 0 : (\
-			    _cvt = sslen(_pw), \
-			    StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
-					_pw, _cvt, _acp)))
-	#else
-
-	    #ifndef _DEBUG
-		    #define SSCVT int _cvt; _cvt; UINT _acp=CP_ACP; _acp;\
-			     PCWSTR _pw; _pw; PCSTR _pa; _pa
-	    #else
-		    #define SSCVT int _cvt = 0; _cvt; UINT _acp=CP_ACP; \
-			    _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa
-	    #endif
-	    #define SSA2W(pa) (\
-		    ((_pa = pa) == 0) ? 0 : (\
-			    _cvt = (sslen(_pa)),\
-			    StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
-					_pa, _cvt)))
-	    #define SSW2A(pw) (\
-		    ((_pw = pw) == 0) ? 0 : (\
-			    _cvt = (sslen(_pw)),\
-			    StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
-					_pw, _cvt)))
-    #endif
-
-    #define SSA2CW(pa) ((PCWSTR)SSA2W((pa)))
-    #define SSW2CA(pw) ((PCSTR)SSW2A((pw)))
-
-    #ifdef UNICODE
-	    #define SST2A	SSW2A
-	    #define SSA2T	SSA2W
-	    #define SST2CA	SSW2CA
-	    #define SSA2CT	SSA2CW
-		// (Did you get a compiler error here about not being able to convert
-		// PTSTR into PWSTR?  Then your _UNICODE and UNICODE flags are messed 
-		// up.  Best bet: #define BOTH macros before including any MS headers.)
-	    inline PWSTR	SST2W(PTSTR p)			{ return p; }
-	    inline PTSTR	SSW2T(PWSTR p)			{ return p; }
-	    inline PCWSTR	SST2CW(PCTSTR p)		{ return p; }
-	    inline PCTSTR	SSW2CT(PCWSTR p)		{ return p; }
-    #else
-	    #define SST2W	SSA2W
-	    #define SSW2T	SSW2A
-	    #define SST2CW	SSA2CW
-	    #define SSW2CT	SSW2CA
-	    inline PSTR		SST2A(PTSTR p)			{ return p; }
-	    inline PTSTR	SSA2T(PSTR p)			{ return p; }
-	    inline PCSTR	SST2CA(PCTSTR p)		{ return p; }
-	    inline PCTSTR	SSA2CT(PCSTR p)			{ return p; }
-    #endif // #ifdef UNICODE
-
-    #if defined(UNICODE)
-    // in these cases the default (TCHAR) is the same as OLECHAR
-	    inline PCOLESTR	SST2COLE(PCTSTR p)		{ return p; }
-	    inline PCTSTR	SSOLE2CT(PCOLESTR p)	{ return p; }
-	    inline POLESTR	SST2OLE(PTSTR p)		{ return p; }
-	    inline PTSTR	SSOLE2T(POLESTR p)		{ return p; }
-    #elif defined(OLE2ANSI)
-    // in these cases the default (TCHAR) is the same as OLECHAR
-	    inline PCOLESTR	SST2COLE(PCTSTR p)		{ return p; }
-	    inline PCTSTR	SSOLE2CT(PCOLESTR p)	{ return p; }
-	    inline POLESTR	SST2OLE(PTSTR p)		{ return p; }
-	    inline PTSTR	SSOLE2T(POLESTR p)		{ return p; }
-    #else
-	    //CharNextW doesn't work on Win95 so we use this
-	    #define SST2COLE(pa)	SSA2CW((pa))
-	    #define SST2OLE(pa)		SSA2W((pa))
-	    #define SSOLE2CT(po)	SSW2CA((po))
-	    #define SSOLE2T(po)		SSW2A((po))
-    #endif
-
-    #ifdef OLE2ANSI
-	    #define SSW2OLE		SSW2A
-	    #define SSOLE2W		SSA2W
-	    #define SSW2COLE	SSW2CA
-	    #define SSOLE2CW	SSA2CW
-	    inline POLESTR		SSA2OLE(PSTR p)		{ return p; }
-	    inline PSTR			SSOLE2A(POLESTR p)	{ return p; }
-	    inline PCOLESTR		SSA2COLE(PCSTR p)	{ return p; }
-	    inline PCSTR		SSOLE2CA(PCOLESTR p){ return p; }
-    #else
-	    #define SSA2OLE		SSA2W
-	    #define SSOLE2A		SSW2A
-	    #define SSA2COLE	SSA2CW
-	    #define SSOLE2CA	SSW2CA
-	    inline POLESTR		SSW2OLE(PWSTR p)	{ return p; }
-	    inline PWSTR		SSOLE2W(POLESTR p)	{ return p; }
-	    inline PCOLESTR		SSW2COLE(PCWSTR p)	{ return p; }
-	    inline PCWSTR		SSOLE2CW(PCOLESTR p){ return p; }
-    #endif
-
-    // Above we've defined macros that look like MS' but all have
-    // an 'SS' prefix.  Now we need the real macros.  We'll either
-    // get them from the macros above or from MFC/ATL. 
-
-	#if defined (USES_CONVERSION)
-
-		#define _NO_STDCONVERSION	// just to be consistent
-
-	#else
-
-		#ifdef _MFC_VER
-
-			#include <afxconv.h>
-			#define _NO_STDCONVERSION // just to be consistent
-
-		#else
-
-			#define USES_CONVERSION SSCVT
-			#define A2CW			SSA2CW
-			#define W2CA			SSW2CA
-			#define T2A				SST2A
-			#define A2T				SSA2T
-			#define T2W				SST2W
-			#define W2T				SSW2T
-			#define T2CA			SST2CA
-			#define A2CT			SSA2CT
-			#define T2CW			SST2CW
-			#define W2CT			SSW2CT
-			#define ocslen			sslen
-			#define ocscpy			sscpy
-			#define T2COLE			SST2COLE
-			#define OLE2CT			SSOLE2CT
-			#define T2OLE			SST2COLE
-			#define OLE2T			SSOLE2CT
-			#define A2OLE			SSA2OLE
-			#define OLE2A			SSOLE2A
-			#define W2OLE			SSW2OLE
-			#define OLE2W			SSOLE2W
-			#define A2COLE			SSA2COLE
-			#define OLE2CA			SSOLE2CA
-			#define W2COLE			SSW2COLE
-			#define OLE2CW			SSOLE2CW
-	
-		#endif // #ifdef _MFC_VER
-	#endif // #ifndef USES_CONVERSION
-#endif // #ifndef SS_NO_CONVERSION
-
-// Define ostring - generic name for std::basic_string<OLECHAR>
-
-#if !defined(ostring) && !defined(OSTRING_DEFINED)
-	typedef std::basic_string<OLECHAR> ostring;
-	#define OSTRING_DEFINED
-#endif
-
-// StdCodeCvt when there's no conversion to be done
-inline PSTR StdCodeCvt(PSTR pDst, int nDst, PCSTR pSrc, int nSrc)
-{
-	int nChars = SSMIN(nSrc, nDst);
-
-	if ( nChars > 0 )
-	{
-		pDst[0]				= '\0';
-		std::basic_string<char>::traits_type::copy(pDst, pSrc, nChars);
-//		std::char_traits<char>::copy(pDst, pSrc, nChars);
-		pDst[nChars]	= '\0';
-	}
-
-	return pDst;
-}
-inline PSTR StdCodeCvt(PSTR pDst, int nDst, PCUSTR pSrc, int nSrc)
-{
-	return StdCodeCvt(pDst, nDst, (PCSTR)pSrc, nSrc);
-}
-inline PUSTR StdCodeCvt(PUSTR pDst, int nDst, PCSTR pSrc, int nSrc)
-{
-	return (PUSTR)StdCodeCvt((PSTR)pDst, nDst, pSrc, nSrc);
-}
-
-inline PWSTR StdCodeCvt(PWSTR pDst, int nDst, PCWSTR pSrc, int nSrc)
-{
-	int nChars = SSMIN(nSrc, nDst);
-
-	if ( nChars > 0 )
-	{
-		pDst[0]				= '\0';
-		std::basic_string<wchar_t>::traits_type::copy(pDst, pSrc, nChars);
-//		std::char_traits<wchar_t>::copy(pDst, pSrc, nChars);
-		pDst[nChars]	= '\0';
-	}
-
-	return pDst;
-}
-
-
-// Define tstring -- generic name for std::basic_string<TCHAR>
-
-#if !defined(tstring) && !defined(TSTRING_DEFINED)
-	typedef std::basic_string<TCHAR> tstring;
-	#define TSTRING_DEFINED
-#endif
-
-// a very shorthand way of applying the fix for KB problem Q172398
-// (basic_string assignment bug)
-
-#if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
-	#define Q172398(x) (x).erase()
-#else
-	#define Q172398(x)
-#endif
-
-// =============================================================================
-// INLINE FUNCTIONS ON WHICH CSTDSTRING RELIES
-//
-// Usually for generic text mapping, we rely on preprocessor macro definitions
-// to map to string functions.  However the CStdStr<> template cannot use
-// macro-based generic text mappings because its character types do not get
-// resolved until template processing which comes AFTER macro processing.  In
-// other words, the preprocessor macro UNICODE is of little help to us in the
-// CStdStr template
-//
-// Therefore, to keep the CStdStr declaration simple, we have these inline
-// functions.  The template calls them often.  Since they are inline (and NOT
-// exported when this is built as a DLL), they will probably be resolved away
-// to nothing. 
-//
-// Without these functions, the CStdStr<> template would probably have to broken
-// out into two, almost identical classes.  Either that or it would be a huge,
-// convoluted mess, with tons of "if" statements all over the place checking the
-// size of template parameter CT.
-// =============================================================================
-
-#ifdef SS_NO_LOCALE
-
-	// --------------------------------------------------------------------------
-	// Win32 GetStringTypeEx wrappers
-	// --------------------------------------------------------------------------
-	inline bool wsGetStringType(LCID lc, DWORD dwT, PCSTR pS, int nSize, 
-		WORD* pWd)
-	{
-		return FALSE != GetStringTypeExA(lc, dwT, pS, nSize, pWd);
-	}
-	inline bool wsGetStringType(LCID lc, DWORD dwT, PCWSTR pS, int nSize, 
-		WORD* pWd)
-	{
-		return FALSE != GetStringTypeExW(lc, dwT, pS, nSize, pWd);
-	}
-
-
-	template<typename CT>
-		inline bool ssisspace (CT t)
-	{ 
-		WORD toYourMother;
-		return	wsGetStringType(GetThreadLocale(), CT_CTYPE1, &t, 1, &toYourMother)
-			&& 0 != (C1_BLANK & toYourMother);
-	}
-
-#endif
-
-// If they defined SS_NO_REFCOUNT, then we must convert all assignments
-
-#if defined (_MSC_VER) && (_MSC_VER < 1300)
-	#ifdef SS_NO_REFCOUNT
-		#define SSREF(x) (x).c_str()
-	#else
-		#define SSREF(x) (x)
-	#endif
-#else
-	#define SSREF(x) (x)
-#endif
-
-// -----------------------------------------------------------------------------
-// sslen: strlen/wcslen wrappers
-// -----------------------------------------------------------------------------
-template<typename CT> inline int sslen(const CT* pT)
-{
-	return 0 == pT ? 0 : (int)std::basic_string<CT>::traits_type::length(pT);
-//	return 0 == pT ? 0 : std::char_traits<CT>::length(pT);
-}
-inline SS_NOTHROW int sslen(const std::string& s)
-{
-	return static_cast<int>(s.length());
-}
-inline SS_NOTHROW int sslen(const std::wstring& s)
-{
-	return static_cast<int>(s.length());
-}
-
-// -----------------------------------------------------------------------------
-// sstolower/sstoupper -- convert characters to upper/lower case
-// -----------------------------------------------------------------------------
-
-#ifdef SS_NO_LOCALE
-	inline char sstoupper(char ch)		{ return (char)::toupper(ch); }
-	inline wchar_t sstoupper(wchar_t ch){ return (wchar_t)::towupper(ch); }
-	inline char sstolower(char ch)		{ return (char)::tolower(ch); }
-	inline wchar_t sstolower(wchar_t ch){ return (wchar_t)::tolower(ch); }
-#else
-	template<typename CT>
-	inline CT sstolower(const CT& t, const std::locale& loc = std::locale())
-	{
-		return std::tolower<CT>(t, loc);
-	}
-	template<typename CT>
-	inline CT sstoupper(const CT& t, const std::locale& loc = std::locale())
-	{
-		return std::toupper<CT>(t, loc);
-	}
-#endif
-
-// -----------------------------------------------------------------------------
-// ssasn: assignment functions -- assign "sSrc" to "sDst"
-// -----------------------------------------------------------------------------
-typedef std::string::size_type		SS_SIZETYPE; // just for shorthand, really
-typedef std::string::pointer		SS_PTRTYPE;  
-typedef std::wstring::size_type		SW_SIZETYPE;
-typedef std::wstring::pointer		SW_PTRTYPE;  
-
-inline void	ssasn(std::string& sDst, const std::string& sSrc)
-{
-	if ( sDst.c_str() != sSrc.c_str() )
-	{
-		sDst.erase();
-		sDst.assign(SSREF(sSrc));
-	}
-}
-inline void	ssasn(std::string& sDst, PCSTR pA)
-{
-	// Watch out for NULLs, as always.
-
-	if ( 0 == pA )
-	{
-		sDst.erase();
-	}
-
-	// If pA actually points to part of sDst, we must NOT erase(), but
-	// rather take a substring
-
-	else if ( pA >= sDst.c_str() && pA <= sDst.c_str() + sDst.size() )
-	{
-		sDst =sDst.substr(static_cast<SS_SIZETYPE>(pA-sDst.c_str()));
-	}
-
-	// Otherwise (most cases) apply the assignment bug fix, if applicable
-	// and do the assignment
-
-	else
-	{
-		Q172398(sDst);
-		sDst.assign(pA);
-	}
-}
-inline void	ssasn(std::string& sDst, const std::wstring& sSrc)
-{
-	if ( sSrc.empty() )
-	{
-		sDst.erase();
-	}
-	else
-	{
-		int nDst	= static_cast<int>(sSrc.size());
-
-		// In MBCS builds, pad the buffer to account for the possibility of
-		// some 3 byte characters.  Not perfect but should get most cases.
-
-#ifdef SS_MBCS
-		nDst	= static_cast<int>(static_cast<double>(nDst) * 1.3);
-#endif
-
-		sDst.resize(nDst+1);
-		PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
-			sSrc.c_str(), static_cast<int>(sSrc.size()));
-
-		// In MBCS builds, we don't know how long the destination string will be.
-
-#ifdef SS_MBCS
-		sDst.resize(sslen(szCvt));
-#else
-		szCvt;
-		sDst.resize(sSrc.size());
-#endif
-	}
-}
-inline void	ssasn(std::string& sDst, PCWSTR pW)
-{
-	int nSrc	= sslen(pW);
-	if ( nSrc > 0 )
-	{
-		int nSrc	= sslen(pW);
-		int nDst	= nSrc;
-
-		// In MBCS builds, pad the buffer to account for the possibility of
-		// some 3 byte characters.  Not perfect but should get most cases.
-
-#ifdef SS_MBCS
-		nDst	= static_cast<int>(static_cast<double>(nDst) * 1.3);
-#endif
-
-		sDst.resize(nDst + 1);
-		PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
-			pW, nSrc);
-
-		// In MBCS builds, we don't know how long the destination string will be.
-
-#ifdef SS_MBCS
-		sDst.resize(sslen(szCvt));
-#else
-		sDst.resize(nDst);
-		szCvt;
-#endif
-	}
-	else
-	{
-		sDst.erase();
-	}
-}
-inline void ssasn(std::string& sDst, const int nNull)
-{
-	UNUSED(nNull);
-	ASSERT(nNull==0);
-	sDst.assign("");
-}	
-inline void	ssasn(std::wstring& sDst, const std::wstring& sSrc)
-{
-	if ( sDst.c_str() != sSrc.c_str() )
-	{
-		sDst.erase();
-		sDst.assign(SSREF(sSrc));
-	}
-}
-inline void	ssasn(std::wstring& sDst, PCWSTR pW)
-{
-	// Watch out for NULLs, as always.
-
-	if ( 0 == pW )
-	{
-		sDst.erase();
-	}
-
-	// If pW actually points to part of sDst, we must NOT erase(), but
-	// rather take a substring
-
-	else if ( pW >= sDst.c_str() && pW <= sDst.c_str() + sDst.size() )
-	{
-		sDst = sDst.substr(static_cast<SW_SIZETYPE>(pW-sDst.c_str()));
-	}
-
-	// Otherwise (most cases) apply the assignment bug fix, if applicable
-	// and do the assignment
-
-	else
-	{
-		Q172398(sDst);
-		sDst.assign(pW);
-	}
-}
-#undef StrSizeType
-inline void	ssasn(std::wstring& sDst, const std::string& sSrc)
-{
-	if ( sSrc.empty() )
-	{
-		sDst.erase();
-	}
-	else
-	{
-		int nSrc	= static_cast<int>(sSrc.size());
-		int nDst	= nSrc;
-
-		sDst.resize(nSrc+1);
-		PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), nDst,
-			sSrc.c_str(), nSrc);
-
-		sDst.resize(sslen(szCvt));
-	}
-}
-inline void	ssasn(std::wstring& sDst, PCSTR pA)
-{
-	int nSrc	= sslen(pA);
-
-	if ( 0 == nSrc )
-	{
-		sDst.erase();
-	}
-	else
-	{
-		int nDst	= nSrc;
-		sDst.resize(nDst+1);
-		PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), nDst, pA,
-			nSrc);
-
-		sDst.resize(sslen(szCvt));
-	}
-}
-inline void ssasn(std::wstring& sDst, const int nNull)
-{
-	UNUSED(nNull);
-	ASSERT(nNull==0);
-	sDst.assign(L"");
-}
-
-
-// -----------------------------------------------------------------------------
-// ssadd: string object concatenation -- add second argument to first
-// -----------------------------------------------------------------------------
-inline void	ssadd(std::string& sDst, const std::wstring& sSrc)
-{
-	int nSrc	= static_cast<int>(sSrc.size());
-
-	if ( nSrc > 0 )
-	{
-		int nDst	= static_cast<int>(sDst.size());
-		int nAdd	= nSrc;
-
-		// In MBCS builds, pad the buffer to account for the possibility of
-		// some 3 byte characters.  Not perfect but should get most cases.
-
-#ifdef SS_MBCS
-		nAdd		= static_cast<int>(static_cast<double>(nAdd) * 1.3);
-#endif
-
-		sDst.resize(nDst+nAdd+1);
-		PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst),
-			nAdd, sSrc.c_str(), nSrc);
-
-#ifdef SS_MBCS
-		sDst.resize(nDst + sslen(szCvt));
-#else
-		sDst.resize(nDst + nAdd);
-		szCvt;
-#endif
-	}
-}
-inline void	ssadd(std::string& sDst, const std::string& sSrc)
-{
-	sDst += sSrc;
-}
-inline void	ssadd(std::string& sDst, PCWSTR pW)
-{
-	int nSrc		= sslen(pW);
-	if ( nSrc > 0 )
-	{
-		int nDst	= static_cast<int>(sDst.size());
-		int nAdd	= nSrc;
-
-#ifdef SS_MBCS
-		nAdd	= static_cast<int>(static_cast<double>(nAdd) * 1.3);
-#endif
-
-		sDst.resize(nDst + nAdd + 1);
-		PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst),
-			nAdd, pW, nSrc);
-
-#ifdef SS_MBCS
-		sDst.resize(nDst + sslen(szCvt));
-#else
-		sDst.resize(nDst + nSrc);
-		szCvt;
-#endif
-	}
-}
-inline void	ssadd(std::string& sDst, PCSTR pA)
-{
-	if ( pA )
-	{
-		// If the string being added is our internal string or a part of our
-		// internal string, then we must NOT do any reallocation without
-		// first copying that string to another object (since we're using a
-		// direct pointer)
-
-		if ( pA >= sDst.c_str() && pA <= sDst.c_str()+sDst.length())
-		{
-			if ( sDst.capacity() <= sDst.size()+sslen(pA) )
-				sDst.append(std::string(pA));
-			else
-				sDst.append(pA);
-		}
-		else
-		{
-			sDst.append(pA); 
-		}
-	}
-}
-inline void	ssadd(std::wstring& sDst, const std::wstring& sSrc)
-{
-	sDst += sSrc;
-}
-inline void	ssadd(std::wstring& sDst, const std::string& sSrc)
-{
-	if ( !sSrc.empty() )
-	{
-		int nSrc	= static_cast<int>(sSrc.size());
-		int nDst	= static_cast<int>(sDst.size());
-
-		sDst.resize(nDst + nSrc + 1);
-		PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst), 
-			nSrc, sSrc.c_str(), nSrc+1);
-
-#ifdef SS_MBCS
-		sDst.resize(nDst + sslen(szCvt));
-#else
-		sDst.resize(nDst + nSrc);
-		szCvt;
-#endif
-	}
-}
-inline void	ssadd(std::wstring& sDst, PCSTR pA)
-{
-	int nSrc		= sslen(pA);
-
-	if ( nSrc > 0 )
-	{
-		int nDst	= static_cast<int>(sDst.size());
-
-		sDst.resize(nDst + nSrc + 1);
-		PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst),
-			nSrc, pA, nSrc+1);
-
-#ifdef SS_MBCS
-		sDst.resize(nDst + sslen(szCvt));
-#else
-		sDst.resize(nDst + nSrc);
-		szCvt;
-#endif
-	}
-}
-inline void	ssadd(std::wstring& sDst, PCWSTR pW)
-{
-	if ( pW )
-	{
-		// If the string being added is our internal string or a part of our
-		// internal string, then we must NOT do any reallocation without
-		// first copying that string to another object (since we're using a
-		// direct pointer)
-
-		if ( pW >= sDst.c_str() && pW <= sDst.c_str()+sDst.length())
-		{
-			if ( sDst.capacity() <= sDst.size()+sslen(pW) )
-				sDst.append(std::wstring(pW));
-			else
-				sDst.append(pW);
-		}
-		else
-		{
-			sDst.append(pW);
-		}
-	}
-}
-
-
-// -----------------------------------------------------------------------------
-// sscmp: comparison (case sensitive, not affected by locale)
-// -----------------------------------------------------------------------------
-template<typename CT>
-inline int sscmp(const CT* pA1, const CT* pA2)
-{
-    CT f;
-    CT l;
-
-    do 
-    {
-	    f = *(pA1++);
-	    l = *(pA2++);
-    } while ( (f) && (f == l) );
-
-    return (int)(f - l);
-}
-
-// -----------------------------------------------------------------------------
-// ssicmp: comparison (case INsensitive, not affected by locale)
-// -----------------------------------------------------------------------------
-template<typename CT>
-inline int ssicmp(const CT* pA1, const CT* pA2)
-{
-	// Using the "C" locale = "not affected by locale"
-
-	std::locale loc = std::locale::classic();
-    const std::ctype<CT>& ct = SS_USE_FACET(loc, std::ctype<CT>);
-    CT f;
-    CT l;
-
-    do 
-    {
-	    f = ct.tolower(*(pA1++));
-	    l = ct.tolower(*(pA2++));
-    } while ( (f) && (f == l) );
-
-    return (int)(f - l);
-}
-
-// -----------------------------------------------------------------------------
-// ssupr/sslwr: Uppercase/Lowercase conversion functions
-// -----------------------------------------------------------------------------
-
-template<typename CT>
-inline void sslwr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
-{
-	SS_USE_FACET(loc, std::ctype<CT>).tolower(pT, pT+nLen);
-}
-template<typename CT>
-inline void ssupr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
-{
-	SS_USE_FACET(loc, std::ctype<CT>).toupper(pT, pT+nLen);
-}
-
-// -----------------------------------------------------------------------------
-// vsprintf/vswprintf or _vsnprintf/_vsnwprintf equivalents.  In standard
-// builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions.
-//
-// -----------------------------------------------------------------------------
-// Borland's headers put some ANSI "C" functions in the 'std' namespace. 
-// Promote them to the global namespace so we can use them here.
-
-#if defined(__BORLANDC__)
-    using std::vsprintf;
-    using std::vswprintf;
-#endif
-
-	// GNU is supposed to have vsnprintf and vsnwprintf.  But only the newer
-	// distributions do.
-
-#if defined(__GNUC__)
-
-	inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
-	{ 
-		return vsnprintf(pA, nCount, pFmtA, vl);
-	}
-	inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
-	{
-		return vswprintf(pW, nCount, pFmtW, vl);
-	}
-
-	// Else if this is VC++ in a regular (non-ANSI) build
-#elif defined(_MSC_VER) && !defined(SS_ANSI)
-
-	inline int	ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
-	{ 
-		return _vsnprintf(pA, nCount, pFmtA, vl);
-	}
-	inline int	ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
-	{
-		return _vsnwprintf(pW, nCount, pFmtW, vl);
-	}
-
-	// Else (an ANSI build) if they want to allow "dangerous" (i.e. non-length-
-	// checked) formatting
-#elif defined (SS_DANGEROUS_FORMAT)  // ignore buffer size parameter if needed?
-
-	inline int ssvsprintf(PSTR pA, size_t /*nCount*/, PCSTR pFmtA, va_list vl)
-	{
-		return vsprintf(pA, pFmtA, vl);
-	}
-
-	inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
-	{
-		// JMO: Some distributions of the "C" have a version of vswprintf that
-        // takes 3 arguments (e.g. Microsoft, Borland, GNU).  Others have a 
-        // version which takes 4 arguments (an extra "count" argument in the
-        // second position.  The best stab I can take at this so far is that if
-        // you are NOT running with MS, Borland, or GNU, then I'll assume you
-        // have the version that takes 4 arguments.
-        //
-        // I'm sure that these checks don't catch every platform correctly so if
-        // you get compiler errors on one of the lines immediately below, it's
-        // probably because your implemntation takes a different number of
-        // arguments.  You can comment out the offending line (and use the
-        // alternate version) or you can figure out what compiler flag to check
-        // and add that preprocessor check in.  Regardless, if you get an error
-        // on these lines, I'd sure like to hear from you about it.
-        //
-        // Thanks to Ronny Schulz for the SGI-specific checks here.
-
-//	#if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC)
-    #if    !defined(_MSC_VER) \
-        && !defined (__BORLANDC__) \
-        && !defined(__GNUC__) \
-        && !defined(__sgi)
-
-        return vswprintf(pW, nCount, pFmtW, vl);
-
-    // suddenly with the current SGI 7.3 compiler there is no such function as
-    // vswprintf and the substitute needs explicit casts to compile
-
-    #elif defined(__sgi)
-
-        nCount;
-        return vsprintf( (char *)pW, (char *)pFmtW, vl);
-
-    #else
-
-        nCount;
-        return vswprintf(pW, pFmtW, vl);
-
-    #endif
-
-	}
-
-	// OK, it's some kind of ANSI build but no "dangerous" formatting allowed
-#else 
-
-	// GOT COMPILER PROBLEMS HERE?
-	// ---------------------------
-	// Does your compiler choke on one or more of the following 2 functions?  It
-	// probably means that you don't have have either vsnprintf or vsnwprintf in
-	// your version of the CRT.  This is understandable since neither is an ANSI
-	// "C" function.  However it still leaves you in a dilemma.  In order to make
-	// this code build, you're going to have to to use some non-length-checked
-	// formatting functions that every CRT has:  vsprintf and vswprintf.  
-	//
-	// This is very dangerous.  With the proper erroneous (or malicious) code, it
-	// can lead to buffer overlows and crashing your PC.  Use at your own risk
-	// In order to use them, just #define SS_DANGEROUS_FORMAT at the top of
-	// this file.
-	//
-	// Even THEN you might not be all the way home due to some non-conforming
-	// distributions.  More on this in the comments below.
-
-	inline int	ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
-	{
-	#ifdef _MSC_VER
-			return _vsnprintf(pA, nCount, pFmtA, vl);
-	#else
-			return vsnprintf(pA, nCount, pFmtA, vl);
-	#endif
-	}
-	inline int	ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
-	{
-	#ifdef _MSC_VER
-			return _vsnwprintf(pW, nCount, pFmtW, vl);
-	#else
-			return vsnwprintf(pW, nCount, pFmtW, vl);
-	#endif
-	}
-
-#endif
-
-
-
-
-// -----------------------------------------------------------------------------
-// ssload: Type safe, overloaded ::LoadString wrappers
-// There is no equivalent of these in non-Win32-specific builds.  However, I'm
-// thinking that with the message facet, there might eventually be one
-// -----------------------------------------------------------------------------
-#if defined (SS_WIN32) && !defined(SS_ANSI)
-	inline int ssload(HMODULE hInst, UINT uId, PSTR pBuf, int nMax)
-	{
-		return ::LoadStringA(hInst, uId, pBuf, nMax);
-	}
-	inline int ssload(HMODULE hInst, UINT uId, PWSTR pBuf, int nMax)
-	{
-		return ::LoadStringW(hInst, uId, pBuf, nMax);
-	}
-#endif
-
-
-// -----------------------------------------------------------------------------
-// sscoll/ssicoll: Collation wrappers
-//		Note -- with MSVC I have reversed the arguments order here because the
-//		functions appear to return the opposite of what they should
-// -----------------------------------------------------------------------------
-#ifndef SS_NO_LOCALE
-template <typename CT>
-inline int sscoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
-{
-	const std::collate<CT>& coll =
-		SS_USE_FACET(std::locale(), std::collate<CT>);
-
-	return coll.compare(sz2, sz2+nLen2, sz1, sz1+nLen1);
-}
-template <typename CT>
-inline int ssicoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
-{
-	const std::locale loc;
-	const std::collate<CT>& coll = SS_USE_FACET(loc, std::collate<CT>);
-
-	// Some implementations seem to have trouble using the collate<>
-	// facet typedefs so we'll just default to basic_string and hope
-	// that's what the collate facet uses (which it generally should)
-
-//	std::collate<CT>::string_type s1(sz1);
-//	std::collate<CT>::string_type s2(sz2);
-	const std::basic_string<CT> sEmpty;
-    std::basic_string<CT> s1(sz1 ? sz1 : sEmpty.c_str());
-    std::basic_string<CT> s2(sz2 ? sz2 : sEmpty.c_str());
-
-	sslwr(const_cast<CT*>(s1.c_str()), nLen1, loc);
-	sslwr(const_cast<CT*>(s2.c_str()), nLen2, loc);
-	return coll.compare(s2.c_str(), s2.c_str()+nLen2,
-						s1.c_str(), s1.c_str()+nLen1);
-}
-#endif
-
-
-// -----------------------------------------------------------------------------
-// ssfmtmsg: FormatMessage equivalents.  Needed because I added a CString facade
-// Again -- no equivalent of these on non-Win32 builds but their might one day
-// be one if the message facet gets implemented
-// -----------------------------------------------------------------------------
-#if defined (SS_WIN32) && !defined(SS_ANSI)
-	inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
-						  DWORD dwLangId, PSTR pBuf, DWORD nSize,
-						  va_list* vlArgs)
-	{ 
-		return FormatMessageA(dwFlags, pSrc, dwMsgId, dwLangId,
-							  pBuf, nSize,vlArgs);
-	}
-	inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
-						  DWORD dwLangId, PWSTR pBuf, DWORD nSize,
-						  va_list* vlArgs)
-	{
-		return FormatMessageW(dwFlags, pSrc, dwMsgId, dwLangId,
-							  pBuf, nSize,vlArgs);
-	}
-#else
-#endif
- 
-
-
-// FUNCTION: sscpy.  Copies up to 'nMax' characters from pSrc to pDst.
-// -----------------------------------------------------------------------------
-// FUNCTION:  sscpy
-//		inline int sscpy(PSTR pDst, PCSTR pSrc, int nMax=-1);
-//		inline int sscpy(PUSTR pDst,  PCSTR pSrc, int nMax=-1)
-//		inline int sscpy(PSTR pDst, PCWSTR pSrc, int nMax=-1);
-//		inline int sscpy(PWSTR pDst, PCWSTR pSrc, int nMax=-1);
-//		inline int sscpy(PWSTR pDst, PCSTR pSrc, int nMax=-1);
-//
-// DESCRIPTION:
-//		This function is very much (but not exactly) like strcpy.  These
-//		overloads simplify copying one C-style string into another by allowing
-//		the caller to specify two different types of strings if necessary.
-//
-//		The strings must NOT overlap
-//
-//		"Character" is expressed in terms of the destination string, not
-//		the source.  If no 'nMax' argument is supplied, then the number of
-//		characters copied will be sslen(pSrc).  A NULL terminator will
-//		also be added so pDst must actually be big enough to hold nMax+1
-//		characters.  The return value is the number of characters copied,
-//		not including the NULL terminator.
-//
-// PARAMETERS: 
-//		pSrc - the string to be copied FROM.  May be a char based string, an
-//			   MBCS string (in Win32 builds) or a wide string (wchar_t).
-//		pSrc - the string to be copied TO.  Also may be either MBCS or wide
-//		nMax - the maximum number of characters to be copied into szDest.  Note
-//			   that this is expressed in whatever a "character" means to pDst.
-//			   If pDst is a wchar_t type string than this will be the maximum
-//			   number of wchar_ts that my be copied.  The pDst string must be
-//			   large enough to hold least nMaxChars+1 characters.
-//			   If the caller supplies no argument for nMax this is a signal to
-//			   the routine to copy all the characters in pSrc, regardless of
-//			   how long it is.
-//
-// RETURN VALUE: none
-// -----------------------------------------------------------------------------
-template<typename CT1, typename CT2>
-inline int sscpycvt(CT1* pDst, const CT2* pSrc, int nMax)
-{
-	// Note -- we assume pDst is big enough to hold pSrc.  If not, we're in
-	// big trouble.  No bounds checking.  Caveat emptor.
-	
-	int nSrc = sslen(pSrc);
-
-	const CT1* szCvt = StdCodeCvt(pDst, nMax, pSrc, nSrc);
-
-	// If we're copying the same size characters, then all the "code convert"
-	// just did was basically memcpy so the #of characters copied is the same
-	// as the number requested.  I should probably specialize this function
-	// template to achieve this purpose as it is silly to do a runtime check
-	// of a fact known at compile time.  I'll get around to it.
-
-	return sslen(szCvt);
-}
-
-inline int sscpycvt(PSTR pDst, PCSTR pSrc, int nMax)
-{
-	int nCount = nMax;
-	for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount)
-		std::basic_string<char>::traits_type::assign(*pDst, *pSrc);
-
-	*pDst =  '\0';
-	return nMax - nCount;
-}
-inline int sscpycvt(PWSTR pDst, PCWSTR pSrc, int nMax)
-{
-	int nCount = nMax;
-	for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount)
-		std::basic_string<wchar_t>::traits_type::assign(*pDst, *pSrc);
-
-	*pDst = L'\0';
-	return nMax - nCount;
-}
-inline int sscpycvt(PWSTR pDst, PCSTR pSrc, int nMax)
-{
-	// Note -- we assume pDst is big enough to hold pSrc.  If not, we're in
-	// big trouble.  No bounds checking.  Caveat emptor.
-
-	const PWSTR szCvt = StdCodeCvt(pDst, nMax, pSrc, nMax);
-	return sslen(szCvt);
-}
-
-template<typename CT1, typename CT2>
-inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax, int nLen)
-{
-	return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen));
-}
-template<typename CT1, typename CT2>
-inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax)
-{
-	return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc)));
-}
-template<typename CT1, typename CT2>
-inline int sscpy(CT1* pDst, const CT2* pSrc)
-{
-	return sscpycvt(pDst, pSrc, sslen(pSrc));
-}
-template<typename CT1, typename CT2>
-inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc, int nMax)
-{
-	return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int)sSrc.length()));
-}
-template<typename CT1, typename CT2>
-inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc)
-{
-	return sscpycvt(pDst, sSrc.c_str(), (int)sSrc.length());
-}
-
-#ifdef SS_INC_COMDEF
-	template<typename CT1>
-	inline int sscpy(CT1* pDst, const _bstr_t& bs, int nMax)
-	{
-		return sscpycvt(pDst, static_cast<PCOLESTR>(bs),
-            SSMIN(nMax, static_cast<int>(bs.length())));
-	}
-	template<typename CT1>
-	inline int sscpy(CT1* pDst, const _bstr_t& bs)
-	{
-		return sscpy(pDst, bs, static_cast<int>(bs.length()));
-	}
-#endif
-
-
-// -----------------------------------------------------------------------------
-// Functional objects for changing case.  They also let you pass locales
-// -----------------------------------------------------------------------------
-
-#ifdef SS_NO_LOCALE
-	template<typename CT>
-	struct SSToUpper : public std::unary_function<CT, CT>
-	{
-		inline CT operator()(const CT& t) const
-		{
-			return sstoupper(t);
-		}
-	};
-	template<typename CT>
-	struct SSToLower : public std::unary_function<CT, CT>
-	{
-		inline CT operator()(const CT& t) const
-		{
-			return sstolower(t);
-		}
-	};
-#else
-	template<typename CT>
-	struct SSToUpper : public std::binary_function<CT, std::locale, CT>
-	{
-		inline CT operator()(const CT& t, const std::locale& loc) const
-		{
-			return sstoupper<CT>(t, loc);
-		}
-	};
-	template<typename CT>
-	struct SSToLower : public std::binary_function<CT, std::locale, CT>
-	{
-		inline CT operator()(const CT& t, const std::locale& loc) const
-		{
-			return sstolower<CT>(t, loc);
-		}
-	};
-#endif
-
-// This struct is used for TrimRight() and TrimLeft() function implementations.
-//template<typename CT>
-//struct NotSpace : public std::unary_function<CT, bool>
-//{
-//	const std::locale& loc;
-//	inline NotSpace(const std::locale& locArg) : loc(locArg) {}
-//	inline bool operator() (CT t) { return !std::isspace(t, loc); }
-//};
-template<typename CT>
-struct NotSpace : public std::unary_function<CT, bool>
-{
-	// DINKUMWARE BUG:
-	// Note -- using std::isspace in a COM DLL gives us access violations
-	// because it causes the dynamic addition of a function to be called
-	// when the library shuts down.  Unfortunately the list is maintained
-	// in DLL memory but the function is in static memory.  So the COM DLL
-	// goes away along with the function that was supposed to be called,
-	// and then later when the DLL CRT shuts down it unloads the list and
-	// tries to call the long-gone function.
-	// This is DinkumWare's implementation problem.  If you encounter this
-	// problem, you may replace the calls here with good old isspace() and
-	// iswspace() from the CRT unless they specify SS_ANSI
-    
-#ifdef SS_NO_LOCALE
-	
-	bool operator() (CT t) const { return !ssisspace(t); }
-
-#else
-	const std::locale loc;
-	NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {}
-	bool operator() (CT t) const { return !std::isspace(t, loc); }
-#endif
-};
-
-
-
-
-//			Now we can define the template (finally!)
-// =============================================================================
-// TEMPLATE: CStdStr
-//		template<typename CT> class CStdStr : public std::basic_string<CT>
-//
-// REMARKS:
-//		This template derives from basic_string<CT> and adds some MFC CString-
-//		like functionality
-//
-//		Basically, this is my attempt to make Standard C++ library strings as
-//		easy to use as the MFC CString class.
-//
-//		Note that although this is a template, it makes the assumption that the
-//		template argument (CT, the character type) is either char or wchar_t.  
-// =============================================================================
-
-//#define CStdStr _SS	// avoid compiler warning 4786
-
-//    template<typename ARG> ARG& FmtArg(ARG& arg)  { return arg; }
-//    PCSTR  FmtArg(const std::string& arg)  { return arg.c_str(); }
-//    PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); }
-
-template<typename ARG>
-struct FmtArg
-{
-    explicit FmtArg(const ARG& arg) : a_(arg) {}
-    const ARG& operator()() const { return a_; }
-    const ARG& a_;
-private:
-    FmtArg& operator=(const FmtArg&) { return *this; }
-};
-
-template<typename CT>
-class CStdStr : public std::basic_string<CT>
-{
-	// Typedefs for shorter names.  Using these names also appears to help
-	// us avoid some ambiguities that otherwise arise on some platforms
-
-	#define MYBASE std::basic_string<CT>				 // my base class
-	//typedef typename std::basic_string<CT>		MYBASE;	 // my base class
-	typedef CStdStr<CT>							MYTYPE;	 // myself
-	typedef typename MYBASE::const_pointer		PCMYSTR; // PCSTR or PCWSTR 
-	typedef typename MYBASE::pointer			PMYSTR;	 // PSTR or PWSTR
-	typedef typename MYBASE::iterator			MYITER;  // my iterator type
-	typedef typename MYBASE::const_iterator		MYCITER; // you get the idea...
-	typedef typename MYBASE::reverse_iterator	MYRITER;
-	typedef typename MYBASE::size_type			MYSIZE;   
-	typedef typename MYBASE::value_type			MYVAL; 
-	typedef typename MYBASE::allocator_type		MYALLOC;
-	
-public:
-	// shorthand conversion from PCTSTR to string resource ID
-	#define SSRES(pctstr)  LOWORD(reinterpret_cast<unsigned long>(pctstr))	
-
-	bool TryLoad(const void* pT)
-	{
-		bool bLoaded = false;
-
-#if defined(SS_WIN32) && !defined(SS_ANSI)
-		if ( ( pT != NULL ) && SS_IS_INTRESOURCE(pT) )
-		{
-			UINT nId = LOWORD(reinterpret_cast<unsigned long>(pT));
-			if ( !LoadString(nId) )
-			{
-				TRACE(_T("Can't load string %u\n"), SSRES(pT));
-			}
-			bLoaded = true;
-		}
-#endif
-
-		return bLoaded;
-	}
-
-
-	// CStdStr inline constructors
-	CStdStr()
-	{
-	}
-
-	CStdStr(const MYTYPE& str) : MYBASE(SSREF(str))
-	{
-	}
-
-	CStdStr(const std::string& str)
-	{
-		ssasn(*this, SSREF(str));
-	}
-
-	CStdStr(const std::wstring& str)
-	{
-		ssasn(*this, SSREF(str));
-	}
-
-	CStdStr(PCMYSTR pT, MYSIZE n) : MYBASE(NULL == pT ? MYTYPE().c_str() : pT, n)
-	{
-	}
-
-#ifdef SS_UNSIGNED
-	CStdStr(PCUSTR pU)
-	{
-		*this = reinterpret_cast<PCSTR>(pU);
-	}
-#endif
-
-	CStdStr(PCSTR pA)
-	{
-	#ifdef SS_ANSI
-		*this = pA;
-	#else
-		if ( !TryLoad(pA) )
-			*this = pA;
-	#endif
-	}
-
-	CStdStr(PCWSTR pW)
-	{
-	#ifdef SS_ANSI
-		*this = pW;
-	#else
-		if ( !TryLoad(pW) )
-			*this = pW;
-	#endif
-	}
-
-	CStdStr(MYCITER first, MYCITER last)
-		: MYBASE(first, last)
-	{
-	}
-
-	CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC())
-		: MYBASE(nSize, ch, al)
-	{
-	}
-
-	#ifdef SS_INC_COMDEF
-		CStdStr(const _bstr_t& bstr)
-		{
-			if ( bstr.length() > 0 )
-				this->append(static_cast<PCMYSTR>(bstr), bstr.length());
-		}
-	#endif
-
-	// CStdStr inline assignment operators -- the ssasn function now takes care
-	// of fixing  the MSVC assignment bug (see knowledge base article Q172398).
-	MYTYPE& operator=(const MYTYPE& str)
-	{ 
-		ssasn(*this, str); 
-		return *this;
-	}
-
-	MYTYPE& operator=(const std::string& str)
-	{
-		ssasn(*this, str);
-		return *this;
-	}
-
-	MYTYPE& operator=(const std::wstring& str)
-	{
-		ssasn(*this, str);
-		return *this;
-	}
-
-	MYTYPE& operator=(PCSTR pA)
-	{
-		ssasn(*this, pA);
-		return *this;
-	}
-
-	MYTYPE& operator=(PCWSTR pW)
-	{
-		ssasn(*this, pW);
-		return *this;
-	}
-
-#ifdef SS_UNSIGNED
-	MYTYPE& operator=(PCUSTR pU)
-	{
-		ssasn(*this, reinterpret_cast<PCSTR>(pU));
-		return *this;
-	}
-#endif
-
-	MYTYPE& operator=(CT t)
-	{
-		Q172398(*this);
-		this->assign(1, t);
-		return *this;
-	}
-
-	#ifdef SS_INC_COMDEF
-		MYTYPE& operator=(const _bstr_t& bstr)
-		{
-			if ( bstr.length() > 0 )
-			{
-				this->assign(static_cast<PCMYSTR>(bstr), bstr.length());
-				return *this;
-			}
-			else
-			{
-				this->erase();
-				return *this;
-			}
-		}
-	#endif
-
-
-	// Overloads  also needed to fix the MSVC assignment bug (KB: Q172398)
-	//  *** Thanks to Pete The Plumber for catching this one ***
-	// They also are compiled if you have explicitly turned off refcounting
-	#if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT) 
-
-		MYTYPE& assign(const MYTYPE& str)
-		{
-			Q172398(*this);
-			sscpy(GetBuffer(str.size()+1), SSREF(str));
-			this->ReleaseBuffer(str.size());
-			return *this;
-		}
-
-		MYTYPE& assign(const MYTYPE& str, MYSIZE nStart, MYSIZE nChars)
-		{
-			// This overload of basic_string::assign is supposed to assign up to
-			// <nChars> or the NULL terminator, whichever comes first.  Since we
-			// are about to call a less forgiving overload (in which <nChars>
-			// must be a valid length), we must adjust the length here to a safe
-			// value.  Thanks to Ullrich Poll�hne for catching this bug
-
-			nChars		= SSMIN(nChars, str.length() - nStart);
-			MYTYPE strTemp(str.c_str()+nStart, nChars);
-			Q172398(*this);
-			this->assign(strTemp);
-			return *this;
-		}
-
-		MYTYPE& assign(const MYBASE& str)
-		{
-			ssasn(*this, str);
-			return *this;
-		}
-
-		MYTYPE& assign(const MYBASE& str, MYSIZE nStart, MYSIZE nChars)
-		{
-			// This overload of basic_string::assign is supposed to assign up to
-			// <nChars> or the NULL terminator, whichever comes first.  Since we
-			// are about to call a less forgiving overload (in which <nChars>
-			// must be a valid length), we must adjust the length here to a safe
-			// value. Thanks to Ullrich Poll�hne for catching this bug
-
-			nChars		= SSMIN(nChars, str.length() - nStart);
-
-			// Watch out for assignment to self
-
-			if ( this == &str )
-			{
-				MYTYPE strTemp(str.c_str() + nStart, nChars);
-				static_cast<MYBASE*>(this)->assign(strTemp);
-			}
-			else
-			{
-				Q172398(*this);
-				static_cast<MYBASE*>(this)->assign(str.c_str()+nStart, nChars);
-			}
-			return *this;
-		}
-
-		MYTYPE& assign(const CT* pC, MYSIZE nChars)
-		{
-			// Q172398 only fix -- erase before assigning, but not if we're
-			// assigning from our own buffer
-
-	#if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
-			if ( !this->empty() &&
-				( pC < this->data() || pC > this->data() + this->capacity() ) )
-			{
-				this->erase();
-			}
-	#endif
-			Q172398(*this);
-			static_cast<MYBASE*>(this)->assign(pC, nChars);
-			return *this;
-		}
-
-		MYTYPE& assign(MYSIZE nChars, MYVAL val)
-		{
-			Q172398(*this);
-			static_cast<MYBASE*>(this)->assign(nChars, val);
-			return *this;
-		}
-
-		MYTYPE& assign(const CT* pT)
-		{
-			return this->assign(pT, MYBASE::traits_type::length(pT));
-		}
-
-		MYTYPE& assign(MYCITER iterFirst, MYCITER iterLast)
-		{
-	#if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) 
-			// Q172398 fix.  don't call erase() if we're assigning from ourself
-			if ( iterFirst < this->begin() ||
-                 iterFirst > this->begin() + this->size() )
-            {
-				this->erase()
-            }
-	#endif
-			this->replace(this->begin(), this->end(), iterFirst, iterLast);
-			return *this;
-		}
-	#endif
-
-
-	// -------------------------------------------------------------------------
-	// CStdStr inline concatenation.
-	// -------------------------------------------------------------------------
-	MYTYPE& operator+=(const MYTYPE& str)
-	{
-		ssadd(*this, str);
-		return *this;
-	}
-
-	MYTYPE& operator+=(const std::string& str)
-	{
-		ssadd(*this, str);
-		return *this; 
-	}
-
-	MYTYPE& operator+=(const std::wstring& str)
-	{
-		ssadd(*this, str);
-		return *this;
-	}
-
-	MYTYPE& operator+=(PCSTR pA)
-	{
-		ssadd(*this, pA);
-		return *this;
-	}
-
-	MYTYPE& operator+=(PCWSTR pW)
-	{
-		ssadd(*this, pW);
-		return *this;
-	}
-
-	MYTYPE& operator+=(CT t)
-	{
-		this->append(1, t);
-		return *this;
-	}
-	#ifdef SS_INC_COMDEF	// if we have _bstr_t, define a += for it too.
-		MYTYPE& operator+=(const _bstr_t& bstr)
-		{
-			return this->operator+=(static_cast<PCMYSTR>(bstr));
-		}
-	#endif
-
-
-	// -------------------------------------------------------------------------
-	// Case changing functions
-	// -------------------------------------------------------------------------
-
-    MYTYPE& ToUpper(const std::locale& loc=std::locale())
-	{
-		// Note -- if there are any MBCS character sets in which the lowercase
-		// form a character takes up a different number of bytes than the
-		// uppercase form, this would probably not work...
-
-		std::transform(this->begin(),
-					   this->end(),
-					   this->begin(),
-#ifdef SS_NO_LOCALE
-					   SSToUpper<CT>());
-#else
-					   std::bind2nd(SSToUpper<CT>(), loc));
-#endif
-
-		// ...but if it were, this would probably work better.  Also, this way
-		// seems to be a bit faster when anything other then the "C" locale is
-		// used...
-
-//		if ( !empty() )
-//		{
-//			ssupr(this->GetBuf(), this->size(), loc);
-//			this->RelBuf();
-//		}
-
-		return *this;
-	}
-
-	MYTYPE& ToLower(const std::locale& loc=std::locale())
-	{
-		// Note -- if there are any MBCS character sets in which the lowercase
-		// form a character takes up a different number of bytes than the
-		// uppercase form, this would probably not work...
-
-		std::transform(this->begin(),
-					   this->end(),
-					   this->begin(),
-#ifdef SS_NO_LOCALE
-					   SSToLower<CT>());
-#else
-					   std::bind2nd(SSToLower<CT>(), loc));
-#endif
-
-		// ...but if it were, this would probably work better.  Also, this way
-		// seems to be a bit faster when anything other then the "C" locale is
-		// used...
-
-//		if ( !empty() )
-//		{
-//			sslwr(this->GetBuf(), this->size(), loc);
-//			this->RelBuf();
-//		}
-		return *this;
-	}
-
-
-	MYTYPE& Normalize()
-	{
-		return Trim().ToLower();
-	}
-
-
-	// -------------------------------------------------------------------------
-	// CStdStr -- Direct access to character buffer.  In the MS' implementation,
-	// the at() function that we use here also calls _Freeze() providing us some
-	// protection from multithreading problems associated with ref-counting.
-    // In VC 7 and later, of course, the ref-counting stuff is gone.
-	// -------------------------------------------------------------------------
-
-	CT* GetBuf(int nMinLen=-1)
-	{
-		if ( static_cast<int>(this->size()) < nMinLen )
-			this->resize(static_cast<MYSIZE>(nMinLen));
-
-		return this->empty() ? const_cast<CT*>(this->data()) : &(this->at(0));
-	}
-
-	CT* SetBuf(int nLen)
-	{
-		nLen = ( nLen > 0 ? nLen : 0 );
-		if ( this->capacity() < 1 && nLen == 0 )
-			this->resize(1);
-
-		this->resize(static_cast<MYSIZE>(nLen));
-		return const_cast<CT*>(this->data());
-	}
-	void RelBuf(int nNewLen=-1)
-	{
-		this->resize(static_cast<MYSIZE>(nNewLen > -1 ? nNewLen :
-                                                        sslen(this->c_str())));
-	}
-
-	void BufferRel()		 { RelBuf(); }			// backwards compatability
-	CT*  Buffer()			 { return GetBuf(); }	// backwards compatability
-	CT*  BufferSet(int nLen) { return SetBuf(nLen);}// backwards compatability
-
-	bool Equals(const CT* pT, bool bUseCase=false) const
-	{
-		return  0 == (bUseCase ? this->compare(pT) : ssicmp(this->c_str(), pT));
-	} 
-
-	// -------------------------------------------------------------------------
-	// FUNCTION:  CStdStr::Load
-	// REMARKS:
-	//		Loads string from resource specified by nID
-	//
-	// PARAMETERS:
-	//		nID - resource Identifier.  Purely a Win32 thing in this case
-	//
-	// RETURN VALUE:
-	//		true if successful, false otherwise
-	// -------------------------------------------------------------------------
-
-#ifndef SS_ANSI
-
-	bool Load(UINT nId, HMODULE hModule=NULL)
-	{
-		bool bLoaded		= false;	// set to true of we succeed.
-
-	#ifdef _MFC_VER		// When in Rome (or MFC land)...
-
-		// If they gave a resource handle, use it.  Note - this is archaic
-		// and not really what I would recommend.  But then again, in MFC
-		// land, you ought to be using CString for resources anyway since
-		// it walks the resource chain for you.
-
-		HMODULE hModuleOld = NULL;
-
-		if ( NULL != hModule )
-		{
-			hModuleOld = AfxGetResourceHandle();
-			AfxSetResourceHandle(hModule);
-		}
-
-		// ...load the string
-
-		CString strRes;
-		bLoaded				= FALSE != strRes.LoadString(nId);
-
-		// ...and if we set the resource handle, restore it.
-
-		if ( NULL != hModuleOld )
-			AfxSetResourceHandle(hModule);
-
-		if ( bLoaded )
-			*this			= strRes;
-
-	#else // otherwise make our own hackneyed version of CString's Load
-		
-		// Get the resource name and module handle
-
-		if ( NULL == hModule )
-			hModule			= GetResourceHandle();
-
-		PCTSTR szName		= MAKEINTRESOURCE((nId>>4)+1); // lifted 
-		DWORD dwSize		= 0;
-
-		// No sense continuing if we can't find the resource
-
-		HRSRC hrsrc			= ::FindResource(hModule, szName, RT_STRING);
-
-		if ( NULL == hrsrc )
-		{
-			TRACE(_T("Cannot find resource %d: 0x%X"), nId, ::GetLastError());
-		}
-		else if ( 0 == (dwSize = ::SizeofResource(hModule, hrsrc) / sizeof(CT)))
-		{
-			TRACE(_T("Cant get size of resource %d 0x%X\n"),nId,GetLastError());
-		}
-		else
-		{
-			bLoaded			= 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize);
-			ReleaseBuffer();
-		}
-
-	#endif  // #ifdef _MFC_VER
-
-		if ( !bLoaded )
-			TRACE(_T("String not loaded 0x%X\n"), ::GetLastError());
-
-		return bLoaded;
-	}
-
-#endif  // #ifdef SS_ANSI
-	
-	// -------------------------------------------------------------------------
-	// FUNCTION:  CStdStr::Format
-	//		void _cdecl Formst(CStdStringA& PCSTR szFormat, ...)
-	//		void _cdecl Format(PCSTR szFormat);
-	//           
-	// DESCRIPTION:
-	//		This function does sprintf/wsprintf style formatting on CStdStringA
-	//		objects.  It looks a lot like MFC's CString::Format.  Some people
-	//		might even call this identical.  Fortunately, these people are now
-	//		dead... heh heh.
-	//
-	// PARAMETERS: 
-	//		nId - ID of string resource holding the format string
-	//		szFormat - a PCSTR holding the format specifiers
-	//		argList - a va_list holding the arguments for the format specifiers.
-	//
-	// RETURN VALUE:  None.
-	// -------------------------------------------------------------------------
-	// formatting (using wsprintf style formatting)
-
-    // If they want a Format() function that safely handles string objects
-    // without casting
- 
-#ifdef SS_SAFE_FORMAT       
-    
-    // Question:  Joe, you wacky coder you, why do you have so many overloads
-    //      of the Format() function
-    // Answer:  One reason only - CString compatability.  In short, by making
-    //      the Format() function a template this way, I can do strong typing
-    //      and allow people to pass CStdString arguments as fillers for
-    //      "%s" format specifiers without crashing their program!  The downside
-    //      is that I need to overload on the number of arguments.   If you are
-    //      passing more arguments than I have listed below in any of my
-    //      overloads, just add another one.
-    //
-    //      Yes, yes, this is really ugly.  In essence what I am doing here is
-    //      protecting people from a bad (and incorrect) programming practice
-    //      that they should not be doing anyway.  I am protecting them from
-    //      themselves.  Why am I doing this?  Well, if you had any idea the
-    //      number of times I've been emailed by people about this
-    //      "incompatability" in my code, you wouldn't ask.
-
-	void Fmt(const CT* szFmt, ...)
-	{
-		va_list argList;
-		va_start(argList, szFmt);
-		FormatV(szFmt, argList);
-		va_end(argList);
-	}
-
-#ifndef SS_ANSI
-
-    void Format(UINT nId)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) ) 
-            this->swap(strFmt);
-    }
-    template<class A1>
-    void Format(UINT nId, const A1& v)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-            Fmt(strFmt, FmtArg<A1>(v)());
-    }
-    template<class A1, class A2>
-    void Format(UINT nId, const A1& v1, const A2& v2)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-           Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)());
-    }
-    template<class A1, class A2, class A3>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(),FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(),FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-           Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(), FmtArg<A10>(v10)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(),FmtArg<A10>(v10)(),FmtArg<A11>(v11)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-                FmtArg<A12>(v12)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-                FmtArg<A12>(v12)(), FmtArg<A13>(v13)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-                FmtArg<A12>(v12)(), FmtArg<A13>(v13)(),FmtArg<A14>(v14)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14, class A15>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14, const A15& v15)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-                FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
-                FmtArg<A15>(v15)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14, class A15, class A16>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14, const A15& v15,
-                const A16& v16)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-                FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
-                FmtArg<A15>(v15)(), FmtArg<A16>(v16)());
-        }
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14, class A15, class A16, class A17>
-    void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14, const A15& v15,
-                const A16& v16, const A17& v17)
-    {
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-        {
-            Fmt(strFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-                FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-                FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-                FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-                FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
-                FmtArg<A15>(v15)(),FmtArg<A16>(v16)(),FmtArg<A17>(v17)());
-        }
-    }
-    
-#endif // #ifndef SS_ANSI
-
-    // ...now the other overload of Format: the one that takes a string literal
-
-    void Format(const CT* szFmt)
-    {
-        *this = szFmt;
-    }
-    template<class A1>
-    void Format(const CT* szFmt, const A1& v)
-    {
-        Fmt(szFmt, FmtArg<A1>(v)());
-    }
-    template<class A1, class A2>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)());
-    }
-    template<class A1, class A2, class A3>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)());
-    }
-    template<class A1, class A2, class A3, class A4>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(), FmtArg<A10>(v10)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(),FmtArg<A10>(v10)(),FmtArg<A11>(v11)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-            FmtArg<A12>(v12)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-            FmtArg<A12>(v12)(), FmtArg<A13>(v13)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-            FmtArg<A12>(v12)(), FmtArg<A13>(v13)(),FmtArg<A14>(v14)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14, class A15>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14, const A15& v15)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-            FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
-            FmtArg<A15>(v15)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14, class A15, class A16>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14, const A15& v15,
-                const A16& v16)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-            FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
-            FmtArg<A15>(v15)(), FmtArg<A16>(v16)());
-    }
-    template<class A1, class A2, class A3, class A4, class A5, class A6,
-        class A7, class A8, class A9, class A10, class A11, class A12,
-        class A13, class A14, class A15, class A16, class A17>
-    void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3,
-                const A4& v4, const A5& v5, const A6& v6, const A7& v7,
-                const A8& v8, const A9& v9, const A10& v10, const A11& v11,
-                const A12& v12, const A13& v13, const A14& v14, const A15& v15,
-                const A16& v16, const A17& v17)
-    {
-        Fmt(szFmt, FmtArg<A1>(v1)(), FmtArg<A2>(v2)(),
-            FmtArg<A3>(v3)(), FmtArg<A4>(v4)(), FmtArg<A5>(v5)(),
-            FmtArg<A6>(v6)(), FmtArg<A7>(v7)(), FmtArg<A8>(v8)(),
-            FmtArg<A9>(v9)(), FmtArg<A10>(v10)(),FmtArg<A11>(v11)(),
-            FmtArg<A12>(v12)(),FmtArg<A13>(v13)(),FmtArg<A14>(v14)(),
-            FmtArg<A15>(v15)(),FmtArg<A16>(v16)(),FmtArg<A17>(v17)());
-    }
-
-#else  // #ifdef SS_SAFE_FORMAT
-
-
-#ifndef SS_ANSI
-
-	void Format(UINT nId, ...)
-	{
-		va_list argList;
-		va_start(argList, nId);
-
-		MYTYPE strFmt;
-		if ( strFmt.Load(nId) )
-			FormatV(strFmt, argList);
-
-		va_end(argList);
-	}
-    
-#endif  // #ifdef SS_ANSI
-
-	void Format(const CT* szFmt, ...)
-	{
-		va_list argList;
-		va_start(argList, szFmt);
-		FormatV(szFmt, argList);
-		va_end(argList);
-	}
-
-#endif // #ifdef SS_SAFE_FORMAT
-
-	void AppendFormat(const CT* szFmt, ...)
-	{
-		va_list argList;
-		va_start(argList, szFmt);
-		AppendFormatV(szFmt, argList);
-		va_end(argList);
-	}
-
-	#define MAX_FMT_TRIES		5	 // #of times we try 
-	#define FMT_BLOCK_SIZE		2048 // # of bytes to increment per try
-	#define BUFSIZE_1ST	256
-	#define BUFSIZE_2ND 512
-	#define STD_BUF_SIZE		1024
-
-	// an efficient way to add formatted characters to the string.  You may only
-	// add up to STD_BUF_SIZE characters at a time, though
-	void AppendFormatV(const CT* szFmt, va_list argList)
-	{
-		CT szBuf[STD_BUF_SIZE];
-		int nLen = ssvsprintf(szBuf, STD_BUF_SIZE-1, szFmt, argList);
-
-		if ( 0 < nLen )
-			this->append(szBuf, nLen);
-	}
-
-	// -------------------------------------------------------------------------
-	// FUNCTION:  FormatV
-	//		void FormatV(PCSTR szFormat, va_list, argList);
-	//           
-	// DESCRIPTION:
-	//		This function formats the string with sprintf style format-specs. 
-	//		It makes a general guess at required buffer size and then tries
-	//		successively larger buffers until it finds one big enough or a
-	//		threshold (MAX_FMT_TRIES) is exceeded.
-	//
-	// PARAMETERS: 
-	//		szFormat - a PCSTR holding the format of the output
-	//		argList - a Microsoft specific va_list for variable argument lists
-	//
-	// RETURN VALUE: 
-	// -------------------------------------------------------------------------
-
-	void FormatV(const CT* szFormat, va_list argList)
-	{
-	#ifdef SS_ANSI
-		MYTYPE str;
-		int nLen	= sslen(szFormat) + STD_BUF_SIZE;
-		ssvsprintf(str.GetBuffer(nLen), nLen-1, szFormat, argList);
-		str.ReleaseBuffer();
-		*this = str;
-
-	#else
-
-		CT* pBuf			= NULL;
-		int nChars			= 1;
-		int nUsed			= 0;
-		size_type nActual	= 0;
-		int nTry			= 0;
-
-		do	
-		{
-			// Grow more than linearly (e.g. 512, 1536, 3072, etc)
-
-			nChars			+= ((nTry+1) * FMT_BLOCK_SIZE);
-			pBuf			= reinterpret_cast<CT*>(_alloca(sizeof(CT)*nChars));
-			nUsed			= ssvsprintf(pBuf, nChars-1, szFormat, argList);
-
-			// Ensure proper NULL termination.
-
-			nActual			= nUsed == -1 ? nChars-1 : SSMIN(nUsed, nChars-1);
-			pBuf[nActual]= '\0';
-
-
-		} while ( nUsed < 0 && nTry++ < MAX_FMT_TRIES );
-
-		// assign whatever we managed to format
-
-		this->assign(pBuf, nActual);
-
-	#endif
-	}
-
-	// -------------------------------------------------------------------------
-	// CString Facade Functions:
-	//
-	// The following methods are intended to allow you to use this class as a
-	// near drop-in replacement for CString.
-	// -------------------------------------------------------------------------
-	#ifdef SS_WIN32
-		BSTR AllocSysString() const
-		{
-			ostring os;
-			ssasn(os, *this);
-			return ::SysAllocString(os.c_str());
-		}
-	#endif
-
-#ifndef SS_NO_LOCALE
-	int Collate(PCMYSTR szThat) const
-	{
-		return sscoll(this->c_str(), this->length(), szThat, sslen(szThat));
-	}
-
-	int CollateNoCase(PCMYSTR szThat) const
-	{
-		return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat));
-	}
-#endif
-	int Compare(PCMYSTR szThat) const
-	{
-		return this->compare(szThat);	
-	}
-
-	int CompareNoCase(PCMYSTR szThat)	const
-	{
-		return ssicmp(this->c_str(), szThat);
-	}
-
-	int Delete(int nIdx, int nCount=1)
-	{
-        if ( nIdx < 0 )
-			nIdx = 0;
-
-		if ( nIdx < this->GetLength() )
-			this->erase(static_cast<MYSIZE>(nIdx), static_cast<MYSIZE>(nCount));
-
-		return GetLength();
-	}
-
-	void Empty()
-	{
-		this->erase();
-	}
-
-	int Find(CT ch) const
-	{
-		MYSIZE nIdx	= this->find_first_of(ch);
-		return static_cast<int>(MYBASE::npos == nIdx  ? -1 : nIdx);
-	}
-
-	int Find(PCMYSTR szSub) const
-	{
-		MYSIZE nIdx	= this->find(szSub);
-		return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
-	}
-
-	int Find(CT ch, int nStart) const
-	{
-		// CString::Find docs say add 1 to nStart when it's not zero
-		// CString::Find code doesn't do that however.  We'll stick
-		// with what the code does
-
-		MYSIZE nIdx	= this->find_first_of(ch, static_cast<MYSIZE>(nStart));
-		return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
-	}
-
-	int Find(PCMYSTR szSub, int nStart) const
-	{
-		// CString::Find docs say add 1 to nStart when it's not zero
-		// CString::Find code doesn't do that however.  We'll stick
-		// with what the code does
-
-		MYSIZE nIdx	= this->find(szSub, static_cast<MYSIZE>(nStart));
-		return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
-	}
-
-	int FindOneOf(PCMYSTR szCharSet) const
-	{
-		MYSIZE nIdx = this->find_first_of(szCharSet);
-		return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
-	}
-
-#ifndef SS_ANSI
-	void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception)
-	{
-		va_list argList;
-		va_start(argList, szFormat);
-		PMYSTR szTemp;
-		if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
-					   szFormat, 0, 0,
-					   reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||
-			 szTemp == 0 )
-		{
-			throw std::runtime_error("out of memory");
-		}
-		*this = szTemp;
-		LocalFree(szTemp);
-		va_end(argList);
-	}
-
-	void FormatMessage(UINT nFormatId, ...) throw(std::exception)
-	{
-		MYTYPE sFormat;
-		VERIFY(sFormat.LoadString(nFormatId));
-		va_list argList;
-		va_start(argList, nFormatId);
-		PMYSTR szTemp;
-		if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
-					   sFormat, 0, 0,
-					   reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||
-			szTemp == 0)
-		{
-			throw std::runtime_error("out of memory");
-		}
-		*this = szTemp;
-		LocalFree(szTemp);
-		va_end(argList);
-	}
-#endif
-
-	// GetAllocLength -- an MSVC7 function but it costs us nothing to add it.
-
-	int GetAllocLength()
-	{
-		return static_cast<int>(this->capacity());
-	}
-
-	// -------------------------------------------------------------------------
-	// GetXXXX -- Direct access to character buffer
-	// -------------------------------------------------------------------------
-	CT GetAt(int nIdx) const
-	{
-		return this->at(static_cast<MYSIZE>(nIdx));
-	}
-
-	CT* GetBuffer(int nMinLen=-1)
-	{
-		return GetBuf(nMinLen);
-	}
-
-	CT* GetBufferSetLength(int nLen)
-	{
-		return BufferSet(nLen);
-	}
-
-	// GetLength() -- MFC docs say this is the # of BYTES but
-	// in truth it is the number of CHARACTERs (chars or wchar_ts)
-
-	int GetLength() const
-	{
-		return static_cast<int>(this->length());
-	}
-	
-    // GetString function added in Visual Studio 2008, if I recall correctly.
-
-    PCMYSTR GetString() const
-    {
-        return this->c_str();
-    }
-
-	int Insert(int nIdx, CT ch)
-	{
-		if ( static_cast<MYSIZE>(nIdx) > this->size()-1 )
-			this->append(1, ch);
-		else
-			this->insert(static_cast<MYSIZE>(nIdx), 1, ch);
-
-		return GetLength();
-	}
-	int Insert(int nIdx, PCMYSTR sz)
-	{
-		if ( static_cast<MYSIZE>(nIdx) >= this->size() )
-			this->append(sz, static_cast<MYSIZE>(sslen(sz)));
-		else
-			this->insert(static_cast<MYSIZE>(nIdx), sz);
-
-		return GetLength();
-	}
-
-	bool IsEmpty() const
-	{
-		return this->empty();
-	}
-
-	MYTYPE Left(int nCount) const
-	{
-        // Range check the count.
-
-		nCount = SSMAX(0, SSMIN(nCount, static_cast<int>(this->size())));
-		return this->substr(0, static_cast<MYSIZE>(nCount)); 
-	}
-
-#ifndef SS_ANSI
-	bool LoadString(UINT nId)
-	{
-		return this->Load(nId);
-	}
-#endif
-
-	void MakeLower()
-	{
-		ToLower();
-	}
-
-	void MakeReverse()
-	{
-		std::reverse(this->begin(), this->end());
-	}
-
-	void MakeUpper()
-	{ 
-		ToUpper();
-	}
-
-	MYTYPE Mid(int nFirst) const
-	{
-		return Mid(nFirst, this->GetLength()-nFirst);
-	}
-
-	MYTYPE Mid(int nFirst, int nCount) const
-	{
-		// CString does range checking here.  Since we're trying to emulate it,
-		// we must check too.
-
-		if ( nFirst < 0 )
-			nFirst = 0;
-		if ( nCount < 0 )
-			nCount = 0;
-
-		int nSize = static_cast<int>(this->size());
-
-		if ( nFirst + nCount > nSize )
-			nCount = nSize - nFirst;
-
-		if ( nFirst > nSize )
-			return MYTYPE();
-
-		ASSERT(nFirst >= 0);
-		ASSERT(nFirst + nCount <= nSize);
-
-		return this->substr(static_cast<MYSIZE>(nFirst),
-							static_cast<MYSIZE>(nCount));
-	}
-
-	void ReleaseBuffer(int nNewLen=-1)
-	{
-		RelBuf(nNewLen);
-	}
-
-	int Remove(CT ch)
-	{
-		MYSIZE nIdx		= 0;
-		int nRemoved	= 0;
-		while ( (nIdx=this->find_first_of(ch)) != MYBASE::npos )
-		{
-			this->erase(nIdx, 1);
-			nRemoved++;
-		}
-		return nRemoved;
-	}
-
-	int Replace(CT chOld, CT chNew)
-	{
-		int nReplaced	= 0;
-
-		for ( MYITER iter=this->begin(); iter != this->end(); ++iter )
-		{
-			if ( *iter == chOld )
-			{
-				*iter = chNew;
-				nReplaced++;
-			}
-		}
-
-		return nReplaced;
-	}
-
-	int Replace(PCMYSTR szOld, PCMYSTR szNew)
-	{
-		int nReplaced		= 0;
-		MYSIZE nIdx			= 0;
-		MYSIZE nOldLen		= sslen(szOld);
-
-		if ( 0 != nOldLen )
-		{
-			// If the replacement string is longer than the one it replaces, this
-			// string is going to have to grow in size,  Figure out how much
-			// and grow it all the way now, rather than incrementally
-
-			MYSIZE nNewLen		= sslen(szNew);
-			if ( nNewLen > nOldLen )
-			{
-				int nFound			= 0;
-				while ( nIdx < this->length() &&
-					(nIdx=this->find(szOld, nIdx)) != MYBASE::npos )
-				{
-					nFound++;
-					nIdx += nOldLen;
-				}
-				this->reserve(this->size() + nFound * (nNewLen - nOldLen));
-			}
-
-
-			static const CT ch	= CT(0);
-			PCMYSTR szRealNew	= szNew == 0 ? &ch : szNew;
-			nIdx				= 0;
-
-			while ( nIdx < this->length() && 
-				(nIdx=this->find(szOld, nIdx)) != MYBASE::npos )
-			{
-				this->replace(this->begin()+nIdx, this->begin()+nIdx+nOldLen,
-					szRealNew);
-
-				nReplaced++;
-				nIdx += nNewLen;
-			}
-		}
-
-		return nReplaced;
-	}
-
-	int ReverseFind(CT ch) const
-	{
-		MYSIZE nIdx	= this->find_last_of(ch);
-		return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
-	}
-
-	// ReverseFind overload that's not in CString but might be useful
-	int ReverseFind(PCMYSTR szFind, MYSIZE pos=MYBASE::npos) const
-	{
-		MYSIZE nIdx	= this->rfind(0 == szFind ? MYTYPE() : szFind, pos);
-		return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
-	}
-
-	MYTYPE Right(int nCount) const
-	{
-        // Range check the count.
-
-		nCount = SSMAX(0, SSMIN(nCount, static_cast<int>(this->size())));
-		return this->substr(this->size()-static_cast<MYSIZE>(nCount));
-	}
-
-	void SetAt(int nIndex, CT ch)
-	{
-		ASSERT(this->size() > static_cast<MYSIZE>(nIndex));
-		this->at(static_cast<MYSIZE>(nIndex))		= ch;
-	}
-
-#ifndef SS_ANSI
-	BSTR SetSysString(BSTR* pbstr) const
-	{
-		ostring os;
-		ssasn(os, *this);
-		if ( !::SysReAllocStringLen(pbstr, os.c_str(), os.length()) )
-			throw std::runtime_error("out of memory");
-
-		ASSERT(*pbstr != 0);
-		return *pbstr;
-	}
-#endif
-
-	MYTYPE SpanExcluding(PCMYSTR szCharSet) const
-	{
-        MYSIZE pos = this->find_first_of(szCharSet);
-        return pos == MYBASE::npos ? *this : Left(pos);
-	}
-
-	MYTYPE SpanIncluding(PCMYSTR szCharSet) const
-	{
-        MYSIZE pos = this->find_first_not_of(szCharSet);
-        return pos == MYBASE::npos ? *this : Left(pos);
-	}
-
-#if defined SS_WIN32 && !defined(UNICODE) && !defined(SS_ANSI)
-
-	// CString's OemToAnsi and AnsiToOem functions are available only in
-	// Unicode builds.  However since we're a template we also need a
-	// runtime check of CT and a reinterpret_cast to account for the fact
-	// that CStdStringW gets instantiated even in non-Unicode builds.
-
-	void AnsiToOem()
-	{
-		if ( sizeof(CT) == sizeof(char) && !empty() )
-		{
-			::CharToOem(reinterpret_cast<PCSTR>(this->c_str()),
-						reinterpret_cast<PSTR>(GetBuf()));
-		}
-		else
-		{
-			ASSERT(false);
-		}
-	}
-
-	void OemToAnsi()
-	{
-		if ( sizeof(CT) == sizeof(char) && !empty() )
-		{
-			::OemToChar(reinterpret_cast<PCSTR>(this->c_str()),
-						reinterpret_cast<PSTR>(GetBuf()));
-		}
-		else
-		{
-			ASSERT(false);
-		}
-	}
-
-#endif
-	
-
-	// -------------------------------------------------------------------------
-	// Trim and its variants
-	// -------------------------------------------------------------------------
-	MYTYPE& Trim()
-	{
-		return TrimLeft().TrimRight();
-	}
-
-	MYTYPE& TrimLeft()
-	{
-		this->erase(this->begin(),
-			std::find_if(this->begin(), this->end(), NotSpace<CT>()));
-
-		return *this;
-	}
-
-	MYTYPE&  TrimLeft(CT tTrim)
-	{
-		this->erase(0, this->find_first_not_of(tTrim));
-		return *this;
-	}
-
-	MYTYPE&  TrimLeft(PCMYSTR szTrimChars)
-	{
-		this->erase(0, this->find_first_not_of(szTrimChars));
-		return *this;
-	}
-
-	MYTYPE& TrimRight()
-	{
-		// NOTE:  When comparing reverse_iterators here (MYRITER), I avoid using
-		// operator!=.  This is because namespace rel_ops also has a template
-		// operator!= which conflicts with the global operator!= already defined
-		// for reverse_iterator in the header <utility>.
-		// Thanks to John James for alerting me to this.
-
-		MYRITER it = std::find_if(this->rbegin(), this->rend(), NotSpace<CT>());
-		if ( !(this->rend() == it) )
-			this->erase(this->rend() - it);
-
-		this->erase(!(it == this->rend()) ? this->find_last_of(*it) + 1 : 0);
-		return *this;
-	}
-
-	MYTYPE&  TrimRight(CT tTrim)
-	{
-		MYSIZE nIdx	= this->find_last_not_of(tTrim);
-		this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);
-		return *this;
-	}
-
-	MYTYPE&  TrimRight(PCMYSTR szTrimChars)
-	{
-		MYSIZE nIdx	= this->find_last_not_of(szTrimChars);
-		this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);
-		return *this;
-	}
-
-	void			FreeExtra()
-	{
-		MYTYPE mt;
-		this->swap(mt);
-		if ( !mt.empty() )
-			this->assign(mt.c_str(), mt.size());
-	}
-
-	// I have intentionally not implemented the following CString
-	// functions.   You cannot make them work without taking advantage
-	// of implementation specific behavior.  However if you absolutely
-	// MUST have them, uncomment out these lines for "sort-of-like"
-	// their behavior.  You're on your own.
-
-//	CT*				LockBuffer()	{ return GetBuf(); }// won't really lock
-//	void			UnlockBuffer(); { }	// why have UnlockBuffer w/o LockBuffer?
-
-	// Array-indexing operators.  Required because we defined an implicit cast
-	// to operator const CT* (Thanks to Julian Selman for pointing this out)
-
-	CT& operator[](int nIdx)
-	{
-		return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
-	}
-
-	const CT& operator[](int nIdx) const
-	{
-		return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
-	}
-
-	CT& operator[](unsigned int nIdx)
-	{
-		return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
-	}
-
-	const CT& operator[](unsigned int nIdx) const
-	{
-		return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
-	}
-
-#ifndef SS_NO_IMPLICIT_CAST
-	operator const CT*() const
-	{
-		return this->c_str();
-	}
-#endif
-
-	// IStream related functions.  Useful in IPersistStream implementations
-
-#ifdef SS_INC_COMDEF
-
-	// struct SSSHDR - useful for non Std C++ persistence schemes.
-	typedef struct SSSHDR
-	{
-		BYTE	byCtrl;
-		ULONG	nChars;
-	} SSSHDR;	// as in "Standard String Stream Header"
-
-	#define SSSO_UNICODE	0x01	// the string is a wide string
-	#define SSSO_COMPRESS	0x02	// the string is compressed
-
-	// -------------------------------------------------------------------------
-	// FUNCTION: StreamSize
-	// REMARKS:
-	//		Returns how many bytes it will take to StreamSave() this CStdString
-	//		object to an IStream.
-	// -------------------------------------------------------------------------
-	ULONG StreamSize() const
-	{
-		// Control header plus string
-		ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
-		return (this->size() * sizeof(CT)) + sizeof(SSSHDR);
-	}
-
-	// -------------------------------------------------------------------------
-	// FUNCTION: StreamSave
-	// REMARKS:
-	//		Saves this CStdString object to a COM IStream.
-	// -------------------------------------------------------------------------
-	HRESULT StreamSave(IStream* pStream) const
-	{
-		ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
-		HRESULT hr		= E_FAIL;
-		ASSERT(pStream != 0);
-		SSSHDR hdr;
-		hdr.byCtrl		= sizeof(CT) == 2 ? SSSO_UNICODE : 0;
-		hdr.nChars		= this->size();
-
-
-		if ( FAILED(hr=pStream->Write(&hdr, sizeof(SSSHDR), 0)) )
-		{
-			TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),hr);
-		}
-		else if ( empty() )
-		{
-			;		// nothing to write
-		}
-		else if ( FAILED(hr=pStream->Write(this->c_str(),
-			this->size()*sizeof(CT), 0)) )
-		{
-			TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr);
-		}
-
-		return hr;
-	}
-
-
-	// -------------------------------------------------------------------------
-	// FUNCTION: StreamLoad
-	// REMARKS:
-	//		This method loads the object from an IStream.
-	// -------------------------------------------------------------------------
-	HRESULT StreamLoad(IStream* pStream)
-	{
-		ASSERT(pStream != 0);
-		SSSHDR hdr;
-		HRESULT hr			= E_FAIL;
-
-		if ( FAILED(hr=pStream->Read(&hdr, sizeof(SSSHDR), 0)) )
-		{
-			TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr);
-		}
-		else if ( hdr.nChars > 0 )
-		{
-			ULONG nRead		= 0;
-			PMYSTR pMyBuf	= BufferSet(hdr.nChars);
-
-			// If our character size matches the character size of the string
-			// we're trying to read, then we can read it directly into our
-			// buffer. Otherwise, we have to read into an intermediate buffer
-			// and convert.
-			
-			if ( (hdr.byCtrl & SSSO_UNICODE) != 0 )
-			{
-				ULONG nBytes	= hdr.nChars * sizeof(wchar_t);
-				if ( sizeof(CT) == sizeof(wchar_t) )
-				{
-					if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )
-						TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
-				}
-				else
-				{	
-					PWSTR pBufW = reinterpret_cast<PWSTR>(_alloca((nBytes)+1));
-					if ( FAILED(hr=pStream->Read(pBufW, nBytes, &nRead)) )
-						TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
-					else
-						sscpy(pMyBuf, pBufW, hdr.nChars);
-				}
-			}
-			else
-			{
-				ULONG nBytes	= hdr.nChars * sizeof(char);
-				if ( sizeof(CT) == sizeof(char) )
-				{
-					if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )
-						TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
-				}
-				else
-				{
-					PSTR pBufA = reinterpret_cast<PSTR>(_alloca(nBytes));
-					if ( FAILED(hr=pStream->Read(pBufA, hdr.nChars, &nRead)) )
-						TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
-					else
-						sscpy(pMyBuf, pBufA, hdr.nChars);
-				}
-			}
-		}
-		else
-		{
-			this->erase();
-		}
-		return hr;
-	}
-#endif // #ifdef SS_INC_COMDEF
-
-#ifndef SS_ANSI
-
-	// SetResourceHandle/GetResourceHandle.  In MFC builds, these map directly
-	// to AfxSetResourceHandle and AfxGetResourceHandle.  In non-MFC builds they
-	// point to a single static HINST so that those who call the member
-	// functions that take resource IDs can provide an alternate HINST of a DLL
-	// to search.  This is not exactly the list of HMODULES that MFC provides
-	// but it's better than nothing.
-
-	#ifdef _MFC_VER
-		static void SetResourceHandle(HMODULE hNew)
-		{
-			AfxSetResourceHandle(hNew);
-		}
-		static HMODULE GetResourceHandle()
-		{
-			return AfxGetResourceHandle();
-		}
-	#else
-		static void SetResourceHandle(HMODULE hNew)
-		{
-			SSResourceHandle() = hNew;
-		}
-		static HMODULE GetResourceHandle()
-		{
-			return SSResourceHandle();
-		}
-	#endif
-
-#endif
-};
-
-// -----------------------------------------------------------------------------
-// MSVC USERS: HOW TO EXPORT CSTDSTRING FROM A DLL
-//
-// If you are using MS Visual C++ and you want to export CStdStringA and
-// CStdStringW from a DLL, then all you need to
-//
-//		1.	make sure that all components link to the same DLL version
-//			of the CRT (not the static one).
-//		2.	Uncomment the 3 lines of code below
-//		3.	#define 2 macros per the instructions in MS KnowledgeBase
-//			article Q168958.  The macros are:
-//
-//		MACRO		DEFINTION WHEN EXPORTING		DEFINITION WHEN IMPORTING
-//		-----		------------------------		-------------------------
-//		SSDLLEXP	(nothing, just #define it)		extern
-//		SSDLLSPEC	__declspec(dllexport)			__declspec(dllimport)
-//
-//		Note that these macros must be available to ALL clients who want to 
-//		link to the DLL and use the class.  If they 
-//
-// A word of advice: Don't bother.
-//
-// Really, it is not necessary to export CStdString functions from a DLL.  I
-// never do.  In my projects, I do generally link to the DLL version of the
-// Standard C++ Library, but I do NOT attempt to export CStdString functions.
-// I simply include the header where it is needed and allow for the code
-// redundancy.
-//
-// That redundancy is a lot less than you think.  This class does most of its
-// work via the Standard C++ Library, particularly the base_class basic_string<>
-// member functions.  Most of the functions here are small enough to be inlined
-// anyway.  Besides, you'll find that in actual practice you use less than 1/2
-// of the code here, even in big projects and different modules will use as
-// little as 10% of it.  That means a lot less functions actually get linked
-// your binaries.  If you export this code from a DLL, it ALL gets linked in.
-//
-// I've compared the size of the binaries from exporting vs NOT exporting.  Take
-// my word for it -- exporting this code is not worth the hassle.
-//
-// -----------------------------------------------------------------------------
-//#pragma warning(disable:4231) // non-standard extension ("extern template")
-//	SSDLLEXP template class SSDLLSPEC CStdStr<char>;
-//	SSDLLEXP template class SSDLLSPEC CStdStr<wchar_t>;
-
-
-// =============================================================================
-//						END OF CStdStr INLINE FUNCTION DEFINITIONS
-// =============================================================================
-
-//	Now typedef our class names based upon this humongous template
-
-typedef CStdStr<char>		CStdStringA;	// a better std::string
-typedef CStdStr<wchar_t>	CStdStringW;	// a better std::wstring
-typedef CStdStr<OLECHAR>	CStdStringO;	// almost always CStdStringW
-
-// -----------------------------------------------------------------------------
-// CStdStr addition functions defined as inline
-// -----------------------------------------------------------------------------
-
-
-inline CStdStringA operator+(const CStdStringA& s1, const CStdStringA& s2)
-{
-	CStdStringA sRet(SSREF(s1));
-	sRet.append(s2);
-	return sRet;
-}
-inline CStdStringA operator+(const CStdStringA& s1, CStdStringA::value_type t)
-{
-	CStdStringA sRet(SSREF(s1));
-	sRet.append(1, t);
-	return sRet;
-}
-inline CStdStringA operator+(const CStdStringA& s1, PCSTR pA)
-{
-	CStdStringA sRet(SSREF(s1));
-	sRet.append(pA);
-	return sRet;
-}
-inline CStdStringA operator+(PCSTR pA, const CStdStringA& sA)
-{
-	CStdStringA sRet;
-	CStdStringA::size_type nObjSize = sA.size();
-	CStdStringA::size_type nLitSize = 
-		static_cast<CStdStringA::size_type>(sslen(pA));
-
-	sRet.reserve(nLitSize + nObjSize);
-	sRet.assign(pA);
-	sRet.append(sA);
-	return sRet;
-}
-
-
-inline CStdStringA operator+(const CStdStringA& s1, const CStdStringW& s2)
-{
-	return s1 + CStdStringA(s2);
-}
-inline CStdStringW operator+(const CStdStringW& s1, const CStdStringW& s2)
-{
-	CStdStringW sRet(SSREF(s1));
-	sRet.append(s2);
-	return sRet;
-}
-inline CStdStringA operator+(const CStdStringA& s1, PCWSTR pW)
-{
-	return s1 + CStdStringA(pW);
-}
-
-#ifdef UNICODE
-	inline CStdStringW operator+(PCWSTR pW, const CStdStringA& sA)
-	{
-		return CStdStringW(pW) + CStdStringW(SSREF(sA));
-	}
-	inline CStdStringW operator+(PCSTR pA, const CStdStringW& sW)
-	{
-		return CStdStringW(pA) + sW;
-	}
-#else
-	inline CStdStringA operator+(PCWSTR pW, const CStdStringA& sA)
-	{
-		return CStdStringA(pW) + sA;
-	}
-	inline CStdStringA operator+(PCSTR pA, const CStdStringW& sW)
-	{
-		return pA + CStdStringA(sW);
-	}
-#endif
-
-// ...Now the wide string versions.
-inline CStdStringW operator+(const CStdStringW& s1, CStdStringW::value_type t)
-{
-	CStdStringW sRet(SSREF(s1));
-	sRet.append(1, t);
-	return sRet;
-}
-inline CStdStringW operator+(const CStdStringW& s1, PCWSTR pW)
-{
-	CStdStringW sRet(SSREF(s1));
-	sRet.append(pW);
-	return sRet;
-}
-inline CStdStringW operator+(PCWSTR pW, const CStdStringW& sW)
-{
-	CStdStringW sRet;
-	CStdStringW::size_type nObjSize = sW.size();
-	CStdStringA::size_type nLitSize = 
-		static_cast<CStdStringW::size_type>(sslen(pW));
-
-	sRet.reserve(nLitSize + nObjSize);
-	sRet.assign(pW);
-	sRet.append(sW);
-	return sRet;
-}
-
-inline CStdStringW operator+(const CStdStringW& s1, const CStdStringA& s2)
-{
-	return s1 + CStdStringW(s2);
-}
-inline CStdStringW operator+(const CStdStringW& s1, PCSTR pA)
-{
-	return s1 + CStdStringW(pA);
-}
-
-
-// New-style format function is a template
-
-#ifdef SS_SAFE_FORMAT
-
-template<>
-struct FmtArg<CStdStringA>
-{
-    explicit FmtArg(const CStdStringA& arg) : a_(arg) {}
-    PCSTR operator()() const { return a_.c_str(); }
-    const CStdStringA& a_;
-private:
-    FmtArg<CStdStringA>& operator=(const FmtArg<CStdStringA>&) { return *this; }
-};
-template<>
-struct FmtArg<CStdStringW>
-{
-    explicit FmtArg(const CStdStringW& arg) : a_(arg) {}
-    PCWSTR operator()() const { return a_.c_str(); }
-    const CStdStringW& a_;
-private:
-    FmtArg<CStdStringW>& operator=(const FmtArg<CStdStringW>&) { return *this; }
-};
-
-template<>
-struct FmtArg<std::string>
-{
-    explicit FmtArg(const std::string& arg) : a_(arg) {}
-    PCSTR operator()() const { return a_.c_str(); }
-    const std::string& a_;
-private:
-    FmtArg<std::string>& operator=(const FmtArg<std::string>&) { return *this; }
-};
-template<>
-struct FmtArg<std::wstring>
-{
-    explicit FmtArg(const std::wstring& arg) : a_(arg) {}
-    PCWSTR operator()() const { return a_.c_str(); }
-    const std::wstring& a_;
-private:
-    FmtArg<std::wstring>& operator=(const FmtArg<std::wstring>&) {return *this;}
-};
-#endif // #ifdef SS_SAFEFORMAT
-
-#ifndef SS_ANSI
-	// SSResourceHandle: our MFC-like resource handle
-	inline HMODULE& SSResourceHandle()
-	{
-		static HMODULE hModuleSS	= GetModuleHandle(0);
-		return hModuleSS;
-	}
-#endif
-
-
-// In MFC builds, define some global serialization operators
-// Special operators that allow us to serialize CStdStrings to CArchives.
-// Note that we use an intermediate CString object in order to ensure that
-// we use the exact same format.
-
-#ifdef _MFC_VER
-	inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringA& strA)
-	{
-		CString strTemp(strA);
-		return ar << strTemp;
-	}
-	inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringW& strW)
-	{
-		CString strTemp(strW);
-		return ar << strTemp;
-	}
-
-	inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringA& strA)
-	{
-		CString strTemp;
-		ar >> strTemp;
-		strA = strTemp;
-		return ar;
-	}
-	inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringW& strW)
-	{
-		CString strTemp;
-		ar >> strTemp;
-		strW = strTemp;
-		return ar;
-	}
-#endif	// #ifdef _MFC_VER -- (i.e. is this MFC?)
-
-
-
-// -----------------------------------------------------------------------------
-// GLOBAL FUNCTION:  WUFormat
-//		CStdStringA WUFormat(UINT nId, ...);
-//		CStdStringA WUFormat(PCSTR szFormat, ...);
-//
-// REMARKS:
-//		This function allows the caller for format and return a CStdStringA
-//		object with a single line of code.
-// -----------------------------------------------------------------------------
-
-inline CStdStringA WUFormatA(PCSTR szFormat, ...)
-{
-	va_list argList;
-	va_start(argList, szFormat);
-	CStdStringA strOut;
-	strOut.FormatV(szFormat, argList);
-	va_end(argList);
-	return strOut;
-}
-inline CStdStringW WUFormatW(PCWSTR szwFormat, ...)
-{
-	va_list argList;
-	va_start(argList, szwFormat);
-	CStdStringW strOut;
-	strOut.FormatV(szwFormat, argList);
-	va_end(argList);
-	return strOut;
-}
-#ifdef SS_ANSI
-#else
-	inline CStdStringA WUFormatA(UINT nId, ...)
-	{
-		va_list argList;
-		va_start(argList, nId);
-
-		CStdStringA strFmt;
-		CStdStringA strOut;
-		if ( strFmt.Load(nId) )
-			strOut.FormatV(strFmt, argList);
-
-		va_end(argList);
-		return strOut;
-	}
-
-	inline CStdStringW WUFormatW(UINT nId, ...)
-	{
-		va_list argList;
-		va_start(argList, nId);
-
-		CStdStringW strFmt;
-		CStdStringW strOut;
-		if ( strFmt.Load(nId) )
-			strOut.FormatV(strFmt, argList);
-
-		va_end(argList);
-		return strOut;
-	}
-#endif // #ifdef SS_ANSI
-
-
-
-#if defined(SS_WIN32) && !defined (SS_ANSI)
-	// -------------------------------------------------------------------------
-	// FUNCTION: WUSysMessage
-	//	 CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);
-	//	 CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);
-	//           
-	// DESCRIPTION:
-	//	 This function simplifies the process of obtaining a string equivalent
-	//	 of a system error code returned from GetLastError().  You simply
-	//	 supply the value returned by GetLastError() to this function and the
-	//	 corresponding system string is returned in the form of a CStdStringA.
-	//
-	// PARAMETERS: 
-	//	 dwError - a DWORD value representing the error code to be translated
-	//	 dwLangId - the language id to use.  defaults to english.
-	//
-	// RETURN VALUE: 
-	//	 a CStdStringA equivalent of the error code.  Currently, this function
-	//	 only returns either English of the system default language strings.  
-	// -------------------------------------------------------------------------
-	#define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)
-	inline CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID)
-	{
-		CHAR szBuf[512];
-
-		if ( 0 != ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
-								   dwLangId, szBuf, 511, NULL) )
-			return WUFormatA("%s (0x%X)", szBuf, dwError);
-		else
- 			return WUFormatA("Unknown error (0x%X)", dwError);
-	}
-	inline CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID)
-	{
-		WCHAR szBuf[512];
-
-		if ( 0 != ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
-								   dwLangId, szBuf, 511, NULL) )
-			return WUFormatW(L"%s (0x%X)", szBuf, dwError);
-		else
- 			return WUFormatW(L"Unknown error (0x%X)", dwError);
-	}
-#endif
-
-// Define TCHAR based friendly names for some of these functions
-
-#ifdef UNICODE
-	//#define CStdString				CStdStringW
-	typedef CStdStringW				CStdString;
-	#define WUSysMessage			WUSysMessageW
-	#define WUFormat				WUFormatW
-#else
-	//#define CStdString				CStdStringA
-	typedef CStdStringA				CStdString;
-	#define WUSysMessage			WUSysMessageA
-	#define WUFormat				WUFormatA
-#endif
-
-// ...and some shorter names for the space-efficient
-
-#define WUSysMsg					WUSysMessage
-#define WUSysMsgA					WUSysMessageA
-#define WUSysMsgW					WUSysMessageW
-#define WUFmtA						WUFormatA
-#define	WUFmtW						WUFormatW
-#define WUFmt						WUFormat
-#define WULastErrMsg()				WUSysMessage(::GetLastError())
-#define WULastErrMsgA()				WUSysMessageA(::GetLastError())
-#define WULastErrMsgW()				WUSysMessageW(::GetLastError())
-
-
-// -----------------------------------------------------------------------------
-// FUNCTIONAL COMPARATORS:
-// REMARKS:
-//		These structs are derived from the std::binary_function template.  They
-//		give us functional classes (which may be used in Standard C++ Library
-//		collections and algorithms) that perform case-insensitive comparisons of
-//		CStdString objects.  This is useful for maps in which the key may be the
-//		 proper string but in the wrong case.
-// -----------------------------------------------------------------------------
-#define StdStringLessNoCaseW		SSLNCW	// avoid VC compiler warning 4786
-#define StdStringEqualsNoCaseW		SSENCW		
-#define StdStringLessNoCaseA		SSLNCA		
-#define StdStringEqualsNoCaseA		SSENCA		
-
-#ifdef UNICODE
-	#define StdStringLessNoCase		SSLNCW		
-	#define StdStringEqualsNoCase	SSENCW		
-#else
-	#define StdStringLessNoCase		SSLNCA		
-	#define StdStringEqualsNoCase	SSENCA		
-#endif
-
-struct StdStringLessNoCaseW
-	: std::binary_function<CStdStringW, CStdStringW, bool>
-{
-	inline
-	bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const
-	{ return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }
-};
-struct StdStringEqualsNoCaseW
-	: std::binary_function<CStdStringW, CStdStringW, bool>
-{
-	inline
-	bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const
-	{ return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }
-};
-struct StdStringLessNoCaseA
-	: std::binary_function<CStdStringA, CStdStringA, bool>
-{
-	inline
-	bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const
-	{ return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }
-};
-struct StdStringEqualsNoCaseA
-	: std::binary_function<CStdStringA, CStdStringA, bool>
-{
-	inline
-	bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const
-	{ return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }
-};
-
-// If we had to define our own version of TRACE above, get rid of it now
-
-#ifdef TRACE_DEFINED_HERE
-	#undef TRACE
-	#undef TRACE_DEFINED_HERE
-#endif
-
-
-// These std::swap specializations come courtesy of Mike Crusader. 
-
-//namespace std
-//{
-//	inline void swap(CStdStringA& s1, CStdStringA& s2) throw()
-//	{
-//		s1.swap(s2);
-//	}
-//	template<>
-//	inline void swap(CStdStringW& s1, CStdStringW& s2) throw()
-//	{
-//		s1.swap(s2);
-//	}
-//}
-
-// Turn back on any Borland warnings we turned off.
-
-#ifdef __BORLANDC__
-    #pragma option pop  // Turn back on inline function warnings
-//	#pragma warn +inl   // Turn back on inline function warnings
-#endif
-
-#endif	// #ifndef STDSTRING_H
diff --git a/input_devices/mag/node_modules/serialport/test.js b/input_devices/mag/node_modules/serialport/test.js
new file mode 100644
index 00000000..35405051
--- /dev/null
+++ b/input_devices/mag/node_modules/serialport/test.js
@@ -0,0 +1,8 @@
+const SerialPort = require('@serialport/stream')
+const Binding = require('@serialport/binding-mock')
+const parsers = require('./lib/parsers')
+
+SerialPort.Binding = Binding
+SerialPort.parsers = parsers
+
+module.exports = SerialPort
diff --git a/input_devices/mag/node_modules/serialport/test/parsers.js b/input_devices/mag/node_modules/serialport/test/parsers.js
deleted file mode 100644
index c93d09c3..00000000
--- a/input_devices/mag/node_modules/serialport/test/parsers.js
+++ /dev/null
@@ -1,47 +0,0 @@
-'use strict';
-
-var chai = require('chai');
-var expect = chai.expect;
-var sinonChai = require('sinon-chai');
-var sinon = require('sinon');
-chai.use(sinonChai);
-
-var parsers = require('../parsers');
-
-describe('parsers', function () {
-
-  describe('#raw', function () {
-    it('emits data exactly as it\'s written', function () {
-      var data = new Buffer('BOGUS');
-      var spy = sinon.spy();
-      parsers.raw({ emit: spy }, data);
-      expect(spy.getCall(0).args[1]).to.deep.equal(new Buffer('BOGUS'));
-    });
-  });
-
-  describe('#readline', function () {
-    it('emits data events split on a delimiter', function () {
-      var data = new Buffer('I love robots\rEach and Every One\r');
-      var spy = sinon.spy();
-      var parser = parsers.readline();
-      parser({ emit: spy }, data);
-      expect(spy).to.have.been.calledWith('data', 'I love robots');
-      expect(spy).to.have.been.calledWith('data', 'Each and Every One');
-    });
-  });
-
-  describe('#byteLength', function(){
-    it('emits data events every 8 bytes', function () {
-      var data = new Buffer('Robots are so freaking cool!');
-      var spy = sinon.spy();
-      var parser = parsers.byteLength(8);
-      parser({ emit: spy }, data);
-      expect(spy.callCount).to.equal(3);
-      expect(spy.getCall(0).args[1].length).to.equal(8);
-      expect(spy.getCall(0).args[1]).to.deep.equal(new Buffer('Robots a'));
-      expect(spy.getCall(1).args[1]).to.deep.equal(new Buffer('re so fr'));
-      expect(spy.getCall(2).args[1]).to.deep.equal(new Buffer('eaking c'));
-    });
-  });
-
-});
diff --git a/input_devices/mag/node_modules/serialport/test/serialport-basic.js b/input_devices/mag/node_modules/serialport/test/serialport-basic.js
deleted file mode 100644
index 50edc9b8..00000000
--- a/input_devices/mag/node_modules/serialport/test/serialport-basic.js
+++ /dev/null
@@ -1,275 +0,0 @@
-'use strict';
-
-var sinon = require('sinon');
-var chai = require('chai');
-var expect = chai.expect;
-
-var MockedSerialPort = require('../test_mocks/linux-hardware');
-var SerialPort = MockedSerialPort.SerialPort;
-var hardware = MockedSerialPort.hardware;
-
-describe('SerialPort', function () {
-  var sandbox;
-
-  beforeEach(function () {
-    sandbox = sinon.sandbox.create();
-
-    // Create a port for fun and profit
-    hardware.reset();
-    hardware.createPort('/dev/exists');
-  });
-
-  afterEach(function () {
-    sandbox.restore();
-  });
-
-  describe('Constructor', function () {
-    it('opens the port immediately', function (done) {
-      var port = new SerialPort('/dev/exists', function (err) {
-        expect(err).to.not.be.ok;
-        done();
-      });
-    });
-
-    it('emits the open event', function (done) {
-      var port = new SerialPort('/dev/exists');
-      port.on('open', function(){
-        done();
-      });
-    });
-
-    it('emits an error on the factory when erroring without a callback', function (done) {
-      // finish the test on error
-      MockedSerialPort.once('error', function (err) {
-        chai.assert.isDefined(err, 'didn\'t get an error');
-        done();
-      });
-
-      var port = new SerialPort('/dev/johnJacobJingleheimerSchmidt');
-    });
-
-    it('emits an error on the serialport when explicit error handler present', function (done) {
-      var port = new SerialPort('/dev/johnJacobJingleheimerSchmidt');
-
-      port.once('error', function(err) {
-        chai.assert.isDefined(err);
-        done();
-      });
-    });
-
-    it('errors with invalid databits', function (done) {
-      var errorCallback = function (err) {
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      };
-
-      var port = new SerialPort('/dev/exists', { databits : 19 }, false, errorCallback);
-    });
-
-    it('errors with invalid stopbits', function (done) {
-      var errorCallback = function (err) {
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      };
-
-      var port = new SerialPort('/dev/exists', { stopbits : 19 }, false, errorCallback);
-    });
-
-    it('errors with invalid parity', function (done) {
-      var errorCallback = function (err) {
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      };
-
-      var port = new SerialPort('/dev/exists', { parity : 'pumpkins' }, false, errorCallback);
-    });
-
-    it('errors with invalid flow control', function (done) {
-      var errorCallback = function (err) {
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      };
-
-      var port = new SerialPort('/dev/exists', { flowcontrol : ['pumpkins'] }, false, errorCallback);
-    });
-
-
-    it('allows optional options', function (done) {
-      var cb = function () {};
-      var port = new SerialPort('/dev/exists', cb);
-      expect(typeof port.options).to.eq('object');
-      done();
-    });
-
-  });
-
-  describe('Functions', function () {
-
-    it('write errors when serialport not open', function (done) {
-      var cb = function () {};
-      var port = new SerialPort('/dev/exists', false, cb);
-      port.write(null, function(err){
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      });
-    });
-
-    it('close errors when serialport not open', function (done) {
-      var cb = function () {};
-      var port = new SerialPort('/dev/exists', false, cb);
-      port.close(function(err){
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      });
-    });
-
-    it('flush errors when serialport not open', function (done) {
-      var cb = function () {};
-      var port = new SerialPort('/dev/exists', false, cb);
-      port.flush(function(err){
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      });
-    });
-
-    it('set errors when serialport not open', function (done) {
-      var cb = function () {};
-      var port = new SerialPort('/dev/exists', false, cb);
-      port.set({}, function(err){
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      });
-    });
-
-    it('drain errors when serialport not open', function (done) {
-      var cb = function () {};
-      var port = new SerialPort('/dev/exists', false, cb);
-      port.drain(function(err){
-        chai.assert.isDefined(err, 'err is not defined');
-        done();
-      });
-    });
-
-  });
-
-  describe('reading data', function () {
-
-    it('emits data events by default', function (done) {
-      var testData = new Buffer('I am a really short string');
-      var port = new SerialPort('/dev/exists', function () {
-        port.once('data', function(recvData) {
-          expect(recvData).to.eql(testData);
-          done();
-        });
-        hardware.emitData('/dev/exists', testData);
-      });
-    });
-
-    it('calls the dataCallback if set', function (done) {
-      var testData = new Buffer('I am a really short string');
-      var opt = {
-        dataCallback: function (recvData) {
-          expect(recvData).to.eql(testData);
-          done();
-        }
-      };
-      var port = new SerialPort('/dev/exists', opt, function () {
-        hardware.emitData('/dev/exists', testData);
-      });
-    });
-
-  });
-
-  describe('#open', function () {
-
-    it('passes the port to the bindings', function (done) {
-      var openSpy = sandbox.spy(MockedSerialPort.SerialPortBinding, 'open');
-      var port = new SerialPort('/dev/exists', {}, false);
-      port.open(function (err) {
-        expect(err).to.not.be.ok;
-        expect(openSpy.calledWith('/dev/exists'));
-        done();
-      });
-    });
-
-    it('calls back an error when opening an invalid port', function (done) {
-      var port = new SerialPort('/dev/unhappy', {}, false);
-      port.open(function (err) {
-        expect(err).to.be.ok;
-        done();
-      });
-    });
-
-    it('emits data after being reopened', function (done) {
-      var data = new Buffer('Howdy!');
-      var port = new SerialPort('/dev/exists', function () {
-        port.close();
-        port.open(function () {
-          port.once('data', function (res) {
-            expect(res).to.eql(data);
-            done();
-          });
-          hardware.emitData('/dev/exists', data);
-        });
-      });
-    });
-
-  });
-
-  describe('close', function () {
-    it('fires a close event when it\'s closed', function (done) {
-      var port = new SerialPort('/dev/exists', function () {
-        var closeSpy = sandbox.spy();
-        port.on('close', closeSpy);
-        port.close();
-        expect(closeSpy.calledOnce);
-        done();
-      });
-    });
-
-    it('fires a close event after being reopened', function (done) {
-      var port = new SerialPort('/dev/exists', function () {
-        var closeSpy = sandbox.spy();
-        port.on('close', closeSpy);
-        port.close();
-        port.open();
-        port.close();
-        expect(closeSpy.calledTwice);
-        done();
-      });
-    });
-
-    it('emits a close event', function (done) {
-      var port = new SerialPort('/dev/exists', function () {
-        port.on('close', function () {
-          done();
-        });
-        port.close();
-      });
-    });
-  });
-
-  describe('disconnect', function () {
-    it('fires a disconnect event', function (done) {
-      var port = new SerialPort('/dev/exists', {
-        disconnectedCallback: function (err) {
-          expect(err).to.not.be.ok;
-          done();
-        }
-      }, function () {
-        hardware.disconnect('/dev/exists');
-      });
-    });
-
-    it('emits a disconnect event', function (done) {
-      var port = new SerialPort('/dev/exists', function () {
-        port.on('disconnect', function () {
-          done();
-        });
-        hardware.disconnect('/dev/exists');
-      });
-    });
-  });
-
-});
-
diff --git a/input_devices/mag/node_modules/serialport/test/serialport-c.js b/input_devices/mag/node_modules/serialport/test/serialport-c.js
deleted file mode 100644
index 9cf054cc..00000000
--- a/input_devices/mag/node_modules/serialport/test/serialport-c.js
+++ /dev/null
@@ -1,35 +0,0 @@
-'use strict';
-
-var sinon = require('sinon');
-var chai = require('chai');
-var expect = chai.expect;
-
-describe('SerialPort', function () {
-  var sandbox;
-
-  beforeEach(function () {
-    sandbox = sinon.sandbox.create();
-  });
-
-  afterEach(function () {
-    sandbox.restore();
-  });
-
-
-  describe('Initialization', function () {
-    if (process.version.indexOf('v0.11.') ===0) {
-      it('does not currently work due to an issue with node unstable release, works in master.', function (done) {
-        done();
-      });
-    } else {
-      it('Throws an error in callback when trying to open an invalid port', function (done) {
-        var SerialPort = require('../').SerialPort;
-        var port = new SerialPort('/dev/nullbad', function (err) {
-          chai.assert.isDefined(err, 'didn\'t get an error');
-          done();
-        });
-      });
-    }
-  });
-
-});
diff --git a/input_devices/mag/node_modules/serialport/test_mocks/linux-hardware.js b/input_devices/mag/node_modules/serialport/test_mocks/linux-hardware.js
deleted file mode 100644
index 28ecafa6..00000000
--- a/input_devices/mag/node_modules/serialport/test_mocks/linux-hardware.js
+++ /dev/null
@@ -1,163 +0,0 @@
-// This takes a serial-port factory and mocks the shit out of it in complete isolation per require of this file
-
-"use strict";
-
-var mockSerialportPoller = function (hardware) {
-  var Poller = function (path, cb) {
-    this.port = hardware.ports[path];
-    if (!this.port) {
-      throw new Error(path + " does not exist - please call hardware.createPort(path) first");
-    }
-    this.port.poller = this;
-    this.polling = null;
-    this.cb = cb;
-  };
-  Poller.prototype.start = function () {
-    this.polling = true;
-  };
-  Poller.prototype.close = function () {
-    this.polling = false;
-  };
-  Poller.prototype.detectRead = function () {
-    this.cb();
-  };
-  return Poller;
-};
-
-var Hardware = function () {
-  this.ports = {};
-  this.mockBinding = {
-    list: this.list.bind(this),
-    open: this.open.bind(this),
-    write: this.write.bind(this),
-    close: this.close.bind(this),
-    flush: this.flush.bind(this),
-    SerialportPoller: mockSerialportPoller(this)
-  };
-};
-
-Hardware.prototype.reset = function () {
-  this.ports = {};
-};
-
-Hardware.prototype.createPort = function (path) {
-  this.ports[path] = {
-    data: new Buffer(0),
-    lastWrite: null,
-    open: false,
-    poller: null,
-    info: {
-      comName: path,
-      manufacturer: '',
-      serialNumber: '',
-      pnpId: '',
-      locationId: '',
-      vendorId: '',
-      productId: ''
-    }
-  };
-};
-
-Hardware.prototype.emitData = function (path, data) {
-  var port = this.ports[path];
-  if(!port) {
-    throw new Error(path + " does not exist - please call hardware.createPort(path) first");
-  }
-  port.data = Buffer.concat([port.data, data]);
-  port.poller && port.poller.detectRead();
-};
-
-Hardware.prototype.disconnect = function (path) {
-  var port = this.ports[path];
-  if (!port) {
-    throw new Error(path + " does not exist - please call hardware.createPort(path) first");
-  }
-  port.openOpt.disconnectedCallback();
-};
-
-Hardware.prototype.list = function (cb) {
-  var ports = this.ports;
-  var info = Object.keys(ports).map(function (path) {
-    return ports[path].info;
-  });
-  cb && cb(info);
-};
-
-Hardware.prototype.open = function (path, opt, cb) {
-  var port = this.ports[path];
-  if (!port) {
-    return cb(new Error(path + " does not exist - please call hardware.createPort(path) first"));
-  }
-  port.open = true;
-  port.openOpt = opt;
-  cb && cb(null, path); // using path as the fd for convience
-};
-
-Hardware.prototype.write = function (path, buffer, cb) {
-  var port = this.ports[path];
-  if (!port) {
-    return cb(new Error(path + " does not exist - please call hardware.createPort(path) first"));
-  }
-  port.lastWrite = new Buffer(buffer); //copy
-  cb && cb(null, buffer.length);
-};
-
-Hardware.prototype.close = function (path, cb) {
-  var port = this.ports[path];
-  if (!port) {
-    return cb(new Error(path + " does not exist - please call hardware.createPort(path) first"));
-  }
-  port.open = false;
-  cb && cb(null);
-};
-
-Hardware.prototype.flush = function (path, cb) {
-  var port = this.ports[path];
-  if (!port) {
-    return cb(new Error(path + " does not exist - please call hardware.createPort(path) first"));
-  }
-  cb && cb(null, undefined);
-};
-
-Hardware.prototype.fakeRead = function (path, buffer, offset, length, position, cb) {
-  var port = this.ports[path];
-  if (!port) {
-    return cb(new Error(path + " does not exist - please call hardware.createPort(path) first"));
-  }
-  if (port.data.length === 0) {
-    return cb(null, 0, buffer);
-  }
-  if ((offset + length) > buffer.length) {
-    throw new Error("Length extends beyond buffer");
-  }
-
-  // node v0.8 doesn't like a slice that is bigger then available data
-  length = port.data.length < length ? port.data.length : length;
-  var read = port.data.slice(0, length);
-  port.data = port.data.slice(length);
-  read.copy(buffer, offset);
-  cb(null, read.length, buffer);
-};
-
-var hardware = new Hardware();
-
-var SandboxedModule = require('sandboxed-module');
-
-var serialPort = SandboxedModule.require('../serialport', {
-  requires: {
-    fs: {
-      read: hardware.fakeRead.bind(hardware)
-    }
-  },
-  globals: {
-    process: {
-      platform: 'darwin',
-      nextTick: process.nextTick
-    }
-  }
-});
-
-serialPort.hardware = hardware;
-serialPort.SerialPortBinding = hardware.mockBinding;
-
-module.exports = serialPort;
diff --git a/input_devices/mag/node_modules/set-blocking/CHANGELOG.md b/input_devices/mag/node_modules/set-blocking/CHANGELOG.md
new file mode 100644
index 00000000..03bf5919
--- /dev/null
+++ b/input_devices/mag/node_modules/set-blocking/CHANGELOG.md
@@ -0,0 +1,26 @@
+# Change Log
+
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+<a name="2.0.0"></a>
+# [2.0.0](https://github.com/yargs/set-blocking/compare/v1.0.0...v2.0.0) (2016-05-17)
+
+
+### Features
+
+* add an isTTY check ([#3](https://github.com/yargs/set-blocking/issues/3)) ([66ce277](https://github.com/yargs/set-blocking/commit/66ce277))
+
+
+### BREAKING CHANGES
+
+* stdio/stderr will not be set to blocking if isTTY === false
+
+
+
+<a name="1.0.0"></a>
+# 1.0.0 (2016-05-14)
+
+
+### Features
+
+* implemented shim for stream._handle.setBlocking ([6bde0c0](https://github.com/yargs/set-blocking/commit/6bde0c0))
diff --git a/input_devices/mag/node_modules/set-blocking/LICENSE.txt b/input_devices/mag/node_modules/set-blocking/LICENSE.txt
new file mode 100644
index 00000000..836440be
--- /dev/null
+++ b/input_devices/mag/node_modules/set-blocking/LICENSE.txt
@@ -0,0 +1,14 @@
+Copyright (c) 2016, Contributors
+
+Permission to use, copy, modify, and/or distribute this software
+for any purpose with or without fee is hereby granted, provided
+that the above copyright notice and this permission notice
+appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
+LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/set-blocking/README.md b/input_devices/mag/node_modules/set-blocking/README.md
new file mode 100644
index 00000000..e93b4202
--- /dev/null
+++ b/input_devices/mag/node_modules/set-blocking/README.md
@@ -0,0 +1,31 @@
+# set-blocking
+
+[![Build Status](https://travis-ci.org/yargs/set-blocking.svg)](https://travis-ci.org/yargs/set-blocking)
+[![NPM version](https://img.shields.io/npm/v/set-blocking.svg)](https://www.npmjs.com/package/set-blocking)
+[![Coverage Status](https://coveralls.io/repos/yargs/set-blocking/badge.svg?branch=)](https://coveralls.io/r/yargs/set-blocking?branch=master)
+[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
+
+set blocking `stdio` and `stderr` ensuring that terminal output does not truncate.
+
+```js
+const setBlocking = require('set-blocking')
+setBlocking(true)
+console.log(someLargeStringToOutput)
+```
+
+## Historical Context/Word of Warning
+
+This was created as a shim to address the bug discussed in [node #6456](https://github.com/nodejs/node/issues/6456). This bug crops up on
+newer versions of Node.js (`0.12+`), truncating terminal output.
+
+You should be mindful of the side-effects caused by using `set-blocking`:
+
+* if your module sets blocking to `true`, it will effect other modules
+  consuming your library. In [yargs](https://github.com/yargs/yargs/blob/master/yargs.js#L653) we only call
+  `setBlocking(true)` once we already know we are about to call `process.exit(code)`.
+* this patch will not apply to subprocesses spawned with `isTTY = true`, this is
+  the [default `spawn()` behavior](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options).
+
+## License
+
+ISC
diff --git a/input_devices/mag/node_modules/set-blocking/index.js b/input_devices/mag/node_modules/set-blocking/index.js
new file mode 100644
index 00000000..6f78774b
--- /dev/null
+++ b/input_devices/mag/node_modules/set-blocking/index.js
@@ -0,0 +1,7 @@
+module.exports = function (blocking) {
+  [process.stdout, process.stderr].forEach(function (stream) {
+    if (stream._handle && stream.isTTY && typeof stream._handle.setBlocking === 'function') {
+      stream._handle.setBlocking(blocking)
+    }
+  })
+}
diff --git a/input_devices/mag/node_modules/set-blocking/package.json b/input_devices/mag/node_modules/set-blocking/package.json
new file mode 100644
index 00000000..d9eef9cc
--- /dev/null
+++ b/input_devices/mag/node_modules/set-blocking/package.json
@@ -0,0 +1,98 @@
+{
+  "_args": [
+    [
+      "set-blocking@~2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog"
+    ]
+  ],
+  "_from": "set-blocking@>=2.0.0 <2.1.0",
+  "_id": "set-blocking@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/set-blocking",
+  "_nodeVersion": "0.12.7",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/set-blocking-2.0.0.tgz_1463525966987_0.5456729622092098"
+  },
+  "_npmUser": {
+    "email": "ben@npmjs.com",
+    "name": "bcoe"
+  },
+  "_npmVersion": "2.11.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "set-blocking",
+    "raw": "set-blocking@~2.0.0",
+    "rawSpec": "~2.0.0",
+    "scope": null,
+    "spec": ">=2.0.0 <2.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/npmlog"
+  ],
+  "_resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+  "_shasum": "045f9782d011ae9a6803ddd382b24392b3d890f7",
+  "_shrinkwrap": null,
+  "_spec": "set-blocking@~2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/npmlog",
+  "author": {
+    "email": "ben@npmjs.com",
+    "name": "Ben Coe"
+  },
+  "bugs": {
+    "url": "https://github.com/yargs/set-blocking/issues"
+  },
+  "dependencies": {},
+  "description": "set blocking stdio and stderr ensuring that terminal output does not truncate",
+  "devDependencies": {
+    "chai": "^3.5.0",
+    "coveralls": "^2.11.9",
+    "mocha": "^2.4.5",
+    "nyc": "^6.4.4",
+    "standard": "^7.0.1",
+    "standard-version": "^2.2.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "045f9782d011ae9a6803ddd382b24392b3d890f7",
+    "tarball": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz"
+  },
+  "files": [
+    "LICENSE.txt",
+    "index.js"
+  ],
+  "gitHead": "7eec10577b5fff264de477ba3b9d07f404946eff",
+  "homepage": "https://github.com/yargs/set-blocking#readme",
+  "keywords": [
+    "blocking",
+    "flush",
+    "shim",
+    "stderr",
+    "stdio",
+    "terminal"
+  ],
+  "license": "ISC",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "bcoe",
+      "email": "ben@npmjs.com"
+    }
+  ],
+  "name": "set-blocking",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/yargs/set-blocking.git"
+  },
+  "scripts": {
+    "coverage": "nyc report --reporter=text-lcov | coveralls",
+    "pretest": "standard",
+    "test": "nyc mocha ./test/*.js",
+    "version": "standard-version"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/set-getter/LICENSE b/input_devices/mag/node_modules/set-getter/LICENSE
new file mode 100644
index 00000000..3f525ab1
--- /dev/null
+++ b/input_devices/mag/node_modules/set-getter/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016, Brian Woodward.
+
+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/input_devices/mag/node_modules/set-getter/README.md b/input_devices/mag/node_modules/set-getter/README.md
new file mode 100644
index 00000000..072d3eac
--- /dev/null
+++ b/input_devices/mag/node_modules/set-getter/README.md
@@ -0,0 +1,109 @@
+# set-getter [![NPM version](https://img.shields.io/npm/v/set-getter.svg?style=flat)](https://www.npmjs.com/package/set-getter) [![NPM downloads](https://img.shields.io/npm/dm/set-getter.svg?style=flat)](https://npmjs.org/package/set-getter) [![Build Status](https://img.shields.io/travis/doowb/set-getter.svg?style=flat)](https://travis-ci.org/doowb/set-getter)
+
+> Create nested getter properties and any intermediary dot notation (`'a.b.c'`) paths
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install set-getter --save
+```
+
+## Usage
+
+```js
+var getter = require('set-getter');
+```
+
+set-getter works like [set-value](https://github.com/jonschlinkert/set-value) by adding a property to an object or an object hierarchy using dot notation. The main difference is that the property is added using `Object.defineProperty` and is expected to be a getter function that returns a value.
+
+**Example**
+
+```js
+var obj = {};
+
+// root level property
+getter(obj, 'foo', function() {
+  return 'bar';
+});
+console.log(obj.foo);
+//=> 'bar'
+
+// property dot notation
+getter(obj, 'bar.baz', function() {
+  return 'qux';
+});
+console.log(obj.bar.baz);
+//=> 'qux'
+
+// property array notation
+getter(obj, ['beep', 'boop'], function() {
+  return 'bop';
+});
+console.log(obj.beep.boop);
+//=> 'bop'
+```
+
+## API
+
+### [setGetter](index.js#L27)
+
+Defines a getter function on an object using property path notation.
+
+**Params**
+
+* `obj` **{Object}**: Object to add property to.
+* `prop` **{String|Array}**: Property string or array to add.
+* `getter` **{Function}**: Getter function to add as a property.
+
+**Example**
+
+```js
+var obj = {};
+getter(obj, 'foo', function() {
+  return 'bar';
+});
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/doowb/set-getter/issues/new).
+
+## Building docs
+
+Generate readme and API documentation with [verb](https://github.com/verbose/verb):
+
+```sh
+$ npm install verb && npm run docs
+```
+
+Or, if [verb](https://github.com/verbose/verb) is installed globally:
+
+```sh
+$ verb
+```
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm install -d && npm test
+```
+
+## Author
+
+**Brian Woodward**
+
+* [github/doowb](https://github.com/doowb)
+* [twitter/doowb](http://twitter.com/doowb)
+
+## License
+
+Copyright © 2016, [Brian Woodward](https://github.com/doowb).
+Released under the [MIT license](https://github.com/doowb/set-getter/blob/master/LICENSE).
+
+***
+
+_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on April 29, 2016._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/set-getter/index.js b/input_devices/mag/node_modules/set-getter/index.js
new file mode 100644
index 00000000..ce9a6a0d
--- /dev/null
+++ b/input_devices/mag/node_modules/set-getter/index.js
@@ -0,0 +1,83 @@
+/*!
+ * set-getter (https://github.com/doowb/set-getter)
+ *
+ * Copyright (c) 2016, Brian Woodward.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var toPath = require('to-object-path');
+
+/**
+ * Defines a getter function on an object using property path notation.
+ *
+ * ```js
+ * var obj = {};
+ * getter(obj, 'foo', function() {
+ *   return 'bar';
+ * });
+ * ```
+ * @param {Object} `obj` Object to add property to.
+ * @param {String|Array} `prop` Property string or array to add.
+ * @param {Function} `getter` Getter function to add as a property.
+ * @api public
+ */
+
+function setGetter(obj, prop, getter) {
+  var key = toPath(arguments);
+  return define(obj, key, getter);
+}
+
+/**
+ * Define getter function on object or object hierarchy using dot notation.
+ *
+ * @param  {Object} `obj` Object to define getter property on.
+ * @param  {String} `prop` Property string to define.
+ * @param  {Function} `getter` Getter function to define.
+ * @return {Object} Returns original object.
+ */
+
+function define(obj, prop, getter) {
+  if (!~prop.indexOf('.')) {
+    defineProperty(obj, prop, getter);
+    return obj;
+  }
+
+  var keys = prop.split('.');
+  var last = keys.pop();
+  var target = obj;
+  var key;
+
+  while ((key = keys.shift())) {
+    while (key.slice(-1) === '\\') {
+      key = key.slice(0, -1) + '.' + keys.shift();
+    }
+    target = target[key] || (target[key] = {});
+  }
+
+  defineProperty(target, last, getter);
+  return obj;
+}
+
+/**
+ * Define getter function on object as a configurable and enumerable property.
+ *
+ * @param  {Object} `obj` Object to define property on.
+ * @param  {String} `prop` Property to define.
+ * @param  {Function} `getter` Getter function to define.
+ */
+
+function defineProperty(obj, prop, getter) {
+  Object.defineProperty(obj, prop, {
+    configurable: true,
+    enumerable: true,
+    get: getter
+  });
+}
+
+/**
+ * Expose `setGetter`
+ */
+
+module.exports = setGetter;
diff --git a/input_devices/mag/node_modules/set-getter/package.json b/input_devices/mag/node_modules/set-getter/package.json
new file mode 100644
index 00000000..e7e1be58
--- /dev/null
+++ b/input_devices/mag/node_modules/set-getter/package.json
@@ -0,0 +1,105 @@
+{
+  "_args": [
+    [
+      "set-getter@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/lazy-cache"
+    ]
+  ],
+  "_from": "set-getter@>=0.1.0 <0.2.0",
+  "_id": "set-getter@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/set-getter",
+  "_nodeVersion": "5.1.1",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/set-getter-0.1.0.tgz_1461947468848_0.7060375646688044"
+  },
+  "_npmUser": {
+    "email": "brian.woodward@gmail.com",
+    "name": "doowb"
+  },
+  "_npmVersion": "3.7.5",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "set-getter",
+    "raw": "set-getter@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/lazy-cache"
+  ],
+  "_resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz",
+  "_shasum": "d769c182c9d5a51f409145f2fba82e5e86e80376",
+  "_shrinkwrap": null,
+  "_spec": "set-getter@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/lazy-cache",
+  "author": {
+    "name": "Brian Woodward",
+    "url": "https://github.com/doowb"
+  },
+  "bugs": {
+    "url": "https://github.com/doowb/set-getter/issues"
+  },
+  "dependencies": {
+    "to-object-path": "^0.3.0"
+  },
+  "description": "Create nested getter properties and any intermediary dot notation (`'a.b.c'`) paths",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.9",
+    "mocha": "^2.4.5"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "d769c182c9d5a51f409145f2fba82e5e86e80376",
+    "tarball": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "bfdd988ef9aa472ff05d6d6c7501c33bc36dc39e",
+  "homepage": "https://github.com/doowb/set-getter",
+  "keywords": [],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "set-getter",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/doowb/set-getter.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "set-value",
+      "verb"
+    ],
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/set-value/LICENSE b/input_devices/mag/node_modules/set-value/LICENSE
new file mode 100644
index 00000000..d32ab442
--- /dev/null
+++ b/input_devices/mag/node_modules/set-value/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2018, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/set-value/README.md b/input_devices/mag/node_modules/set-value/README.md
new file mode 100644
index 00000000..e5a9d988
--- /dev/null
+++ b/input_devices/mag/node_modules/set-value/README.md
@@ -0,0 +1,234 @@
+# set-value [![NPM version](https://img.shields.io/npm/v/set-value.svg?style=flat)](https://www.npmjs.com/package/set-value) [![NPM monthly downloads](https://img.shields.io/npm/dm/set-value.svg?style=flat)](https://npmjs.org/package/set-value) [![NPM total downloads](https://img.shields.io/npm/dt/set-value.svg?style=flat)](https://npmjs.org/package/set-value) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/set-value.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/set-value)
+
+> Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save set-value
+```
+
+## Usage
+
+```js
+var set = require('set-value');
+set(object, prop, value);
+```
+
+### Params
+
+* `object` **{object}**: The object to set `value` on
+* `prop` **{string}**: The property to set. Dot-notation may be used.
+* `value` **{any}**: The value to set on `object[prop]`
+
+## Examples
+
+Updates and returns the given object:
+
+```js
+var obj = {};
+set(obj, 'a.b.c', 'd');
+console.log(obj);
+//=> { a: { b: { c: 'd' } } }
+```
+
+### Escaping
+
+**Escaping with backslashes**
+
+Prevent set-value from splitting on a dot by prefixing it with backslashes:
+
+```js
+console.log(set({}, 'a\\.b.c', 'd'));
+//=> { 'a.b': { c: 'd' } }
+
+console.log(set({}, 'a\\.b\\.c', 'd'));
+//=> { 'a.b.c': 'd' }
+```
+
+## Benchmarks
+
+_(benchmarks were run on a MacBook Pro 2.5 GHz Intel Core i7, 16 GB 1600 MHz DDR3)_.
+
+set-value is more reliable and has more features than dot-prop, without sacrificing performance.
+
+```
+# deep (194 bytes)
+  deep-object x 629,744 ops/sec ±0.85% (88 runs sampled)
+  deep-property x 1,470,427 ops/sec ±0.94% (89 runs sampled)
+  deep-set x 1,401,089 ops/sec ±1.02% (91 runs sampled)
+  deephas x 590,005 ops/sec ±1.73% (86 runs sampled)
+  dot-prop x 1,261,408 ops/sec ±0.94% (90 runs sampled)
+  dot2val x 1,672,729 ops/sec ±1.12% (89 runs sampled)
+  es5-dot-prop x 1,313,018 ops/sec ±0.79% (91 runs sampled)
+  lodash-set x 1,074,464 ops/sec ±0.97% (93 runs sampled)
+  object-path-set x 961,198 ops/sec ±2.07% (74 runs sampled)
+  object-set x 258,438 ops/sec ±0.69% (90 runs sampled)
+  set-value x 1,976,843 ops/sec ±2.07% (89 runs sampled)
+
+  fastest is set-value (by 186% avg)
+
+# medium (98 bytes)
+  deep-object x 3,249,287 ops/sec ±1.04% (93 runs sampled)
+  deep-property x 3,409,307 ops/sec ±1.28% (88 runs sampled)
+  deep-set x 3,240,776 ops/sec ±1.13% (93 runs sampled)
+  deephas x 960,504 ops/sec ±1.39% (89 runs sampled)
+  dot-prop x 2,776,388 ops/sec ±0.80% (94 runs sampled)
+  dot2val x 3,889,791 ops/sec ±1.28% (91 runs sampled)
+  es5-dot-prop x 2,779,604 ops/sec ±1.32% (91 runs sampled)
+  lodash-set x 2,791,304 ops/sec ±0.75% (90 runs sampled)
+  object-path-set x 2,462,084 ops/sec ±1.51% (91 runs sampled)
+  object-set x 838,569 ops/sec ±0.87% (90 runs sampled)
+  set-value x 4,767,287 ops/sec ±1.21% (91 runs sampled)
+
+  fastest is set-value (by 181% avg)
+
+# shallow (101 bytes)
+  deep-object x 4,793,168 ops/sec ±0.75% (88 runs sampled)
+  deep-property x 4,669,218 ops/sec ±1.17% (90 runs sampled)
+  deep-set x 4,648,247 ops/sec ±0.73% (91 runs sampled)
+  deephas x 1,246,414 ops/sec ±1.67% (92 runs sampled)
+  dot-prop x 3,913,694 ops/sec ±1.23% (89 runs sampled)
+  dot2val x 5,428,829 ops/sec ±0.76% (92 runs sampled)
+  es5-dot-prop x 3,897,931 ops/sec ±1.19% (92 runs sampled)
+  lodash-set x 6,128,638 ops/sec ±0.95% (87 runs sampled)
+  object-path-set x 5,429,978 ops/sec ±3.31% (87 runs sampled)
+  object-set x 1,529,485 ops/sec ±2.37% (89 runs sampled)
+  set-value x 7,150,921 ops/sec ±1.58% (89 runs sampled)
+
+  fastest is set-value (by 172% avg)
+
+```
+
+### Running the benchmarks
+
+Clone this library into a local directory:
+
+```sh
+$ git clone https://github.com/jonschlinkert/set-value.git
+```
+
+Then install devDependencies and run benchmarks:
+
+```sh
+$ npm install && node benchmark
+```
+
+## Comparisons to other libs, or _"the list of shame"_
+
+These are just a few of the duplicate libraries on NPM.
+
+* [bury](https://github.com/kalmbach/bury) fails all of the tests. I even wrapped it to have it return the object instead of the value, but with all of that work it still fails the vast majority of tests.
+* [deep-get-set](https://github.com/acstll/deep-get-set) fails 22 of 26 unit tests.
+* [deep-object](https://github.com/ayushgp/deep-object) fails 25 of 26 unit tests, completely butchered given objects.
+* [deep-property](https://github.com/mikattack/node-deep-property) fails 17 of 26 unit tests.
+* [deep-set](https://github.com/klaemo/deep-set) fails 13 of 26 unit tests.
+* [deephas](https://github.com/sharpred/deepHas) fails 17 of 26 unit tests.
+* [dot-prop](https://github.com/sindresorhus/dot-prop) fails 9 of 26 unit tests.
+* [dot2val](https://github.com/yangg/dot2val) fails 17 of 26 unit tests.
+* [es5-dot-prop](https://github.com/sindresorhus/dot-prop) fails 15 of 26 unit tests.
+* [getsetdeep](https://github.com/bevry/getsetdeep) fails all unit tests due to `this` being used improperly in the methods. I was able to patch it by binding the (plain) object to the methods, but it still fails 17 of 26 unit tests.
+* [lodash.set](https://lodash.com/) fails 11 of 26 unit tests.
+* [object-path-set](https://github.com/skratchdot/object-path-set) fails 12 of 26 unit tests.
+* [object-path](https://github.com/mariocasciaro/object-path) fails 16 of 26 unit tests.
+* [object-set](https://github.com/gearcase/object-set) fails 13 of 26 unit tests.
+* [set-nested-prop](https://github.com/tiaanduplessis/set-nested-prop) fails 24 of 26 unit tests.
+* [setvalue](https://github.com/blakeembrey/setvalue) (this library is almost identical to a previous version of this library)
+* Many dozens of others
+
+**Others that do the same thing, but use a completely different API**
+
+* [deep-set-in](https://github.com/KulikovskyIgor/deep-set-in)
+* [set-deep](https://github.com/radubrehar/set-deep)
+* [set-deep-prop](https://github.com/mmckelvy/set-deep-prop)
+* [bury](https://github.com/kalmbach/bury)
+* Many dozens of others
+
+## History
+
+### v3.0.0
+
+* Added support for a custom `split` function to be passed on the options.
+* Removed support for splitting on brackets, since a [custom function](https://github.com/jonschlinkert/split-string) can be passed to do this now.
+
+### v2.0.0
+
+* Adds support for escaping with double or single quotes. See [escaping](#escaping) for examples.
+* Will no longer split inside brackets or braces. See [bracket support](#bracket-support) for examples.
+
+If there are any regressions please create a [bug report](../../issues/new). Thanks!
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [assign-value](https://www.npmjs.com/package/assign-value): Assign a value or extend a deeply nested property of an object using object path… [more](https://github.com/jonschlinkert/assign-value) | [homepage](https://github.com/jonschlinkert/assign-value "Assign a value or extend a deeply nested property of an object using object path notation.")
+* [get-value](https://www.npmjs.com/package/get-value): Use property paths like 'a.b.c' to get a nested value from an object. Even works… [more](https://github.com/jonschlinkert/get-value) | [homepage](https://github.com/jonschlinkert/get-value "Use property paths like 'a.b.c' to get a nested value from an object. Even works when keys have dots in them (no other dot-prop library can do this!).")
+* [has-value](https://www.npmjs.com/package/has-value): Returns true if a value exists, false if empty. Works with deeply nested values using… [more](https://github.com/jonschlinkert/has-value) | [homepage](https://github.com/jonschlinkert/has-value "Returns true if a value exists, false if empty. Works with deeply nested values using object paths.")
+* [merge-value](https://www.npmjs.com/package/merge-value): Similar to assign-value but deeply merges object values or nested values using object path/dot notation. | [homepage](https://github.com/jonschlinkert/merge-value "Similar to assign-value but deeply merges object values or nested values using object path/dot notation.")
+* [omit-value](https://www.npmjs.com/package/omit-value): Omit properties from an object or deeply nested property of an object using object path… [more](https://github.com/jonschlinkert/omit-value) | [homepage](https://github.com/jonschlinkert/omit-value "Omit properties from an object or deeply nested property of an object using object path notation.")
+* [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value "Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.")
+* [union-value](https://www.npmjs.com/package/union-value): Set an array of unique values as the property of an object. Supports setting deeply… [more](https://github.com/jonschlinkert/union-value) | [homepage](https://github.com/jonschlinkert/union-value "Set an array of unique values as the property of an object. Supports setting deeply nested properties using using object-paths/dot notation.")
+* [unset-value](https://www.npmjs.com/package/unset-value): Delete nested properties from an object using dot notation. | [homepage](https://github.com/jonschlinkert/unset-value "Delete nested properties from an object using dot notation.")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 64 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [vadimdemedes](https://github.com/vadimdemedes) |
+| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
+* [GitHub Profile](https://github.com/jonschlinkert)
+* [Twitter Profile](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on March 05, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/set-value/index.js b/input_devices/mag/node_modules/set-value/index.js
new file mode 100644
index 00000000..8aee6ab0
--- /dev/null
+++ b/input_devices/mag/node_modules/set-value/index.js
@@ -0,0 +1,116 @@
+/*!
+ * set-value <https://github.com/jonschlinkert/set-value>
+ *
+ * Copyright (c) 2014-2018, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+const isPlain = require('is-plain-object');
+
+function set(target, path, value, options) {
+  if (!isObject(target)) {
+    return target;
+  }
+
+  let opts = options || {};
+  const isArray = Array.isArray(path);
+  if (!isArray && typeof path !== 'string') {
+    return target;
+  }
+
+  let merge = opts.merge;
+  if (merge && typeof merge !== 'function') {
+    merge = Object.assign;
+  }
+
+  const keys = isArray ? path : split(path, opts);
+  const len = keys.length;
+  const orig = target;
+
+  if (!options && keys.length === 1) {
+    result(target, keys[0], value, merge);
+    return target;
+  }
+
+  for (let i = 0; i < len; i++) {
+    let prop = keys[i];
+
+    if (!isObject(target[prop])) {
+      target[prop] = {};
+    }
+
+    if (i === len - 1) {
+      result(target, prop, value, merge);
+      break;
+    }
+
+    target = target[prop];
+  }
+
+  return orig;
+}
+
+function result(target, path, value, merge) {
+  if (merge && isPlain(target[path]) && isPlain(value)) {
+    target[path] = merge({}, target[path], value);
+  } else {
+    target[path] = value;
+  }
+}
+
+function split(path, options) {
+  const id = createKey(path, options);
+  if (set.memo[id]) return set.memo[id];
+
+  const char = (options && options.separator) ? options.separator : '.';
+  let keys = [];
+  let res = [];
+
+  if (options && typeof options.split === 'function') {
+    keys = options.split(path);
+  } else {
+    keys = path.split(char);
+  }
+
+  for (let i = 0; i < keys.length; i++) {
+    let prop = keys[i];
+    while (prop && prop.slice(-1) === '\\' && keys[i + 1]) {
+      prop = prop.slice(0, -1) + char + keys[++i];
+    }
+    res.push(prop);
+  }
+  set.memo[id] = res;
+  return res;
+}
+
+function createKey(pattern, options) {
+  let id = pattern;
+  if (typeof options === 'undefined') {
+    return id + '';
+  }
+  const keys = Object.keys(options);
+  for (let i = 0; i < keys.length; i++) {
+    const key = keys[i];
+    id += ';' + key + '=' + String(options[key]);
+  }
+  return id;
+}
+
+function isObject(val) {
+  switch (typeof val) {
+    case 'null':
+      return false;
+    case 'object':
+      return true;
+    case 'function':
+      return true;
+    default: {
+      return false;
+    }
+  }
+}
+
+set.memo = {};
+module.exports = set;
diff --git a/input_devices/mag/node_modules/set-value/package.json b/input_devices/mag/node_modules/set-value/package.json
new file mode 100644
index 00000000..6568b3c6
--- /dev/null
+++ b/input_devices/mag/node_modules/set-value/package.json
@@ -0,0 +1,203 @@
+{
+  "_args": [
+    [
+      "set-value@^3.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "set-value@>=3.0.0 <4.0.0",
+  "_id": "set-value@3.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/set-value",
+  "_nodeVersion": "9.7.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/set-value_3.0.0_1520293638561_0.3231121588728314"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.7.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "set-value",
+    "raw": "set-value@^3.0.0",
+    "rawSpec": "^3.0.0",
+    "scope": null,
+    "spec": ">=3.0.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/set-value/-/set-value-3.0.0.tgz",
+  "_shasum": "bc021514f46effed8176fd5f0f67e9988531141f",
+  "_shrinkwrap": null,
+  "_spec": "set-value@^3.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/set-value/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "url": "https://github.com/wtgtybhertgeghgtwtg"
+    },
+    {
+      "name": "Vadim Demedes",
+      "url": "https://vadimdemedes.com"
+    }
+  ],
+  "dependencies": {
+    "is-plain-object": "^2.0.4"
+  },
+  "description": "Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.",
+  "devDependencies": {
+    "benchmarked": "^2.0.0",
+    "deep-object": "^1.0.0",
+    "deep-property": "^1.1.0",
+    "deep-set": "^1.0.1",
+    "deephas": "^1.0.5",
+    "dot-prop": "^4.2.0",
+    "dot2val": "^1.2.2",
+    "es5-dot-prop": "^4.1.1",
+    "gulp-format-md": "^1.0.0",
+    "lodash.set": "^4.3.2",
+    "minimist": "^1.2.0",
+    "mocha": "^3.5.3",
+    "object-path-set": "^1.0.0",
+    "object-set": "^1.0.1",
+    "split-string": "^5.0.4",
+    "write": "^1.0.3"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-tqkg9wJ2TOsxbzIMG5NMAmzjdbDTAD0in7XuUzmFpJE4Ipi2QFBfgC2Z1/gfxcAmWCPsuutiEJyDIMRsrjrMOQ==",
+    "shasum": "bc021514f46effed8176fd5f0f67e9988531141f",
+    "tarball": "https://registry.npmjs.org/set-value/-/set-value-3.0.0.tgz",
+    "unpackedSize": 17299
+  },
+  "engines": {
+    "node": ">=6.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "1ac51c3662ce0a2016cb29a492f9e0b243fc4522",
+  "homepage": "https://github.com/jonschlinkert/set-value",
+  "keywords": [
+    "bury",
+    "deep-get-set",
+    "deep-object",
+    "deep-property",
+    "deep-set",
+    "deep-set-in",
+    "deephas",
+    "dot-prop",
+    "dot2val",
+    "es5-dot-prop",
+    "get",
+    "getsetdeep",
+    "has",
+    "hasown",
+    "key",
+    "keys",
+    "lodash.set",
+    "nested",
+    "notation",
+    "object",
+    "object-path",
+    "object-path-set",
+    "object-set",
+    "prop",
+    "properties",
+    "property",
+    "props",
+    "set",
+    "set-deep",
+    "set-deep-prop",
+    "set-nested-prop",
+    "setvalue",
+    "value",
+    "values"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "set-value",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/set-value.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "bury",
+      "deep-get-set",
+      "deep-object",
+      "deep-property",
+      "deep-set",
+      "deep-set-in",
+      "deephas",
+      "dot-prop",
+      "dot2val",
+      "es5-dot-prop",
+      "getsetdeep",
+      "lodash.set",
+      "object-path",
+      "object-path-set",
+      "object-set",
+      "set-deep",
+      "set-deep-prop",
+      "set-nested-prop",
+      "setvalue"
+    ],
+    "related": {
+      "list": [
+        "assign-value",
+        "get-value",
+        "has-value",
+        "merge-value",
+        "omit-value",
+        "set-value",
+        "union-value",
+        "unset-value"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.0.0"
+}
diff --git a/input_devices/mag/node_modules/shallow-clone/LICENSE b/input_devices/mag/node_modules/shallow-clone/LICENSE
new file mode 100644
index 00000000..c0d7f136
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/shallow-clone/README.md b/input_devices/mag/node_modules/shallow-clone/README.md
new file mode 100644
index 00000000..957199b5
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/README.md
@@ -0,0 +1,115 @@
+# shallow-clone [![NPM version](https://img.shields.io/npm/v/shallow-clone.svg?style=flat)](https://www.npmjs.com/package/shallow-clone) [![NPM monthly downloads](https://img.shields.io/npm/dm/shallow-clone.svg?style=flat)](https://npmjs.org/package/shallow-clone) [![NPM total downloads](https://img.shields.io/npm/dt/shallow-clone.svg?style=flat)](https://npmjs.org/package/shallow-clone) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/shallow-clone.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/shallow-clone)
+
+> Make a shallow clone of an object, array or primitive.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save shallow-clone
+```
+
+## Usage
+
+```js
+var clone = require('shallow-clone');
+```
+
+## shallow clones arrays
+
+The array itself is cloned, but not the elements of the array. So any objects in the array will still not be cloned (e.g. they will be the same object as in the orginal array).
+
+```js
+var arr = [{ 'a': 0 }, { 'b': 1 }]
+var foo = clone(arr);
+// foo =>  [{ 'a': 0 }, { 'b': 1 }]
+
+// array is cloned
+assert.equal(actual === expected, false);
+
+// array elements are not
+assert.deepEqual(actual[0], expected[0]); // true
+```
+
+## returns primitives as-is
+
+```js
+clone(0)
+//=> 0
+
+clone('foo')
+//=> 'foo'
+```
+
+## shallow clone a regex
+
+```js
+clone(/foo/g)
+//=> /foo/g
+```
+
+## shallow clone an object
+
+```js
+clone({a: 1, b: 2, c: 3 })
+//=> {a: 1, b: 2, c: 3 }
+```
+
+## About
+
+### Related projects
+
+* [assign-deep](https://www.npmjs.com/package/assign-deep): Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target… [more](https://github.com/jonschlinkert/assign-deep) | [homepage](https://github.com/jonschlinkert/assign-deep "Deeply assign the enumerable properties and/or es6 Symbol properies of source objects to the target (first) object.")
+* [clone-deep](https://www.npmjs.com/package/clone-deep): Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives. | [homepage](https://github.com/jonschlinkert/clone-deep "Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives.")
+* [extend-shallow](https://www.npmjs.com/package/extend-shallow): Extend an object with the properties of additional objects. node.js/javascript util. | [homepage](https://github.com/jonschlinkert/extend-shallow "Extend an object with the properties of additional objects. node.js/javascript util.")
+* [is-plain-object](https://www.npmjs.com/package/is-plain-object): Returns true if an object was created by the `Object` constructor. | [homepage](https://github.com/jonschlinkert/is-plain-object "Returns true if an object was created by the `Object` constructor.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep "Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone.")
+* [mixin-object](https://www.npmjs.com/package/mixin-object): Mixin the own and inherited properties of other objects onto the first object. Pass an… [more](https://github.com/jonschlinkert/mixin-object) | [homepage](https://github.com/jonschlinkert/mixin-object "Mixin the own and inherited properties of other objects onto the first object. Pass an empty object as the first arg to shallow clone.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 2 | [doowb](https://github.com/doowb) |
+| 2 | [jonschlinkert](https://github.com/jonschlinkert) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 16, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/shallow-clone/index.js b/input_devices/mag/node_modules/shallow-clone/index.js
new file mode 100644
index 00000000..87d8ff4f
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/index.js
@@ -0,0 +1,57 @@
+/*!
+ * shallow-clone <https://github.com/jonschlinkert/shallow-clone>
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var isObject = require('is-extendable');
+var mixin = require('mixin-object');
+var typeOf = require('kind-of');
+
+/**
+ * Shallow copy an object, array or primitive.
+ *
+ * @param  {any} `val`
+ * @return {any}
+ */
+
+function clone(val) {
+  var type = typeOf(val);
+  if (clone.hasOwnProperty(type)) {
+    return clone[type](val);
+  }
+  return val;
+}
+
+clone.array = function cloneArray(arr) {
+  return arr.slice();
+};
+
+clone.date = function cloneDate(date) {
+  return new Date(+date);
+};
+
+clone.object = function cloneObject(obj) {
+  if (isObject(obj)) {
+    return mixin({}, obj);
+  } else {
+    return obj;
+  }
+};
+
+clone.regexp = function cloneRegExp(re) {
+  var flags = '';
+  flags += re.multiline ? 'm' : '';
+  flags += re.global ? 'g' : '';
+  flags += re.ignorecase ? 'i' : '';
+  return new RegExp(re.source, flags);
+};
+
+/**
+ * Expose `clone`
+ */
+
+module.exports = clone;
diff --git a/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/README.md b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/README.md
new file mode 100644
index 00000000..170bf304
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/README.md
@@ -0,0 +1,342 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Release history
+
+### v4.0.0
+
+**Added**
+
+* `promise` support
+
+### v5.0.0
+
+**Added**
+
+* `Set Iterator` and `Map Iterator` support
+
+**Fixed**
+
+* Now returns `generatorfunction` for generator functions
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of is more correct than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly tests instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+<details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+<details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+<details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 82 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike](https://github.com/charlike) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on October 13, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/index.js b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/index.js
new file mode 100644
index 00000000..fc5cde96
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/index.js
@@ -0,0 +1,147 @@
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  var type = typeof val;
+
+  // primitivies
+  if (type === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (type === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (type === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (type === 'function' || val instanceof Function) {
+    if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') {
+      return 'generatorfunction';
+    }
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+  if (type === '[object Promise]') {
+    return 'promise';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+  
+  if (type === '[object Map Iterator]') {
+    return 'mapiterator';
+  }
+  if (type === '[object Set Iterator]') {
+    return 'setiterator';
+  }
+  if (type === '[object String Iterator]') {
+    return 'stringiterator';
+  }
+  if (type === '[object Array Iterator]') {
+    return 'arrayiterator';
+  }
+  
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  return val.constructor
+    && typeof val.constructor.isBuffer === 'function'
+    && val.constructor.isBuffer(val);
+}
diff --git a/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/package.json b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/package.json
new file mode 100644
index 00000000..6fc8eff7
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/node_modules/kind-of/package.json
@@ -0,0 +1,179 @@
+{
+  "_args": [
+    [
+      "kind-of@^5.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/shallow-clone"
+    ]
+  ],
+  "_from": "kind-of@>=5.0.0 <6.0.0",
+  "_id": "kind-of@5.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/shallow-clone/kind-of",
+  "_nodeVersion": "8.7.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-5.1.0.tgz_1507878225264_0.114781056297943"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.4.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^5.0.0",
+    "rawSpec": "^5.0.0",
+    "scope": null,
+    "spec": ">=5.0.0 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/shallow-clone"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+  "_shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^5.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/shallow-clone",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.1.1",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^0.1.12",
+    "matched": "^0.4.4",
+    "mocha": "^3.4.2",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+    "shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ed479b6ee194dc1edff852f17095ae1de40bafbc",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "5.1.0"
+}
diff --git a/input_devices/mag/node_modules/shallow-clone/package.json b/input_devices/mag/node_modules/shallow-clone/package.json
new file mode 100644
index 00000000..372ae29b
--- /dev/null
+++ b/input_devices/mag/node_modules/shallow-clone/package.json
@@ -0,0 +1,140 @@
+{
+  "_args": [
+    [
+      "shallow-clone@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep"
+    ]
+  ],
+  "_from": "shallow-clone@>=1.0.0 <2.0.0",
+  "_id": "shallow-clone@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/shallow-clone",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/shallow-clone-1.0.0.tgz_1500207093497_0.3621308500878513"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "shallow-clone",
+    "raw": "shallow-clone@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/clone-deep"
+  ],
+  "_resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz",
+  "_shasum": "4480cd06e882ef68b2ad88a3ea54832e2c48b571",
+  "_shrinkwrap": null,
+  "_spec": "shallow-clone@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/clone-deep",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/shallow-clone/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "is-extendable": "^0.1.1",
+    "kind-of": "^5.0.0",
+    "mixin-object": "^2.0.1"
+  },
+  "description": "Make a shallow clone of an object, array or primitive.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.4.2",
+    "should": "^11.2.1"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==",
+    "shasum": "4480cd06e882ef68b2ad88a3ea54832e2c48b571",
+    "tarball": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "20023f3d8b672f57a59d3af9875998ddb4ebef5f",
+  "homepage": "https://github.com/jonschlinkert/shallow-clone",
+  "keywords": [
+    "array",
+    "clone",
+    "copy",
+    "extend",
+    "mixin",
+    "object",
+    "primitive",
+    "shallow"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "shallow-clone",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/shallow-clone.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "assign-deep",
+        "clone-deep",
+        "extend-shallow",
+        "is-plain-object",
+        "isobject",
+        "kind-of",
+        "mixin-deep",
+        "mixin-object"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/signal-exit/CHANGELOG.md b/input_devices/mag/node_modules/signal-exit/CHANGELOG.md
new file mode 100644
index 00000000..e2f70d22
--- /dev/null
+++ b/input_devices/mag/node_modules/signal-exit/CHANGELOG.md
@@ -0,0 +1,27 @@
+# Change Log
+
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+<a name="3.0.1"></a>
+## [3.0.1](https://github.com/tapjs/signal-exit/compare/v3.0.0...v3.0.1) (2016-09-08)
+
+
+### Bug Fixes
+
+* do not listen on SIGBUS, SIGFPE, SIGSEGV and SIGILL ([#40](https://github.com/tapjs/signal-exit/issues/40)) ([5b105fb](https://github.com/tapjs/signal-exit/commit/5b105fb))
+
+
+
+<a name="3.0.0"></a>
+# [3.0.0](https://github.com/tapjs/signal-exit/compare/v2.1.2...v3.0.0) (2016-06-13)
+
+
+### Bug Fixes
+
+* get our test suite running on Windows ([#23](https://github.com/tapjs/signal-exit/issues/23)) ([6f3eda8](https://github.com/tapjs/signal-exit/commit/6f3eda8))
+* hooking SIGPROF was interfering with profilers see [#21](https://github.com/tapjs/signal-exit/issues/21) ([#24](https://github.com/tapjs/signal-exit/issues/24)) ([1248a4c](https://github.com/tapjs/signal-exit/commit/1248a4c))
+
+
+### BREAKING CHANGES
+
+* signal-exit no longer wires into SIGPROF
diff --git a/input_devices/mag/node_modules/signal-exit/LICENSE.txt b/input_devices/mag/node_modules/signal-exit/LICENSE.txt
new file mode 100644
index 00000000..eead04a1
--- /dev/null
+++ b/input_devices/mag/node_modules/signal-exit/LICENSE.txt
@@ -0,0 +1,16 @@
+The ISC License
+
+Copyright (c) 2015, Contributors
+
+Permission to use, copy, modify, and/or distribute this software
+for any purpose with or without fee is hereby granted, provided
+that the above copyright notice and this permission notice
+appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
+LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/signal-exit/README.md b/input_devices/mag/node_modules/signal-exit/README.md
new file mode 100644
index 00000000..8ebccabe
--- /dev/null
+++ b/input_devices/mag/node_modules/signal-exit/README.md
@@ -0,0 +1,40 @@
+# signal-exit
+
+[![Build Status](https://travis-ci.org/tapjs/signal-exit.png)](https://travis-ci.org/tapjs/signal-exit)
+[![Coverage](https://coveralls.io/repos/tapjs/signal-exit/badge.svg?branch=master)](https://coveralls.io/r/tapjs/signal-exit?branch=master)
+[![NPM version](https://img.shields.io/npm/v/signal-exit.svg)](https://www.npmjs.com/package/signal-exit)
+[![Windows Tests](https://img.shields.io/appveyor/ci/bcoe/signal-exit/master.svg?label=Windows%20Tests)](https://ci.appveyor.com/project/bcoe/signal-exit)
+[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
+
+When you want to fire an event no matter how a process exits:
+
+* reaching the end of execution.
+* explicitly having `process.exit(code)` called.
+* having `process.kill(pid, sig)` called.
+* receiving a fatal signal from outside the process
+
+Use `signal-exit`.
+
+```js
+var onExit = require('signal-exit')
+
+onExit(function (code, signal) {
+  console.log('process exited!')
+})
+```
+
+## API
+
+`var remove = onExit(function (code, signal) {}, options)`
+
+The return value of the function is a function that will remove the
+handler.
+
+Note that the function *only* fires for signals if the signal would
+cause the proces to exit.  That is, there are no other listeners, and
+it is a fatal signal.
+
+## Options
+
+* `alwaysLast`: Run this handler after any other signal or exit
+  handlers.  This causes `process.emit` to be monkeypatched.
diff --git a/input_devices/mag/node_modules/signal-exit/index.js b/input_devices/mag/node_modules/signal-exit/index.js
new file mode 100644
index 00000000..337f691e
--- /dev/null
+++ b/input_devices/mag/node_modules/signal-exit/index.js
@@ -0,0 +1,157 @@
+// Note: since nyc uses this module to output coverage, any lines
+// that are in the direct sync flow of nyc's outputCoverage are
+// ignored, since we can never get coverage for them.
+var assert = require('assert')
+var signals = require('./signals.js')
+
+var EE = require('events')
+/* istanbul ignore if */
+if (typeof EE !== 'function') {
+  EE = EE.EventEmitter
+}
+
+var emitter
+if (process.__signal_exit_emitter__) {
+  emitter = process.__signal_exit_emitter__
+} else {
+  emitter = process.__signal_exit_emitter__ = new EE()
+  emitter.count = 0
+  emitter.emitted = {}
+}
+
+// Because this emitter is a global, we have to check to see if a
+// previous version of this library failed to enable infinite listeners.
+// I know what you're about to say.  But literally everything about
+// signal-exit is a compromise with evil.  Get used to it.
+if (!emitter.infinite) {
+  emitter.setMaxListeners(Infinity)
+  emitter.infinite = true
+}
+
+module.exports = function (cb, opts) {
+  assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler')
+
+  if (loaded === false) {
+    load()
+  }
+
+  var ev = 'exit'
+  if (opts && opts.alwaysLast) {
+    ev = 'afterexit'
+  }
+
+  var remove = function () {
+    emitter.removeListener(ev, cb)
+    if (emitter.listeners('exit').length === 0 &&
+        emitter.listeners('afterexit').length === 0) {
+      unload()
+    }
+  }
+  emitter.on(ev, cb)
+
+  return remove
+}
+
+module.exports.unload = unload
+function unload () {
+  if (!loaded) {
+    return
+  }
+  loaded = false
+
+  signals.forEach(function (sig) {
+    try {
+      process.removeListener(sig, sigListeners[sig])
+    } catch (er) {}
+  })
+  process.emit = originalProcessEmit
+  process.reallyExit = originalProcessReallyExit
+  emitter.count -= 1
+}
+
+function emit (event, code, signal) {
+  if (emitter.emitted[event]) {
+    return
+  }
+  emitter.emitted[event] = true
+  emitter.emit(event, code, signal)
+}
+
+// { <signal>: <listener fn>, ... }
+var sigListeners = {}
+signals.forEach(function (sig) {
+  sigListeners[sig] = function listener () {
+    // If there are no other listeners, an exit is coming!
+    // Simplest way: remove us and then re-send the signal.
+    // We know that this will kill the process, so we can
+    // safely emit now.
+    var listeners = process.listeners(sig)
+    if (listeners.length === emitter.count) {
+      unload()
+      emit('exit', null, sig)
+      /* istanbul ignore next */
+      emit('afterexit', null, sig)
+      /* istanbul ignore next */
+      process.kill(process.pid, sig)
+    }
+  }
+})
+
+module.exports.signals = function () {
+  return signals
+}
+
+module.exports.load = load
+
+var loaded = false
+
+function load () {
+  if (loaded) {
+    return
+  }
+  loaded = true
+
+  // This is the number of onSignalExit's that are in play.
+  // It's important so that we can count the correct number of
+  // listeners on signals, and don't wait for the other one to
+  // handle it instead of us.
+  emitter.count += 1
+
+  signals = signals.filter(function (sig) {
+    try {
+      process.on(sig, sigListeners[sig])
+      return true
+    } catch (er) {
+      return false
+    }
+  })
+
+  process.emit = processEmit
+  process.reallyExit = processReallyExit
+}
+
+var originalProcessReallyExit = process.reallyExit
+function processReallyExit (code) {
+  process.exitCode = code || 0
+  emit('exit', process.exitCode, null)
+  /* istanbul ignore next */
+  emit('afterexit', process.exitCode, null)
+  /* istanbul ignore next */
+  originalProcessReallyExit.call(process, process.exitCode)
+}
+
+var originalProcessEmit = process.emit
+function processEmit (ev, arg) {
+  if (ev === 'exit') {
+    if (arg !== undefined) {
+      process.exitCode = arg
+    }
+    var ret = originalProcessEmit.apply(this, arguments)
+    emit('exit', process.exitCode, null)
+    /* istanbul ignore next */
+    emit('afterexit', process.exitCode, null)
+    return ret
+  } else {
+    return originalProcessEmit.apply(this, arguments)
+  }
+}
diff --git a/input_devices/mag/node_modules/signal-exit/package.json b/input_devices/mag/node_modules/signal-exit/package.json
new file mode 100644
index 00000000..75467da1
--- /dev/null
+++ b/input_devices/mag/node_modules/signal-exit/package.json
@@ -0,0 +1,98 @@
+{
+  "_args": [
+    [
+      "signal-exit@^3.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge"
+    ]
+  ],
+  "_from": "signal-exit@>=3.0.0 <4.0.0",
+  "_id": "signal-exit@3.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/signal-exit",
+  "_nodeVersion": "6.5.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/signal-exit-3.0.2.tgz_1480821660838_0.6809983775019646"
+  },
+  "_npmUser": {
+    "email": "i@izs.me",
+    "name": "isaacs"
+  },
+  "_npmVersion": "3.10.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "signal-exit",
+    "raw": "signal-exit@^3.0.0",
+    "rawSpec": "^3.0.0",
+    "scope": null,
+    "spec": ">=3.0.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge"
+  ],
+  "_resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+  "_shasum": "b5fdc08f1287ea1178628e415e25132b73646c6d",
+  "_shrinkwrap": null,
+  "_spec": "signal-exit@^3.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge",
+  "author": {
+    "email": "ben@npmjs.com",
+    "name": "Ben Coe"
+  },
+  "bugs": {
+    "url": "https://github.com/tapjs/signal-exit/issues"
+  },
+  "dependencies": {},
+  "description": "when you want to fire an event no matter how a process exits.",
+  "devDependencies": {
+    "chai": "^3.5.0",
+    "coveralls": "^2.11.10",
+    "nyc": "^8.1.0",
+    "standard": "^7.1.2",
+    "standard-version": "^2.3.0",
+    "tap": "^8.0.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "b5fdc08f1287ea1178628e415e25132b73646c6d",
+    "tarball": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz"
+  },
+  "files": [
+    "index.js",
+    "signals.js"
+  ],
+  "gitHead": "9c5ad9809fe6135ef22e2623989deaffe2a4fa8a",
+  "homepage": "https://github.com/tapjs/signal-exit",
+  "keywords": [
+    "exit",
+    "signal"
+  ],
+  "license": "ISC",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "bcoe",
+      "email": "ben@npmjs.com"
+    },
+    {
+      "name": "isaacs",
+      "email": "isaacs@npmjs.com"
+    }
+  ],
+  "name": "signal-exit",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/tapjs/signal-exit.git"
+  },
+  "scripts": {
+    "coverage": "nyc report --reporter=text-lcov | coveralls",
+    "pretest": "standard",
+    "release": "standard-version",
+    "test": "tap --timeout=240 ./test/*.js --cov"
+  },
+  "version": "3.0.2"
+}
diff --git a/input_devices/mag/node_modules/signal-exit/signals.js b/input_devices/mag/node_modules/signal-exit/signals.js
new file mode 100644
index 00000000..3bd67a8a
--- /dev/null
+++ b/input_devices/mag/node_modules/signal-exit/signals.js
@@ -0,0 +1,53 @@
+// This is not the set of all possible signals.
+//
+// It IS, however, the set of all signals that trigger
+// an exit on either Linux or BSD systems.  Linux is a
+// superset of the signal names supported on BSD, and
+// the unknown signals just fail to register, so we can
+// catch that easily enough.
+//
+// Don't bother with SIGKILL.  It's uncatchable, which
+// means that we can't fire any callbacks anyway.
+//
+// If a user does happen to register a handler on a non-
+// fatal signal like SIGWINCH or something, and then
+// exit, it'll end up firing `process.emit('exit')`, so
+// the handler will be fired anyway.
+//
+// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
+// artificially, inherently leave the process in a
+// state from which it is not safe to try and enter JS
+// listeners.
+module.exports = [
+  'SIGABRT',
+  'SIGALRM',
+  'SIGHUP',
+  'SIGINT',
+  'SIGTERM'
+]
+
+if (process.platform !== 'win32') {
+  module.exports.push(
+    'SIGVTALRM',
+    'SIGXCPU',
+    'SIGXFSZ',
+    'SIGUSR2',
+    'SIGTRAP',
+    'SIGSYS',
+    'SIGQUIT',
+    'SIGIOT'
+    // should detect profiler and enable/disable accordingly.
+    // see #21
+    // 'SIGPROF'
+  )
+}
+
+if (process.platform === 'linux') {
+  module.exports.push(
+    'SIGIO',
+    'SIGPOLL',
+    'SIGPWR',
+    'SIGSTKFLT',
+    'SIGUNUSED'
+  )
+}
diff --git a/input_devices/mag/node_modules/simple-concat/.travis.yml b/input_devices/mag/node_modules/simple-concat/.travis.yml
new file mode 100644
index 00000000..f178ec0d
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-concat/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+  - 'node'
diff --git a/input_devices/mag/node_modules/simple-concat/LICENSE b/input_devices/mag/node_modules/simple-concat/LICENSE
new file mode 100644
index 00000000..c7e68527
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-concat/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) Feross Aboukhadijeh
+
+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/input_devices/mag/node_modules/simple-concat/README.md b/input_devices/mag/node_modules/simple-concat/README.md
new file mode 100644
index 00000000..572e99c7
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-concat/README.md
@@ -0,0 +1,42 @@
+# simple-concat [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url]
+
+[travis-image]: https://img.shields.io/travis/feross/simple-concat/master.svg
+[travis-url]: https://travis-ci.org/feross/simple-concat
+[npm-image]: https://img.shields.io/npm/v/simple-concat.svg
+[npm-url]: https://npmjs.org/package/simple-concat
+[downloads-image]: https://img.shields.io/npm/dm/simple-concat.svg
+[downloads-url]: https://npmjs.org/package/simple-concat
+
+### Super-minimalist version of `concat-stream`. Less than 15 lines!
+
+## install
+
+```
+npm install simple-concat
+```
+
+## usage
+
+This example is longer than the implementation.
+
+```js
+var s = new stream.PassThrough()
+concat(s, function (err, buf) {
+  if (err) throw err
+  console.error(buf)
+})
+s.write('abc')
+setTimeout(function () {
+  s.write('123')
+}, 10)
+setTimeout(function () {
+  s.write('456')
+}, 20)
+setTimeout(function () {
+  s.end('789')
+}, 30)
+```
+
+## license
+
+MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
diff --git a/input_devices/mag/node_modules/simple-concat/index.js b/input_devices/mag/node_modules/simple-concat/index.js
new file mode 100644
index 00000000..c2d88600
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-concat/index.js
@@ -0,0 +1,14 @@
+module.exports = function (stream, cb) {
+  var chunks = []
+  stream.on('data', function (chunk) {
+    chunks.push(chunk)
+  })
+  stream.once('end', function () {
+    if (cb) cb(null, Buffer.concat(chunks))
+    cb = null
+  })
+  stream.once('error', function (err) {
+    if (cb) cb(err)
+    cb = null
+  })
+}
diff --git a/input_devices/mag/node_modules/simple-concat/package.json b/input_devices/mag/node_modules/simple-concat/package.json
new file mode 100644
index 00000000..3495ee31
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-concat/package.json
@@ -0,0 +1,85 @@
+{
+  "_args": [
+    [
+      "simple-concat@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/simple-get"
+    ]
+  ],
+  "_from": "simple-concat@>=1.0.0 <2.0.0",
+  "_id": "simple-concat@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/simple-concat",
+  "_nodeVersion": "4.4.1",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/simple-concat-1.0.0.tgz_1461229969789_0.8977642937097698"
+  },
+  "_npmUser": {
+    "email": "feross@feross.org",
+    "name": "feross"
+  },
+  "_npmVersion": "2.14.20",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "simple-concat",
+    "raw": "simple-concat@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/simple-get"
+  ],
+  "_resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
+  "_shasum": "7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6",
+  "_shrinkwrap": null,
+  "_spec": "simple-concat@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/simple-get",
+  "author": {
+    "email": "feross@feross.org",
+    "name": "Feross Aboukhadijeh",
+    "url": "http://feross.org/"
+  },
+  "bugs": {
+    "url": "https://github.com/feross/simple-concat/issues"
+  },
+  "dependencies": {},
+  "description": "Super-minimalist version of `concat-stream`. Less than 15 lines!",
+  "devDependencies": {
+    "standard": "^6.0.8",
+    "tape": "^4.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6",
+    "tarball": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz"
+  },
+  "gitHead": "7ea5b5aecfbbbf554c66474dd43a2271373640ed",
+  "homepage": "https://github.com/feross/simple-concat",
+  "keywords": [
+    "concat",
+    "concat stream",
+    "concat-stream"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "feross",
+      "email": "feross@feross.org"
+    }
+  ],
+  "name": "simple-concat",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/feross/simple-concat.git"
+  },
+  "scripts": {
+    "test": "standard && tape test/*.js"
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/simple-concat/test/basic.js b/input_devices/mag/node_modules/simple-concat/test/basic.js
new file mode 100644
index 00000000..f781294a
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-concat/test/basic.js
@@ -0,0 +1,41 @@
+var concat = require('../')
+var stream = require('stream')
+var test = require('tape')
+
+test('basic', function (t) {
+  t.plan(2)
+  var s = new stream.PassThrough()
+  concat(s, function (err, buf) {
+    t.error(err)
+    t.deepEqual(buf, new Buffer('abc123456789'))
+  })
+  s.write('abc')
+  setTimeout(function () {
+    s.write('123')
+  }, 10)
+  setTimeout(function () {
+    s.write('456')
+  }, 20)
+  setTimeout(function () {
+    s.end('789')
+  }, 30)
+})
+
+test('error', function (t) {
+  t.plan(2)
+  var s = new stream.PassThrough()
+  concat(s, function (err, buf) {
+    t.ok(err, 'got expected error')
+    t.ok(!buf)
+  })
+  s.write('abc')
+  setTimeout(function () {
+    s.write('123')
+  }, 10)
+  setTimeout(function () {
+    s.write('456')
+  }, 20)
+  setTimeout(function () {
+    s.emit('error', new Error('error'))
+  }, 30)
+})
diff --git a/input_devices/mag/node_modules/simple-get/LICENSE b/input_devices/mag/node_modules/simple-get/LICENSE
new file mode 100644
index 00000000..c7e68527
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-get/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) Feross Aboukhadijeh
+
+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/input_devices/mag/node_modules/simple-get/README.md b/input_devices/mag/node_modules/simple-get/README.md
new file mode 100644
index 00000000..9787919f
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-get/README.md
@@ -0,0 +1,306 @@
+# simple-get [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
+
+[travis-image]: https://img.shields.io/travis/feross/simple-get/master.svg
+[travis-url]: https://travis-ci.org/feross/simple-get
+[npm-image]: https://img.shields.io/npm/v/simple-get.svg
+[npm-url]: https://npmjs.org/package/simple-get
+[downloads-image]: https://img.shields.io/npm/dm/simple-get.svg
+[downloads-url]: https://npmjs.org/package/simple-get
+[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
+[standard-url]: https://standardjs.com
+
+### Simplest way to make http get requests
+
+## features
+
+This module is the lightest possible wrapper on top of node.js `http`, but supporting these essential features:
+
+- follows redirects
+- automatically handles gzip/deflate responses
+- supports HTTPS
+- supports specifying a timeout
+- supports convenience `url` key so there's no need to use `url.parse` on the url when specifying options
+- composes well with npm packages for features like cookies, proxies, form data, & OAuth
+
+All this in < 120 lines of code.
+
+## install
+
+```
+npm install simple-get
+```
+
+## usage
+
+Note, all these examples also work in the browser with [browserify](http://browserify.org/).
+
+### simple GET request
+
+Doesn't get easier than this:
+
+```js
+const get = require('simple-get')
+
+get('http://example.com', function (err, res) {
+  if (err) throw err
+  console.log(res.statusCode) // 200
+  res.pipe(process.stdout) // `res` is a stream
+})
+```
+
+### even simpler GET request
+
+If you just want the data, and don't want to deal with streams:
+
+```js
+const get = require('simple-get')
+
+get.concat('http://example.com', function (err, res, data) {
+  if (err) throw err
+  console.log(res.statusCode) // 200
+  console.log(data) // Buffer('this is the server response')
+})
+```
+
+### POST, PUT, PATCH, HEAD, DELETE support
+
+For `POST`, call `get.post` or use option `{ method: 'POST' }`.
+
+```js
+const get = require('simple-get')
+
+const opts = {
+  url: 'http://example.com',
+  body: 'this is the POST body'
+}
+get.post(opts, function (err, res) {
+  if (err) throw err
+  res.pipe(process.stdout) // `res` is a stream
+})
+```
+
+#### A more complex example:
+
+```js
+const get = require('simple-get')
+
+get({
+  url: 'http://example.com',
+  method: 'POST',
+  body: 'this is the POST body',
+
+  // simple-get accepts all options that node.js `http` accepts
+  // See: http://nodejs.org/api/http.html#http_http_request_options_callback
+  headers: {
+    'user-agent': 'my cool app'
+  }
+}, function (err, res) {
+  if (err) throw err
+
+  // All properties/methods from http.IncomingResponse are available,
+  // even if a gunzip/inflate transform stream was returned.
+  // See: http://nodejs.org/api/http.html#http_http_incomingmessage
+  res.setTimeout(10000)
+  console.log(res.headers)
+
+  res.on('data', function (chunk) {
+    // `chunk` is the decoded response, after it's been gunzipped or inflated
+    // (if applicable)
+    console.log('got a chunk of the response: ' + chunk)
+  }))
+
+})
+```
+
+### JSON
+
+You can serialize/deserialize request and response with JSON:
+
+```js
+const get = require('simple-get')
+
+const opts = {
+  method: 'POST',
+  url: 'http://example.com',
+  body: {
+    key: 'value'
+  },
+  json: true
+}
+get.concat(opts, function (err, res, data) {
+  if (err) throw err
+  console.log(data.key) // `data` is an object
+})
+```
+
+### Timeout
+
+You can set a timeout (in milliseconds) on the request with the `timeout` option.
+If the request takes longer than `timeout` to complete, then the entire request
+will fail with an `Error`.
+
+```js
+const get = require('simple-get')
+
+const opts = {
+  url: 'http://example.com',
+  timeout: 2000 // 2 second timeout
+}
+
+get(opts, function (err, res) {})
+```
+
+### One Quick Tip
+
+It's a good idea to set the `'user-agent'` header so the provider can more easily
+see how their resource is used.
+
+```js
+const get = require('simple-get')
+const pkg = require('./package.json')
+
+get('http://example.com', {
+  headers: {
+    'user-agent': `my-module/${pkg.version} (https://github.com/username/my-module)`
+  }
+})
+```
+
+### Proxies
+
+You can use the [`tunnel`](https://github.com/koichik/node-tunnel) module with the
+`agent` option to work with proxies:
+
+```js
+const get = require('simple-get')
+const tunnel = require('tunnel')
+
+const opts = {
+  url: 'http://example.com',
+  agent: tunnel.httpOverHttp({
+    proxy: {
+      host: 'localhost'
+    }
+  })
+}
+
+get(opts, function (err, res) {})
+```
+
+### Cookies
+
+You can use the [`cookie`](https://github.com/jshttp/cookie) module to include
+cookies in a request:
+
+```js
+const get = require('simple-get')
+const cookie = require('cookie')
+
+const opts = {
+  url: 'http://example.com',
+  headers: {
+    cookie: cookie.serialize('foo', 'bar')
+  }
+}
+
+get(opts, function (err, res) {})
+```
+
+### Form data
+
+You can use the [`form-data`](https://github.com/form-data/form-data) module to
+create POST request with form data:
+
+```js
+const fs = require('fs')
+const get = require('simple-get')
+const FormData = require('form-data')
+const form = new FormData()
+
+form.append('my_file', fs.createReadStream('/foo/bar.jpg'))
+
+const opts = {
+  url: 'http://example.com',
+  body: form
+}
+
+get.post(opts, function (err, res) {})
+```
+
+#### Or, include `application/x-www-form-urlencoded` form data manually:
+
+```js
+const get = require('simple-get')
+
+const opts = {
+  url: 'http://example.com',
+  form: {
+    key: 'value'
+  }
+}
+get.post(opts, function (err, res) {})
+```
+
+### OAuth
+
+You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) module to create
+a signed OAuth request:
+
+```js
+const get = require('simple-get')
+const crypto  = require('crypto')
+const OAuth = require('oauth-1.0a')
+
+const oauth = OAuth({
+  consumer: {
+    key: process.env.CONSUMER_KEY,
+    secret: process.env.CONSUMER_SECRET
+  },
+  signature_method: 'HMAC-SHA1',
+  hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
+})
+
+const token = {
+  key: process.env.ACCESS_TOKEN,
+  secret: process.env.ACCESS_TOKEN_SECRET
+}
+
+const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json'
+
+const opts = {
+  url: url,
+  headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
+  json: true
+}
+
+get(opts, function (err, res) {})
+```
+
+### Throttle requests
+
+You can use [limiter](https://github.com/jhurliman/node-rate-limiter) to throttle requests. This is useful when calling an API that is rate limited.
+
+```js
+const simpleGet = require('simple-get')
+const RateLimiter = require('limiter').RateLimiter
+const limiter = new RateLimiter(1, 'second')
+
+const get = (opts, cb) => limiter.removeTokens(1, () => simpleGet(opts, cb))
+get.concat = (opts, cb) => limiter.removeTokens(1, () => simpleGet.concat(opts, cb))
+
+var opts = {
+  url: 'http://example.com'
+}
+
+get.concat(opts, processResult)
+get.concat(opts, processResult)
+
+function processResult (err, res, data) {
+  if (err) throw err
+  console.log(data.toString())
+}
+```
+
+## license
+
+MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
diff --git a/input_devices/mag/node_modules/simple-get/index.js b/input_devices/mag/node_modules/simple-get/index.js
new file mode 100644
index 00000000..67214e3b
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-get/index.js
@@ -0,0 +1,113 @@
+module.exports = simpleGet
+
+var concat = require('simple-concat')
+var http = require('http')
+var https = require('https')
+var once = require('once')
+var querystring = require('querystring')
+var decompressResponse = require('decompress-response') // excluded from browser build
+var url = require('url')
+
+function simpleGet (opts, cb) {
+  opts = typeof opts === 'string' ? {url: opts} : Object.assign({}, opts)
+  cb = once(cb)
+
+  opts.headers = Object.assign({}, opts.headers)
+
+  Object.keys(opts.headers).forEach(function (h) {
+    if (h.toLowerCase() !== h) {
+      opts.headers[h.toLowerCase()] = opts.headers[h]
+      delete opts.headers[h]
+    }
+  })
+
+  if (opts.url) {
+    var loc = url.parse(opts.url)
+    if (loc.hostname) opts.hostname = loc.hostname
+    if (loc.port) opts.port = loc.port
+    if (loc.protocol) opts.protocol = loc.protocol
+    if (loc.auth) opts.auth = loc.auth
+    opts.path = loc.path
+    delete opts.url
+  }
+
+  if (opts.maxRedirects == null) opts.maxRedirects = 10
+  if (opts.method) opts.method = opts.method.toUpperCase()
+
+  var body
+  if (opts.body) {
+    body = opts.json && !isStream(opts.body) ? JSON.stringify(opts.body) : opts.body
+  } else if (opts.form) {
+    body = typeof opts.form === 'string' ? opts.form : querystring.stringify(opts.form)
+    opts.headers['content-type'] = 'application/x-www-form-urlencoded'
+  }
+  delete opts.body; delete opts.form
+
+  if (body) {
+    if (!opts.method) opts.method = 'POST'
+    if (!isStream(body)) opts.headers['content-length'] = Buffer.byteLength(body)
+    if (opts.json) opts.headers['content-type'] = 'application/json'
+  }
+
+  if (opts.json) opts.headers.accept = 'application/json'
+  if (!opts.headers['accept-encoding']) opts.headers['accept-encoding'] = 'gzip, deflate' // Prefer gzip
+
+  var protocol = opts.protocol === 'https:' ? https : http // Support http/https urls
+  var req = protocol.request(opts, function (res) {
+    if (res.statusCode >= 300 && res.statusCode < 400 && 'location' in res.headers) {
+      opts.url = res.headers.location // Follow 3xx redirects
+      delete opts.headers.host // Discard `host` header on redirect (see #32)
+      res.resume() // Discard response
+
+      if ((res.statusCode === 301 || res.statusCode === 302) && opts.method === 'POST') {
+        opts.method = 'GET' // On 301/302 redirect, change POST to GET (see #35)
+        delete opts.headers['content-length']
+        delete opts.headers['content-type']
+      }
+
+      if (opts.maxRedirects === 0) return cb(new Error('too many redirects'))
+      opts.maxRedirects -= 1
+      return simpleGet(opts, cb)
+    }
+
+    var tryUnzip = typeof decompressResponse === 'function' && opts.method !== 'HEAD'
+    cb(null, tryUnzip ? decompressResponse(res) : res)
+  })
+  req.on('timeout', function () {
+    req.abort()
+    cb(new Error('Request timed out'))
+  })
+  req.on('error', cb)
+
+  if (body && isStream(body)) body.on('error', cb).pipe(req)
+  else req.end(body)
+
+  return req
+}
+
+simpleGet.concat = function (opts, cb) {
+  return simpleGet(opts, function (err, res) {
+    if (err) return cb(err)
+    concat(res, function (err, data) {
+      if (err) return cb(err)
+      if (opts.json) {
+        try {
+          data = JSON.parse(data.toString())
+        } catch (err) {
+          return cb(err, res, data)
+        }
+      }
+      cb(null, res, data)
+    })
+  })
+}
+
+;['get', 'post', 'put', 'patch', 'head', 'delete'].forEach(function (method) {
+  simpleGet[method] = function (opts, cb) {
+    if (typeof opts === 'string') opts = {url: opts}
+    opts.method = method.toUpperCase()
+    return simpleGet(opts, cb)
+  }
+})
+
+function isStream (obj) { return typeof obj.pipe === 'function' }
diff --git a/input_devices/mag/node_modules/simple-get/package.json b/input_devices/mag/node_modules/simple-get/package.json
new file mode 100644
index 00000000..19955f61
--- /dev/null
+++ b/input_devices/mag/node_modules/simple-get/package.json
@@ -0,0 +1,109 @@
+{
+  "_args": [
+    [
+      "simple-get@^2.7.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "simple-get@>=2.7.0 <3.0.0",
+  "_id": "simple-get@2.8.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/simple-get",
+  "_nodeVersion": "8.11.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/simple-get_2.8.1_1524602670094_0.5544670814451136"
+  },
+  "_npmUser": {
+    "email": "feross@feross.org",
+    "name": "feross"
+  },
+  "_npmVersion": "6.0.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "simple-get",
+    "raw": "simple-get@^2.7.0",
+    "rawSpec": "^2.7.0",
+    "scope": null,
+    "spec": ">=2.7.0 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
+  "_shasum": "0e22e91d4575d87620620bc91308d57a77f44b5d",
+  "_shrinkwrap": null,
+  "_spec": "simple-get@^2.7.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "feross@feross.org",
+    "name": "Feross Aboukhadijeh",
+    "url": "http://feross.org/"
+  },
+  "browser": {
+    "decompress-response": false
+  },
+  "bugs": {
+    "url": "https://github.com/feross/simple-get/issues"
+  },
+  "dependencies": {
+    "decompress-response": "^3.3.0",
+    "once": "^1.3.1",
+    "simple-concat": "^1.0.0"
+  },
+  "description": "Simplest way to make http get requests. Supports HTTPS, redirects, gzip/deflate, streams in < 100 lines.",
+  "devDependencies": {
+    "self-signed-https": "^1.0.5",
+    "standard": "*",
+    "string-to-stream": "^1.0.0",
+    "tape": "^4.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa35cuCRA9TVsSAnZWagAA4OUP/3hXnUIK2BDCbNNmYyMK\nEMegu24zC1vgFqv/ZSVrdspPKcylT/g5baQn2VlS4JGaHYvhxwricToESRg9\nnTqhTw/v5xtA7sSxz9in4M/36pHiwFJKb2C+MsVM5mq7q+aqHxIHeJ+GReQ3\ndRrwobSy9QySshSinG5Pu7uAr81SaAvajKyva/0+CM7o/1vSL+blC1/CY7WW\ni2xzEXAYAMw/u8SpSMPuccqiN5K2+267tem49kNLnSPxFidvfIkEQ9Umghkb\naNvHlKODGj405pyyarfEONDdT8pbDYw1xz7BIUzANsiPuHmdUlWIhm1m+kUL\nBn0YNZdusqAL4loSPwafjFYcb+3hly7LF3JQUxumfZpvoBLGv7os4Aw2IiDG\n4gbTCUT+2Ks8eGKj/SoXdEdQgsvkDtt3eBySbxy3oaHkw0o5uXomXIavEj0E\nFZOvYmvYKHXJmY+oQFLqR7g7j16fMLBuno3KfwYCxkjsQVSic56d+Xsz1OA0\nEV5y1tgfPWj745nFwM3m/eqD9suaZMBhLNQ5heMBIBM9KOK0dr7zuBINeAKv\nXXk7iMp2rOionQhn+4VVNeDU13kgB8369qmMZFsST1R8L6AuaIrOqWJBD2rA\nT++YICxd9wirtK/1HwLmKAgSkjidV0iRbBfJFYGkySIHPpKn+54RzNGHzLID\nU/Lc\r\n=uIpo\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "0e22e91d4575d87620620bc91308d57a77f44b5d",
+    "tarball": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
+    "unpackedSize": 13021
+  },
+  "gitHead": "c0351df7dda5502b6c46728b06743f7b387cb6d7",
+  "homepage": "https://github.com/feross/simple-get",
+  "keywords": [
+    "GET",
+    "deflate",
+    "follow redirects",
+    "get request",
+    "gzip",
+    "http",
+    "http-https",
+    "http.get",
+    "https",
+    "redirects",
+    "request",
+    "simple get",
+    "simple request",
+    "stream"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "feross",
+      "email": "feross@feross.org"
+    }
+  ],
+  "name": "simple-get",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/feross/simple-get.git"
+  },
+  "scripts": {
+    "test": "standard && tape test/*.js"
+  },
+  "version": "2.8.1"
+}
diff --git a/input_devices/mag/node_modules/static-extend/LICENSE b/input_devices/mag/node_modules/static-extend/LICENSE
new file mode 100644
index 00000000..e28e6032
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/static-extend/index.js b/input_devices/mag/node_modules/static-extend/index.js
new file mode 100644
index 00000000..f4124b2a
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/index.js
@@ -0,0 +1,90 @@
+/*!
+ * static-extend <https://github.com/jonschlinkert/static-extend>
+ *
+ * Copyright (c) 2016, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var copy = require('object-copy');
+var define = require('define-property');
+var util = require('util');
+
+/**
+ * Returns a function for extending the static properties,
+ * prototype properties, and descriptors from the `Parent`
+ * constructor onto `Child` constructors.
+ *
+ * ```js
+ * var extend = require('static-extend');
+ * Parent.extend = extend(Parent);
+ *
+ * // optionally pass a custom merge function as the second arg
+ * Parent.extend = extend(Parent, function(Child) {
+ *   Child.prototype.mixin = function(key, val) {
+ *     Child.prototype[key] = val;
+ *   };
+ * });
+ *
+ * // extend "child" constructors
+ * Parent.extend(Child);
+ *
+ * // optionally define prototype methods as the second arg
+ * Parent.extend(Child, {
+ *   foo: function() {},
+ *   bar: function() {}
+ * });
+ * ```
+ * @param {Function} `Parent` Parent ctor
+ * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype.
+ *   @param {Function} `Child` Child ctor
+ *   @param {Object} `proto` Optionally pass additional prototype properties to inherit.
+ *   @return {Object}
+ * @api public
+ */
+
+function extend(Parent, extendFn) {
+  if (typeof Parent !== 'function') {
+    throw new TypeError('expected Parent to be a function.');
+  }
+
+  return function(Ctor, proto) {
+    if (typeof Ctor !== 'function') {
+      throw new TypeError('expected Ctor to be a function.');
+    }
+
+    util.inherits(Ctor, Parent);
+    copy(Ctor, Parent);
+
+    // proto can be null or a plain object
+    if (typeof proto === 'object') {
+      var obj = Object.create(proto);
+
+      for (var k in obj) {
+        Ctor.prototype[k] = obj[k];
+      }
+    }
+
+    // keep a reference to the parent prototype
+    define(Ctor.prototype, '_parent_', {
+      configurable: true,
+      set: function() {},
+      get: function() {
+        return Parent.prototype;
+      }
+    });
+
+    if (typeof extendFn === 'function') {
+      extendFn(Ctor, Parent);
+    }
+
+    Ctor.extend = extend(Ctor, extendFn);
+  };
+};
+
+/**
+ * Expose `extend`
+ */
+
+module.exports = extend;
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/define-property/LICENSE b/input_devices/mag/node_modules/static-extend/node_modules/define-property/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/define-property/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/static-extend/node_modules/define-property/README.md b/input_devices/mag/node_modules/static-extend/node_modules/define-property/README.md
new file mode 100644
index 00000000..8cac698a
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/define-property/README.md
@@ -0,0 +1,77 @@
+# define-property [![NPM version](https://badge.fury.io/js/define-property.svg)](http://badge.fury.io/js/define-property)
+
+> Define a non-enumerable property on an object.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i define-property --save
+```
+
+## Usage
+
+**Params**
+
+* `obj`: The object on which to define the property.
+* `prop`: The name of the property to be defined or modified.
+* `descriptor`: The descriptor for the property being defined or modified.
+
+```js
+var define = require('define-property');
+var obj = {};
+define(obj, 'foo', function(val) {
+  return val.toUpperCase();
+});
+
+console.log(obj);
+//=> {}
+
+console.log(obj.foo('bar'));
+//=> 'BAR'
+```
+
+**get/set**
+
+```js
+define(obj, 'foo', {
+  get: function() {},
+  set: function() {}
+});
+```
+
+## Related projects
+
+* [delegate-object](https://www.npmjs.com/package/delegate-object): Copy properties from an object to another object, where properties with function values will be… [more](https://www.npmjs.com/package/delegate-object) | [homepage](https://github.com/doowb/delegate-object)
+* [forward-object](https://www.npmjs.com/package/forward-object): Copy properties from an object to another object, where properties with function values will be… [more](https://www.npmjs.com/package/forward-object) | [homepage](https://github.com/doowb/forward-object)
+* [mixin-deep](https://www.npmjs.com/package/mixin-deep): Deeply mix the properties of objects into the first object. Like merge-deep, but doesn't clone. | [homepage](https://github.com/jonschlinkert/mixin-deep)
+* [mixin-object](https://www.npmjs.com/package/mixin-object): Mixin the own and inherited properties of other objects onto the first object. Pass an… [more](https://www.npmjs.com/package/mixin-object) | [homepage](https://github.com/jonschlinkert/mixin-object)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/define-property/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on August 31, 2015._
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/define-property/index.js b/input_devices/mag/node_modules/static-extend/node_modules/define-property/index.js
new file mode 100644
index 00000000..3e0e5e13
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/define-property/index.js
@@ -0,0 +1,31 @@
+/*!
+ * define-property <https://github.com/jonschlinkert/define-property>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var isDescriptor = require('is-descriptor');
+
+module.exports = function defineProperty(obj, prop, val) {
+  if (typeof obj !== 'object' && typeof obj !== 'function') {
+    throw new TypeError('expected an object or function.');
+  }
+
+  if (typeof prop !== 'string') {
+    throw new TypeError('expected `prop` to be a string.');
+  }
+
+  if (isDescriptor(val) && ('set' in val || 'get' in val)) {
+    return Object.defineProperty(obj, prop, val);
+  }
+
+  return Object.defineProperty(obj, prop, {
+    configurable: true,
+    enumerable: false,
+    writable: true,
+    value: val
+  });
+};
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/define-property/package.json b/input_devices/mag/node_modules/static-extend/node_modules/define-property/package.json
new file mode 100644
index 00000000..7decd99c
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/define-property/package.json
@@ -0,0 +1,105 @@
+{
+  "_args": [
+    [
+      "define-property@^0.2.5",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend"
+    ]
+  ],
+  "_from": "define-property@>=0.2.5 <0.3.0",
+  "_id": "define-property@0.2.5",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend/define-property",
+  "_nodeVersion": "0.12.4",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.10.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "define-property",
+    "raw": "define-property@^0.2.5",
+    "rawSpec": "^0.2.5",
+    "scope": null,
+    "spec": ">=0.2.5 <0.3.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend"
+  ],
+  "_resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+  "_shasum": "c35b1ef918ec3c990f9a5bc57be04aacec5c8116",
+  "_shrinkwrap": null,
+  "_spec": "define-property@^0.2.5",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/define-property/issues"
+  },
+  "dependencies": {
+    "is-descriptor": "^0.1.0"
+  },
+  "description": "Define a non-enumerable property on an object.",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "^7.0.4"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "c35b1ef918ec3c990f9a5bc57be04aacec5c8116",
+    "tarball": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "5bf4e5e9d8d1fdf8fba07fff4bdf13a5d6df8ae4",
+  "homepage": "https://github.com/jonschlinkert/define-property",
+  "keywords": [
+    "define",
+    "define-property",
+    "enumerable",
+    "key",
+    "non",
+    "non-enumerable",
+    "object",
+    "prop",
+    "property",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "define-property",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/define-property.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "related": {
+      "list": [
+        "delegate-object",
+        "forward-object",
+        "mixin-deep",
+        "mixin-object"
+      ]
+    }
+  },
+  "version": "0.2.5"
+}
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/LICENSE b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/README.md b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/README.md
new file mode 100644
index 00000000..3743fe6b
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/README.md
@@ -0,0 +1,123 @@
+# is-accessor-descriptor [![NPM version](https://img.shields.io/npm/v/is-accessor-descriptor.svg)](https://www.npmjs.com/package/is-accessor-descriptor) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-accessor-descriptor.svg)](https://travis-ci.org/jonschlinkert/is-accessor-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.
+
+- [Install](#install)
+- [Usage](#usage)
+- [Examples](#examples)
+- [API](#api)
+- [Related projects](#related-projects)
+- [Running tests](#running-tests)
+- [Contributing](#contributing)
+- [Author](#author)
+- [License](#license)
+
+_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm i is-accessor-descriptor --save
+```
+
+## Usage
+
+```js
+var isAccessor = require('is-accessor-descriptor');
+
+isAccessor({get: function() {}});
+//=> true
+```
+
+You may also pass an object and property name to check if the property is an accessor:
+
+```js
+isAccessor(foo, 'bar');
+```
+
+## Examples
+
+`false` when not an object
+
+```js
+isAccessor('a')
+isAccessor(null)
+isAccessor([])
+//=> false
+```
+
+`true` when the object has valid properties
+
+and the properties all have the correct JavaScript types:
+
+```js
+isAccessor({get: noop, set: noop})
+isAccessor({get: noop})
+isAccessor({set: noop})
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isAccessor({get: noop, set: noop, bar: 'baz'})
+isAccessor({get: noop, writable: true})
+isAccessor({get: noop, value: true})
+//=> false
+```
+
+`false` when an accessor is not a function
+
+```js
+isAccessor({get: noop, set: 'baz'})
+isAccessor({get: 'foo', set: noop})
+isAccessor({get: 'foo', bar: 'baz'})
+isAccessor({get: 'foo', set: 'baz'})
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isAccessor({get: noop, set: noop, enumerable: 'foo'})
+isAccessor({set: noop, configurable: 'foo'})
+isAccessor({get: noop, configurable: 'foo'})
+//=> false
+```
+
+## Related projects
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor)
+* [is-data-descriptor](https://www.npmjs.com/package/is-data-descriptor): Returns true if a value has the characteristics of a valid JavaScript data descriptor. | [homepage](https://github.com/jonschlinkert/is-data-descriptor)
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://www.npmjs.com/package/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor)
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/is-accessor-descriptor/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 [Jon Schlinkert](https://github.com/jonschlinkert)
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb](https://github.com/verbose/verb) on December 28, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/index.js b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/index.js
new file mode 100644
index 00000000..2ca4af8b
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/index.js
@@ -0,0 +1,69 @@
+/*!
+ * is-accessor-descriptor <https://github.com/jonschlinkert/is-accessor-descriptor>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+// accessor descriptor properties
+var accessor = {
+  get: 'function',
+  set: 'function',
+  configurable: 'boolean',
+  enumerable: 'boolean'
+};
+
+function isAccessorDescriptor(obj, prop) {
+  if (typeof prop === 'string') {
+    var val = Object.getOwnPropertyDescriptor(obj, prop);
+    return typeof val !== 'undefined';
+  }
+
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+
+  if (has(obj, 'value') || has(obj, 'writable')) {
+    return false;
+  }
+
+  if (!has(obj, 'get') || typeof obj.get !== 'function') {
+    return false;
+  }
+
+  // tldr: it's valid to have "set" be undefined
+  // "set" might be undefined if `Object.getOwnPropertyDescriptor`
+  // was used to get the value, and only `get` was defined by the user
+  if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') {
+    return false;
+  }
+
+  for (var key in obj) {
+    if (!accessor.hasOwnProperty(key)) {
+      continue;
+    }
+
+    if (typeOf(obj[key]) === accessor[key]) {
+      continue;
+    }
+
+    if (typeof obj[key] !== 'undefined') {
+      return false;
+    }
+  }
+  return true;
+}
+
+function has(obj, key) {
+  return {}.hasOwnProperty.call(obj, key);
+}
+
+/**
+ * Expose `isAccessorDescriptor`
+ */
+
+module.exports = isAccessorDescriptor;
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..d734237b
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md
new file mode 100644
index 00000000..6a9df36d
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/README.md
@@ -0,0 +1,261 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+## Install
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+
+## About
+
+### Related projects
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 59 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 16, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js
new file mode 100644
index 00000000..b52c2917
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/index.js
@@ -0,0 +1,116 @@
+var isBuffer = require('is-buffer');
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  // primitivies
+  if (typeof val === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (typeof val === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (typeof val === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (typeof val === 'function' || val instanceof Function) {
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  var type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json
new file mode 100644
index 00000000..60a754a6
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of/package.json
@@ -0,0 +1,172 @@
+{
+  "_args": [
+    [
+      "kind-of@^3.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor"
+    ],
+    [
+      "kind-of@^3.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/to-object-path"
+    ]
+  ],
+  "_from": "kind-of@>=3.0.2 <4.0.0",
+  "_id": "kind-of@3.2.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend/is-accessor-descriptor/kind-of",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/kind-of-3.2.2.tgz_1494958899918_0.23780996026471257"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.5.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^3.0.2",
+    "rawSpec": "^3.0.2",
+    "scope": null,
+    "spec": ">=3.0.2 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend/is-accessor-descriptor"
+  ],
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^3.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    }
+  ],
+  "dependencies": {
+    "is-buffer": "^1.1.5"
+  },
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.0.0",
+    "browserify": "^14.3.0",
+    "glob": "^7.1.1",
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.3.0",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "31ea21a734bab9bbb0f32466d893aea51e4a3c64",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "0ffe67cf12f5396047c1bacf04232b7deeb24063",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.2.2"
+}
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/package.json b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/package.json
new file mode 100644
index 00000000..84d9aa72
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-accessor-descriptor/package.json
@@ -0,0 +1,117 @@
+{
+  "_args": [
+    [
+      "is-accessor-descriptor@^0.1.6",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "is-accessor-descriptor@>=0.1.6 <0.2.0",
+  "_id": "is-accessor-descriptor@0.1.6",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend/is-accessor-descriptor",
+  "_nodeVersion": "5.0.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.3.6",
+  "_phantomChildren": {
+    "is-buffer": "1.1.6"
+  },
+  "_requested": {
+    "name": "is-accessor-descriptor",
+    "raw": "is-accessor-descriptor@^0.1.6",
+    "rawSpec": "^0.1.6",
+    "scope": null,
+    "spec": ">=0.1.6 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+  "_shasum": "a9e12cb3ae8d876727eeef3843f8a0897b5c98d6",
+  "_shrinkwrap": null,
+  "_spec": "is-accessor-descriptor@^0.1.6",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-accessor-descriptor/issues"
+  },
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a9e12cb3ae8d876727eeef3843f8a0897b5c98d6",
+    "tarball": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e64ae49c456c9f31dab47934b0183e2a9938b5bd",
+  "homepage": "https://github.com/jonschlinkert/is-accessor-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-accessor-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-accessor-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    }
+  },
+  "version": "0.1.6"
+}
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/LICENSE b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/README.md b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/README.md
new file mode 100644
index 00000000..41e1643f
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/README.md
@@ -0,0 +1,128 @@
+# is-data-descriptor [![NPM version](https://img.shields.io/npm/v/is-data-descriptor.svg)](https://www.npmjs.com/package/is-data-descriptor) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-data-descriptor.svg)](https://travis-ci.org/jonschlinkert/is-data-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript data descriptor.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm i is-data-descriptor --save
+```
+
+## Usage
+
+```js
+var isDataDesc = require('is-data-descriptor');
+```
+
+## Examples
+
+`true` when the descriptor has valid properties with valid values.
+
+```js
+// `value` can be anything
+isDataDesc({value: 'foo'})
+isDataDesc({value: function() {}})
+isDataDesc({value: true})
+//=> true
+```
+
+`false` when not an object
+
+```js
+isDataDesc('a')
+//=> false
+isDataDesc(null)
+//=> false
+isDataDesc([])
+//=> false
+```
+
+`false` when the object has invalid properties
+
+```js
+isDataDesc({value: 'foo', bar: 'baz'})
+//=> false
+isDataDesc({value: 'foo', bar: 'baz'})
+//=> false
+isDataDesc({value: 'foo', get: function(){}})
+//=> false
+isDataDesc({get: function(){}, value: 'foo'})
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDataDesc({value: 'foo', enumerable: 'foo'})
+//=> false
+isDataDesc({value: 'foo', configurable: 'foo'})
+//=> false
+isDataDesc({value: 'foo', writable: 'foo'})
+//=> false
+```
+
+## Valid properties
+
+The only valid data descriptor properties are the following:
+
+* `configurable` (required)
+* `enumerable` (required)
+* `value` (optional)
+* `writable` (optional)
+
+To be a valid data descriptor, either `value` or `writable` must be defined.
+
+**Invalid properties**
+
+A descriptor may have additional _invalid_ properties (an error will **not** be thrown).
+
+```js
+var foo = {};
+
+Object.defineProperty(foo, 'bar', {
+  enumerable: true,
+  whatever: 'blah', // invalid, but doesn't cause an error
+  get: function() {
+    return 'baz';
+  }
+});
+
+console.log(foo.bar);
+//=> 'baz'
+```
+
+## Related projects
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor)
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://www.npmjs.com/package/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor)
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/is-data-descriptor/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 [Jon Schlinkert](https://github.com/jonschlinkert)
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb](https://github.com/verbose/verb) on December 28, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/index.js b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/index.js
new file mode 100644
index 00000000..d4d09c92
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/index.js
@@ -0,0 +1,55 @@
+/*!
+ * is-data-descriptor <https://github.com/jonschlinkert/is-data-descriptor>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+// data descriptor properties
+var data = {
+  configurable: 'boolean',
+  enumerable: 'boolean',
+  writable: 'boolean'
+};
+
+function isDataDescriptor(obj, prop) {
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+
+  if (typeof prop === 'string') {
+    var val = Object.getOwnPropertyDescriptor(obj, prop);
+    return typeof val !== 'undefined';
+  }
+
+  if (!('value' in obj) && !('writable' in obj)) {
+    return false;
+  }
+
+  for (var key in obj) {
+    if (key === 'value') continue;
+
+    if (!data.hasOwnProperty(key)) {
+      continue;
+    }
+
+    if (typeOf(obj[key]) === data[key]) {
+      continue;
+    }
+
+    if (typeof obj[key] !== 'undefined') {
+      return false;
+    }
+  }
+  return true;
+}
+
+/**
+ * Expose `isDataDescriptor`
+ */
+
+module.exports = isDataDescriptor;
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..d734237b
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/README.md b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/README.md
new file mode 100644
index 00000000..6a9df36d
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/README.md
@@ -0,0 +1,261 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+## Install
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+
+## About
+
+### Related projects
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 59 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 16, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/index.js b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/index.js
new file mode 100644
index 00000000..b52c2917
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/index.js
@@ -0,0 +1,116 @@
+var isBuffer = require('is-buffer');
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  // primitivies
+  if (typeof val === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (typeof val === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (typeof val === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (typeof val === 'function' || val instanceof Function) {
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  var type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/package.json b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/package.json
new file mode 100644
index 00000000..edad15f5
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of/package.json
@@ -0,0 +1,172 @@
+{
+  "_args": [
+    [
+      "kind-of@^3.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor"
+    ],
+    [
+      "kind-of@^3.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/to-object-path"
+    ]
+  ],
+  "_from": "kind-of@>=3.0.2 <4.0.0",
+  "_id": "kind-of@3.2.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend/is-data-descriptor/kind-of",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/kind-of-3.2.2.tgz_1494958899918_0.23780996026471257"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.5.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^3.0.2",
+    "rawSpec": "^3.0.2",
+    "scope": null,
+    "spec": ">=3.0.2 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend/is-data-descriptor"
+  ],
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^3.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    }
+  ],
+  "dependencies": {
+    "is-buffer": "^1.1.5"
+  },
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.0.0",
+    "browserify": "^14.3.0",
+    "glob": "^7.1.1",
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.3.0",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "31ea21a734bab9bbb0f32466d893aea51e4a3c64",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "0ffe67cf12f5396047c1bacf04232b7deeb24063",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.2.2"
+}
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/package.json b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/package.json
new file mode 100644
index 00000000..9d9efb1f
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-data-descriptor/package.json
@@ -0,0 +1,116 @@
+{
+  "_args": [
+    [
+      "is-data-descriptor@^0.1.4",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "is-data-descriptor@>=0.1.4 <0.2.0",
+  "_id": "is-data-descriptor@0.1.4",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend/is-data-descriptor",
+  "_nodeVersion": "5.0.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.3.6",
+  "_phantomChildren": {
+    "is-buffer": "1.1.6"
+  },
+  "_requested": {
+    "name": "is-data-descriptor",
+    "raw": "is-data-descriptor@^0.1.4",
+    "rawSpec": "^0.1.4",
+    "scope": null,
+    "spec": ">=0.1.4 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+  "_shasum": "0b5ee648388e2c860282e793f1856fec3f301b56",
+  "_shrinkwrap": null,
+  "_spec": "is-data-descriptor@^0.1.4",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-data-descriptor/issues"
+  },
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript data descriptor.",
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "0b5ee648388e2c860282e793f1856fec3f301b56",
+    "tarball": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "e6317dbcb27a95281a60120bac83f5938dda4e2c",
+  "homepage": "https://github.com/jonschlinkert/is-data-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-data-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-data-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    }
+  },
+  "version": "0.1.4"
+}
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/LICENSE b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/LICENSE
new file mode 100644
index 00000000..c0d7f136
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert.
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/README.md b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/README.md
new file mode 100644
index 00000000..658e5330
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/README.md
@@ -0,0 +1,193 @@
+# is-descriptor [![NPM version](https://img.shields.io/npm/v/is-descriptor.svg?style=flat)](https://www.npmjs.com/package/is-descriptor) [![NPM monthly downloads](https://img.shields.io/npm/dm/is-descriptor.svg?style=flat)](https://npmjs.org/package/is-descriptor) [![NPM total downloads](https://img.shields.io/npm/dt/is-descriptor.svg?style=flat)](https://npmjs.org/package/is-descriptor) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/is-descriptor.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/is-descriptor)
+
+> Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-descriptor
+```
+
+## Usage
+
+```js
+var isDescriptor = require('is-descriptor');
+
+isDescriptor({value: 'foo'})
+//=> true
+isDescriptor({get: function(){}, set: function(){}})
+//=> true
+isDescriptor({get: 'foo', set: function(){}})
+//=> false
+```
+
+You may also check for a descriptor by passing an object as the first argument and property name (`string`) as the second argument.
+
+```js
+var obj = {};
+obj.foo = 'abc';
+
+Object.defineProperty(obj, 'bar', {
+  value: 'xyz'
+});
+
+isDescriptor(obj, 'foo');
+//=> true
+isDescriptor(obj, 'bar');
+//=> true
+```
+
+## Examples
+
+### value type
+
+`false` when not an object
+
+```js
+isDescriptor('a');
+//=> false
+isDescriptor(null);
+//=> false
+isDescriptor([]);
+//=> false
+```
+
+### data descriptor
+
+`true` when the object has valid properties with valid values.
+
+```js
+isDescriptor({value: 'foo'});
+//=> true
+isDescriptor({value: noop});
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isDescriptor({value: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({value: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({value: 'foo', get: noop});
+//=> false
+isDescriptor({get: noop, value: noop});
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDescriptor({value: 'foo', enumerable: 'foo'});
+//=> false
+isDescriptor({value: 'foo', configurable: 'foo'});
+//=> false
+isDescriptor({value: 'foo', writable: 'foo'});
+//=> false
+```
+
+### accessor descriptor
+
+`true` when the object has valid properties with valid values.
+
+```js
+isDescriptor({get: noop, set: noop});
+//=> true
+isDescriptor({get: noop});
+//=> true
+isDescriptor({set: noop});
+//=> true
+```
+
+`false` when the object has invalid properties
+
+```js
+isDescriptor({get: noop, set: noop, bar: 'baz'});
+//=> false
+isDescriptor({get: noop, writable: true});
+//=> false
+isDescriptor({get: noop, value: true});
+//=> false
+```
+
+`false` when an accessor is not a function
+
+```js
+isDescriptor({get: noop, set: 'baz'});
+//=> false
+isDescriptor({get: 'foo', set: noop});
+//=> false
+isDescriptor({get: 'foo', bar: 'baz'});
+//=> false
+isDescriptor({get: 'foo', set: 'baz'});
+//=> false
+```
+
+`false` when a value is not the correct type
+
+```js
+isDescriptor({get: noop, set: noop, enumerable: 'foo'});
+//=> false
+isDescriptor({set: noop, configurable: 'foo'});
+//=> false
+isDescriptor({get: noop, configurable: 'foo'});
+//=> false
+```
+
+## About
+
+### Related projects
+
+* [is-accessor-descriptor](https://www.npmjs.com/package/is-accessor-descriptor): Returns true if a value has the characteristics of a valid JavaScript accessor descriptor. | [homepage](https://github.com/jonschlinkert/is-accessor-descriptor "Returns true if a value has the characteristics of a valid JavaScript accessor descriptor.")
+* [is-data-descriptor](https://www.npmjs.com/package/is-data-descriptor): Returns true if a value has the characteristics of a valid JavaScript data descriptor. | [homepage](https://github.com/jonschlinkert/is-data-descriptor "Returns true if a value has the characteristics of a valid JavaScript data descriptor.")
+* [is-descriptor](https://www.npmjs.com/package/is-descriptor): Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for… [more](https://github.com/jonschlinkert/is-descriptor) | [homepage](https://github.com/jonschlinkert/is-descriptor "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.")
+* [isobject](https://www.npmjs.com/package/isobject): Returns true if the value is an object and not an array or null. | [homepage](https://github.com/jonschlinkert/isobject "Returns true if the value is an object and not an array or null.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 24 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [doowb](https://github.com/doowb) |
+| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on July 22, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/index.js b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/index.js
new file mode 100644
index 00000000..c9b91d76
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/index.js
@@ -0,0 +1,22 @@
+/*!
+ * is-descriptor <https://github.com/jonschlinkert/is-descriptor>
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+var isAccessor = require('is-accessor-descriptor');
+var isData = require('is-data-descriptor');
+
+module.exports = function isDescriptor(obj, key) {
+  if (typeOf(obj) !== 'object') {
+    return false;
+  }
+  if ('get' in obj) {
+    return isAccessor(obj, key);
+  }
+  return isData(obj, key);
+};
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/package.json b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/package.json
new file mode 100644
index 00000000..b77a1f98
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor/package.json
@@ -0,0 +1,142 @@
+{
+  "_args": [
+    [
+      "is-descriptor@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/define-property"
+    ]
+  ],
+  "_from": "is-descriptor@>=0.1.0 <0.2.0",
+  "_id": "is-descriptor@0.1.6",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend/is-descriptor",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/is-descriptor-0.1.6.tgz_1500744018543_0.5760307745076716"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-descriptor",
+    "raw": "is-descriptor@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend/define-property"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+  "_shasum": "366d8240dde487ca51823b1ab9f07a10a78251ca",
+  "_shrinkwrap": null,
+  "_spec": "is-descriptor@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/define-property",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-descriptor/issues"
+  },
+  "contributors": [
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "url": "https://github.com/wtgtybhertgeghgtwtg"
+    }
+  ],
+  "dependencies": {
+    "is-accessor-descriptor": "^0.1.6",
+    "is-data-descriptor": "^0.1.4",
+    "kind-of": "^5.0.0"
+  },
+  "description": "Returns true if a value has the characteristics of a valid JavaScript descriptor. Works for data descriptors and accessor descriptors.",
+  "devDependencies": {
+    "gulp-format-md": "^1.0.0",
+    "mocha": "^3.4.2"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+    "shasum": "366d8240dde487ca51823b1ab9f07a10a78251ca",
+    "tarball": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "7559403830553097fcdd56ae93fe69d4ef2b21db",
+  "homepage": "https://github.com/jonschlinkert/is-descriptor",
+  "keywords": [
+    "accessor",
+    "check",
+    "data",
+    "descriptor",
+    "get",
+    "getter",
+    "is",
+    "keys",
+    "object",
+    "properties",
+    "property",
+    "set",
+    "setter",
+    "type",
+    "valid",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "is-descriptor",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-descriptor.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "is-accessor-descriptor",
+        "is-data-descriptor",
+        "is-descriptor",
+        "isobject"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.1.6"
+}
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/kind-of/LICENSE b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/LICENSE
new file mode 100644
index 00000000..3f2eca18
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2017, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/static-extend/node_modules/kind-of/README.md b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/README.md
new file mode 100644
index 00000000..170bf304
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/README.md
@@ -0,0 +1,342 @@
+# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of)
+
+> Get the native type of a value.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save kind-of
+```
+
+Install with [bower](https://bower.io/)
+
+```sh
+$ bower install kind-of --save
+```
+
+## Why use this?
+
+1. [it's fast](#benchmarks) | [optimizations](#optimizations)
+2. [better type checking](#better-type-checking)
+
+## Usage
+
+> es5, browser and es6 ready
+
+```js
+var kindOf = require('kind-of');
+
+kindOf(undefined);
+//=> 'undefined'
+
+kindOf(null);
+//=> 'null'
+
+kindOf(true);
+//=> 'boolean'
+
+kindOf(false);
+//=> 'boolean'
+
+kindOf(new Boolean(true));
+//=> 'boolean'
+
+kindOf(new Buffer(''));
+//=> 'buffer'
+
+kindOf(42);
+//=> 'number'
+
+kindOf(new Number(42));
+//=> 'number'
+
+kindOf('str');
+//=> 'string'
+
+kindOf(new String('str'));
+//=> 'string'
+
+kindOf(arguments);
+//=> 'arguments'
+
+kindOf({});
+//=> 'object'
+
+kindOf(Object.create(null));
+//=> 'object'
+
+kindOf(new Test());
+//=> 'object'
+
+kindOf(new Date());
+//=> 'date'
+
+kindOf([]);
+//=> 'array'
+
+kindOf([1, 2, 3]);
+//=> 'array'
+
+kindOf(new Array());
+//=> 'array'
+
+kindOf(/foo/);
+//=> 'regexp'
+
+kindOf(new RegExp('foo'));
+//=> 'regexp'
+
+kindOf(function () {});
+//=> 'function'
+
+kindOf(function * () {});
+//=> 'function'
+
+kindOf(new Function());
+//=> 'function'
+
+kindOf(new Map());
+//=> 'map'
+
+kindOf(new WeakMap());
+//=> 'weakmap'
+
+kindOf(new Set());
+//=> 'set'
+
+kindOf(new WeakSet());
+//=> 'weakset'
+
+kindOf(Symbol('str'));
+//=> 'symbol'
+
+kindOf(new Int8Array());
+//=> 'int8array'
+
+kindOf(new Uint8Array());
+//=> 'uint8array'
+
+kindOf(new Uint8ClampedArray());
+//=> 'uint8clampedarray'
+
+kindOf(new Int16Array());
+//=> 'int16array'
+
+kindOf(new Uint16Array());
+//=> 'uint16array'
+
+kindOf(new Int32Array());
+//=> 'int32array'
+
+kindOf(new Uint32Array());
+//=> 'uint32array'
+
+kindOf(new Float32Array());
+//=> 'float32array'
+
+kindOf(new Float64Array());
+//=> 'float64array'
+```
+
+## Release history
+
+### v4.0.0
+
+**Added**
+
+* `promise` support
+
+### v5.0.0
+
+**Added**
+
+* `Set Iterator` and `Map Iterator` support
+
+**Fixed**
+
+* Now returns `generatorfunction` for generator functions
+
+## Benchmarks
+
+Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of).
+Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`.
+
+```bash
+#1: array
+  current x 23,329,397 ops/sec ±0.82% (94 runs sampled)
+  lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled)
+  lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled)
+
+#2: boolean
+  current x 27,197,115 ops/sec ±0.85% (94 runs sampled)
+  lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled)
+  lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled)
+
+#3: date
+  current x 20,190,117 ops/sec ±0.86% (92 runs sampled)
+  lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled)
+  lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled)
+
+#4: function
+  current x 23,855,460 ops/sec ±0.60% (97 runs sampled)
+  lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled)
+  lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled)
+
+#5: null
+  current x 27,061,047 ops/sec ±0.97% (96 runs sampled)
+  lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled)
+  lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled)
+
+#6: number
+  current x 25,075,682 ops/sec ±0.53% (99 runs sampled)
+  lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled)
+  lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled)
+
+#7: object
+  current x 3,348,980 ops/sec ±0.49% (99 runs sampled)
+  lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled)
+  lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled)
+
+#8: regex
+  current x 21,284,827 ops/sec ±0.72% (96 runs sampled)
+  lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled)
+  lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled)
+
+#9: string
+  current x 25,379,234 ops/sec ±0.58% (96 runs sampled)
+  lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled)
+  lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled)
+
+#10: undef
+  current x 27,459,221 ops/sec ±1.01% (93 runs sampled)
+  lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled)
+  lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled)
+
+```
+
+## Optimizations
+
+In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library:
+
+1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot.
+2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it.
+3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'`
+4. There is no reason to make the code in a microlib as terse as possible, just to win points for making it shorter. It's always better to favor performant code over terse code. You will always only be using a single `require()` statement to use the library anyway, regardless of how the code is written.
+
+## Better type checking
+
+kind-of is more correct than other type checking libs I've looked at. For example, here are some differing results from other popular libs:
+
+### [typeof](https://github.com/CodingFu/typeof) lib
+
+Incorrectly tests instances of custom constructors (pretty common):
+
+```js
+var typeOf = require('typeof');
+function Test() {}
+console.log(typeOf(new Test()));
+//=> 'test'
+```
+
+Returns `object` instead of `arguments`:
+
+```js
+function foo() {
+  console.log(typeOf(arguments)) //=> 'object'
+}
+foo();
+```
+
+### [type-of](https://github.com/ForbesLindesay/type-of) lib
+
+Incorrectly returns `object` for generator functions, buffers, `Map`, `Set`, `WeakMap` and `WeakSet`:
+
+```js
+function * foo() {}
+console.log(typeOf(foo));
+//=> 'object'
+console.log(typeOf(new Buffer('')));
+//=> 'object'
+console.log(typeOf(new Map()));
+//=> 'object'
+console.log(typeOf(new Set()));
+//=> 'object'
+console.log(typeOf(new WeakMap()));
+//=> 'object'
+console.log(typeOf(new WeakSet()));
+//=> 'object'
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+<details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+<details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+<details>
+
+### Related projects
+
+You might also be interested in these projects:
+
+* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet")
+* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 82 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 3 | [aretecode](https://github.com/aretecode) |
+| 2 | [miguelmota](https://github.com/miguelmota) |
+| 1 | [dtothefp](https://github.com/dtothefp) |
+| 1 | [ksheedlo](https://github.com/ksheedlo) |
+| 1 | [pdehaan](https://github.com/pdehaan) |
+| 1 | [laggingreflex](https://github.com/laggingreflex) |
+| 1 | [charlike](https://github.com/charlike) |
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on October 13, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/kind-of/index.js b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/index.js
new file mode 100644
index 00000000..fc5cde96
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/index.js
@@ -0,0 +1,147 @@
+var toString = Object.prototype.toString;
+
+/**
+ * Get the native `typeof` a value.
+ *
+ * @param  {*} `val`
+ * @return {*} Native javascript type
+ */
+
+module.exports = function kindOf(val) {
+  var type = typeof val;
+
+  // primitivies
+  if (type === 'undefined') {
+    return 'undefined';
+  }
+  if (val === null) {
+    return 'null';
+  }
+  if (val === true || val === false || val instanceof Boolean) {
+    return 'boolean';
+  }
+  if (type === 'string' || val instanceof String) {
+    return 'string';
+  }
+  if (type === 'number' || val instanceof Number) {
+    return 'number';
+  }
+
+  // functions
+  if (type === 'function' || val instanceof Function) {
+    if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') {
+      return 'generatorfunction';
+    }
+    return 'function';
+  }
+
+  // array
+  if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
+    return 'array';
+  }
+
+  // check for instances of RegExp and Date before calling `toString`
+  if (val instanceof RegExp) {
+    return 'regexp';
+  }
+  if (val instanceof Date) {
+    return 'date';
+  }
+
+  // other objects
+  type = toString.call(val);
+
+  if (type === '[object RegExp]') {
+    return 'regexp';
+  }
+  if (type === '[object Date]') {
+    return 'date';
+  }
+  if (type === '[object Arguments]') {
+    return 'arguments';
+  }
+  if (type === '[object Error]') {
+    return 'error';
+  }
+  if (type === '[object Promise]') {
+    return 'promise';
+  }
+
+  // buffer
+  if (isBuffer(val)) {
+    return 'buffer';
+  }
+
+  // es6: Map, WeakMap, Set, WeakSet
+  if (type === '[object Set]') {
+    return 'set';
+  }
+  if (type === '[object WeakSet]') {
+    return 'weakset';
+  }
+  if (type === '[object Map]') {
+    return 'map';
+  }
+  if (type === '[object WeakMap]') {
+    return 'weakmap';
+  }
+  if (type === '[object Symbol]') {
+    return 'symbol';
+  }
+  
+  if (type === '[object Map Iterator]') {
+    return 'mapiterator';
+  }
+  if (type === '[object Set Iterator]') {
+    return 'setiterator';
+  }
+  if (type === '[object String Iterator]') {
+    return 'stringiterator';
+  }
+  if (type === '[object Array Iterator]') {
+    return 'arrayiterator';
+  }
+  
+  // typed arrays
+  if (type === '[object Int8Array]') {
+    return 'int8array';
+  }
+  if (type === '[object Uint8Array]') {
+    return 'uint8array';
+  }
+  if (type === '[object Uint8ClampedArray]') {
+    return 'uint8clampedarray';
+  }
+  if (type === '[object Int16Array]') {
+    return 'int16array';
+  }
+  if (type === '[object Uint16Array]') {
+    return 'uint16array';
+  }
+  if (type === '[object Int32Array]') {
+    return 'int32array';
+  }
+  if (type === '[object Uint32Array]') {
+    return 'uint32array';
+  }
+  if (type === '[object Float32Array]') {
+    return 'float32array';
+  }
+  if (type === '[object Float64Array]') {
+    return 'float64array';
+  }
+
+  // must be a plain object
+  return 'object';
+};
+
+/**
+ * If you need to support Safari 5-7 (8-10 yr-old browser),
+ * take a look at https://github.com/feross/is-buffer
+ */
+
+function isBuffer(val) {
+  return val.constructor
+    && typeof val.constructor.isBuffer === 'function'
+    && val.constructor.isBuffer(val);
+}
diff --git a/input_devices/mag/node_modules/static-extend/node_modules/kind-of/package.json b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/package.json
new file mode 100644
index 00000000..d846b19d
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/node_modules/kind-of/package.json
@@ -0,0 +1,179 @@
+{
+  "_args": [
+    [
+      "kind-of@^5.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor"
+    ]
+  ],
+  "_from": "kind-of@>=5.0.0 <6.0.0",
+  "_id": "kind-of@5.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend/kind-of",
+  "_nodeVersion": "8.7.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/kind-of-5.1.0.tgz_1507878225264_0.114781056297943"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.4.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "kind-of",
+    "raw": "kind-of@^5.0.0",
+    "rawSpec": "^5.0.0",
+    "scope": null,
+    "spec": ">=5.0.0 <6.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/static-extend/is-descriptor"
+  ],
+  "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+  "_shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+  "_shrinkwrap": null,
+  "_spec": "kind-of@^5.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/static-extend/node_modules/is-descriptor",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/kind-of/issues"
+  },
+  "contributors": [
+    {
+      "name": "David Fox-Powell",
+      "url": "https://dtothefp.github.io/me"
+    },
+    {
+      "name": "James",
+      "url": "https://twitter.com/aretecode"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Ken Sheedlo",
+      "url": "kensheedlo.com"
+    },
+    {
+      "name": "laggingreflex",
+      "url": "https://github.com/laggingreflex"
+    },
+    {
+      "name": "Miguel Mota",
+      "url": "https://miguelmota.com"
+    },
+    {
+      "name": "Peter deHaan",
+      "url": "http://about.me/peterdehaan"
+    },
+    {
+      "name": "tunnckoCore",
+      "url": "https://i.am.charlike.online"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get the native type of a value.",
+  "devDependencies": {
+    "ansi-bold": "^0.1.1",
+    "benchmarked": "^1.1.1",
+    "browserify": "^14.4.0",
+    "gulp-format-md": "^0.1.12",
+    "matched": "^0.4.4",
+    "mocha": "^3.4.2",
+    "type-of": "^2.0.1",
+    "typeof": "^1.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+    "shasum": "729c91e2d857b7a419a1f9aa65685c4c33f5845d",
+    "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ed479b6ee194dc1edff852f17095ae1de40bafbc",
+  "homepage": "https://github.com/jonschlinkert/kind-of",
+  "keywords": [
+    "arguments",
+    "array",
+    "boolean",
+    "check",
+    "date",
+    "function",
+    "is",
+    "is-type",
+    "is-type-of",
+    "kind",
+    "kind-of",
+    "number",
+    "object",
+    "of",
+    "regexp",
+    "string",
+    "test",
+    "type",
+    "type-of",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "kind-of",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/kind-of.git"
+  },
+  "scripts": {
+    "prepublish": "browserify -o browser.js -e index.js -s index --bare",
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "type-of",
+      "typeof",
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "is-glob",
+        "is-number",
+        "is-primitive"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "5.1.0"
+}
diff --git a/input_devices/mag/node_modules/static-extend/package.json b/input_devices/mag/node_modules/static-extend/package.json
new file mode 100644
index 00000000..a4438990
--- /dev/null
+++ b/input_devices/mag/node_modules/static-extend/package.json
@@ -0,0 +1,123 @@
+{
+  "_args": [
+    [
+      "static-extend@^0.1.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base"
+    ]
+  ],
+  "_from": "static-extend@>=0.1.2 <0.2.0",
+  "_id": "static-extend@0.1.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/static-extend",
+  "_nodeVersion": "6.2.0",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/static-extend-0.1.2.tgz_1465497934772_0.6460855521727353"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.8.9",
+  "_phantomChildren": {
+    "is-buffer": "1.1.6"
+  },
+  "_requested": {
+    "name": "static-extend",
+    "raw": "static-extend@^0.1.2",
+    "rawSpec": "^0.1.2",
+    "scope": null,
+    "spec": ">=0.1.2 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-base"
+  ],
+  "_resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+  "_shasum": "60809c39cbff55337226fd5e0b520f341f1fb5c6",
+  "_shrinkwrap": null,
+  "_spec": "static-extend@^0.1.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-base",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/static-extend/issues"
+  },
+  "dependencies": {
+    "define-property": "^0.2.5",
+    "object-copy": "^0.1.0"
+  },
+  "description": "Adds a static `extend` method to a class, to simplify inheritance. Extends the static properties, prototype properties, and descriptors from a `Parent` constructor onto `Child` constructors.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.9",
+    "mocha": "^2.5.3"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "60809c39cbff55337226fd5e0b520f341f1fb5c6",
+    "tarball": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "ce41369391163eb9403848a1b4daf00be981c56b",
+  "homepage": "https://github.com/jonschlinkert/static-extend",
+  "keywords": [
+    "class",
+    "ctor",
+    "descriptor",
+    "extend",
+    "extends",
+    "inherit",
+    "inheritance",
+    "merge",
+    "method",
+    "prop",
+    "properties",
+    "property",
+    "prototype"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "static-extend",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/static-extend.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-readme-generator"
+    ],
+    "run": true,
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "0.1.2"
+}
diff --git a/input_devices/mag/node_modules/string-width/index.js b/input_devices/mag/node_modules/string-width/index.js
new file mode 100644
index 00000000..b9bec624
--- /dev/null
+++ b/input_devices/mag/node_modules/string-width/index.js
@@ -0,0 +1,37 @@
+'use strict';
+var stripAnsi = require('strip-ansi');
+var codePointAt = require('code-point-at');
+var isFullwidthCodePoint = require('is-fullwidth-code-point');
+
+// https://github.com/nodejs/io.js/blob/cff7300a578be1b10001f2d967aaedc88aee6402/lib/readline.js#L1345
+module.exports = function (str) {
+	if (typeof str !== 'string' || str.length === 0) {
+		return 0;
+	}
+
+	var width = 0;
+
+	str = stripAnsi(str);
+
+	for (var i = 0; i < str.length; i++) {
+		var code = codePointAt(str, i);
+
+		// ignore control characters
+		if (code <= 0x1f || (code >= 0x7f && code <= 0x9f)) {
+			continue;
+		}
+
+		// surrogates
+		if (code >= 0x10000) {
+			i++;
+		}
+
+		if (isFullwidthCodePoint(code)) {
+			width += 2;
+		} else {
+			width++;
+		}
+	}
+
+	return width;
+};
diff --git a/input_devices/mag/node_modules/string-width/license b/input_devices/mag/node_modules/string-width/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/string-width/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/string-width/package.json b/input_devices/mag/node_modules/string-width/package.json
new file mode 100644
index 00000000..bc3b166b
--- /dev/null
+++ b/input_devices/mag/node_modules/string-width/package.json
@@ -0,0 +1,116 @@
+{
+  "_args": [
+    [
+      "string-width@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge"
+    ]
+  ],
+  "_from": "string-width@>=1.0.1 <2.0.0",
+  "_id": "string-width@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/string-width",
+  "_nodeVersion": "4.4.5",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/string-width-1.0.2.tgz_1471188233009_0.6573935742489994"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "2.15.5",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "string-width",
+    "raw": "string-width@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge",
+    "/wide-align"
+  ],
+  "_resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+  "_shasum": "118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3",
+  "_shrinkwrap": null,
+  "_spec": "string-width@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/string-width/issues"
+  },
+  "dependencies": {
+    "code-point-at": "^1.0.0",
+    "is-fullwidth-code-point": "^1.0.0",
+    "strip-ansi": "^3.0.0"
+  },
+  "description": "Get the visual width of a string - the number of columns required to display it",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3",
+    "tarball": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "282cf3d53918a92cc3ee0778dcf938039bcbc47b",
+  "homepage": "https://github.com/sindresorhus/string-width#readme",
+  "keywords": [
+    "ansi",
+    "char",
+    "character",
+    "chinese",
+    "cjk",
+    "cli",
+    "codes",
+    "column",
+    "columns",
+    "command-line",
+    "console",
+    "escape",
+    "fixed-width",
+    "full",
+    "full-width",
+    "fullwidth",
+    "japanese",
+    "korean",
+    "str",
+    "string",
+    "terminal",
+    "unicode",
+    "visual",
+    "width"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "string-width",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/string-width.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/string-width/readme.md b/input_devices/mag/node_modules/string-width/readme.md
new file mode 100644
index 00000000..1ab42c93
--- /dev/null
+++ b/input_devices/mag/node_modules/string-width/readme.md
@@ -0,0 +1,42 @@
+# string-width [![Build Status](https://travis-ci.org/sindresorhus/string-width.svg?branch=master)](https://travis-ci.org/sindresorhus/string-width)
+
+> Get the visual width of a string - the number of columns required to display it
+
+Some Unicode characters are [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) and use double the normal width. [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code) are stripped and doesn't affect the width.
+
+Useful to be able to measure the actual width of command-line output.
+
+
+## Install
+
+```
+$ npm install --save string-width
+```
+
+
+## Usage
+
+```js
+const stringWidth = require('string-width');
+
+stringWidth('古');
+//=> 2
+
+stringWidth('\u001b[1m古\u001b[22m');
+//=> 2
+
+stringWidth('a');
+//=> 1
+```
+
+
+## Related
+
+- [string-width-cli](https://github.com/sindresorhus/string-width-cli) - CLI for this module
+- [string-length](https://github.com/sindresorhus/string-length) - Get the real length of a string
+- [widest-line](https://github.com/sindresorhus/widest-line) - Get the visual width of the widest line in a string
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/string_decoder/.travis.yml b/input_devices/mag/node_modules/string_decoder/.travis.yml
new file mode 100644
index 00000000..3347a725
--- /dev/null
+++ b/input_devices/mag/node_modules/string_decoder/.travis.yml
@@ -0,0 +1,50 @@
+sudo: false
+language: node_js
+before_install:
+  - npm install -g npm@2
+  - test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g
+notifications:
+  email: false
+matrix:
+  fast_finish: true
+  include:
+  - node_js: '0.8'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: '0.10'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: '0.11'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: '0.12'
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 1
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 2
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 3
+    env:
+      - TASK=test
+      - NPM_LEGACY=true
+  - node_js: 4
+    env: TASK=test
+  - node_js: 5
+    env: TASK=test
+  - node_js: 6
+    env: TASK=test
+  - node_js: 7
+    env: TASK=test
+  - node_js: 8
+    env: TASK=test
+  - node_js: 9
+    env: TASK=test
diff --git a/input_devices/mag/node_modules/string_decoder/LICENSE b/input_devices/mag/node_modules/string_decoder/LICENSE
new file mode 100644
index 00000000..778edb20
--- /dev/null
+++ b/input_devices/mag/node_modules/string_decoder/LICENSE
@@ -0,0 +1,48 @@
+Node.js is licensed for use as follows:
+
+"""
+Copyright Node.js contributors. All rights reserved.
+
+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.
+"""
+
+This license applies to parts of Node.js originating from the
+https://github.com/joyent/node repository:
+
+"""
+Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+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/input_devices/mag/node_modules/string_decoder/README.md b/input_devices/mag/node_modules/string_decoder/README.md
new file mode 100644
index 00000000..5fd58315
--- /dev/null
+++ b/input_devices/mag/node_modules/string_decoder/README.md
@@ -0,0 +1,47 @@
+# string_decoder
+
+***Node-core v8.9.4 string_decoder for userland***
+
+
+[![NPM](https://nodei.co/npm/string_decoder.png?downloads=true&downloadRank=true)](https://nodei.co/npm/string_decoder/)
+[![NPM](https://nodei.co/npm-dl/string_decoder.png?&months=6&height=3)](https://nodei.co/npm/string_decoder/)
+
+
+```bash
+npm install --save string_decoder
+```
+
+***Node-core string_decoder for userland***
+
+This package is a mirror of the string_decoder implementation in Node-core.
+
+Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.9.4/docs/api/).
+
+As of version 1.0.0 **string_decoder** uses semantic versioning.
+
+## Previous versions
+
+Previous version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10.
+
+## Update
+
+The *build/* directory contains a build script that will scrape the source from the [nodejs/node](https://github.com/nodejs/node) repo given a specific Node version.
+
+## Streams Working Group
+
+`string_decoder` is maintained by the Streams Working Group, which
+oversees the development and maintenance of the Streams API within
+Node.js. The responsibilities of the Streams Working Group include:
+
+* Addressing stream issues on the Node.js issue tracker.
+* Authoring and editing stream documentation within the Node.js project.
+* Reviewing changes to stream subclasses within the Node.js project.
+* Redirecting changes to streams from the Node.js project to this
+  project.
+* Assisting in the implementation of stream providers within Node.js.
+* Recommending versions of `readable-stream` to be included in Node.js.
+* Messaging about the future of streams to give the community advance
+  notice of changes.
+
+See [readable-stream](https://github.com/nodejs/readable-stream) for
+more details.
diff --git a/input_devices/mag/node_modules/string_decoder/lib/string_decoder.js b/input_devices/mag/node_modules/string_decoder/lib/string_decoder.js
new file mode 100644
index 00000000..2e89e63f
--- /dev/null
+++ b/input_devices/mag/node_modules/string_decoder/lib/string_decoder.js
@@ -0,0 +1,296 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// 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.
+
+'use strict';
+
+/*<replacement>*/
+
+var Buffer = require('safe-buffer').Buffer;
+/*</replacement>*/
+
+var isEncoding = Buffer.isEncoding || function (encoding) {
+  encoding = '' + encoding;
+  switch (encoding && encoding.toLowerCase()) {
+    case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw':
+      return true;
+    default:
+      return false;
+  }
+};
+
+function _normalizeEncoding(enc) {
+  if (!enc) return 'utf8';
+  var retried;
+  while (true) {
+    switch (enc) {
+      case 'utf8':
+      case 'utf-8':
+        return 'utf8';
+      case 'ucs2':
+      case 'ucs-2':
+      case 'utf16le':
+      case 'utf-16le':
+        return 'utf16le';
+      case 'latin1':
+      case 'binary':
+        return 'latin1';
+      case 'base64':
+      case 'ascii':
+      case 'hex':
+        return enc;
+      default:
+        if (retried) return; // undefined
+        enc = ('' + enc).toLowerCase();
+        retried = true;
+    }
+  }
+};
+
+// Do not cache `Buffer.isEncoding` when checking encoding names as some
+// modules monkey-patch it to support additional encodings
+function normalizeEncoding(enc) {
+  var nenc = _normalizeEncoding(enc);
+  if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc);
+  return nenc || enc;
+}
+
+// StringDecoder provides an interface for efficiently splitting a series of
+// buffers into a series of JS strings without breaking apart multi-byte
+// characters.
+exports.StringDecoder = StringDecoder;
+function StringDecoder(encoding) {
+  this.encoding = normalizeEncoding(encoding);
+  var nb;
+  switch (this.encoding) {
+    case 'utf16le':
+      this.text = utf16Text;
+      this.end = utf16End;
+      nb = 4;
+      break;
+    case 'utf8':
+      this.fillLast = utf8FillLast;
+      nb = 4;
+      break;
+    case 'base64':
+      this.text = base64Text;
+      this.end = base64End;
+      nb = 3;
+      break;
+    default:
+      this.write = simpleWrite;
+      this.end = simpleEnd;
+      return;
+  }
+  this.lastNeed = 0;
+  this.lastTotal = 0;
+  this.lastChar = Buffer.allocUnsafe(nb);
+}
+
+StringDecoder.prototype.write = function (buf) {
+  if (buf.length === 0) return '';
+  var r;
+  var i;
+  if (this.lastNeed) {
+    r = this.fillLast(buf);
+    if (r === undefined) return '';
+    i = this.lastNeed;
+    this.lastNeed = 0;
+  } else {
+    i = 0;
+  }
+  if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
+  return r || '';
+};
+
+StringDecoder.prototype.end = utf8End;
+
+// Returns only complete characters in a Buffer
+StringDecoder.prototype.text = utf8Text;
+
+// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer
+StringDecoder.prototype.fillLast = function (buf) {
+  if (this.lastNeed <= buf.length) {
+    buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
+    return this.lastChar.toString(this.encoding, 0, this.lastTotal);
+  }
+  buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
+  this.lastNeed -= buf.length;
+};
+
+// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
+// continuation byte. If an invalid byte is detected, -2 is returned.
+function utf8CheckByte(byte) {
+  if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4;
+  return byte >> 6 === 0x02 ? -1 : -2;
+}
+
+// Checks at most 3 bytes at the end of a Buffer in order to detect an
+// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
+// needed to complete the UTF-8 character (if applicable) are returned.
+function utf8CheckIncomplete(self, buf, i) {
+  var j = buf.length - 1;
+  if (j < i) return 0;
+  var nb = utf8CheckByte(buf[j]);
+  if (nb >= 0) {
+    if (nb > 0) self.lastNeed = nb - 1;
+    return nb;
+  }
+  if (--j < i || nb === -2) return 0;
+  nb = utf8CheckByte(buf[j]);
+  if (nb >= 0) {
+    if (nb > 0) self.lastNeed = nb - 2;
+    return nb;
+  }
+  if (--j < i || nb === -2) return 0;
+  nb = utf8CheckByte(buf[j]);
+  if (nb >= 0) {
+    if (nb > 0) {
+      if (nb === 2) nb = 0;else self.lastNeed = nb - 3;
+    }
+    return nb;
+  }
+  return 0;
+}
+
+// Validates as many continuation bytes for a multi-byte UTF-8 character as
+// needed or are available. If we see a non-continuation byte where we expect
+// one, we "replace" the validated continuation bytes we've seen so far with
+// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding
+// behavior. The continuation byte check is included three times in the case
+// where all of the continuation bytes for a character exist in the same buffer.
+// It is also done this way as a slight performance increase instead of using a
+// loop.
+function utf8CheckExtraBytes(self, buf, p) {
+  if ((buf[0] & 0xC0) !== 0x80) {
+    self.lastNeed = 0;
+    return '\ufffd';
+  }
+  if (self.lastNeed > 1 && buf.length > 1) {
+    if ((buf[1] & 0xC0) !== 0x80) {
+      self.lastNeed = 1;
+      return '\ufffd';
+    }
+    if (self.lastNeed > 2 && buf.length > 2) {
+      if ((buf[2] & 0xC0) !== 0x80) {
+        self.lastNeed = 2;
+        return '\ufffd';
+      }
+    }
+  }
+}
+
+// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer.
+function utf8FillLast(buf) {
+  var p = this.lastTotal - this.lastNeed;
+  var r = utf8CheckExtraBytes(this, buf, p);
+  if (r !== undefined) return r;
+  if (this.lastNeed <= buf.length) {
+    buf.copy(this.lastChar, p, 0, this.lastNeed);
+    return this.lastChar.toString(this.encoding, 0, this.lastTotal);
+  }
+  buf.copy(this.lastChar, p, 0, buf.length);
+  this.lastNeed -= buf.length;
+}
+
+// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a
+// partial character, the character's bytes are buffered until the required
+// number of bytes are available.
+function utf8Text(buf, i) {
+  var total = utf8CheckIncomplete(this, buf, i);
+  if (!this.lastNeed) return buf.toString('utf8', i);
+  this.lastTotal = total;
+  var end = buf.length - (total - this.lastNeed);
+  buf.copy(this.lastChar, 0, end);
+  return buf.toString('utf8', i, end);
+}
+
+// For UTF-8, a replacement character is added when ending on a partial
+// character.
+function utf8End(buf) {
+  var r = buf && buf.length ? this.write(buf) : '';
+  if (this.lastNeed) return r + '\ufffd';
+  return r;
+}
+
+// UTF-16LE typically needs two bytes per character, but even if we have an even
+// number of bytes available, we need to check if we end on a leading/high
+// surrogate. In that case, we need to wait for the next two bytes in order to
+// decode the last character properly.
+function utf16Text(buf, i) {
+  if ((buf.length - i) % 2 === 0) {
+    var r = buf.toString('utf16le', i);
+    if (r) {
+      var c = r.charCodeAt(r.length - 1);
+      if (c >= 0xD800 && c <= 0xDBFF) {
+        this.lastNeed = 2;
+        this.lastTotal = 4;
+        this.lastChar[0] = buf[buf.length - 2];
+        this.lastChar[1] = buf[buf.length - 1];
+        return r.slice(0, -1);
+      }
+    }
+    return r;
+  }
+  this.lastNeed = 1;
+  this.lastTotal = 2;
+  this.lastChar[0] = buf[buf.length - 1];
+  return buf.toString('utf16le', i, buf.length - 1);
+}
+
+// For UTF-16LE we do not explicitly append special replacement characters if we
+// end on a partial character, we simply let v8 handle that.
+function utf16End(buf) {
+  var r = buf && buf.length ? this.write(buf) : '';
+  if (this.lastNeed) {
+    var end = this.lastTotal - this.lastNeed;
+    return r + this.lastChar.toString('utf16le', 0, end);
+  }
+  return r;
+}
+
+function base64Text(buf, i) {
+  var n = (buf.length - i) % 3;
+  if (n === 0) return buf.toString('base64', i);
+  this.lastNeed = 3 - n;
+  this.lastTotal = 3;
+  if (n === 1) {
+    this.lastChar[0] = buf[buf.length - 1];
+  } else {
+    this.lastChar[0] = buf[buf.length - 2];
+    this.lastChar[1] = buf[buf.length - 1];
+  }
+  return buf.toString('base64', i, buf.length - n);
+}
+
+function base64End(buf) {
+  var r = buf && buf.length ? this.write(buf) : '';
+  if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed);
+  return r;
+}
+
+// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex)
+function simpleWrite(buf) {
+  return buf.toString(this.encoding);
+}
+
+function simpleEnd(buf) {
+  return buf && buf.length ? this.write(buf) : '';
+}
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/string_decoder/package.json b/input_devices/mag/node_modules/string_decoder/package.json
new file mode 100644
index 00000000..f9d41b63
--- /dev/null
+++ b/input_devices/mag/node_modules/string_decoder/package.json
@@ -0,0 +1,105 @@
+{
+  "_args": [
+    [
+      "string_decoder@~1.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream"
+    ]
+  ],
+  "_from": "string_decoder@>=1.1.1 <1.2.0",
+  "_id": "string_decoder@1.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/string_decoder",
+  "_nodeVersion": "8.10.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/string_decoder_1.1.1_1522397654739_0.2722524344416213"
+  },
+  "_npmUser": {
+    "email": "hello@matteocollina.com",
+    "name": "matteo.collina"
+  },
+  "_npmVersion": "5.8.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "string_decoder",
+    "raw": "string_decoder@~1.1.1",
+    "rawSpec": "~1.1.1",
+    "scope": null,
+    "spec": ">=1.1.1 <1.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readable-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+  "_shasum": "9cf1611ba62685d7030ae9e4ba34149c3af03fc8",
+  "_shrinkwrap": null,
+  "_spec": "string_decoder@~1.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream",
+  "bugs": {
+    "url": "https://github.com/nodejs/string_decoder/issues"
+  },
+  "dependencies": {
+    "safe-buffer": "~5.1.0"
+  },
+  "description": "The string_decoder module from Node core",
+  "devDependencies": {
+    "babel-polyfill": "^6.23.0",
+    "core-util-is": "^1.0.2",
+    "inherits": "^2.0.3",
+    "tap": "~0.4.8"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 5,
+    "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+    "shasum": "9cf1611ba62685d7030ae9e4ba34149c3af03fc8",
+    "tarball": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+    "unpackedSize": 15298
+  },
+  "gitHead": "18c7f89c894ced5f610505bb006dfde9a3d1ac5e",
+  "homepage": "https://github.com/nodejs/string_decoder",
+  "keywords": [
+    "browser",
+    "browserify",
+    "decoder",
+    "string"
+  ],
+  "license": "MIT",
+  "main": "lib/string_decoder.js",
+  "maintainers": [
+    {
+      "name": "cwmma",
+      "email": "calvin.metcalf@gmail.com"
+    },
+    {
+      "name": "matteo.collina",
+      "email": "hello@matteocollina.com"
+    },
+    {
+      "name": "nodejs-foundation",
+      "email": "build@iojs.org"
+    },
+    {
+      "name": "rvagg",
+      "email": "rod@vagg.org"
+    },
+    {
+      "name": "substack",
+      "email": "substack@gmail.com"
+    }
+  ],
+  "name": "string_decoder",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/nodejs/string_decoder.git"
+  },
+  "scripts": {
+    "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js",
+    "test": "tap test/parallel/*.js && node test/verify-dependencies"
+  },
+  "version": "1.1.1"
+}
diff --git a/input_devices/mag/node_modules/strip-ansi/index.js b/input_devices/mag/node_modules/strip-ansi/index.js
new file mode 100644
index 00000000..099480fb
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-ansi/index.js
@@ -0,0 +1,6 @@
+'use strict';
+var ansiRegex = require('ansi-regex')();
+
+module.exports = function (str) {
+	return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
diff --git a/input_devices/mag/node_modules/strip-ansi/license b/input_devices/mag/node_modules/strip-ansi/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-ansi/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/strip-ansi/package.json b/input_devices/mag/node_modules/strip-ansi/package.json
new file mode 100644
index 00000000..97ed43eb
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-ansi/package.json
@@ -0,0 +1,116 @@
+{
+  "_args": [
+    [
+      "strip-ansi@^3.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge"
+    ]
+  ],
+  "_from": "strip-ansi@>=3.0.1 <4.0.0",
+  "_id": "strip-ansi@3.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/strip-ansi",
+  "_nodeVersion": "0.12.7",
+  "_npmOperationalInternal": {
+    "host": "packages-9-west.internal.npmjs.com",
+    "tmp": "tmp/strip-ansi-3.0.1.tgz_1456057278183_0.28958667791448534"
+  },
+  "_npmUser": {
+    "email": "jappelman@xebia.com",
+    "name": "jbnicolai"
+  },
+  "_npmVersion": "2.11.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "strip-ansi",
+    "raw": "strip-ansi@^3.0.1",
+    "rawSpec": "^3.0.1",
+    "scope": null,
+    "spec": ">=3.0.1 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge",
+    "/string-width"
+  ],
+  "_resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+  "_shasum": "6a385fb8853d952d5ff05d0e8aaf94278dc63dcf",
+  "_shrinkwrap": null,
+  "_spec": "strip-ansi@^3.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/chalk/strip-ansi/issues"
+  },
+  "dependencies": {
+    "ansi-regex": "^2.0.0"
+  },
+  "description": "Strip ANSI escape codes",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "6a385fb8853d952d5ff05d0e8aaf94278dc63dcf",
+    "tarball": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "8270705c704956da865623e564eba4875c3ea17f",
+  "homepage": "https://github.com/chalk/strip-ansi",
+  "keywords": [
+    "256",
+    "ansi",
+    "color",
+    "colors",
+    "colour",
+    "command-line",
+    "console",
+    "escape",
+    "formatting",
+    "log",
+    "logging",
+    "remove",
+    "rgb",
+    "shell",
+    "string",
+    "strip",
+    "styles",
+    "terminal",
+    "text",
+    "trim",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    },
+    {
+      "name": "jbnicolai",
+      "email": "jappelman@xebia.com"
+    }
+  ],
+  "name": "strip-ansi",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/chalk/strip-ansi.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "3.0.1"
+}
diff --git a/input_devices/mag/node_modules/strip-ansi/readme.md b/input_devices/mag/node_modules/strip-ansi/readme.md
new file mode 100644
index 00000000..cb7d9ff7
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-ansi/readme.md
@@ -0,0 +1,33 @@
+# strip-ansi [![Build Status](https://travis-ci.org/chalk/strip-ansi.svg?branch=master)](https://travis-ci.org/chalk/strip-ansi)
+
+> Strip [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code)
+
+
+## Install
+
+```
+$ npm install --save strip-ansi
+```
+
+
+## Usage
+
+```js
+var stripAnsi = require('strip-ansi');
+
+stripAnsi('\u001b[4mcake\u001b[0m');
+//=> 'cake'
+```
+
+
+## Related
+
+- [strip-ansi-cli](https://github.com/chalk/strip-ansi-cli) - CLI for this module
+- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
+- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
+- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
+
+
+## License
+
+MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/strip-color/LICENSE b/input_devices/mag/node_modules/strip-color/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-color/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/strip-color/README.md b/input_devices/mag/node_modules/strip-color/README.md
new file mode 100644
index 00000000..5a2872f6
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-color/README.md
@@ -0,0 +1,58 @@
+# strip-color [![NPM version](https://badge.fury.io/js/strip-color.svg)](http://badge.fury.io/js/strip-color)
+
+> Strip ansi characters from a string.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i strip-color --save
+```
+
+## Usage
+
+```js
+var strip = require('strip-color');
+var red = require('ansi-red');
+var str = red('abc');
+
+console.log(strip(str));
+//=> 'abc';
+```
+
+## Related projects
+
+* [ansi-bold](https://www.npmjs.com/package/ansi-bold): The color bold, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-bold)
+* [ansi-cyan](https://www.npmjs.com/package/ansi-cyan): The color cyan, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-cyan)
+* [ansi-red](https://www.npmjs.com/package/ansi-red): The color red, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-red)
+* [ansi-yellow](https://www.npmjs.com/package/ansi-yellow): The color yellow, in ansi. | [homepage](https://github.com/jonschlinkert/ansi-yellow)
+* [wrap-ansi](https://www.npmjs.com/package/wrap-ansi): Wordwrap a string with ANSI escape codes | [homepage](https://github.com/chalk/wrap-ansi)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/strip-color/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on October 18, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/strip-color/index.js b/input_devices/mag/node_modules/strip-color/index.js
new file mode 100644
index 00000000..e00f8a17
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-color/index.js
@@ -0,0 +1,12 @@
+/*!
+ * strip-color <https://github.com/jonschlinkert/strip-color>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+module.exports = function(str) {
+  return str.replace(/\x1B[[(?);]{0,2}(;?\d)*./g, '');
+};
diff --git a/input_devices/mag/node_modules/strip-color/package.json b/input_devices/mag/node_modules/strip-color/package.json
new file mode 100644
index 00000000..ec2e2973
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-color/package.json
@@ -0,0 +1,133 @@
+{
+  "_args": [
+    [
+      "strip-color@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "strip-color@>=0.1.0 <0.2.0",
+  "_id": "strip-color@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/strip-color",
+  "_nodeVersion": "4.1.1",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.14.4",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "strip-color",
+    "raw": "strip-color@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/choices-separator",
+    "/prompt-choices",
+    "/readline-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz",
+  "_shasum": "106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b",
+  "_shrinkwrap": null,
+  "_spec": "strip-color@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/strip-color/issues"
+  },
+  "dependencies": {},
+  "description": "Strip ANSI color codes from a string. No dependencies.",
+  "devDependencies": {
+    "ansi-cyan": "^0.1.1",
+    "ansi-red": "^0.1.1",
+    "ansi-yellow": "^0.1.1",
+    "mocha": "^2.3.3"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b",
+    "tarball": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "f18fb7802b54be5acc44e069702fcc6265ff785d",
+  "homepage": "https://github.com/jonschlinkert/strip-color",
+  "keywords": [
+    "ansi",
+    "chalk",
+    "cli",
+    "codes",
+    "color",
+    "colors",
+    "colour",
+    "colours",
+    "command",
+    "command-line",
+    "console",
+    "escape",
+    "format",
+    "formatting",
+    "log",
+    "logging",
+    "match",
+    "pattern",
+    "re",
+    "regex",
+    "regexp",
+    "regular-expression",
+    "remove",
+    "rgb",
+    "shell",
+    "string",
+    "strip",
+    "style",
+    "styles",
+    "styling",
+    "terminal",
+    "text",
+    "trim",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "strip-color",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/strip-color.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "related": {
+      "list": [
+        "ansi-bold",
+        "ansi-cyan",
+        "ansi-red",
+        "ansi-yellow",
+        "wrap-ansi"
+      ]
+    }
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/strip-json-comments/index.js b/input_devices/mag/node_modules/strip-json-comments/index.js
new file mode 100644
index 00000000..4e6576e6
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-json-comments/index.js
@@ -0,0 +1,70 @@
+'use strict';
+var singleComment = 1;
+var multiComment = 2;
+
+function stripWithoutWhitespace() {
+	return '';
+}
+
+function stripWithWhitespace(str, start, end) {
+	return str.slice(start, end).replace(/\S/g, ' ');
+}
+
+module.exports = function (str, opts) {
+	opts = opts || {};
+
+	var currentChar;
+	var nextChar;
+	var insideString = false;
+	var insideComment = false;
+	var offset = 0;
+	var ret = '';
+	var strip = opts.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace;
+
+	for (var i = 0; i < str.length; i++) {
+		currentChar = str[i];
+		nextChar = str[i + 1];
+
+		if (!insideComment && currentChar === '"') {
+			var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\';
+			if (!escaped) {
+				insideString = !insideString;
+			}
+		}
+
+		if (insideString) {
+			continue;
+		}
+
+		if (!insideComment && currentChar + nextChar === '//') {
+			ret += str.slice(offset, i);
+			offset = i;
+			insideComment = singleComment;
+			i++;
+		} else if (insideComment === singleComment && currentChar + nextChar === '\r\n') {
+			i++;
+			insideComment = false;
+			ret += strip(str, offset, i);
+			offset = i;
+			continue;
+		} else if (insideComment === singleComment && currentChar === '\n') {
+			insideComment = false;
+			ret += strip(str, offset, i);
+			offset = i;
+		} else if (!insideComment && currentChar + nextChar === '/*') {
+			ret += str.slice(offset, i);
+			offset = i;
+			insideComment = multiComment;
+			i++;
+			continue;
+		} else if (insideComment === multiComment && currentChar + nextChar === '*/') {
+			i++;
+			insideComment = false;
+			ret += strip(str, offset, i + 1);
+			offset = i + 1;
+			continue;
+		}
+	}
+
+	return ret + (insideComment ? strip(str.substr(offset)) : str.substr(offset));
+};
diff --git a/input_devices/mag/node_modules/strip-json-comments/license b/input_devices/mag/node_modules/strip-json-comments/license
new file mode 100644
index 00000000..654d0bfe
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-json-comments/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+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/input_devices/mag/node_modules/strip-json-comments/package.json b/input_devices/mag/node_modules/strip-json-comments/package.json
new file mode 100644
index 00000000..02b4c923
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-json-comments/package.json
@@ -0,0 +1,102 @@
+{
+  "_args": [
+    [
+      "strip-json-comments@~2.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/rc"
+    ]
+  ],
+  "_from": "strip-json-comments@>=2.0.1 <2.1.0",
+  "_id": "strip-json-comments@2.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/strip-json-comments",
+  "_nodeVersion": "4.2.4",
+  "_npmOperationalInternal": {
+    "host": "packages-9-west.internal.npmjs.com",
+    "tmp": "tmp/strip-json-comments-2.0.1.tgz_1455006605207_0.8280157081317157"
+  },
+  "_npmUser": {
+    "email": "sindresorhus@gmail.com",
+    "name": "sindresorhus"
+  },
+  "_npmVersion": "3.7.2",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "strip-json-comments",
+    "raw": "strip-json-comments@~2.0.1",
+    "rawSpec": "~2.0.1",
+    "scope": null,
+    "spec": ">=2.0.1 <2.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/rc"
+  ],
+  "_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+  "_shasum": "3c531942e908c2697c0ec344858c286c7ca0a60a",
+  "_shrinkwrap": null,
+  "_spec": "strip-json-comments@~2.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/rc",
+  "author": {
+    "email": "sindresorhus@gmail.com",
+    "name": "Sindre Sorhus",
+    "url": "sindresorhus.com"
+  },
+  "bugs": {
+    "url": "https://github.com/sindresorhus/strip-json-comments/issues"
+  },
+  "dependencies": {},
+  "description": "Strip comments from JSON. Lets you use comments in your JSON files!",
+  "devDependencies": {
+    "ava": "*",
+    "xo": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "3c531942e908c2697c0ec344858c286c7ca0a60a",
+    "tarball": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "1aef99eaa70d07981156e8aaa722e750c3b4eaf9",
+  "homepage": "https://github.com/sindresorhus/strip-json-comments#readme",
+  "keywords": [
+    "comments",
+    "conf",
+    "config",
+    "configuration",
+    "delete",
+    "env",
+    "environment",
+    "json",
+    "multiline",
+    "parse",
+    "remove",
+    "settings",
+    "strip",
+    "trim",
+    "util"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "sindresorhus",
+      "email": "sindresorhus@gmail.com"
+    }
+  ],
+  "name": "strip-json-comments",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/sindresorhus/strip-json-comments.git"
+  },
+  "scripts": {
+    "test": "xo && ava"
+  },
+  "version": "2.0.1"
+}
diff --git a/input_devices/mag/node_modules/strip-json-comments/readme.md b/input_devices/mag/node_modules/strip-json-comments/readme.md
new file mode 100644
index 00000000..0ee58dfe
--- /dev/null
+++ b/input_devices/mag/node_modules/strip-json-comments/readme.md
@@ -0,0 +1,64 @@
+# strip-json-comments [![Build Status](https://travis-ci.org/sindresorhus/strip-json-comments.svg?branch=master)](https://travis-ci.org/sindresorhus/strip-json-comments)
+
+> Strip comments from JSON. Lets you use comments in your JSON files!
+
+This is now possible:
+
+```js
+{
+	// rainbows
+	"unicorn": /* ❤ */ "cake"
+}
+```
+
+It will replace single-line comments `//` and multi-line comments `/**/` with whitespace. This allows JSON error positions to remain as close as possible to the original source.
+
+Also available as a [gulp](https://github.com/sindresorhus/gulp-strip-json-comments)/[grunt](https://github.com/sindresorhus/grunt-strip-json-comments)/[broccoli](https://github.com/sindresorhus/broccoli-strip-json-comments) plugin.
+
+
+## Install
+
+```
+$ npm install --save strip-json-comments
+```
+
+
+## Usage
+
+```js
+const json = '{/*rainbows*/"unicorn":"cake"}';
+
+JSON.parse(stripJsonComments(json));
+//=> {unicorn: 'cake'}
+```
+
+
+## API
+
+### stripJsonComments(input, [options])
+
+#### input
+
+Type: `string`
+
+Accepts a string with JSON and returns a string without comments.
+
+#### options
+
+##### whitespace
+
+Type: `boolean`  
+Default: `true`
+
+Replace comments with whitespace instead of stripping them entirely.
+
+
+## Related
+
+- [strip-json-comments-cli](https://github.com/sindresorhus/strip-json-comments-cli) - CLI for this module
+- [strip-css-comments](https://github.com/sindresorhus/strip-css-comments) - Strip comments from CSS
+
+
+## License
+
+MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/input_devices/mag/node_modules/success-symbol/LICENSE b/input_devices/mag/node_modules/success-symbol/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/success-symbol/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/success-symbol/README.md b/input_devices/mag/node_modules/success-symbol/README.md
new file mode 100644
index 00000000..fbc558c4
--- /dev/null
+++ b/input_devices/mag/node_modules/success-symbol/README.md
@@ -0,0 +1,52 @@
+# success-symbol [![NPM version](https://badge.fury.io/js/success-symbol.svg)](http://badge.fury.io/js/success-symbol)
+
+> Cross-platform success symbol.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i success-symbol --save
+```
+
+## Usage
+
+```js
+var success = require('success-symbol');
+```
+
+## Related projects
+
+* [success-symbol](https://github.com/jonschlinkert/success-symbol)
+* [warning-symbol](https://github.com/jonschlinkert/warning-symbol)
+* [error-symbol](https://github.com/jonschlinkert/error-symbol)
+* [info-symbol](https://github.com/jonschlinkert/info-symbol)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/success-symbol/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 27, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/success-symbol/index.js b/input_devices/mag/node_modules/success-symbol/index.js
new file mode 100644
index 00000000..49e89d5a
--- /dev/null
+++ b/input_devices/mag/node_modules/success-symbol/index.js
@@ -0,0 +1 @@
+module.exports = process.platform === 'win32' ? '√' : '✔';
diff --git a/input_devices/mag/node_modules/success-symbol/package.json b/input_devices/mag/node_modules/success-symbol/package.json
new file mode 100644
index 00000000..473e615c
--- /dev/null
+++ b/input_devices/mag/node_modules/success-symbol/package.json
@@ -0,0 +1,107 @@
+{
+  "_args": [
+    [
+      "success-symbol@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils"
+    ]
+  ],
+  "_from": "success-symbol@>=0.1.0 <0.2.0",
+  "_id": "success-symbol@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/success-symbol",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "success-symbol",
+    "raw": "success-symbol@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/log-ok",
+    "/log-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/success-symbol/-/success-symbol-0.1.0.tgz",
+  "_shasum": "24022e486f3bf1cdca094283b769c472d3b72897",
+  "_shrinkwrap": null,
+  "_spec": "success-symbol@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/success-symbol/issues"
+  },
+  "dependencies": {},
+  "description": "Cross-platform success symbol.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "24022e486f3bf1cdca094283b769c472d3b72897",
+    "tarball": "https://registry.npmjs.org/success-symbol/-/success-symbol-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/success-symbol",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "success",
+    "symbol",
+    "symbols",
+    "terminal",
+    "text",
+    "tty",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "success-symbol",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/success-symbol.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/async/.travis.yml b/input_devices/mag/node_modules/tar-fs/.travis.yml
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/async/.travis.yml
rename to input_devices/mag/node_modules/tar-fs/.travis.yml
diff --git a/input_devices/mag/node_modules/tar-fs/LICENSE b/input_devices/mag/node_modules/tar-fs/LICENSE
new file mode 100644
index 00000000..757562ec
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mathias Buus
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/tar-fs/README.md b/input_devices/mag/node_modules/tar-fs/README.md
new file mode 100644
index 00000000..acdc843f
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/README.md
@@ -0,0 +1,163 @@
+# tar-fs
+
+filesystem bindings for [tar-stream](https://github.com/mafintosh/tar-stream).
+
+```
+npm install tar-fs
+```
+
+[![build status](https://secure.travis-ci.org/mafintosh/tar-fs.png)](http://travis-ci.org/mafintosh/tar-fs)
+
+## Usage
+
+tar-fs allows you to pack directories into tarballs and extract tarballs into directories.
+
+It doesn't gunzip for you, so if you want to extract a `.tar.gz` with this you'll need to use something like [gunzip-maybe](https://github.com/mafintosh/gunzip-maybe) in addition to this.
+
+``` js
+var tar = require('tar-fs')
+var fs = require('fs')
+
+// packing a directory
+tar.pack('./my-directory').pipe(fs.createWriteStream('my-tarball.tar'))
+
+// extracting a directory
+fs.createReadStream('my-other-tarball.tar').pipe(tar.extract('./my-other-directory'))
+```
+
+To ignore various files when packing or extracting add a ignore function to the options. `ignore`
+is also an alias for `filter`. Additionally you get `header` if you use ignore while extracting.
+That way you could also filter by metadata.
+
+``` js
+var pack = tar.pack('./my-directory', {
+  ignore: function(name) {
+    return path.extname(name) === '.bin' // ignore .bin files when packing
+  }
+})
+
+var extract = tar.extract('./my-other-directory', {
+  ignore: function(name) {
+    return path.extname(name) === '.bin' // ignore .bin files inside the tarball when extracing
+  }
+})
+
+var extractFilesDirs = tar.extract('./my-other-other-directory', {
+  ignore: function(_, header) {
+    // pass files & directories, ignore e.g. symlinks
+    return header.type !== 'file' && header.type !== 'directory'
+  }
+})
+```
+
+You can also specify which entries to pack using the `entries` option
+
+```js
+var pack = tar.pack('./my-directory', {
+  entries: ['file1', 'subdir/file2'] // only the specific entries will be packed
+})
+```
+
+If you want to modify the headers when packing/extracting add a map function to the options
+
+``` js
+var pack = tar.pack('./my-directory', {
+  map: function(header) {
+    header.name = 'prefixed/'+header.name
+    return header
+  }
+})
+
+var extract = tar.extract('./my-directory', {
+  map: function(header) {
+    header.name = 'another-prefix/'+header.name
+    return header
+  }
+})
+```
+
+Similarly you can use `mapStream` incase you wanna modify the input/output file streams
+
+``` js
+var pack = tar.pack('./my-directory', {
+  mapStream: function(fileStream, header) {
+    if (path.extname(header.name) === '.js') {
+      return fileStream.pipe(someTransform)
+    }
+    return fileStream;
+  }
+})
+
+var extract = tar.extract('./my-directory', {
+  mapStream: function(fileStream, header) {
+    if (path.extname(header.name) === '.js') {
+      return fileStream.pipe(someTransform)
+    }
+    return fileStream;
+  }
+})
+```
+
+Set `options.fmode` and `options.dmode` to ensure that files/directories extracted have the corresponding modes
+
+``` js
+var extract = tar.extract('./my-directory', {
+  dmode: parseInt(555, 8), // all dirs should be readable
+  fmode: parseInt(444, 8) // all files should be readable
+})
+```
+
+It can be useful to use `dmode` and `fmode` if you are packing/unpacking tarballs between *nix/windows to ensure that all files/directories unpacked are readable.
+
+Alternatively you can set `options.readable` and/or `options.writable` to set the dmode and fmode to readable/writable.
+
+``` js
+var extract = tar.extract('./my-directory', {
+  readable: true, // all dirs and files should be readable
+  writable: true, // all dirs and files should be writable
+})
+```
+
+Set `options.strict` to `false` if you want to ignore errors due to unsupported entry types (like device files)
+
+To dereference symlinks (pack the contents of the symlink instead of the link itself) set `options.dereference` to `true`.
+
+## Copy a directory
+
+Copying a directory with permissions and mtime intact is as simple as
+
+``` js
+tar.pack('source-directory').pipe(tar.extract('dest-directory'))
+```
+
+## Interaction with [`tar-stream`](https://github.com/mafintosh/tar-stream)
+
+Use `finalize: false` and the `finish` hook to
+leave the pack stream open for further entries (see
+[`tar-stream#pack`](https://github.com/mafintosh/tar-stream#packing)),
+and use `pack` to pass an existing pack stream.
+
+``` js
+var mypack = tar.pack('./my-directory', {
+  finalize: false,
+  finish: function(sameAsMypack) {
+    mypack.entry({name: 'generated-file.txt'}, "hello")
+    tar.pack('./other-directory', {
+      pack: sameAsMypack
+    })
+  }
+})
+```
+
+
+## Performance
+
+Packing and extracting a 6.1 GB with 2496 directories and 2398 files yields the following results on my Macbook Air.
+[See the benchmark here](https://gist.github.com/mafintosh/8102201)
+
+* tar-fs: 34.261 ms
+* [node-tar](https://github.com/isaacs/node-tar): 366.123 ms (or 10x slower)
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/tar-fs/index.js b/input_devices/mag/node_modules/tar-fs/index.js
new file mode 100644
index 00000000..be902310
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/index.js
@@ -0,0 +1,345 @@
+var chownr = require('chownr')
+var tar = require('tar-stream')
+var pump = require('pump')
+var mkdirp = require('mkdirp')
+var fs = require('fs')
+var path = require('path')
+var os = require('os')
+
+var win32 = os.platform() === 'win32'
+
+var noop = function () {}
+
+var echo = function (name) {
+  return name
+}
+
+var normalize = !win32 ? echo : function (name) {
+  return name.replace(/\\/g, '/').replace(/[:?<>|]/g, '_')
+}
+
+var statAll = function (fs, stat, cwd, ignore, entries, sort) {
+  var queue = entries || ['.']
+
+  return function loop (callback) {
+    if (!queue.length) return callback()
+    var next = queue.shift()
+    var nextAbs = path.join(cwd, next)
+
+    stat(nextAbs, function (err, stat) {
+      if (err) return callback(err)
+
+      if (!stat.isDirectory()) return callback(null, next, stat)
+
+      fs.readdir(nextAbs, function (err, files) {
+        if (err) return callback(err)
+
+        if (sort) files.sort()
+        for (var i = 0; i < files.length; i++) {
+          if (!ignore(path.join(cwd, next, files[i]))) queue.push(path.join(next, files[i]))
+        }
+
+        callback(null, next, stat)
+      })
+    })
+  }
+}
+
+var strip = function (map, level) {
+  return function (header) {
+    header.name = header.name.split('/').slice(level).join('/')
+
+    var linkname = header.linkname
+    if (linkname && (header.type === 'link' || path.isAbsolute(linkname))) {
+      header.linkname = linkname.split('/').slice(level).join('/')
+    }
+
+    return map(header)
+  }
+}
+
+exports.pack = function (cwd, opts) {
+  if (!cwd) cwd = '.'
+  if (!opts) opts = {}
+
+  var xfs = opts.fs || fs
+  var ignore = opts.ignore || opts.filter || noop
+  var map = opts.map || noop
+  var mapStream = opts.mapStream || echo
+  var statNext = statAll(xfs, opts.dereference ? xfs.stat : xfs.lstat, cwd, ignore, opts.entries, opts.sort)
+  var strict = opts.strict !== false
+  var umask = typeof opts.umask === 'number' ? ~opts.umask : ~processUmask()
+  var dmode = typeof opts.dmode === 'number' ? opts.dmode : 0
+  var fmode = typeof opts.fmode === 'number' ? opts.fmode : 0
+  var pack = opts.pack || tar.pack()
+  var finish = opts.finish || noop
+
+  if (opts.strip) map = strip(map, opts.strip)
+
+  if (opts.readable) {
+    dmode |= parseInt(555, 8)
+    fmode |= parseInt(444, 8)
+  }
+  if (opts.writable) {
+    dmode |= parseInt(333, 8)
+    fmode |= parseInt(222, 8)
+  }
+
+  var onsymlink = function (filename, header) {
+    xfs.readlink(path.join(cwd, filename), function (err, linkname) {
+      if (err) return pack.destroy(err)
+      header.linkname = normalize(linkname)
+      pack.entry(header, onnextentry)
+    })
+  }
+
+  var onstat = function (err, filename, stat) {
+    if (err) return pack.destroy(err)
+    if (!filename) {
+      if (opts.finalize !== false) pack.finalize()
+      return finish(pack)
+    }
+
+    if (stat.isSocket()) return onnextentry() // tar does not support sockets...
+
+    var header = {
+      name: normalize(filename),
+      mode: (stat.mode | (stat.isDirectory() ? dmode : fmode)) & umask,
+      mtime: stat.mtime,
+      size: stat.size,
+      type: 'file',
+      uid: stat.uid,
+      gid: stat.gid
+    }
+
+    if (stat.isDirectory()) {
+      header.size = 0
+      header.type = 'directory'
+      header = map(header) || header
+      return pack.entry(header, onnextentry)
+    }
+
+    if (stat.isSymbolicLink()) {
+      header.size = 0
+      header.type = 'symlink'
+      header = map(header) || header
+      return onsymlink(filename, header)
+    }
+
+    // TODO: add fifo etc...
+
+    header = map(header) || header
+
+    if (!stat.isFile()) {
+      if (strict) return pack.destroy(new Error('unsupported type for ' + filename))
+      return onnextentry()
+    }
+
+    var entry = pack.entry(header, onnextentry)
+    if (!entry) return
+
+    var rs = mapStream(xfs.createReadStream(path.join(cwd, filename)), header)
+
+    rs.on('error', function (err) { // always forward errors on destroy
+      entry.destroy(err)
+    })
+
+    pump(rs, entry)
+  }
+
+  var onnextentry = function (err) {
+    if (err) return pack.destroy(err)
+    statNext(onstat)
+  }
+
+  onnextentry()
+
+  return pack
+}
+
+var head = function (list) {
+  return list.length ? list[list.length - 1] : null
+}
+
+var processGetuid = function () {
+  return process.getuid ? process.getuid() : -1
+}
+
+var processUmask = function () {
+  return process.umask ? process.umask() : 0
+}
+
+exports.extract = function (cwd, opts) {
+  if (!cwd) cwd = '.'
+  if (!opts) opts = {}
+
+  var xfs = opts.fs || fs
+  var ignore = opts.ignore || opts.filter || noop
+  var map = opts.map || noop
+  var mapStream = opts.mapStream || echo
+  var own = opts.chown !== false && !win32 && processGetuid() === 0
+  var extract = opts.extract || tar.extract()
+  var stack = []
+  var now = new Date()
+  var umask = typeof opts.umask === 'number' ? ~opts.umask : ~processUmask()
+  var dmode = typeof opts.dmode === 'number' ? opts.dmode : 0
+  var fmode = typeof opts.fmode === 'number' ? opts.fmode : 0
+  var strict = opts.strict !== false
+
+  if (opts.strip) map = strip(map, opts.strip)
+
+  if (opts.readable) {
+    dmode |= parseInt(555, 8)
+    fmode |= parseInt(444, 8)
+  }
+  if (opts.writable) {
+    dmode |= parseInt(333, 8)
+    fmode |= parseInt(222, 8)
+  }
+
+  var utimesParent = function (name, cb) { // we just set the mtime on the parent dir again everytime we write an entry
+    var top
+    while ((top = head(stack)) && name.slice(0, top[0].length) !== top[0]) stack.pop()
+    if (!top) return cb()
+    xfs.utimes(top[0], now, top[1], cb)
+  }
+
+  var utimes = function (name, header, cb) {
+    if (opts.utimes === false) return cb()
+
+    if (header.type === 'directory') return xfs.utimes(name, now, header.mtime, cb)
+    if (header.type === 'symlink') return utimesParent(name, cb) // TODO: how to set mtime on link?
+
+    xfs.utimes(name, now, header.mtime, function (err) {
+      if (err) return cb(err)
+      utimesParent(name, cb)
+    })
+  }
+
+  var chperm = function (name, header, cb) {
+    var link = header.type === 'symlink'
+    var chmod = link ? xfs.lchmod : xfs.chmod
+    var chown = link ? xfs.lchown : xfs.chown
+
+    if (!chmod) return cb()
+
+    var mode = (header.mode | (header.type === 'directory' ? dmode : fmode)) & umask
+    chmod(name, mode, function (err) {
+      if (err) return cb(err)
+      if (!own) return cb()
+      if (!chown) return cb()
+      chown(name, header.uid, header.gid, cb)
+    })
+  }
+
+  extract.on('entry', function (header, stream, next) {
+    header = map(header) || header
+    header.name = normalize(header.name)
+    var name = path.join(cwd, path.join('/', header.name))
+
+    if (ignore(name, header)) {
+      stream.resume()
+      return next()
+    }
+
+    var stat = function (err) {
+      if (err) return next(err)
+      utimes(name, header, function (err) {
+        if (err) return next(err)
+        if (win32) return next()
+        chperm(name, header, next)
+      })
+    }
+
+    var onsymlink = function () {
+      if (win32) return next() // skip symlinks on win for now before it can be tested
+      xfs.unlink(name, function () {
+        xfs.symlink(header.linkname, name, stat)
+      })
+    }
+
+    var onlink = function () {
+      if (win32) return next() // skip links on win for now before it can be tested
+      xfs.unlink(name, function () {
+        var srcpath = path.join(cwd, path.join('/', header.linkname))
+
+        xfs.link(srcpath, name, function (err) {
+          if (err && err.code === 'EPERM' && opts.hardlinkAsFilesFallback) {
+            stream = xfs.createReadStream(srcpath)
+            return onfile()
+          }
+
+          stat(err)
+        })
+      })
+    }
+
+    var onfile = function () {
+      var ws = xfs.createWriteStream(name)
+      var rs = mapStream(stream, header)
+
+      ws.on('error', function (err) { // always forward errors on destroy
+        rs.destroy(err)
+      })
+
+      pump(rs, ws, function (err) {
+        if (err) return next(err)
+        ws.on('close', stat)
+      })
+    }
+
+    if (header.type === 'directory') {
+      stack.push([name, header.mtime])
+      return mkdirfix(name, {
+        fs: xfs, own: own, uid: header.uid, gid: header.gid
+      }, stat)
+    }
+
+    var dir = path.dirname(name)
+
+    validate(xfs, dir, path.join(cwd, '.'), function (err, valid) {
+      if (err) return next(err)
+      if (!valid) return next(new Error(dir + ' is not a valid path'))
+
+      mkdirfix(dir, {
+        fs: xfs, own: own, uid: header.uid, gid: header.gid
+      }, function (err) {
+        if (err) return next(err)
+
+        switch (header.type) {
+          case 'file': return onfile()
+          case 'link': return onlink()
+          case 'symlink': return onsymlink()
+        }
+
+        if (strict) return next(new Error('unsupported type for ' + name + ' (' + header.type + ')'))
+
+        stream.resume()
+        next()
+      })
+    })
+  })
+
+  if (opts.finish) extract.on('finish', opts.finish)
+
+  return extract
+}
+
+function validate (fs, name, root, cb) {
+  if (name === root) return cb(null, true)
+  fs.lstat(name, function (err, st) {
+    if (err && err.code !== 'ENOENT') return cb(err)
+    if (err || st.isDirectory()) return validate(fs, path.join(name, '..'), root, cb)
+    cb(null, false)
+  })
+}
+
+function mkdirfix (name, opts, cb) {
+  mkdirp(name, {fs: opts.fs}, function (err, made) {
+    if (!err && made && opts.own) {
+      chownr(made, opts.uid, opts.gid, cb)
+    } else {
+      cb(err)
+    }
+  })
+}
diff --git a/input_devices/mag/node_modules/tar-fs/node_modules/pump/.travis.yml b/input_devices/mag/node_modules/tar-fs/node_modules/pump/.travis.yml
new file mode 100644
index 00000000..17f94330
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/node_modules/pump/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - "0.10"
+
+script: "npm test"
diff --git a/input_devices/mag/node_modules/tar-fs/node_modules/pump/LICENSE b/input_devices/mag/node_modules/tar-fs/node_modules/pump/LICENSE
new file mode 100644
index 00000000..757562ec
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/node_modules/pump/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mathias Buus
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/tar-fs/node_modules/pump/README.md b/input_devices/mag/node_modules/tar-fs/node_modules/pump/README.md
new file mode 100644
index 00000000..5029b27d
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/node_modules/pump/README.md
@@ -0,0 +1,56 @@
+# pump
+
+pump is a small node module that pipes streams together and destroys all of them if one of them closes.
+
+```
+npm install pump
+```
+
+[![build status](http://img.shields.io/travis/mafintosh/pump.svg?style=flat)](http://travis-ci.org/mafintosh/pump)
+
+## What problem does it solve?
+
+When using standard `source.pipe(dest)` source will _not_ be destroyed if dest emits close or an error.
+You are also not able to provide a callback to tell when then pipe has finished.
+
+pump does these two things for you
+
+## Usage
+
+Simply pass the streams you want to pipe together to pump and add an optional callback
+
+``` js
+var pump = require('pump')
+var fs = require('fs')
+
+var source = fs.createReadStream('/dev/random')
+var dest = fs.createWriteStream('/dev/null')
+
+pump(source, dest, function(err) {
+  console.log('pipe finished', err)
+})
+
+setTimeout(function() {
+  dest.destroy() // when dest is closed pump will destroy source
+}, 1000)
+```
+
+You can use pump to pipe more than two streams together as well
+
+``` js
+var transform = someTransformStream()
+
+pump(source, transform, anotherTransform, dest, function(err) {
+  console.log('pipe finished', err)
+})
+```
+
+If `source`, `transform`, `anotherTransform` or `dest` closes all of them will be destroyed.
+
+## License
+
+MIT
+
+## Related
+
+`pump` is part of the [mississippi stream utility collection](https://github.com/maxogden/mississippi) which includes more useful stream modules similar to this one.
diff --git a/input_devices/mag/node_modules/tar-fs/node_modules/pump/index.js b/input_devices/mag/node_modules/tar-fs/node_modules/pump/index.js
new file mode 100644
index 00000000..f0c639a8
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/node_modules/pump/index.js
@@ -0,0 +1,80 @@
+var once = require('once')
+var eos = require('end-of-stream')
+var fs = require('fs') // we only need fs to get the ReadStream and WriteStream prototypes
+
+var noop = function () {}
+
+var isFn = function (fn) {
+  return typeof fn === 'function'
+}
+
+var isFS = function (stream) {
+  if (!fs) return false // browser
+  return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close)
+}
+
+var isRequest = function (stream) {
+  return stream.setHeader && isFn(stream.abort)
+}
+
+var destroyer = function (stream, reading, writing, callback) {
+  callback = once(callback)
+
+  var closed = false
+  stream.on('close', function () {
+    closed = true
+  })
+
+  eos(stream, {readable: reading, writable: writing}, function (err) {
+    if (err) return callback(err)
+    closed = true
+    callback()
+  })
+
+  var destroyed = false
+  return function (err) {
+    if (closed) return
+    if (destroyed) return
+    destroyed = true
+
+    if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks
+    if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want
+
+    if (isFn(stream.destroy)) return stream.destroy()
+
+    callback(err || new Error('stream was destroyed'))
+  }
+}
+
+var call = function (fn) {
+  fn()
+}
+
+var pipe = function (from, to) {
+  return from.pipe(to)
+}
+
+var pump = function () {
+  var streams = Array.prototype.slice.call(arguments)
+  var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop
+
+  if (Array.isArray(streams[0])) streams = streams[0]
+  if (streams.length < 2) throw new Error('pump requires two streams per minimum')
+
+  var error
+  var destroys = streams.map(function (stream, i) {
+    var reading = i < streams.length - 1
+    var writing = i > 0
+    return destroyer(stream, reading, writing, function (err) {
+      if (!error) error = err
+      if (err) destroys.forEach(call)
+      if (reading) return
+      destroys.forEach(call)
+      callback(error)
+    })
+  })
+
+  return streams.reduce(pipe)
+}
+
+module.exports = pump
diff --git a/input_devices/mag/node_modules/tar-fs/node_modules/pump/package.json b/input_devices/mag/node_modules/tar-fs/node_modules/pump/package.json
new file mode 100644
index 00000000..c9cc3c1c
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/node_modules/pump/package.json
@@ -0,0 +1,88 @@
+{
+  "_args": [
+    [
+      "pump@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-fs"
+    ]
+  ],
+  "_from": "pump@>=1.0.0 <2.0.0",
+  "_id": "pump@1.0.3",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/tar-fs/pump",
+  "_nodeVersion": "8.9.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/pump-1.0.3.tgz_1510865055632_0.71864059031941"
+  },
+  "_npmUser": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "mafintosh"
+  },
+  "_npmVersion": "5.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "pump",
+    "raw": "pump@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-fs"
+  ],
+  "_resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
+  "_shasum": "5dfe8311c33bbf6fc18261f9f34702c47c08a954",
+  "_shrinkwrap": null,
+  "_spec": "pump@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-fs",
+  "author": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "Mathias Buus Madsen"
+  },
+  "browser": {
+    "fs": false
+  },
+  "bugs": {
+    "url": "https://github.com/mafintosh/pump/issues"
+  },
+  "dependencies": {
+    "end-of-stream": "^1.1.0",
+    "once": "^1.3.1"
+  },
+  "description": "pipe streams together and close all of them if one of them closes",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
+    "shasum": "5dfe8311c33bbf6fc18261f9f34702c47c08a954",
+    "tarball": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz"
+  },
+  "gitHead": "28557d8349d8e3b6878f9955d28b4a52c6a44de3",
+  "homepage": "https://github.com/mafintosh/pump#readme",
+  "keywords": [
+    "callback",
+    "destroy",
+    "pipe",
+    "streams"
+  ],
+  "license": "MIT",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    }
+  ],
+  "name": "pump",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mafintosh/pump.git"
+  },
+  "scripts": {
+    "test": "node test.js"
+  },
+  "version": "1.0.3"
+}
diff --git a/input_devices/mag/node_modules/tar-fs/node_modules/pump/test-browser.js b/input_devices/mag/node_modules/tar-fs/node_modules/pump/test-browser.js
new file mode 100644
index 00000000..80e852c7
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/node_modules/pump/test-browser.js
@@ -0,0 +1,58 @@
+var stream = require('stream')
+var pump = require('./index')
+
+var rs = new stream.Readable()
+var ws = new stream.Writable()
+
+rs._read = function (size) {
+  this.push(Buffer(size).fill('abc'))
+}
+
+ws._write = function (chunk, encoding, cb) {
+  setTimeout(function () {
+    cb()
+  }, 100)
+}
+
+var toHex = function () {
+  var reverse = new (require('stream').Transform)()
+
+  reverse._transform = function (chunk, enc, callback) {
+    reverse.push(chunk.toString('hex'))
+    callback()
+  }
+
+  return reverse
+}
+
+var wsClosed = false
+var rsClosed = false
+var callbackCalled = false
+
+var check = function () {
+  if (wsClosed && rsClosed && callbackCalled) console.log('done')
+}
+
+ws.on('finish', function () {
+  wsClosed = true
+  check()
+})
+
+rs.on('end', function () {
+  rsClosed = true
+  check()
+})
+
+pump(rs, toHex(), toHex(), toHex(), ws, function () {
+  callbackCalled = true
+  check()
+})
+
+setTimeout(function () {
+  rs.push(null)
+  rs.emit('close')
+}, 1000)
+
+setTimeout(function () {
+  if (!check()) throw new Error('timeout')
+}, 5000)
diff --git a/input_devices/mag/node_modules/tar-fs/node_modules/pump/test.js b/input_devices/mag/node_modules/tar-fs/node_modules/pump/test.js
new file mode 100644
index 00000000..64e772ca
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/node_modules/pump/test.js
@@ -0,0 +1,46 @@
+var pump = require('./index')
+
+var rs = require('fs').createReadStream('/dev/random')
+var ws = require('fs').createWriteStream('/dev/null')
+
+var toHex = function () {
+  var reverse = new (require('stream').Transform)()
+
+  reverse._transform = function (chunk, enc, callback) {
+    reverse.push(chunk.toString('hex'))
+    callback()
+  }
+
+  return reverse
+}
+
+var wsClosed = false
+var rsClosed = false
+var callbackCalled = false
+
+var check = function () {
+  if (wsClosed && rsClosed && callbackCalled) process.exit(0)
+}
+
+ws.on('close', function () {
+  wsClosed = true
+  check()
+})
+
+rs.on('close', function () {
+  rsClosed = true
+  check()
+})
+
+pump(rs, toHex(), toHex(), toHex(), ws, function () {
+  callbackCalled = true
+  check()
+})
+
+setTimeout(function () {
+  rs.destroy()
+}, 1000)
+
+setTimeout(function () {
+  throw new Error('timeout')
+}, 5000)
diff --git a/input_devices/mag/node_modules/tar-fs/package.json b/input_devices/mag/node_modules/tar-fs/package.json
new file mode 100644
index 00000000..3ec9ee33
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/package.json
@@ -0,0 +1,105 @@
+{
+  "_args": [
+    [
+      "tar-fs@^1.13.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "tar-fs@>=1.13.0 <2.0.0",
+  "_id": "tar-fs@1.16.3",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/tar-fs",
+  "_nodeVersion": "10.3.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/tar-fs_1.16.3_1529482839287_0.9628256030497233"
+  },
+  "_npmUser": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "mafintosh"
+  },
+  "_npmVersion": "6.1.0",
+  "_phantomChildren": {
+    "end-of-stream": "1.4.1",
+    "once": "1.4.0"
+  },
+  "_requested": {
+    "name": "tar-fs",
+    "raw": "tar-fs@^1.13.0",
+    "rawSpec": "^1.13.0",
+    "scope": null,
+    "spec": ">=1.13.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
+  "_shasum": "966a628841da2c4010406a82167cbd5e0c72d509",
+  "_shrinkwrap": null,
+  "_spec": "tar-fs@^1.13.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "name": "Mathias Buus"
+  },
+  "bugs": {
+    "url": "https://github.com/mafintosh/tar-fs/issues"
+  },
+  "dependencies": {
+    "chownr": "^1.0.1",
+    "mkdirp": "^0.5.1",
+    "pump": "^1.0.0",
+    "tar-stream": "^1.1.2"
+  },
+  "description": "filesystem bindings for tar-stream",
+  "devDependencies": {
+    "rimraf": "^2.2.8",
+    "standard": "^4.5.4",
+    "tape": "^3.0.0"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "dist": {
+    "fileCount": 16,
+    "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbKg5YCRA9TVsSAnZWagAAxLcP/3ciyULwU9bea6dkO8g+\nlfnHf8GQGSuEVTXRCVNFN9oF9WxX793561Kr+blU2dRdn+B10PBeuUpdgFKd\nJn6DE2Tq77GMRKwUQbcNl/G4RMFPIKOd51yDn5mZjZVFYEF2TjOHYN6bJaWk\nbDch+WDzVuoTSQWOpz27dF9vLUFXMNTaJi2rb1WtXR4TzgVftfKhZtuFYYFv\nIN1Cs2jlI3L5aoUfJwNSBswpyJ2fZE65/IC/Drxa+GflFJO0KZ1GjdEhZx9v\n4pug+ASPqvA+Vx+EyZrv3wO6rpSz7+15jpFMtUeaArxp4QnNMDs+ogKBfQGp\n/j0wYxDFkajUyejxzBC5+XJr0Hoi8gmlQYCczD8O2fFvH5EeqNbmRLszpbri\nT2BFTRDFdEEQRIYvMzXlGxqE7KY+BPttONx6Iy0YpJMfKt0Jp4tmdPaE2kQO\nzvb5qtSf+7CzSzVRE9pXsksXYSDls1RA1w3NMCWtDQQE6zt/JtSogUsmWiAO\nlvT2JaGiphzh5aB6hnopfvY8CNJmz5BLODtdknw/z9Ab7Q2BL+7HkL2cQ/HX\n2yk41jmxswcN1ats6MapfprYYnlLmlK6oD5zIpk0ucbsXjVRndi7qvpScBvs\nk8wF7C08Kbhxnyj1t70ny8Pb5VetG/qno+wxJcFE5RpUMGUojrjP5cppXUmJ\nBhTI\r\n=Uk1O\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "966a628841da2c4010406a82167cbd5e0c72d509",
+    "tarball": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
+    "unpackedSize": 27601
+  },
+  "gitHead": "873cda1e15503b1686aa544b4420f42bd6aa55a5",
+  "homepage": "https://github.com/mafintosh/tar-fs",
+  "keywords": [
+    "directory",
+    "file",
+    "fs",
+    "stream",
+    "tar",
+    "tarball"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    },
+    {
+      "name": "maxogden",
+      "email": "max@maxogden.com"
+    }
+  ],
+  "name": "tar-fs",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/mafintosh/tar-fs.git"
+  },
+  "scripts": {
+    "test": "standard && tape test/index.js"
+  },
+  "version": "1.16.3"
+}
diff --git a/input_devices/mag/node_modules/tar-fs/test/fixtures/a/hello.txt b/input_devices/mag/node_modules/tar-fs/test/fixtures/a/hello.txt
new file mode 100644
index 00000000..3b18e512
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/test/fixtures/a/hello.txt
@@ -0,0 +1 @@
+hello world
diff --git a/input_devices/mag/node_modules/tar-fs/test/fixtures/b/a/test.txt b/input_devices/mag/node_modules/tar-fs/test/fixtures/b/a/test.txt
new file mode 100644
index 00000000..9daeafb9
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/test/fixtures/b/a/test.txt
@@ -0,0 +1 @@
+test
diff --git a/input_devices/mag/node_modules/serialport/build/Release/linker.lock b/input_devices/mag/node_modules/tar-fs/test/fixtures/d/file1
similarity index 100%
rename from input_devices/mag/node_modules/serialport/build/Release/linker.lock
rename to input_devices/mag/node_modules/tar-fs/test/fixtures/d/file1
diff --git a/input_devices/mag/node_modules/serialport/build/Release/obj.target/action_after_build.stamp b/input_devices/mag/node_modules/tar-fs/test/fixtures/d/file2
similarity index 100%
rename from input_devices/mag/node_modules/serialport/build/Release/obj.target/action_after_build.stamp
rename to input_devices/mag/node_modules/tar-fs/test/fixtures/d/file2
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/linker.lock b/input_devices/mag/node_modules/tar-fs/test/fixtures/d/sub-dir/file5
similarity index 100%
rename from input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/linker.lock
rename to input_devices/mag/node_modules/tar-fs/test/fixtures/d/sub-dir/file5
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/linker.lock b/input_devices/mag/node_modules/tar-fs/test/fixtures/d/sub-files/file3
similarity index 100%
rename from input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/linker.lock
rename to input_devices/mag/node_modules/tar-fs/test/fixtures/d/sub-files/file3
diff --git a/input_devices/mag/node_modules/tar-fs/test/fixtures/d/sub-files/file4 b/input_devices/mag/node_modules/tar-fs/test/fixtures/d/sub-files/file4
new file mode 100644
index 00000000..e69de29b
diff --git a/input_devices/mag/node_modules/tar-fs/test/fixtures/e/directory/.ignore b/input_devices/mag/node_modules/tar-fs/test/fixtures/e/directory/.ignore
new file mode 100644
index 00000000..e69de29b
diff --git a/input_devices/mag/node_modules/tar-fs/test/fixtures/e/file b/input_devices/mag/node_modules/tar-fs/test/fixtures/e/file
new file mode 100644
index 00000000..e69de29b
diff --git a/input_devices/mag/node_modules/tar-fs/test/fixtures/invalid.tar b/input_devices/mag/node_modules/tar-fs/test/fixtures/invalid.tar
new file mode 100644
index 0000000000000000000000000000000000000000..a645e9ce59e35b70c748a3c47c5b791c86d61ae3
GIT binary patch
literal 2560
zcmYex&u5@DFfcGMGci$MFaQH|8X{<DY-Da|Y-(g?Xrf?XXkch!sK8*Pr>9SAw=t9!
zmn0T37#L7$5!f3B2+vV!9-Z{3<>%`sB^J@tHp205s(=>%Cg!FJ3>3!+F}@n%@t={J
blSBIwfS8CFRWlj_qaiRF0;3^7&kz6rnE)h9

literal 0
HcmV?d00001

diff --git a/input_devices/mag/node_modules/tar-fs/test/index.js b/input_devices/mag/node_modules/tar-fs/test/index.js
new file mode 100644
index 00000000..a03844e4
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-fs/test/index.js
@@ -0,0 +1,346 @@
+var test = require('tape')
+var rimraf = require('rimraf')
+var tar = require('../index')
+var tarStream = require('tar-stream')
+var path = require('path')
+var fs = require('fs')
+var os = require('os')
+
+var win32 = os.platform() === 'win32'
+
+var mtime = function (st) {
+  return Math.floor(st.mtime.getTime() / 1000)
+}
+
+test('copy a -> copy/a', function (t) {
+  t.plan(5)
+
+  var a = path.join(__dirname, 'fixtures', 'a')
+  var b = path.join(__dirname, 'fixtures', 'copy', 'a')
+
+  rimraf.sync(b)
+  tar.pack(a)
+    .pipe(tar.extract(b))
+    .on('finish', function () {
+      var files = fs.readdirSync(b)
+      t.same(files.length, 1)
+      t.same(files[0], 'hello.txt')
+      var fileB = path.join(b, files[0])
+      var fileA = path.join(a, files[0])
+      t.same(fs.readFileSync(fileB, 'utf-8'), fs.readFileSync(fileA, 'utf-8'))
+      t.same(fs.statSync(fileB).mode, fs.statSync(fileA).mode)
+      t.same(mtime(fs.statSync(fileB)), mtime(fs.statSync(fileA)))
+    })
+})
+
+test('copy b -> copy/b', function (t) {
+  t.plan(8)
+
+  var a = path.join(__dirname, 'fixtures', 'b')
+  var b = path.join(__dirname, 'fixtures', 'copy', 'b')
+
+  rimraf.sync(b)
+  tar.pack(a)
+    .pipe(tar.extract(b))
+    .on('finish', function () {
+      var files = fs.readdirSync(b)
+      t.same(files.length, 1)
+      t.same(files[0], 'a')
+      var dirB = path.join(b, files[0])
+      var dirA = path.join(a, files[0])
+      t.same(fs.statSync(dirB).mode, fs.statSync(dirA).mode)
+      t.same(mtime(fs.statSync(dirB)), mtime(fs.statSync(dirA)))
+      t.ok(fs.statSync(dirB).isDirectory())
+      var fileB = path.join(dirB, 'test.txt')
+      var fileA = path.join(dirA, 'test.txt')
+      t.same(fs.readFileSync(fileB, 'utf-8'), fs.readFileSync(fileA, 'utf-8'))
+      t.same(fs.statSync(fileB).mode, fs.statSync(fileA).mode)
+      t.same(mtime(fs.statSync(fileB)), mtime(fs.statSync(fileA)))
+    })
+})
+
+test('symlink', function (t) {
+  if (win32) { // no symlink support on win32 currently. TODO: test if this can be enabled somehow
+    t.plan(1)
+    t.ok(true)
+    return
+  }
+
+  t.plan(5)
+
+  var a = path.join(__dirname, 'fixtures', 'c')
+
+  rimraf.sync(path.join(a, 'link'))
+  fs.symlinkSync('.gitignore', path.join(a, 'link'))
+
+  var b = path.join(__dirname, 'fixtures', 'copy', 'c')
+
+  rimraf.sync(b)
+  tar.pack(a)
+    .pipe(tar.extract(b))
+    .on('finish', function () {
+      var files = fs.readdirSync(b).sort()
+      t.same(files.length, 2)
+      t.same(files[0], '.gitignore')
+      t.same(files[1], 'link')
+
+      var linkA = path.join(a, 'link')
+      var linkB = path.join(b, 'link')
+
+      t.same(mtime(fs.lstatSync(linkB)), mtime(fs.lstatSync(linkA)))
+      t.same(fs.readlinkSync(linkB), fs.readlinkSync(linkA))
+    })
+})
+
+test('follow symlinks', function (t) {
+  if (win32) { // no symlink support on win32 currently. TODO: test if this can be enabled somehow
+    t.plan(1)
+    t.ok(true)
+    return
+  }
+
+  t.plan(5)
+
+  var a = path.join(__dirname, 'fixtures', 'c')
+
+  rimraf.sync(path.join(a, 'link'))
+  fs.symlinkSync('.gitignore', path.join(a, 'link'))
+
+  var b = path.join(__dirname, 'fixtures', 'copy', 'c-dereference')
+
+  rimraf.sync(b)
+  tar.pack(a, {dereference: true})
+    .pipe(tar.extract(b))
+    .on('finish', function () {
+      var files = fs.readdirSync(b).sort()
+      t.same(files.length, 2)
+      t.same(files[0], '.gitignore')
+      t.same(files[1], 'link')
+
+      var file1 = path.join(b, '.gitignore')
+      var file2 = path.join(b, 'link')
+
+      t.same(mtime(fs.lstatSync(file1)), mtime(fs.lstatSync(file2)))
+      t.same(fs.readFileSync(file1), fs.readFileSync(file2))
+    })
+})
+
+test('strip', function (t) {
+  t.plan(2)
+
+  var a = path.join(__dirname, 'fixtures', 'b')
+  var b = path.join(__dirname, 'fixtures', 'copy', 'b-strip')
+
+  rimraf.sync(b)
+
+  tar.pack(a)
+    .pipe(tar.extract(b, {strip: 1}))
+    .on('finish', function () {
+      var files = fs.readdirSync(b).sort()
+      t.same(files.length, 1)
+      t.same(files[0], 'test.txt')
+    })
+})
+
+test('strip + map', function (t) {
+  t.plan(2)
+
+  var a = path.join(__dirname, 'fixtures', 'b')
+  var b = path.join(__dirname, 'fixtures', 'copy', 'b-strip')
+
+  rimraf.sync(b)
+
+  var uppercase = function (header) {
+    header.name = header.name.toUpperCase()
+    return header
+  }
+
+  tar.pack(a)
+    .pipe(tar.extract(b, {strip: 1, map: uppercase}))
+    .on('finish', function () {
+      var files = fs.readdirSync(b).sort()
+      t.same(files.length, 1)
+      t.same(files[0], 'TEST.TXT')
+    })
+})
+
+test('map + dir + permissions', function (t) {
+  t.plan(win32 ? 1 : 2) // skip chmod test, it's not working like unix
+
+  var a = path.join(__dirname, 'fixtures', 'b')
+  var b = path.join(__dirname, 'fixtures', 'copy', 'a-perms')
+
+  rimraf.sync(b)
+
+  var aWithMode = function (header) {
+    if (header.name === 'a') {
+      header.mode = parseInt(700, 8)
+    }
+    return header
+  }
+
+  tar.pack(a)
+      .pipe(tar.extract(b, {map: aWithMode}))
+      .on('finish', function () {
+        var files = fs.readdirSync(b).sort()
+        var stat = fs.statSync(path.join(b, 'a'))
+        t.same(files.length, 1)
+        if (!win32) {
+          t.same(stat.mode & parseInt(777, 8), parseInt(700, 8))
+        }
+      })
+})
+
+test('specific entries', function (t) {
+  t.plan(6)
+
+  var a = path.join(__dirname, 'fixtures', 'd')
+  var b = path.join(__dirname, 'fixtures', 'copy', 'd-entries')
+
+  var entries = [ 'file1', 'sub-files/file3', 'sub-dir' ]
+
+  rimraf.sync(b)
+  tar.pack(a, {entries: entries})
+    .pipe(tar.extract(b))
+    .on('finish', function () {
+      var files = fs.readdirSync(b)
+      t.same(files.length, 3)
+      t.notSame(files.indexOf('file1'), -1)
+      t.notSame(files.indexOf('sub-files'), -1)
+      t.notSame(files.indexOf('sub-dir'), -1)
+      var subFiles = fs.readdirSync(path.join(b, 'sub-files'))
+      t.same(subFiles, ['file3'])
+      var subDir = fs.readdirSync(path.join(b, 'sub-dir'))
+      t.same(subDir, ['file5'])
+    })
+})
+
+test('check type while mapping header on packing', function (t) {
+  t.plan(3)
+
+  var e = path.join(__dirname, 'fixtures', 'e')
+
+  var checkHeaderType = function (header) {
+    if (header.name.indexOf('.') === -1) t.same(header.type, header.name)
+  }
+
+  tar.pack(e, { map: checkHeaderType })
+})
+
+test('finish callbacks', function (t) {
+  t.plan(3)
+
+  var a = path.join(__dirname, 'fixtures', 'a')
+  var b = path.join(__dirname, 'fixtures', 'copy', 'a')
+
+  rimraf.sync(b)
+
+  var packEntries = 0
+  var extractEntries = 0
+
+  var countPackEntry = function (header) { packEntries++ }
+  var countExtractEntry = function (header) { extractEntries++ }
+
+  var pack
+  var onPackFinish = function (passedPack) {
+    t.equal(packEntries, 2, 'All entries have been packed') // 2 entries - the file and base directory
+    t.equal(passedPack, pack, 'The finish hook passes the pack')
+  }
+
+  var onExtractFinish = function () { t.equal(extractEntries, 2) }
+
+  pack = tar.pack(a, {map: countPackEntry, finish: onPackFinish})
+
+  pack.pipe(tar.extract(b, {map: countExtractEntry, finish: onExtractFinish}))
+    .on('finish', function () {
+      t.end()
+    })
+})
+
+test('not finalizing the pack', function (t) {
+  t.plan(2)
+
+  var a = path.join(__dirname, 'fixtures', 'a')
+  var b = path.join(__dirname, 'fixtures', 'b')
+
+  var out = path.join(__dirname, 'fixtures', 'copy', 'merged-packs')
+
+  rimraf.sync(out)
+
+  var prefixer = function (prefix) {
+    return function (header) {
+      header.name = path.join(prefix, header.name)
+      return header
+    }
+  }
+
+  tar.pack(a, {
+    map: prefixer('a-files'),
+    finalize: false,
+    finish: packB
+  })
+
+  function packB (pack) {
+    tar.pack(b, {pack: pack, map: prefixer('b-files')})
+      .pipe(tar.extract(out))
+      .on('finish', assertResults)
+  }
+
+  function assertResults () {
+    var containers = fs.readdirSync(out)
+    t.deepEqual(containers, ['a-files', 'b-files'])
+    var aFiles = fs.readdirSync(path.join(out, 'a-files'))
+    t.deepEqual(aFiles, ['hello.txt'])
+  }
+})
+
+test('do not extract invalid tar', function (t) {
+  var a = path.join(__dirname, 'fixtures', 'invalid.tar')
+
+  var out = path.join(__dirname, 'fixtures', 'invalid')
+
+  rimraf.sync(out)
+
+  fs.createReadStream(a)
+    .pipe(tar.extract(out))
+    .on('error', function (err) {
+      t.ok(/is not a valid path/i.test(err.message))
+      fs.stat(path.join(out, '../bar'), function (err) {
+        t.ok(err)
+        t.end()
+      })
+    })
+})
+
+test('no abs hardlink targets', function (t) {
+  var out = path.join(__dirname, 'fixtures', 'invalid')
+  var outside = path.join(__dirname, 'fixtures', 'outside')
+
+  rimraf.sync(out)
+
+  var s = tarStream.pack()
+
+  fs.writeFileSync(outside, 'something')
+
+  s.entry({
+    type: 'link',
+    name: 'link',
+    linkname: outside
+  })
+
+  s.entry({
+    name: 'link'
+  }, 'overwrite')
+
+  s.finalize()
+
+  s.pipe(tar.extract(out))
+    .on('error', function (err) {
+      t.ok(err, 'had error')
+      fs.readFile(outside, 'utf-8', function (err, str) {
+        t.error(err, 'no error')
+        t.same(str, 'something')
+        t.end()
+      })
+    })
+})
diff --git a/input_devices/mag/node_modules/tar-stream/LICENSE b/input_devices/mag/node_modules/tar-stream/LICENSE
new file mode 100644
index 00000000..757562ec
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-stream/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mathias Buus
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/tar-stream/README.md b/input_devices/mag/node_modules/tar-stream/README.md
new file mode 100644
index 00000000..96abbca1
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-stream/README.md
@@ -0,0 +1,168 @@
+# tar-stream
+
+tar-stream is a streaming tar parser and generator and nothing else. It is streams2 and operates purely using streams which means you can easily extract/parse tarballs without ever hitting the file system.
+
+Note that you still need to gunzip your data if you have a `.tar.gz`. We recommend using [gunzip-maybe](https://github.com/mafintosh/gunzip-maybe) in conjunction with this.
+
+```
+npm install tar-stream
+```
+
+[![build status](https://secure.travis-ci.org/mafintosh/tar-stream.png)](http://travis-ci.org/mafintosh/tar-stream)
+[![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT)
+
+## Usage
+
+tar-stream exposes two streams, [pack](https://github.com/mafintosh/tar-stream#packing) which creates tarballs and [extract](https://github.com/mafintosh/tar-stream#extracting) which extracts tarballs. To [modify an existing tarball](https://github.com/mafintosh/tar-stream#modifying-existing-tarballs) use both.
+
+
+It implementes USTAR with additional support for pax extended headers. It should be compatible with all popular tar distributions out there (gnutar, bsdtar etc)
+
+## Related
+
+If you want to pack/unpack directories on the file system check out [tar-fs](https://github.com/mafintosh/tar-fs) which provides file system bindings to this module.
+
+## Packing
+
+To create a pack stream use `tar.pack()` and call `pack.entry(header, [callback])` to add tar entries.
+
+``` js
+var tar = require('tar-stream')
+var pack = tar.pack() // pack is a streams2 stream
+
+// add a file called my-test.txt with the content "Hello World!"
+pack.entry({ name: 'my-test.txt' }, 'Hello World!')
+
+// add a file called my-stream-test.txt from a stream
+var entry = pack.entry({ name: 'my-stream-test.txt', size: 11 }, function(err) {
+  // the stream was added
+  // no more entries
+  pack.finalize()
+})
+
+entry.write('hello')
+entry.write(' ')
+entry.write('world')
+entry.end()
+
+// pipe the pack stream somewhere
+pack.pipe(process.stdout)
+```
+
+## Extracting
+
+To extract a stream use `tar.extract()` and listen for `extract.on('entry', (header, stream, next) )`
+
+``` js
+var extract = tar.extract()
+
+extract.on('entry', function(header, stream, next) {
+  // header is the tar header
+  // stream is the content body (might be an empty stream)
+  // call next when you are done with this entry
+
+  stream.on('end', function() {
+    next() // ready for next entry
+  })
+
+  stream.resume() // just auto drain the stream
+})
+
+extract.on('finish', function() {
+  // all entries read
+})
+
+pack.pipe(extract)
+```
+
+The tar archive is streamed sequentially, meaning you **must** drain each entry's stream as you get them or else the main extract stream will receive backpressure and stop reading.
+
+## Headers
+
+The header object using in `entry` should contain the following properties.
+Most of these values can be found by stat'ing a file.
+
+``` js
+{
+  name: 'path/to/this/entry.txt',
+  size: 1314,        // entry size. defaults to 0
+  mode: 0644,        // entry mode. defaults to to 0755 for dirs and 0644 otherwise
+  mtime: new Date(), // last modified date for entry. defaults to now.
+  type: 'file',      // type of entry. defaults to file. can be:
+                     // file | link | symlink | directory | block-device
+                     // character-device | fifo | contiguous-file
+  linkname: 'path',  // linked file name
+  uid: 0,            // uid of entry owner. defaults to 0
+  gid: 0,            // gid of entry owner. defaults to 0
+  uname: 'maf',      // uname of entry owner. defaults to null
+  gname: 'staff',    // gname of entry owner. defaults to null
+  devmajor: 0,       // device major version. defaults to 0
+  devminor: 0        // device minor version. defaults to 0
+}
+```
+
+## Modifying existing tarballs
+
+Using tar-stream it is easy to rewrite paths / change modes etc in an existing tarball.
+
+``` js
+var extract = tar.extract()
+var pack = tar.pack()
+var path = require('path')
+
+extract.on('entry', function(header, stream, callback) {
+  // let's prefix all names with 'tmp'
+  header.name = path.join('tmp', header.name)
+  // write the new entry to the pack stream
+  stream.pipe(pack.entry(header, callback))
+})
+
+extract.on('finish', function() {
+  // all entries done - lets finalize it
+  pack.finalize()
+})
+
+// pipe the old tarball to the extractor
+oldTarballStream.pipe(extract)
+
+// pipe the new tarball the another stream
+pack.pipe(newTarballStream)
+```
+
+## Saving tarball to fs
+
+
+``` js
+var fs = require('fs')
+var tar = require('tar-stream')
+
+var pack = tar.pack() // pack is a streams2 stream
+var path = 'YourTarBall.tar'
+var yourTarball = fs.createWriteStream(path)
+
+// add a file called YourFile.txt with the content "Hello World!"
+pack.entry({name: 'YourFile.txt'}, 'Hello World!', function (err) {
+  if (err) throw err
+  pack.finalize()
+})
+
+// pipe the pack stream to your file
+pack.pipe(yourTarball)
+
+yourTarball.on('close', function () {
+  console.log(path + ' has been written')
+  fs.stat(path, function(err, stats) {
+    if (err) throw err
+    console.log(stats)
+    console.log('Got file info successfully!')
+  })
+})
+```
+
+## Performance
+
+[See tar-fs for a performance comparison with node-tar](https://github.com/mafintosh/tar-fs/blob/master/README.md#performance)
+
+# License
+
+MIT
diff --git a/input_devices/mag/node_modules/tar-stream/extract.js b/input_devices/mag/node_modules/tar-stream/extract.js
new file mode 100644
index 00000000..19a4255a
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-stream/extract.js
@@ -0,0 +1,258 @@
+var util = require('util')
+var bl = require('bl')
+var xtend = require('xtend')
+var headers = require('./headers')
+
+var Writable = require('readable-stream').Writable
+var PassThrough = require('readable-stream').PassThrough
+
+var noop = function () {}
+
+var overflow = function (size) {
+  size &= 511
+  return size && 512 - size
+}
+
+var emptyStream = function (self, offset) {
+  var s = new Source(self, offset)
+  s.end()
+  return s
+}
+
+var mixinPax = function (header, pax) {
+  if (pax.path) header.name = pax.path
+  if (pax.linkpath) header.linkname = pax.linkpath
+  if (pax.size) header.size = parseInt(pax.size, 10)
+  header.pax = pax
+  return header
+}
+
+var Source = function (self, offset) {
+  this._parent = self
+  this.offset = offset
+  PassThrough.call(this)
+}
+
+util.inherits(Source, PassThrough)
+
+Source.prototype.destroy = function (err) {
+  this._parent.destroy(err)
+}
+
+var Extract = function (opts) {
+  if (!(this instanceof Extract)) return new Extract(opts)
+  Writable.call(this, opts)
+
+  opts = opts || {}
+
+  this._offset = 0
+  this._buffer = bl()
+  this._missing = 0
+  this._partial = false
+  this._onparse = noop
+  this._header = null
+  this._stream = null
+  this._overflow = null
+  this._cb = null
+  this._locked = false
+  this._destroyed = false
+  this._pax = null
+  this._paxGlobal = null
+  this._gnuLongPath = null
+  this._gnuLongLinkPath = null
+
+  var self = this
+  var b = self._buffer
+
+  var oncontinue = function () {
+    self._continue()
+  }
+
+  var onunlock = function (err) {
+    self._locked = false
+    if (err) return self.destroy(err)
+    if (!self._stream) oncontinue()
+  }
+
+  var onstreamend = function () {
+    self._stream = null
+    var drain = overflow(self._header.size)
+    if (drain) self._parse(drain, ondrain)
+    else self._parse(512, onheader)
+    if (!self._locked) oncontinue()
+  }
+
+  var ondrain = function () {
+    self._buffer.consume(overflow(self._header.size))
+    self._parse(512, onheader)
+    oncontinue()
+  }
+
+  var onpaxglobalheader = function () {
+    var size = self._header.size
+    self._paxGlobal = headers.decodePax(b.slice(0, size))
+    b.consume(size)
+    onstreamend()
+  }
+
+  var onpaxheader = function () {
+    var size = self._header.size
+    self._pax = headers.decodePax(b.slice(0, size))
+    if (self._paxGlobal) self._pax = xtend(self._paxGlobal, self._pax)
+    b.consume(size)
+    onstreamend()
+  }
+
+  var ongnulongpath = function () {
+    var size = self._header.size
+    this._gnuLongPath = headers.decodeLongPath(b.slice(0, size), opts.filenameEncoding)
+    b.consume(size)
+    onstreamend()
+  }
+
+  var ongnulonglinkpath = function () {
+    var size = self._header.size
+    this._gnuLongLinkPath = headers.decodeLongPath(b.slice(0, size), opts.filenameEncoding)
+    b.consume(size)
+    onstreamend()
+  }
+
+  var onheader = function () {
+    var offset = self._offset
+    var header
+    try {
+      header = self._header = headers.decode(b.slice(0, 512), opts.filenameEncoding)
+    } catch (err) {
+      self.emit('error', err)
+    }
+    b.consume(512)
+
+    if (!header) {
+      self._parse(512, onheader)
+      oncontinue()
+      return
+    }
+    if (header.type === 'gnu-long-path') {
+      self._parse(header.size, ongnulongpath)
+      oncontinue()
+      return
+    }
+    if (header.type === 'gnu-long-link-path') {
+      self._parse(header.size, ongnulonglinkpath)
+      oncontinue()
+      return
+    }
+    if (header.type === 'pax-global-header') {
+      self._parse(header.size, onpaxglobalheader)
+      oncontinue()
+      return
+    }
+    if (header.type === 'pax-header') {
+      self._parse(header.size, onpaxheader)
+      oncontinue()
+      return
+    }
+
+    if (self._gnuLongPath) {
+      header.name = self._gnuLongPath
+      self._gnuLongPath = null
+    }
+
+    if (self._gnuLongLinkPath) {
+      header.linkname = self._gnuLongLinkPath
+      self._gnuLongLinkPath = null
+    }
+
+    if (self._pax) {
+      self._header = header = mixinPax(header, self._pax)
+      self._pax = null
+    }
+
+    self._locked = true
+
+    if (!header.size || header.type === 'directory') {
+      self._parse(512, onheader)
+      self.emit('entry', header, emptyStream(self, offset), onunlock)
+      return
+    }
+
+    self._stream = new Source(self, offset)
+
+    self.emit('entry', header, self._stream, onunlock)
+    self._parse(header.size, onstreamend)
+    oncontinue()
+  }
+
+  this._onheader = onheader
+  this._parse(512, onheader)
+}
+
+util.inherits(Extract, Writable)
+
+Extract.prototype.destroy = function (err) {
+  if (this._destroyed) return
+  this._destroyed = true
+
+  if (err) this.emit('error', err)
+  this.emit('close')
+  if (this._stream) this._stream.emit('close')
+}
+
+Extract.prototype._parse = function (size, onparse) {
+  if (this._destroyed) return
+  this._offset += size
+  this._missing = size
+  if (onparse === this._onheader) this._partial = false
+  this._onparse = onparse
+}
+
+Extract.prototype._continue = function () {
+  if (this._destroyed) return
+  var cb = this._cb
+  this._cb = noop
+  if (this._overflow) this._write(this._overflow, undefined, cb)
+  else cb()
+}
+
+Extract.prototype._write = function (data, enc, cb) {
+  if (this._destroyed) return
+
+  var s = this._stream
+  var b = this._buffer
+  var missing = this._missing
+  if (data.length) this._partial = true
+
+  // we do not reach end-of-chunk now. just forward it
+
+  if (data.length < missing) {
+    this._missing -= data.length
+    this._overflow = null
+    if (s) return s.write(data, cb)
+    b.append(data)
+    return cb()
+  }
+
+  // end-of-chunk. the parser should call cb.
+
+  this._cb = cb
+  this._missing = 0
+
+  var overflow = null
+  if (data.length > missing) {
+    overflow = data.slice(missing)
+    data = data.slice(0, missing)
+  }
+
+  if (s) s.end(data)
+  else b.append(data)
+
+  this._overflow = overflow
+  this._onparse()
+}
+
+Extract.prototype._final = function (cb) {
+  if (this._partial) return this.destroy(new Error('Unexpected end of data'))
+  cb()
+}
+
+module.exports = Extract
diff --git a/input_devices/mag/node_modules/tar-stream/headers.js b/input_devices/mag/node_modules/tar-stream/headers.js
new file mode 100644
index 00000000..6efbc4a3
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-stream/headers.js
@@ -0,0 +1,283 @@
+var toBuffer = require('to-buffer')
+var alloc = require('buffer-alloc')
+
+var ZEROS = '0000000000000000000'
+var SEVENS = '7777777777777777777'
+var ZERO_OFFSET = '0'.charCodeAt(0)
+var USTAR = 'ustar\x0000'
+var MASK = parseInt('7777', 8)
+
+var clamp = function (index, len, defaultValue) {
+  if (typeof index !== 'number') return defaultValue
+  index = ~~index // Coerce to integer.
+  if (index >= len) return len
+  if (index >= 0) return index
+  index += len
+  if (index >= 0) return index
+  return 0
+}
+
+var toType = function (flag) {
+  switch (flag) {
+    case 0:
+      return 'file'
+    case 1:
+      return 'link'
+    case 2:
+      return 'symlink'
+    case 3:
+      return 'character-device'
+    case 4:
+      return 'block-device'
+    case 5:
+      return 'directory'
+    case 6:
+      return 'fifo'
+    case 7:
+      return 'contiguous-file'
+    case 72:
+      return 'pax-header'
+    case 55:
+      return 'pax-global-header'
+    case 27:
+      return 'gnu-long-link-path'
+    case 28:
+    case 30:
+      return 'gnu-long-path'
+  }
+
+  return null
+}
+
+var toTypeflag = function (flag) {
+  switch (flag) {
+    case 'file':
+      return 0
+    case 'link':
+      return 1
+    case 'symlink':
+      return 2
+    case 'character-device':
+      return 3
+    case 'block-device':
+      return 4
+    case 'directory':
+      return 5
+    case 'fifo':
+      return 6
+    case 'contiguous-file':
+      return 7
+    case 'pax-header':
+      return 72
+  }
+
+  return 0
+}
+
+var indexOf = function (block, num, offset, end) {
+  for (; offset < end; offset++) {
+    if (block[offset] === num) return offset
+  }
+  return end
+}
+
+var cksum = function (block) {
+  var sum = 8 * 32
+  for (var i = 0; i < 148; i++) sum += block[i]
+  for (var j = 156; j < 512; j++) sum += block[j]
+  return sum
+}
+
+var encodeOct = function (val, n) {
+  val = val.toString(8)
+  if (val.length > n) return SEVENS.slice(0, n) + ' '
+  else return ZEROS.slice(0, n - val.length) + val + ' '
+}
+
+/* Copied from the node-tar repo and modified to meet
+ * tar-stream coding standard.
+ *
+ * Source: https://github.com/npm/node-tar/blob/51b6627a1f357d2eb433e7378e5f05e83b7aa6cd/lib/header.js#L349
+ */
+function parse256 (buf) {
+  // first byte MUST be either 80 or FF
+  // 80 for positive, FF for 2's comp
+  var positive
+  if (buf[0] === 0x80) positive = true
+  else if (buf[0] === 0xFF) positive = false
+  else return null
+
+  // build up a base-256 tuple from the least sig to the highest
+  var zero = false
+  var tuple = []
+  for (var i = buf.length - 1; i > 0; i--) {
+    var byte = buf[i]
+    if (positive) tuple.push(byte)
+    else if (zero && byte === 0) tuple.push(0)
+    else if (zero) {
+      zero = false
+      tuple.push(0x100 - byte)
+    } else tuple.push(0xFF - byte)
+  }
+
+  var sum = 0
+  var l = tuple.length
+  for (i = 0; i < l; i++) {
+    sum += tuple[i] * Math.pow(256, i)
+  }
+
+  return positive ? sum : -1 * sum
+}
+
+var decodeOct = function (val, offset, length) {
+  val = val.slice(offset, offset + length)
+  offset = 0
+
+  // If prefixed with 0x80 then parse as a base-256 integer
+  if (val[offset] & 0x80) {
+    return parse256(val)
+  } else {
+    // Older versions of tar can prefix with spaces
+    while (offset < val.length && val[offset] === 32) offset++
+    var end = clamp(indexOf(val, 32, offset, val.length), val.length, val.length)
+    while (offset < end && val[offset] === 0) offset++
+    if (end === offset) return 0
+    return parseInt(val.slice(offset, end).toString(), 8)
+  }
+}
+
+var decodeStr = function (val, offset, length, encoding) {
+  return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString(encoding)
+}
+
+var addLength = function (str) {
+  var len = Buffer.byteLength(str)
+  var digits = Math.floor(Math.log(len) / Math.log(10)) + 1
+  if (len + digits >= Math.pow(10, digits)) digits++
+
+  return (len + digits) + str
+}
+
+exports.decodeLongPath = function (buf, encoding) {
+  return decodeStr(buf, 0, buf.length, encoding)
+}
+
+exports.encodePax = function (opts) { // TODO: encode more stuff in pax
+  var result = ''
+  if (opts.name) result += addLength(' path=' + opts.name + '\n')
+  if (opts.linkname) result += addLength(' linkpath=' + opts.linkname + '\n')
+  var pax = opts.pax
+  if (pax) {
+    for (var key in pax) {
+      result += addLength(' ' + key + '=' + pax[key] + '\n')
+    }
+  }
+  return toBuffer(result)
+}
+
+exports.decodePax = function (buf) {
+  var result = {}
+
+  while (buf.length) {
+    var i = 0
+    while (i < buf.length && buf[i] !== 32) i++
+    var len = parseInt(buf.slice(0, i).toString(), 10)
+    if (!len) return result
+
+    var b = buf.slice(i + 1, len - 1).toString()
+    var keyIndex = b.indexOf('=')
+    if (keyIndex === -1) return result
+    result[b.slice(0, keyIndex)] = b.slice(keyIndex + 1)
+
+    buf = buf.slice(len)
+  }
+
+  return result
+}
+
+exports.encode = function (opts) {
+  var buf = alloc(512)
+  var name = opts.name
+  var prefix = ''
+
+  if (opts.typeflag === 5 && name[name.length - 1] !== '/') name += '/'
+  if (Buffer.byteLength(name) !== name.length) return null // utf-8
+
+  while (Buffer.byteLength(name) > 100) {
+    var i = name.indexOf('/')
+    if (i === -1) return null
+    prefix += prefix ? '/' + name.slice(0, i) : name.slice(0, i)
+    name = name.slice(i + 1)
+  }
+
+  if (Buffer.byteLength(name) > 100 || Buffer.byteLength(prefix) > 155) return null
+  if (opts.linkname && Buffer.byteLength(opts.linkname) > 100) return null
+
+  buf.write(name)
+  buf.write(encodeOct(opts.mode & MASK, 6), 100)
+  buf.write(encodeOct(opts.uid, 6), 108)
+  buf.write(encodeOct(opts.gid, 6), 116)
+  buf.write(encodeOct(opts.size, 11), 124)
+  buf.write(encodeOct((opts.mtime.getTime() / 1000) | 0, 11), 136)
+
+  buf[156] = ZERO_OFFSET + toTypeflag(opts.type)
+
+  if (opts.linkname) buf.write(opts.linkname, 157)
+
+  buf.write(USTAR, 257)
+  if (opts.uname) buf.write(opts.uname, 265)
+  if (opts.gname) buf.write(opts.gname, 297)
+  buf.write(encodeOct(opts.devmajor || 0, 6), 329)
+  buf.write(encodeOct(opts.devminor || 0, 6), 337)
+
+  if (prefix) buf.write(prefix, 345)
+
+  buf.write(encodeOct(cksum(buf), 6), 148)
+
+  return buf
+}
+
+exports.decode = function (buf, filenameEncoding) {
+  var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET
+
+  var name = decodeStr(buf, 0, 100, filenameEncoding)
+  var mode = decodeOct(buf, 100, 8)
+  var uid = decodeOct(buf, 108, 8)
+  var gid = decodeOct(buf, 116, 8)
+  var size = decodeOct(buf, 124, 12)
+  var mtime = decodeOct(buf, 136, 12)
+  var type = toType(typeflag)
+  var linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100, filenameEncoding)
+  var uname = decodeStr(buf, 265, 32)
+  var gname = decodeStr(buf, 297, 32)
+  var devmajor = decodeOct(buf, 329, 8)
+  var devminor = decodeOct(buf, 337, 8)
+
+  if (buf[345]) name = decodeStr(buf, 345, 155, filenameEncoding) + '/' + name
+
+  // to support old tar versions that use trailing / to indicate dirs
+  if (typeflag === 0 && name && name[name.length - 1] === '/') typeflag = 5
+
+  var c = cksum(buf)
+
+  // checksum is still initial value if header was null.
+  if (c === 8 * 32) return null
+
+  // valid checksum
+  if (c !== decodeOct(buf, 148, 8)) throw new Error('Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?')
+
+  return {
+    name: name,
+    mode: mode,
+    uid: uid,
+    gid: gid,
+    size: size,
+    mtime: new Date(1000 * mtime),
+    type: type,
+    linkname: linkname,
+    uname: uname,
+    gname: gname,
+    devmajor: devmajor,
+    devminor: devminor
+  }
+}
diff --git a/input_devices/mag/node_modules/tar-stream/index.js b/input_devices/mag/node_modules/tar-stream/index.js
new file mode 100644
index 00000000..64817048
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-stream/index.js
@@ -0,0 +1,2 @@
+exports.extract = require('./extract')
+exports.pack = require('./pack')
diff --git a/input_devices/mag/node_modules/tar-stream/pack.js b/input_devices/mag/node_modules/tar-stream/pack.js
new file mode 100644
index 00000000..72d96a0c
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-stream/pack.js
@@ -0,0 +1,255 @@
+var constants = require('fs-constants')
+var eos = require('end-of-stream')
+var util = require('util')
+var alloc = require('buffer-alloc')
+var toBuffer = require('to-buffer')
+
+var Readable = require('readable-stream').Readable
+var Writable = require('readable-stream').Writable
+var StringDecoder = require('string_decoder').StringDecoder
+
+var headers = require('./headers')
+
+var DMODE = parseInt('755', 8)
+var FMODE = parseInt('644', 8)
+
+var END_OF_TAR = alloc(1024)
+
+var noop = function () {}
+
+var overflow = function (self, size) {
+  size &= 511
+  if (size) self.push(END_OF_TAR.slice(0, 512 - size))
+}
+
+function modeToType (mode) {
+  switch (mode & constants.S_IFMT) {
+    case constants.S_IFBLK: return 'block-device'
+    case constants.S_IFCHR: return 'character-device'
+    case constants.S_IFDIR: return 'directory'
+    case constants.S_IFIFO: return 'fifo'
+    case constants.S_IFLNK: return 'symlink'
+  }
+
+  return 'file'
+}
+
+var Sink = function (to) {
+  Writable.call(this)
+  this.written = 0
+  this._to = to
+  this._destroyed = false
+}
+
+util.inherits(Sink, Writable)
+
+Sink.prototype._write = function (data, enc, cb) {
+  this.written += data.length
+  if (this._to.push(data)) return cb()
+  this._to._drain = cb
+}
+
+Sink.prototype.destroy = function () {
+  if (this._destroyed) return
+  this._destroyed = true
+  this.emit('close')
+}
+
+var LinkSink = function () {
+  Writable.call(this)
+  this.linkname = ''
+  this._decoder = new StringDecoder('utf-8')
+  this._destroyed = false
+}
+
+util.inherits(LinkSink, Writable)
+
+LinkSink.prototype._write = function (data, enc, cb) {
+  this.linkname += this._decoder.write(data)
+  cb()
+}
+
+LinkSink.prototype.destroy = function () {
+  if (this._destroyed) return
+  this._destroyed = true
+  this.emit('close')
+}
+
+var Void = function () {
+  Writable.call(this)
+  this._destroyed = false
+}
+
+util.inherits(Void, Writable)
+
+Void.prototype._write = function (data, enc, cb) {
+  cb(new Error('No body allowed for this entry'))
+}
+
+Void.prototype.destroy = function () {
+  if (this._destroyed) return
+  this._destroyed = true
+  this.emit('close')
+}
+
+var Pack = function (opts) {
+  if (!(this instanceof Pack)) return new Pack(opts)
+  Readable.call(this, opts)
+
+  this._drain = noop
+  this._finalized = false
+  this._finalizing = false
+  this._destroyed = false
+  this._stream = null
+}
+
+util.inherits(Pack, Readable)
+
+Pack.prototype.entry = function (header, buffer, callback) {
+  if (this._stream) throw new Error('already piping an entry')
+  if (this._finalized || this._destroyed) return
+
+  if (typeof buffer === 'function') {
+    callback = buffer
+    buffer = null
+  }
+
+  if (!callback) callback = noop
+
+  var self = this
+
+  if (!header.size || header.type === 'symlink') header.size = 0
+  if (!header.type) header.type = modeToType(header.mode)
+  if (!header.mode) header.mode = header.type === 'directory' ? DMODE : FMODE
+  if (!header.uid) header.uid = 0
+  if (!header.gid) header.gid = 0
+  if (!header.mtime) header.mtime = new Date()
+
+  if (typeof buffer === 'string') buffer = toBuffer(buffer)
+  if (Buffer.isBuffer(buffer)) {
+    header.size = buffer.length
+    this._encode(header)
+    this.push(buffer)
+    overflow(self, header.size)
+    process.nextTick(callback)
+    return new Void()
+  }
+
+  if (header.type === 'symlink' && !header.linkname) {
+    var linkSink = new LinkSink()
+    eos(linkSink, function (err) {
+      if (err) { // stream was closed
+        self.destroy()
+        return callback(err)
+      }
+
+      header.linkname = linkSink.linkname
+      self._encode(header)
+      callback()
+    })
+
+    return linkSink
+  }
+
+  this._encode(header)
+
+  if (header.type !== 'file' && header.type !== 'contiguous-file') {
+    process.nextTick(callback)
+    return new Void()
+  }
+
+  var sink = new Sink(this)
+
+  this._stream = sink
+
+  eos(sink, function (err) {
+    self._stream = null
+
+    if (err) { // stream was closed
+      self.destroy()
+      return callback(err)
+    }
+
+    if (sink.written !== header.size) { // corrupting tar
+      self.destroy()
+      return callback(new Error('size mismatch'))
+    }
+
+    overflow(self, header.size)
+    if (self._finalizing) self.finalize()
+    callback()
+  })
+
+  return sink
+}
+
+Pack.prototype.finalize = function () {
+  if (this._stream) {
+    this._finalizing = true
+    return
+  }
+
+  if (this._finalized) return
+  this._finalized = true
+  this.push(END_OF_TAR)
+  this.push(null)
+}
+
+Pack.prototype.destroy = function (err) {
+  if (this._destroyed) return
+  this._destroyed = true
+
+  if (err) this.emit('error', err)
+  this.emit('close')
+  if (this._stream && this._stream.destroy) this._stream.destroy()
+}
+
+Pack.prototype._encode = function (header) {
+  if (!header.pax) {
+    var buf = headers.encode(header)
+    if (buf) {
+      this.push(buf)
+      return
+    }
+  }
+  this._encodePax(header)
+}
+
+Pack.prototype._encodePax = function (header) {
+  var paxHeader = headers.encodePax({
+    name: header.name,
+    linkname: header.linkname,
+    pax: header.pax
+  })
+
+  var newHeader = {
+    name: 'PaxHeader',
+    mode: header.mode,
+    uid: header.uid,
+    gid: header.gid,
+    size: paxHeader.length,
+    mtime: header.mtime,
+    type: 'pax-header',
+    linkname: header.linkname && 'PaxHeader',
+    uname: header.uname,
+    gname: header.gname,
+    devmajor: header.devmajor,
+    devminor: header.devminor
+  }
+
+  this.push(headers.encode(newHeader))
+  this.push(paxHeader)
+  overflow(this, paxHeader.length)
+
+  newHeader.size = header.size
+  newHeader.type = header.type
+  this.push(headers.encode(newHeader))
+}
+
+Pack.prototype._read = function (n) {
+  var drain = this._drain
+  this._drain = noop
+  drain()
+}
+
+module.exports = Pack
diff --git a/input_devices/mag/node_modules/tar-stream/package.json b/input_devices/mag/node_modules/tar-stream/package.json
new file mode 100644
index 00000000..4c1f0689
--- /dev/null
+++ b/input_devices/mag/node_modules/tar-stream/package.json
@@ -0,0 +1,119 @@
+{
+  "_args": [
+    [
+      "tar-stream@^1.1.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-fs"
+    ]
+  ],
+  "_from": "tar-stream@>=1.1.2 <2.0.0",
+  "_hasShrinkwrap": false,
+  "_id": "tar-stream@1.6.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/tar-stream",
+  "_nodeVersion": "10.11.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/tar-stream_1.6.2_1537619777167_0.6014045653605695"
+  },
+  "_npmUser": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "mafintosh"
+  },
+  "_npmVersion": "6.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "tar-stream",
+    "raw": "tar-stream@^1.1.2",
+    "rawSpec": "^1.1.2",
+    "scope": null,
+    "spec": ">=1.1.2 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-fs"
+  ],
+  "_resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
+  "_shasum": "8ea55dab37972253d9a9af90fdcd559ae435c555",
+  "_shrinkwrap": null,
+  "_spec": "tar-stream@^1.1.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-fs",
+  "author": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "Mathias Buus"
+  },
+  "bugs": {
+    "url": "https://github.com/mafintosh/tar-stream/issues"
+  },
+  "dependencies": {
+    "bl": "^1.0.0",
+    "buffer-alloc": "^1.2.0",
+    "end-of-stream": "^1.0.0",
+    "fs-constants": "^1.0.0",
+    "readable-stream": "^2.3.0",
+    "to-buffer": "^1.1.1",
+    "xtend": "^4.0.0"
+  },
+  "description": "tar-stream is a streaming tar parser and generator and nothing else. It is streams2 and operates purely using streams which means you can easily extract/parse tarballs without ever hitting the file system.",
+  "devDependencies": {
+    "concat-stream": "^1.6.2",
+    "standard": "^11.0.1",
+    "tape": "^4.9.0"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "dist": {
+    "fileCount": 7,
+    "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbpjdBCRA9TVsSAnZWagAA6qMP/2NLa3eMJBbvkSu6C+bD\n6dCiNPs5Y01QcivkSgtlTHBH2MT/kdOpUUV0S8Rgn++sIwNXKsPp+QJ+YPmW\n8Gb8PY35GwA/FHeMJ6hXKxcov96somIJ+lTsHvxeZxqB08fGvsGYMgTCqNfX\nVw8HA5cBC80t50cYWXKv8yVBqVBwJcIxEqJMdokx3ABbgJXvJM5zQiFGH+0m\n1QkNFUcOhAWGcUfZ144rMp/Pl5zvb94sGr2295FDlQDK4PUzh1FrE4HapF6Y\nRXBqV4TklnlWvHFHjI5+F8ziXBNKBa18fDWvHz9qICD92Ml2+vgkjFdGcqsB\nhRFjDfJmGEQOpkloMR60HPbXijLJNrnC1PG6TnM5z6fOLZukeojwAQ1EbbNm\nUO8EwoMIJ9dbbdycOLSGkEGZGh2GImMRzyFHwhnUg3qELkxG1nyQehB6+UBC\ntTlXQIDPKAjW4fsl2NBEDU1m814cxOqb0XTh+jmy2JbZBqX+qSIe3kFEdcNo\n8N5WP6BfkHK57T09N2QZkn1PIK6ldsjLiWhNZpuBeYwpBzfLkixA4mYPzDV0\nI3fVKHdSZUn5HKbpSRM+YKe9XIY0fORUZpZBjfg/eOxXxDfgXTYxls2GBZMi\nThTAxj40vKKE0W/qsSLP0GRSgDcnL0hHr+lM9JIJtZfvh698ehAgs3zGWMs3\nEAaa\r\n=Lqwy\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "8ea55dab37972253d9a9af90fdcd559ae435c555",
+    "tarball": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
+    "unpackedSize": 26782
+  },
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "gitHead": "a9927c7c989dc5ee2f16d1d9e27a1c028c9de708",
+  "homepage": "https://github.com/mafintosh/tar-stream",
+  "keywords": [
+    "extract",
+    "generate",
+    "generator",
+    "modify",
+    "pack",
+    "parse",
+    "parser",
+    "stream",
+    "stream2",
+    "streaming",
+    "streams",
+    "streams2",
+    "tar",
+    "tarball"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    },
+    {
+      "name": "maxogden",
+      "email": "max@maxogden.com"
+    }
+  ],
+  "name": "tar-stream",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/mafintosh/tar-stream.git"
+  },
+  "scripts": {
+    "test": "standard && tape test/extract.js test/pack.js",
+    "test-all": "standard && tape test/*.js"
+  },
+  "version": "1.6.2"
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/LICENSE b/input_devices/mag/node_modules/terminal-paginator/LICENSE
new file mode 100644
index 00000000..b11cb796
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/terminal-paginator/README.md b/input_devices/mag/node_modules/terminal-paginator/README.md
new file mode 100644
index 00000000..0a6d9285
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/README.md
@@ -0,0 +1,70 @@
+# terminal-paginator [![NPM version](https://img.shields.io/npm/v/terminal-paginator.svg?style=flat)](https://www.npmjs.com/package/terminal-paginator) [![NPM monthly downloads](https://img.shields.io/npm/dm/terminal-paginator.svg?style=flat)](https://npmjs.org/package/terminal-paginator) [![NPM total downloads](https://img.shields.io/npm/dt/terminal-paginator.svg?style=flat)](https://npmjs.org/package/terminal-paginator)
+
+> Paginator used for rendering lists or choices for prompts in the terminal.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save terminal-paginator
+```
+
+## Usage
+
+```js
+var Paginator = require('terminal-paginator');
+var paginator = new Paginator();
+paginator.paginate(string, selectedIndex, pageLimit);
+```
+
+## Attribution
+
+Based on the Paginator in Inquirer.
+
+## About
+
+### Related projects
+
+* [choices-separator](https://www.npmjs.com/package/choices-separator): Separator for choices arrays in prompts. Based on the Separator from inquirer. | [homepage](https://github.com/enquirer/choices-separator "Separator for choices arrays in prompts. Based on the Separator from inquirer.")
+* [enquirer](https://www.npmjs.com/package/enquirer): Intuitive, plugin-based prompt system for node.js. Much faster and lighter alternative to Inquirer, with all… [more](https://github.com/enquirer/enquirer) | [homepage](https://github.com/enquirer/enquirer "Intuitive, plugin-based prompt system for node.js. Much faster and lighter alternative to Inquirer, with all the same prompt types and more, but without the bloat.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+* [readline-utils](https://www.npmjs.com/package/readline-utils): Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more. | [homepage](https://github.com/enquirer/readline-utils "Readline utils, for moving the cursor, clearing lines, creating a readline interface, and more.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 24, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/terminal-paginator/index.js b/input_devices/mag/node_modules/terminal-paginator/index.js
new file mode 100644
index 00000000..5b976bf5
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/index.js
@@ -0,0 +1,86 @@
+'use strict';
+
+var debug = require('debug')('terminal-paginator');
+var extend = require('extend-shallow');
+var log = require('log-utils');
+
+/**
+ * The paginator keeps track of a position index in a list
+ * and returns a subset of the choices if the list is too
+ * long.
+ */
+
+function Paginator(options) {
+  debug('initializing from <%s>', __filename);
+  this.options = options || {};
+  this.footer = this.options.footer;
+  if (typeof this.footer !== 'string') {
+    this.footer = '(Move up and down to reveal more choices)';
+  }
+  this.firstRender = true;
+  this.lastIndex = 0;
+  this.position = 0;
+}
+
+/**
+ * Paginate the given `output` string and update the cursor position.
+ *
+ * @param {String} `output`
+ * @param {Number} `pos`
+ * @param {Object} `options`
+ * @return {String}
+ * @api public
+ */
+
+Paginator.prototype.paginate = function(output, pos, options) {
+  var opts = extend({limit: 7}, this.options, options);
+  var lines = output.split('\n');
+  var limit = opts.limit;
+
+  // Return if we don't have enough visible lines to paginate
+  if (lines.length <= limit || opts.paginate === false) {
+    return output;
+  }
+
+  // get the approximate "middle" of the visible list
+  var middle = Math.floor(limit / 2);
+
+  // Move the position when a down keypress is entered, and limit
+  // it to approximately half the length of the limit to keep the
+  // position the middle of the visible list
+  if (this.position < middle && this.lastIndex < pos && pos - this.lastIndex < limit) {
+    this.position = Math.min(middle, this.position + pos - this.lastIndex);
+  }
+
+  // store reference to the index of the currently pos item
+  this.lastIndex = pos;
+
+  // Duplicate lines to create the illusion of an infinite list
+  var infinite = lines.concat(lines).concat(lines);
+  if (opts.filterList !== false) {
+    infinite = infinite.filter(Boolean);
+  }
+
+  var topIndex = Math.max(0, pos + lines.length - this.position - 1);
+
+  // Create the visible list based on the limit and current cursor position
+  var visible = infinite.splice(topIndex, limit).join('\n');
+  if (this.footer) {
+    visible += '\n';
+    visible += log.dim(this.footer);
+  }
+
+  // ensure that output has a leading newline, so that the first
+  // list item begins on the next line after the prompt question
+  if (visible.charAt(0) !== '\n') {
+    visible = '\n' + visible;
+  }
+
+  return visible;
+};
+
+/**
+ * Expose `Paginator`
+ */
+
+module.exports = Paginator;
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.coveralls.yml b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.eslintrc b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+  "rules": {
+    "no-console": 0,
+    "no-empty": [1, { "allowEmptyCatch": true }]
+  },
+  "extends": "eslint:recommended"
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.npmignore b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.travis.yml b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+  - "6"
+  - "5"
+  - "4"
+
+install:
+  - make node_modules
+
+script:
+  - make lint
+  - make test
+  - make coveralls
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/CHANGELOG.md b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+  * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+  * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+  * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+  * Fix: Inline extend function in node implementation (#452, @dougwilson)
+  * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+  
+  * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+  * Misc: clean up browser reference checks (#447, @thebigredgeek)
+  * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+  * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+  * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+  * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+  * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+  * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+  * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+  * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+  * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+  * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+  * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+  * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+  * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+  * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+  * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+  * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+  * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+  * Docs: fixed README typo (#391, @lurch)
+  * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+  * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+  * Fix: wrong reference in bower file (@thebigredgeek)
+  * Fix: webworker compatibility (@thebigredgeek)
+  * Fix: output formatting issue (#388, @kribblo)
+  * Fix: babel-loader compatibility (#383, @escwald)
+  * Misc: removed built asset from repo and publications (@thebigredgeek)
+  * Misc: moved source files to /src (#378, @yamikuronue)
+  * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+  * Test: coveralls integration (#378, @yamikuronue)
+  * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+  * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+  * Fix: custom log function (#379, @hsiliev)
+  * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+  * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+  * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+  * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+  * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+  * Fix: browser colors (#367, @tootallnate)
+  * Misc: travis ci integration (@thebigredgeek)
+  * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+  * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+  * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+  * Fix: revert "handle regex special characters" (@tootallnate)
+  * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+  * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+  * Improvement: allow colors in workers (#335, @botverse)
+  * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+  * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+  * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+  * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+  * Fix: be super-safe in index.js as well (@TooTallNate)
+  * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+  * Fix: Added electron compatibility (#324, @paulcbetts)
+  * Improvement: Added performance optimizations (@tootallnate)
+  * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+  * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+  * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+  * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+  * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+  * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+  * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+  * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+  * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+  * Readme: fix USE_COLORS to DEBUG_COLORS
+  * Readme: Doc fixes for format string sugar (#269, @mlucool)
+  * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+  * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+  * Readme: better docs for browser support (#224, @matthewmueller)
+  * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+  * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+  * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+  * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+  * package: update "ms" to v0.7.1 (#202, @dougwilson)
+  * README: add logging to file example (#193, @DanielOchoa)
+  * README: fixed a typo (#191, @amir-s)
+  * browser: expose `storage` (#190, @stephenmathieson)
+  * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+  * Updated stdout/stderr example (#186)
+  * Updated example/stdout.js to match debug current behaviour
+  * Renamed example/stderr.js to stdout.js
+  * Update Readme.md (#184)
+  * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+  * dist: recompile
+  * update "ms" to v0.7.0
+  * package: update "browserify" to v9.0.3
+  * component: fix "ms.js" repo location
+  * changed bower package name
+  * updated documentation about using debug in a browser
+  * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+  * browser: use `typeof` to check for `console` existence
+  * browser: check for `console.log` truthiness (fix IE 8/9)
+  * browser: add support for Chrome apps
+  * Readme: added Windows usage remarks
+  * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+  * node: implement `DEBUG_FD` env variable support
+  * package: update "browserify" to v6.1.0
+  * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+  * package: update "browserify" to v5.11.0
+  * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+  * dist: recompile
+  * example: remove `console.info()` log usage
+  * example: add "Content-Type" UTF-8 header to browser example
+  * browser: place %c marker after the space character
+  * browser: reset the "content" color via `color: inherit`
+  * browser: add colors support for Firefox >= v31
+  * debug: prefer an instance `log()` function over the global one (#119)
+  * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+  * Add support for multiple wildcards in namespaces (#122, @seegno)
+  * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+  * browser: update color palette (#113, @gscottolson)
+  * common: make console logging function configurable (#108, @timoxley)
+  * node: fix %o colors on old node <= 0.8.x
+  * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+  * browser: use `removeItem()` to clear localStorage
+  * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+  * package: add "contributors" section
+  * node: fix comment typo
+  * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+  * make ms diff be global, not be scope
+  * debug: ignore empty strings in enable()
+  * node: make DEBUG_COLORS able to disable coloring
+  * *: export the `colors` array
+  * npmignore: don't publish the `dist` dir
+  * Makefile: refactor to use browserify
+  * package: add "browserify" as a dev dependency
+  * Readme: add Web Inspector Colors section
+  * node: reset terminal color for the debug content
+  * node: map "%o" to `util.inspect()`
+  * browser: map "%j" to `JSON.stringify()`
+  * debug: add custom "formatters"
+  * debug: use "ms" module for humanizing the diff
+  * Readme: add "bash" syntax highlighting
+  * browser: add Firebug color support
+  * browser: add colors for WebKit browsers
+  * node: apply log to `console`
+  * rewrite: abstract common logic for Node & browsers
+  * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+  * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+  * add `enable()` method for nodejs. Closes #27
+  * change from stderr to stdout
+  * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+  * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+  * fix: catch localStorage security error when cookies are blocked (Chrome)
+  * add debug(err) support. Closes #46
+  * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/LICENSE b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
+
+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/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/Makefile b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+	@NODE_ENV= $(PKG) install
+	@touch node_modules
+
+lint: .FORCE
+	eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+	istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+	mkdir -p dist
+
+	@$(BROWSERIFY) \
+		--standalone debug \
+		. > dist/debug.js
+
+	karma start --single-run
+	rimraf dist
+
+test: .FORCE
+	concurrently \
+		"make test-node" \
+		"make test-browser"
+
+coveralls:
+	cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/README.md b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug)  [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)  [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) 
+[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+  ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+
+## Conventions
+
+  If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+  The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+  When running through Node.js, you can set a few environment variables that will
+  change the behavior of the debug logging:
+
+| Name      | Purpose                                         |
+|-----------|-------------------------------------------------|
+| `DEBUG`   | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+  __Note:__ The environment variables beginning with `DEBUG_` end up being
+  converted into an Options object that gets used with `%o`/`%O` formatters.
+  See the Node.js documentation for
+  [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+  for the complete list.
+
+## Formatters
+
+
+  Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O`      | Pretty-print an Object on multiple lines. |
+| `%o`      | Pretty-print an Object all on a single line. |
+| `%s`      | String. |
+| `%d`      | Number (both integer and float). |
+| `%j`      | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%`      | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+  You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+  return v.toString('hex')
+}
+
+// …elsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+//   foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+  You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+  or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+  if you don't want to build it yourself.
+
+  Debug's enable state is currently persisted by `localStorage`.
+  Consider the situation shown below where you have `worker:a` and `worker:b`,
+  and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+  Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+  option. These are WebKit web inspectors, Firefox ([since version
+  31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+  and the Firebug plugin for Firefox (any version).
+
+  Colored output looks something like:
+
+  ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
+
+
+## Output streams
+
+  By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+ 
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
+<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/component.json b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+  "name": "debug",
+  "repo": "visionmedia/debug",
+  "description": "small debugging utility",
+  "version": "2.6.9",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "main": "src/browser.js",
+  "scripts": [
+    "src/browser.js",
+    "src/debug.js"
+  ],
+  "dependencies": {
+    "rauchg/ms.js": "0.7.1"
+  }
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/karma.conf.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['mocha', 'chai', 'sinon'],
+
+
+    // list of files / patterns to load in the browser
+    files: [
+      'dist/debug.js',
+      'test/*spec.js'
+    ],
+
+
+    // list of files to exclude
+    exclude: [
+      'src/node.js'
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['progress'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false,
+
+    // Concurrency level
+    // how many browser should be started simultaneous
+    concurrency: Infinity
+  })
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/node.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/package.json b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/package.json
new file mode 100644
index 00000000..79aca6d8
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/package.json
@@ -0,0 +1,128 @@
+{
+  "_args": [
+    [
+      "debug@^2.6.6",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/terminal-paginator"
+    ]
+  ],
+  "_from": "debug@>=2.6.6 <3.0.0",
+  "_id": "debug@2.6.9",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/terminal-paginator/debug",
+  "_nodeVersion": "8.4.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196"
+  },
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "5.3.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "debug",
+    "raw": "debug@^2.6.6",
+    "rawSpec": "^2.6.6",
+    "scope": null,
+    "spec": ">=2.6.6 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/terminal-paginator"
+  ],
+  "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+  "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+  "_shrinkwrap": null,
+  "_spec": "debug@^2.6.6",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/terminal-paginator",
+  "author": {
+    "email": "tj@vision-media.ca",
+    "name": "TJ Holowaychuk"
+  },
+  "browser": "./src/browser.js",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "component": {
+    "scripts": {
+      "debug/debug.js": "debug.js",
+      "debug/index.js": "browser.js"
+    }
+  },
+  "contributors": [
+    {
+      "name": "Nathan Rajlich",
+      "email": "nathan@tootallnate.net",
+      "url": "http://n8.io"
+    },
+    {
+      "name": "Andrew Rhyne",
+      "email": "rhyneandrew@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "ms": "2.0.0"
+  },
+  "description": "small debugging utility",
+  "devDependencies": {
+    "browserify": "9.0.3",
+    "chai": "^3.5.0",
+    "concurrently": "^3.1.0",
+    "coveralls": "^2.11.15",
+    "eslint": "^3.12.1",
+    "istanbul": "^0.4.5",
+    "karma": "^1.3.0",
+    "karma-chai": "^0.1.0",
+    "karma-mocha": "^1.3.0",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "karma-sinon": "^1.0.5",
+    "mocha": "^3.2.0",
+    "mocha-lcov-reporter": "^1.2.0",
+    "rimraf": "^2.5.4",
+    "sinon": "^1.17.6",
+    "sinon-chai": "^2.8.0"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+    "shasum": "5d128515df134ff327e90a4c93f4e077a536341f",
+    "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
+  },
+  "gitHead": "13abeae468fea297d0dccc50bc55590809241083",
+  "homepage": "https://github.com/visionmedia/debug#readme",
+  "keywords": [
+    "debug",
+    "debugger",
+    "log"
+  ],
+  "license": "MIT",
+  "main": "./src/index.js",
+  "maintainers": [
+    {
+      "name": "thebigredgeek",
+      "email": "rhyneandrew@gmail.com"
+    },
+    {
+      "name": "kolban",
+      "email": "kolban1@kolban.com"
+    },
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    },
+    {
+      "name": "tjholowaychuk",
+      "email": "tj@vision-media.ca"
+    }
+  ],
+  "name": "debug",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "version": "2.6.9"
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/browser.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+               && 'undefined' != typeof chrome.storage
+                  ? chrome.storage.local
+                  : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+  'lightseagreen',
+  'forestgreen',
+  'goldenrod',
+  'dodgerblue',
+  'darkorchid',
+  'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+  // NB: In an Electron preload script, document will be defined but not fully
+  // initialized. Since we know we're in Chrome, we'll just detect this case
+  // explicitly
+  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+    return true;
+  }
+
+  // is webkit? http://stackoverflow.com/a/16459606/376773
+  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+    // is firebug? http://stackoverflow.com/a/398120/376773
+    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+    // is firefox >= v31?
+    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+    // double check webkit in userAgent just in case we are in a worker
+    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+  try {
+    return JSON.stringify(v);
+  } catch (err) {
+    return '[UnexpectedJSONParseError]: ' + err.message;
+  }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var useColors = this.useColors;
+
+  args[0] = (useColors ? '%c' : '')
+    + this.namespace
+    + (useColors ? ' %c' : ' ')
+    + args[0]
+    + (useColors ? '%c ' : ' ')
+    + '+' + exports.humanize(this.diff);
+
+  if (!useColors) return;
+
+  var c = 'color: ' + this.color;
+  args.splice(1, 0, c, 'color: inherit')
+
+  // the final "%c" is somewhat tricky, because there could be other
+  // arguments passed either before or after the %c, so we need to
+  // figure out the correct index to insert the CSS into
+  var index = 0;
+  var lastC = 0;
+  args[0].replace(/%[a-zA-Z%]/g, function(match) {
+    if ('%%' === match) return;
+    index++;
+    if ('%c' === match) {
+      // we only are interested in the *last* %c
+      // (the user may have provided their own)
+      lastC = index;
+    }
+  });
+
+  args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+  // this hackery is required for IE8/9, where
+  // the `console.log` function doesn't have 'apply'
+  return 'object' === typeof console
+    && console.log
+    && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  try {
+    if (null == namespaces) {
+      exports.storage.removeItem('debug');
+    } else {
+      exports.storage.debug = namespaces;
+    }
+  } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  var r;
+  try {
+    r = exports.storage.debug;
+  } catch(e) {}
+
+  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+  if (!r && typeof process !== 'undefined' && 'env' in process) {
+    r = process.env.DEBUG;
+  }
+
+  return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+  try {
+    return window.localStorage;
+  } catch (e) {}
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/debug.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+  var hash = 0, i;
+
+  for (i in namespace) {
+    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
+    hash |= 0; // Convert to 32bit integer
+  }
+
+  return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+  function debug() {
+    // disabled?
+    if (!debug.enabled) return;
+
+    var self = debug;
+
+    // set `diff` timestamp
+    var curr = +new Date();
+    var ms = curr - (prevTime || curr);
+    self.diff = ms;
+    self.prev = prevTime;
+    self.curr = curr;
+    prevTime = curr;
+
+    // turn the `arguments` into a proper Array
+    var args = new Array(arguments.length);
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i];
+    }
+
+    args[0] = exports.coerce(args[0]);
+
+    if ('string' !== typeof args[0]) {
+      // anything else let's inspect with %O
+      args.unshift('%O');
+    }
+
+    // apply any `formatters` transformations
+    var index = 0;
+    args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+      // if we encounter an escaped % then don't increase the array index
+      if (match === '%%') return match;
+      index++;
+      var formatter = exports.formatters[format];
+      if ('function' === typeof formatter) {
+        var val = args[index];
+        match = formatter.call(self, val);
+
+        // now we need to remove `args[index]` since it's inlined in the `format`
+        args.splice(index, 1);
+        index--;
+      }
+      return match;
+    });
+
+    // apply env-specific formatting (colors, etc.)
+    exports.formatArgs.call(self, args);
+
+    var logFn = debug.log || exports.log || console.log.bind(console);
+    logFn.apply(self, args);
+  }
+
+  debug.namespace = namespace;
+  debug.enabled = exports.enabled(namespace);
+  debug.useColors = exports.useColors();
+  debug.color = selectColor(namespace);
+
+  // env-specific initialization logic for debug instances
+  if ('function' === typeof exports.init) {
+    exports.init(debug);
+  }
+
+  return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+  exports.save(namespaces);
+
+  exports.names = [];
+  exports.skips = [];
+
+  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+  var len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    if (!split[i]) continue; // ignore empty strings
+    namespaces = split[i].replace(/\*/g, '.*?');
+    if (namespaces[0] === '-') {
+      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+    } else {
+      exports.names.push(new RegExp('^' + namespaces + '$'));
+    }
+  }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+  exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+  var i, len;
+  for (i = 0, len = exports.skips.length; i < len; i++) {
+    if (exports.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (i = 0, len = exports.names.length; i < len; i++) {
+    if (exports.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+  if (val instanceof Error) return val.stack || val.message;
+  return val;
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/index.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+  module.exports = require('./browser.js');
+} else {
+  module.exports = require('./node.js');
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/inspector-log.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+  const stdout = console._stdout;
+  console._stdout = nullStream;
+  console.log.apply(console, arguments);
+  console._stdout = stdout;
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/node.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+  return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+  // camel-case
+  var prop = key
+    .substring(6)
+    .toLowerCase()
+    .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+  // coerce string value into JS value
+  var val = process.env[key];
+  if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+  else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+  else if (val === 'null') val = null;
+  else val = Number(val);
+
+  obj[prop] = val;
+  return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ *   $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+  util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+             2 === fd ? process.stderr :
+             createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+  return 'colors' in exports.inspectOpts
+    ? Boolean(exports.inspectOpts.colors)
+    : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts)
+    .split('\n').map(function(str) {
+      return str.trim()
+    }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+  this.inspectOpts.colors = this.useColors;
+  return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+  var name = this.namespace;
+  var useColors = this.useColors;
+
+  if (useColors) {
+    var c = this.color;
+    var prefix = '  \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+    args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+    args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+  } else {
+    args[0] = new Date().toUTCString()
+      + ' ' + name + ' ' + args[0];
+  }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+  return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+  if (null == namespaces) {
+    // If you set a process.env field to null or undefined, it gets cast to the
+    // string 'null' or 'undefined'. Just delete instead.
+    delete process.env.DEBUG;
+  } else {
+    process.env.DEBUG = namespaces;
+  }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+  return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+  var stream;
+  var tty_wrap = process.binding('tty_wrap');
+
+  // Note stream._type is used for test-module-load-list.js
+
+  switch (tty_wrap.guessHandleType(fd)) {
+    case 'TTY':
+      stream = new tty.WriteStream(fd);
+      stream._type = 'tty';
+
+      // Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    case 'FILE':
+      var fs = require('fs');
+      stream = new fs.SyncWriteStream(fd, { autoClose: false });
+      stream._type = 'fs';
+      break;
+
+    case 'PIPE':
+    case 'TCP':
+      var net = require('net');
+      stream = new net.Socket({
+        fd: fd,
+        readable: false,
+        writable: true
+      });
+
+      // FIXME Should probably have an option in net.Socket to create a
+      // stream from an existing fd which is writable only. But for now
+      // we'll just add this hack and set the `readable` member to false.
+      // Test: ./node test/fixtures/echo.js < /etc/passwd
+      stream.readable = false;
+      stream.read = null;
+      stream._type = 'pipe';
+
+      // FIXME Hack to have stream not keep the event loop alive.
+      // See https://github.com/joyent/node/issues/1726
+      if (stream._handle && stream._handle.unref) {
+        stream._handle.unref();
+      }
+      break;
+
+    default:
+      // Probably an error on in uv_guess_handle()
+      throw new Error('Implement me. Unknown stream file type!');
+  }
+
+  // For supporting legacy API we put the FD here.
+  stream.fd = fd;
+
+  stream._isStdio = true;
+
+  return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+  debug.inspectOpts = {};
+
+  var keys = Object.keys(exports.inspectOpts);
+  for (var i = 0; i < keys.length; i++) {
+    debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+  }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/index.js b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ *  - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+  options = options || {};
+  var type = typeof val;
+  if (type === 'string' && val.length > 0) {
+    return parse(val);
+  } else if (type === 'number' && isNaN(val) === false) {
+    return options.long ? fmtLong(val) : fmtShort(val);
+  }
+  throw new Error(
+    'val is not a non-empty string or a valid number. val=' +
+      JSON.stringify(val)
+  );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+  str = String(str);
+  if (str.length > 100) {
+    return;
+  }
+  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+    str
+  );
+  if (!match) {
+    return;
+  }
+  var n = parseFloat(match[1]);
+  var type = (match[2] || 'ms').toLowerCase();
+  switch (type) {
+    case 'years':
+    case 'year':
+    case 'yrs':
+    case 'yr':
+    case 'y':
+      return n * y;
+    case 'days':
+    case 'day':
+    case 'd':
+      return n * d;
+    case 'hours':
+    case 'hour':
+    case 'hrs':
+    case 'hr':
+    case 'h':
+      return n * h;
+    case 'minutes':
+    case 'minute':
+    case 'mins':
+    case 'min':
+    case 'm':
+      return n * m;
+    case 'seconds':
+    case 'second':
+    case 'secs':
+    case 'sec':
+    case 's':
+      return n * s;
+    case 'milliseconds':
+    case 'millisecond':
+    case 'msecs':
+    case 'msec':
+    case 'ms':
+      return n;
+    default:
+      return undefined;
+  }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+  if (ms >= d) {
+    return Math.round(ms / d) + 'd';
+  }
+  if (ms >= h) {
+    return Math.round(ms / h) + 'h';
+  }
+  if (ms >= m) {
+    return Math.round(ms / m) + 'm';
+  }
+  if (ms >= s) {
+    return Math.round(ms / s) + 's';
+  }
+  return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+  return plural(ms, d, 'day') ||
+    plural(ms, h, 'hour') ||
+    plural(ms, m, 'minute') ||
+    plural(ms, s, 'second') ||
+    ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+  if (ms < n) {
+    return;
+  }
+  if (ms < n * 1.5) {
+    return Math.floor(ms / n) + ' ' + name;
+  }
+  return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/license.md b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/package.json b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/package.json
new file mode 100644
index 00000000..52f8f7cb
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/package.json
@@ -0,0 +1,101 @@
+{
+  "_args": [
+    [
+      "ms@2.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/terminal-paginator/node_modules/debug"
+    ]
+  ],
+  "_from": "ms@2.0.0",
+  "_id": "ms@2.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/terminal-paginator/ms",
+  "_nodeVersion": "7.8.0",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945"
+  },
+  "_npmUser": {
+    "email": "leo@zeit.co",
+    "name": "leo"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ms",
+    "raw": "ms@2.0.0",
+    "rawSpec": "2.0.0",
+    "scope": null,
+    "spec": "2.0.0",
+    "type": "version"
+  },
+  "_requiredBy": [
+    "/terminal-paginator/debug"
+  ],
+  "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+  "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+  "_shrinkwrap": null,
+  "_spec": "ms@2.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/terminal-paginator/node_modules/debug",
+  "bugs": {
+    "url": "https://github.com/zeit/ms/issues"
+  },
+  "dependencies": {},
+  "description": "Tiny milisecond conversion utility",
+  "devDependencies": {
+    "eslint": "3.19.0",
+    "expect.js": "0.3.1",
+    "husky": "0.13.3",
+    "lint-staged": "3.4.1",
+    "mocha": "3.4.1"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8",
+    "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
+  },
+  "eslintConfig": {
+    "env": {
+      "es6": true,
+      "node": true
+    },
+    "extends": "eslint:recommended"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4",
+  "homepage": "https://github.com/zeit/ms#readme",
+  "license": "MIT",
+  "lint-staged": {
+    "*.js": [
+      "git add",
+      "npm run lint",
+      "prettier --single-quote --write"
+    ]
+  },
+  "main": "./index",
+  "maintainers": [
+    {
+      "name": "leo",
+      "email": "leo@zeit.co"
+    },
+    {
+      "name": "rauchg",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "name": "ms",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zeit/ms.git"
+  },
+  "scripts": {
+    "lint": "eslint lib/* bin/*",
+    "precommit": "lint-staged",
+    "test": "mocha tests.js"
+  },
+  "version": "2.0.0"
+}
diff --git a/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/readme.md b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days')  // 172800000
+ms('1d')      // 86400000
+ms('10h')     // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h')      // 7200000
+ms('1m')      // 60000
+ms('5s')      // 5000
+ms('1y')      // 31557600000
+ms('100')     // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000)             // "1m"
+ms(2 * 60000)         // "2m"
+ms(ms('10 hours'))    // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true })             // "1 minute"
+ms(2 * 60000, { long: true })         // "2 minutes"
+ms(ms('10 hours'), { long: true })    // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/input_devices/mag/node_modules/terminal-paginator/package.json b/input_devices/mag/node_modules/terminal-paginator/package.json
new file mode 100644
index 00000000..1775d3b9
--- /dev/null
+++ b/input_devices/mag/node_modules/terminal-paginator/package.json
@@ -0,0 +1,139 @@
+{
+  "_args": [
+    [
+      "terminal-paginator@^2.0.2",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "terminal-paginator@>=2.0.2 <3.0.0",
+  "_id": "terminal-paginator@2.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/terminal-paginator",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/terminal-paginator-2.0.2.tgz_1496403826312_0.6634529195725918"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "5.0.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "terminal-paginator",
+    "raw": "terminal-paginator@^2.0.2",
+    "rawSpec": "^2.0.2",
+    "scope": null,
+    "spec": ">=2.0.2 <3.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/terminal-paginator/-/terminal-paginator-2.0.2.tgz",
+  "_shasum": "967e66056f28fe8f55ba7c1eebfb7c3ef371c1d3",
+  "_shrinkwrap": null,
+  "_spec": "terminal-paginator@^2.0.2",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/enquirer/terminal-paginator/issues"
+  },
+  "dependencies": {
+    "debug": "^2.6.6",
+    "extend-shallow": "^2.0.1",
+    "log-utils": "^0.2.1"
+  },
+  "description": "Paginator used for rendering lists or choices for prompts in the terminal.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12"
+  },
+  "directories": {},
+  "dist": {
+    "integrity": "sha512-IZMT5ECF9p4s+sNCV8uvZSW9E1+9zy9Ji9xz2oee8Jfo7hUFpauyjxkhfRcIH6Lu3Wdepv5D1kVRc8Hx74/LfQ==",
+    "shasum": "967e66056f28fe8f55ba7c1eebfb7c3ef371c1d3",
+    "tarball": "https://registry.npmjs.org/terminal-paginator/-/terminal-paginator-2.0.2.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "b1a847a9ffea7de846009acd0efb862c6b84a006",
+  "homepage": "https://github.com/enquirer/terminal-paginator",
+  "keywords": [
+    "answer",
+    "answers",
+    "ask",
+    "checkbox",
+    "choice",
+    "choices",
+    "cli",
+    "command",
+    "enquirer",
+    "enquirerprompt",
+    "input",
+    "inquire",
+    "inquirer",
+    "interact",
+    "list",
+    "menu",
+    "paginator",
+    "password",
+    "prompt",
+    "prompts",
+    "question",
+    "readline",
+    "stdin",
+    "stdout",
+    "terminal",
+    "tty",
+    "ui"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "terminal-paginator",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/enquirer/terminal-paginator.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "choices-separator",
+        "enquirer",
+        "prompt-choices",
+        "readline-utils"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "2.0.2"
+}
diff --git a/input_devices/mag/node_modules/time-stamp/LICENSE b/input_devices/mag/node_modules/time-stamp/LICENSE
new file mode 100644
index 00000000..83b56e70
--- /dev/null
+++ b/input_devices/mag/node_modules/time-stamp/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/time-stamp/README.md b/input_devices/mag/node_modules/time-stamp/README.md
new file mode 100644
index 00000000..a12d3e15
--- /dev/null
+++ b/input_devices/mag/node_modules/time-stamp/README.md
@@ -0,0 +1,132 @@
+# time-stamp [![NPM version](https://img.shields.io/npm/v/time-stamp.svg?style=flat)](https://www.npmjs.com/package/time-stamp) [![NPM monthly downloads](https://img.shields.io/npm/dm/time-stamp.svg?style=flat)](https://npmjs.org/package/time-stamp) [![NPM total downloads](https://img.shields.io/npm/dt/time-stamp.svg?style=flat)](https://npmjs.org/package/time-stamp) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/time-stamp.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/time-stamp)
+
+> Get a formatted timestamp.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save time-stamp
+```
+
+## Usage
+
+```js
+var timestamp = require('time-stamp');
+
+timestamp();
+//=> 2017:05:14
+
+timestamp('YYYYMMDD');
+//=> 20170514
+
+timestamp('YYYYMMDD:ss');
+//=> 20170514:26
+
+timestamp('YYYY/MM/DD:mm:ss');
+//=> 2017/05/14:52:26
+
+timestamp('YYYY:MM:DD');
+//=> 2017:05:14
+
+timestamp('[YYYY:MM:DD]');
+//=> [2017:05:14]
+
+timestamp('YYYY/MM/DD');
+//=> 2017/05/14
+
+timestamp('YYYY:MM');
+//=> 2017:05
+
+timestamp('YYYY');
+//=> 2017
+
+timestamp('MM');
+//=> 05
+
+timestamp('DD');
+//=> 14
+
+timestamp('HH');
+//=> 20
+
+timestamp('mm');
+//=> 52
+
+timestamp('ss');
+//=> 26
+
+timestamp('ms');
+//=> 481
+```
+
+**Valid patterns**
+
+* `YYYY`: full year (ex: **2017**)
+* `MM`: month (ex: **04**)
+* `DD`: day (ex: **01**)
+* `HH`: hours (ex: **12**)
+* `mm`: minutes (ex: **59**)
+* `ss`: seconds (ex: **09**)
+* `ms`: milliseconds (ex: **532**)
+
+## About
+
+### Related projects
+
+* [days](https://www.npmjs.com/package/days): Days of the week. | [homepage](https://github.com/jonschlinkert/days "Days of the week.")
+* [iso-week](https://www.npmjs.com/package/iso-week): Get the ISO week of the year. | [homepage](https://github.com/jonschlinkert/iso-week "Get the ISO week of the year.")
+* [month](https://www.npmjs.com/package/month): Get the name or number of the current month or any month of the year. | [homepage](https://github.com/datetime/month "Get the name or number of the current month or any month of the year.")
+* [months](https://www.npmjs.com/package/months): Months of the year. | [homepage](https://github.com/jonschlinkert/months "Months of the year.")
+* [o-clock](https://www.npmjs.com/package/o-clock): Simple javascript utility for displaying the time in 12-hour clock format. | [homepage](https://github.com/jonschlinkert/o-clock "Simple javascript utility for displaying the time in 12-hour clock format.")
+* [seconds](https://www.npmjs.com/package/seconds): Get the number of seconds for a minute, hour, day and week. | [homepage](https://github.com/jonschlinkert/seconds "Get the number of seconds for a minute, hour, day and week.")
+* [week](https://www.npmjs.com/package/week): Get the current week number. | [homepage](https://github.com/datetime/week "Get the current week number.")
+* [weekday](https://www.npmjs.com/package/weekday): Get the name and number of the current weekday. Or get the name of the… [more](https://github.com/datetime/weekday) | [homepage](https://github.com/datetime/weekday "Get the name and number of the current weekday. Or get the name of the weekday for a given number.")
+* [year](https://www.npmjs.com/package/year): Simple utility to get the current year with 2 or 4 digits. | [homepage](https://github.com/jonschlinkert/year "Simple utility to get the current year with 2 or 4 digits.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** | 
+| --- | --- |
+| 21 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [evocateur](https://github.com/evocateur) |
+| 1 | [mendenhallmagic](https://github.com/mendenhallmagic) |
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 14, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/time-stamp/index.js b/input_devices/mag/node_modules/time-stamp/index.js
new file mode 100644
index 00000000..0c930482
--- /dev/null
+++ b/input_devices/mag/node_modules/time-stamp/index.js
@@ -0,0 +1,56 @@
+/*!
+ * time-stamp <https://github.com/jonschlinkert/time-stamp>
+ *
+ * Copyright (c) 2015-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+/**
+ * Parse the given pattern and return a formatted
+ * timestamp.
+ *
+ * @param  {String} `pattern` Date pattern.
+ * @param  {Date} `date` Date object.
+ * @return {String}
+ */
+
+module.exports = function(pattern, date) {
+  if (typeof pattern !== 'string') {
+    date = pattern;
+    pattern = 'YYYY:MM:DD';
+  }
+
+  if (!date) date = new Date();
+
+  function timestamp() {
+    var regex = /(?=(YYYY|YY|MM|DD|HH|mm|ss|ms))\1([:\/]*)/;
+    var match = regex.exec(pattern);
+
+    if (match) {
+      var increment = method(match[1]);
+      var val = '00' + String(date[increment[0]]() + (increment[2] || 0));
+      var res = val.slice(-increment[1]) + (match[2] || '');
+      pattern = pattern.replace(match[0], res);
+      timestamp();
+    }
+  }
+
+  timestamp(pattern);
+  return pattern;
+};
+
+function method(key) {
+  return ({
+    YYYY: ['getFullYear', 4],
+    YY: ['getFullYear', 2],
+    // getMonth is zero-based, thus the extra increment field
+    MM: ['getMonth', 2, 1],
+    DD: ['getDate', 2],
+    HH: ['getHours', 2],
+    mm: ['getMinutes', 2],
+    ss: ['getSeconds', 2],
+    ms: ['getMilliseconds', 3]
+  })[key];
+}
diff --git a/input_devices/mag/node_modules/time-stamp/package.json b/input_devices/mag/node_modules/time-stamp/package.json
new file mode 100644
index 00000000..f8c7066d
--- /dev/null
+++ b/input_devices/mag/node_modules/time-stamp/package.json
@@ -0,0 +1,145 @@
+{
+  "_args": [
+    [
+      "time-stamp@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils"
+    ]
+  ],
+  "_from": "time-stamp@>=1.0.1 <2.0.0",
+  "_id": "time-stamp@1.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/time-stamp",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/time-stamp-1.1.0.tgz_1494809609879_0.2116724606603384"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.5.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "time-stamp",
+    "raw": "time-stamp@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/log-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
+  "_shasum": "764a5a11af50561921b133f3b44e618687e0f5c3",
+  "_shrinkwrap": null,
+  "_spec": "time-stamp@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/time-stamp/issues"
+  },
+  "contributors": [
+    {
+      "name": "Daniel Stockman",
+      "url": "http://evocateur.org"
+    },
+    {
+      "name": "Drew",
+      "url": "https://github.com/mendenhallmagic"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {},
+  "description": "Get a formatted timestamp.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.4.1",
+    "pad-left": "^2.1.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "764a5a11af50561921b133f3b44e618687e0f5c3",
+    "tarball": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "30533a5f71944f368b3b1ccaedd895a26b6c5bff",
+  "homepage": "https://github.com/jonschlinkert/time-stamp",
+  "keywords": [
+    "console",
+    "date",
+    "format",
+    "formatting",
+    "log",
+    "pretty",
+    "stamp",
+    "terminal",
+    "time",
+    "time-stamp"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "time-stamp",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/time-stamp.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "helpers": {
+      "timestamp": "./index.js"
+    },
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb"
+    ],
+    "related": {
+      "list": [
+        "days",
+        "iso-week",
+        "month",
+        "months",
+        "o-clock",
+        "seconds",
+        "week",
+        "weekday",
+        "year"
+      ]
+    },
+    "run": true,
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.1.0"
+}
diff --git a/input_devices/mag/node_modules/to-buffer/.travis.yml b/input_devices/mag/node_modules/to-buffer/.travis.yml
new file mode 100644
index 00000000..ac468723
--- /dev/null
+++ b/input_devices/mag/node_modules/to-buffer/.travis.yml
@@ -0,0 +1,9 @@
+sudo: false
+
+language: node_js
+
+node_js:
+  - "5"
+  - "4"
+  - "0.12"
+  - "0.10"
diff --git a/input_devices/mag/node_modules/to-buffer/LICENSE b/input_devices/mag/node_modules/to-buffer/LICENSE
new file mode 100644
index 00000000..bae9da7b
--- /dev/null
+++ b/input_devices/mag/node_modules/to-buffer/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Mathias Buus
+
+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/input_devices/mag/node_modules/to-buffer/README.md b/input_devices/mag/node_modules/to-buffer/README.md
new file mode 100644
index 00000000..fe334a4f
--- /dev/null
+++ b/input_devices/mag/node_modules/to-buffer/README.md
@@ -0,0 +1,23 @@
+# to-buffer
+
+Pass in a string, get a buffer back. Pass in a buffer, get the same buffer back.
+
+```
+npm install to-buffer
+```
+
+[![build status](https://travis-ci.org/mafintosh/to-buffer.svg?branch=master)](https://travis-ci.org/mafintosh/to-buffer)
+
+## Usage
+
+``` js
+var toBuffer = require('to-buffer')
+console.log(toBuffer('hi')) // <Buffer 68 69>
+console.log(toBuffer(Buffer('hi'))) // <Buffer 68 69>
+console.log(toBuffer('6869', 'hex')) // <Buffer 68 69>
+console.log(toBuffer(43)) // throws
+```
+
+## License
+
+MIT
diff --git a/input_devices/mag/node_modules/to-buffer/index.js b/input_devices/mag/node_modules/to-buffer/index.js
new file mode 100644
index 00000000..9bd49788
--- /dev/null
+++ b/input_devices/mag/node_modules/to-buffer/index.js
@@ -0,0 +1,14 @@
+module.exports = toBuffer
+
+var makeBuffer = Buffer.from && Buffer.from !== Uint8Array.from ? Buffer.from : bufferFrom
+
+function bufferFrom (buf, enc) {
+  return new Buffer(buf, enc)
+}
+
+function toBuffer (buf, enc) {
+  if (Buffer.isBuffer(buf)) return buf
+  if (typeof buf === 'string') return makeBuffer(buf, enc)
+  if (Array.isArray(buf)) return makeBuffer(buf)
+  throw new Error('Input should be a buffer or a string')
+}
diff --git a/input_devices/mag/node_modules/to-buffer/package.json b/input_devices/mag/node_modules/to-buffer/package.json
new file mode 100644
index 00000000..b0f4ce9b
--- /dev/null
+++ b/input_devices/mag/node_modules/to-buffer/package.json
@@ -0,0 +1,83 @@
+{
+  "_args": [
+    [
+      "to-buffer@^1.1.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream"
+    ]
+  ],
+  "_from": "to-buffer@>=1.1.1 <2.0.0",
+  "_id": "to-buffer@1.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/to-buffer",
+  "_nodeVersion": "9.11.1",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/to-buffer_1.1.1_1524754584618_0.8258302631612433"
+  },
+  "_npmUser": {
+    "email": "mathiasbuus@gmail.com",
+    "name": "mafintosh"
+  },
+  "_npmVersion": "5.6.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "to-buffer",
+    "raw": "to-buffer@^1.1.1",
+    "rawSpec": "^1.1.1",
+    "scope": null,
+    "spec": ">=1.1.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
+  "_shasum": "493bd48f62d7c43fcded313a03dcadb2e1213a80",
+  "_shrinkwrap": null,
+  "_spec": "to-buffer@^1.1.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream",
+  "author": {
+    "name": "Mathias Buus",
+    "url": "@mafintosh"
+  },
+  "bugs": {
+    "url": "https://github.com/mafintosh/to-buffer/issues"
+  },
+  "dependencies": {},
+  "description": "Pass in a string, get a buffer back. Pass in a buffer, get the same buffer back",
+  "devDependencies": {
+    "standard": "^6.0.5",
+    "tape": "^4.4.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 6,
+    "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4eiZCRA9TVsSAnZWagAA8LgQAJ5GG58jcIfPKs/HYLqA\n2YKCnomJUKJyazkUHaKhm+0yHLfQosxFnWM0W+GrIYtotUunuoczOX1Ba1dc\nqC5QVRUg2/Zvwu/TC9d6QVc+To8bQaGexp6rG9F6MX0GcUD2Huv6JdFyT9Wu\nC88fRK8QCNQNP0BUOI5KkYZ/bsq3U8iXi1zDW9WmNORPrjM4pJhK+phzENM4\nuHXzCfVbF17mnIMIcqdA6+cORHHRCirs6oUruxgTgUmbXUG0mGgsIjfCzDdx\nPhrXNvqXzclxRxaoDYoGefa0gT0m08exrfOu7h9RAjHOYyGoXNzHyF9vkeZm\nc/2GnUgjVM3r7kugexMMqJ0dq6eJ/BmmgNJT42vDXXsvTRa1Q9qWzyJBMXvs\nZ/ssrllUspBAOAPFfDuKJ1n0nNl/MZg7HXFgwDDdmn2/ySm+XEDSM8xV0OJJ\nFkOhOu8jn5nZT22aaum21fvI63TStuiOC/tO01rT2xSuPf2i4pHgzxJoLPnq\nRaEig4ylwnT5nHLGwYr6kSYo7l0yneSIEpcxIUuLXj3GlcJMwHz77zXJsppu\nxtpHZjgEwQ+8jK0HJ8tDCE++W/v7p+klws17GBLZQl4YDQVqIJvFy+6YkuML\n/QVKEWXR59xUA/thIXtcyLC4ZIsZqjefE0EtRtNTpYNocMl76+o1Re5vwTbb\ntxDk\r\n=QAFc\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "493bd48f62d7c43fcded313a03dcadb2e1213a80",
+    "tarball": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
+    "unpackedSize": 3254
+  },
+  "gitHead": "17a1aa27bfce0218979472cfe4776b50438e8857",
+  "homepage": "https://github.com/mafintosh/to-buffer",
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "mafintosh",
+      "email": "mathiasbuus@gmail.com"
+    }
+  ],
+  "name": "to-buffer",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/mafintosh/to-buffer.git"
+  },
+  "scripts": {
+    "test": "standard && tape test.js"
+  },
+  "version": "1.1.1"
+}
diff --git a/input_devices/mag/node_modules/to-buffer/test.js b/input_devices/mag/node_modules/to-buffer/test.js
new file mode 100644
index 00000000..f5e97d6e
--- /dev/null
+++ b/input_devices/mag/node_modules/to-buffer/test.js
@@ -0,0 +1,26 @@
+var tape = require('tape')
+var toBuffer = require('./')
+
+tape('buffer returns buffer', function (t) {
+  t.same(toBuffer(Buffer('hi')), Buffer('hi'))
+  t.end()
+})
+
+tape('string returns buffer', function (t) {
+  t.same(toBuffer('hi'), Buffer('hi'))
+  t.end()
+})
+
+tape('string + enc returns buffer', function (t) {
+  t.same(toBuffer('6869', 'hex'), Buffer('hi'))
+  t.end()
+})
+
+tape('other input throws', function (t) {
+  try {
+    toBuffer(42)
+  } catch (err) {
+    t.same(err.message, 'Input should be a buffer or a string')
+    t.end()
+  }
+})
diff --git a/input_devices/mag/node_modules/to-object-path/LICENSE b/input_devices/mag/node_modules/to-object-path/LICENSE
new file mode 100644
index 00000000..1e49edf8
--- /dev/null
+++ b/input_devices/mag/node_modules/to-object-path/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2016, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/to-object-path/README.md b/input_devices/mag/node_modules/to-object-path/README.md
new file mode 100644
index 00000000..7f3cfb16
--- /dev/null
+++ b/input_devices/mag/node_modules/to-object-path/README.md
@@ -0,0 +1,71 @@
+# to-object-path [![NPM version](https://badge.fury.io/js/to-object-path.svg)](http://badge.fury.io/js/to-object-path)
+
+> Create an object path from a list or array of strings.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i to-object-path --save
+```
+
+## Usage
+
+```js
+var toPath = require('to-object-path');
+
+toPath('foo', 'bar', 'baz');
+toPath('foo', ['bar', 'baz']);
+//=> 'foo.bar.baz'
+```
+
+Also supports passing an arguments object (without having to slice args):
+
+```js
+function foo()
+  return toPath(arguments);
+}
+
+foo('foo', 'bar', 'baz');
+foo('foo', ['bar', 'baz']);
+//=> 'foo.bar.baz'
+```
+
+Visit the [example](./example.js) to see how this could be used in an application.
+
+## Related projects
+
+* [get-value](https://www.npmjs.com/package/get-value): Use property paths (`  a.b.c`) to get a nested value from an object. | [homepage](https://github.com/jonschlinkert/get-value)
+* [has-value](https://www.npmjs.com/package/has-value): Returns true if a value exists, false if empty. Works with deeply nested values using… [more](https://www.npmjs.com/package/has-value) | [homepage](https://github.com/jonschlinkert/has-value)
+* [omit-value](https://www.npmjs.com/package/omit-value): Omit properties from an object or deeply nested property of an object using object path… [more](https://www.npmjs.com/package/omit-value) | [homepage](https://github.com/jonschlinkert/omit-value)
+* [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value)
+* [unset-value](https://www.npmjs.com/package/unset-value): Delete nested properties from an object using dot notation. | [homepage](https://github.com/jonschlinkert/unset-value)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/to-object-path/issues/new).
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on October 28, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/to-object-path/index.js b/input_devices/mag/node_modules/to-object-path/index.js
new file mode 100644
index 00000000..489f8f68
--- /dev/null
+++ b/input_devices/mag/node_modules/to-object-path/index.js
@@ -0,0 +1,33 @@
+/*!
+ * to-object-path <https://github.com/jonschlinkert/to-object-path>
+ *
+ * Copyright (c) 2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+module.exports = function toPath(args) {
+  if (typeOf(args) !== 'arguments') {
+    args = arguments;
+  }
+  return filter(args).join('.');
+};
+
+function filter(arr) {
+  var len = arr.length;
+  var idx = -1;
+  var res = [];
+
+  while (++idx < len) {
+    var ele = arr[idx];
+    if (typeOf(ele) === 'arguments' || Array.isArray(ele)) {
+      res.push.apply(res, filter(ele));
+    } else if (typeof ele === 'string') {
+      res.push(ele);
+    }
+  }
+  return res;
+}
diff --git a/input_devices/mag/node_modules/to-object-path/package.json b/input_devices/mag/node_modules/to-object-path/package.json
new file mode 100644
index 00000000..b52bca7f
--- /dev/null
+++ b/input_devices/mag/node_modules/to-object-path/package.json
@@ -0,0 +1,102 @@
+{
+  "_args": [
+    [
+      "to-object-path@^0.3.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/set-getter"
+    ]
+  ],
+  "_from": "to-object-path@>=0.3.0 <0.4.0",
+  "_id": "to-object-path@0.3.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/to-object-path",
+  "_nodeVersion": "5.3.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.3.12",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "to-object-path",
+    "raw": "to-object-path@^0.3.0",
+    "rawSpec": "^0.3.0",
+    "scope": null,
+    "spec": ">=0.3.0 <0.4.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/set-getter"
+  ],
+  "_resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+  "_shasum": "297588b7b0e7e0ac08e04e672f85c1f4999e17af",
+  "_shrinkwrap": null,
+  "_spec": "to-object-path@^0.3.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/set-getter",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/to-object-path/issues"
+  },
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Create an object path from a list or array of strings.",
+  "devDependencies": {
+    "base": "^0.6.7",
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "297588b7b0e7e0ac08e04e672f85c1f4999e17af",
+    "tarball": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "56f6627285b7f5b7563e6f3ffe3766d966368c17",
+  "homepage": "https://github.com/jonschlinkert/to-object-path",
+  "keywords": [
+    "dot",
+    "nested",
+    "notation",
+    "object",
+    "path",
+    "stringify"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "to-object-path",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/to-object-path.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "related": {
+      "list": [
+        "get-value",
+        "has-value",
+        "omit-value",
+        "set-value",
+        "unset-value"
+      ]
+    }
+  },
+  "version": "0.3.0"
+}
diff --git a/input_devices/mag/node_modules/toggle-array/LICENSE b/input_devices/mag/node_modules/toggle-array/LICENSE
new file mode 100644
index 00000000..b11cb796
--- /dev/null
+++ b/input_devices/mag/node_modules/toggle-array/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/toggle-array/README.md b/input_devices/mag/node_modules/toggle-array/README.md
new file mode 100644
index 00000000..93eec540
--- /dev/null
+++ b/input_devices/mag/node_modules/toggle-array/README.md
@@ -0,0 +1,128 @@
+# toggle-array [![NPM version](https://img.shields.io/npm/v/toggle-array.svg?style=flat)](https://www.npmjs.com/package/toggle-array) [![NPM monthly downloads](https://img.shields.io/npm/dm/toggle-array.svg?style=flat)](https://npmjs.org/package/toggle-array) [![NPM total downloads](https://img.shields.io/npm/dt/toggle-array.svg?style=flat)](https://npmjs.org/package/toggle-array) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/toggle-array.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/toggle-array)
+
+> In an array of objects, this enables a property on the object at the specified index, while disabling the property on all other objects.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save toggle-array
+```
+
+## Usage
+
+```js
+var toggle = require('toggle-array');
+var arr = [
+  {foo: true},
+  {foo: true},
+  {foo: true},
+  {foo: true},
+  {foo: true}
+];
+
+console.log(toggle(arr, 'foo', 2));
+// [ { foo: true },
+//   { foo: false },
+//   { foo: true },
+//   { foo: true },
+//   { foo: true } ]
+
+console.log(toggle(arr, 'foo', 2));
+// [ { foo: false },
+//   { foo: true },
+//   { foo: false },
+//   { foo: false },
+//   { foo: false } ]
+```
+
+## .enable
+
+Enables the element at the given index, and disables all other items:
+
+```js
+var toggle = require('toggle-array');
+var arr = [
+  {foo: true},
+  {foo: true},
+  {foo: true},
+  {foo: true},
+  {foo: true}
+];
+
+console.log(toggle.enable(arr, 'foo', 2));
+// [ { foo: false },
+//   { foo: false },
+//   { foo: true },
+//   { foo: false },
+//   { foo: false } ]
+```
+
+## .disable
+
+Disabled the element at the given index, and enables all other items:
+
+```js
+var toggle = require('toggle-array');
+var arr = [
+  {foo: false},
+  {foo: false},
+  {foo: false},
+  {foo: false},
+  {foo: false}
+];
+
+console.log(toggle.disable(arr, 'foo', 2));
+// [ { foo: true },
+//   { foo: true },
+//   { foo: false },
+//   { foo: true },
+//   { foo: true } ]
+```
+
+## About
+
+### Related projects
+
+* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays.")
+* [array-unique](https://www.npmjs.com/package/array-unique): Remove duplicate values from an array. Fastest ES5 implementation. | [homepage](https://github.com/jonschlinkert/array-unique "Remove duplicate values from an array. Fastest ES5 implementation.")
+* [prompt-choices](https://www.npmjs.com/package/prompt-choices): Create an array of multiple choice objects for use in prompts. | [homepage](https://github.com/enquirer/prompt-choices "Create an array of multiple choice objects for use in prompts.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 07, 2017._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/toggle-array/index.js b/input_devices/mag/node_modules/toggle-array/index.js
new file mode 100644
index 00000000..dbbb4eed
--- /dev/null
+++ b/input_devices/mag/node_modules/toggle-array/index.js
@@ -0,0 +1,42 @@
+'use strict';
+
+var isObject = require('isobject');
+
+function toggle(arr, prop, idx) {
+  var ele = arr[idx];
+  var init = isObject(ele) ? ele[prop] : false;
+  var len = arr.length;
+  var i = -1;
+
+  while (++i < len) {
+    ele = arr[i];
+    if (!isObject(ele)) {
+      continue;
+    }
+    if (i !== idx) {
+      ele[prop] = !!init;
+    } else {
+      ele[prop] = !init;
+    }
+  }
+  return arr;
+}
+
+toggle.enable = function(arr, prop, i) {
+  return initial(arr, prop, i, false);
+};
+
+toggle.disable = function(arr, prop, i) {
+  return initial(arr, prop, i, true);
+};
+
+function initial(arr, prop, i, init) {
+  if (isObject(arr[i])) arr[i][prop] = init;
+  return toggle(arr, prop, i);
+}
+
+/**
+ * Expose `toggle`
+ */
+
+module.exports = toggle;
diff --git a/input_devices/mag/node_modules/toggle-array/package.json b/input_devices/mag/node_modules/toggle-array/package.json
new file mode 100644
index 00000000..5566d2ff
--- /dev/null
+++ b/input_devices/mag/node_modules/toggle-array/package.json
@@ -0,0 +1,111 @@
+{
+  "_args": [
+    [
+      "toggle-array@^1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices"
+    ]
+  ],
+  "_from": "toggle-array@>=1.0.1 <2.0.0",
+  "_id": "toggle-array@1.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/toggle-array",
+  "_nodeVersion": "7.7.3",
+  "_npmOperationalInternal": {
+    "host": "packages-18-east.internal.npmjs.com",
+    "tmp": "tmp/toggle-array-1.0.1.tgz_1494186770035_0.1892693880945444"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "4.2.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "toggle-array",
+    "raw": "toggle-array@^1.0.1",
+    "rawSpec": "^1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prompt-choices"
+  ],
+  "_resolved": "https://registry.npmjs.org/toggle-array/-/toggle-array-1.0.1.tgz",
+  "_shasum": "cbf5840792bd5097f33117ae824c932affe87d58",
+  "_shrinkwrap": null,
+  "_spec": "toggle-array@^1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prompt-choices",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/toggle-array/issues"
+  },
+  "dependencies": {
+    "isobject": "^3.0.0"
+  },
+  "description": "In an array of objects, this enables a property on the object at the specified index, while disabling the property on all other objects.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "mocha": "^3.3.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "cbf5840792bd5097f33117ae824c932affe87d58",
+    "tarball": "https://registry.npmjs.org/toggle-array/-/toggle-array-1.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "d8b2ebbd7bc1dd7f885c33f05573e2b60fc5cc5c",
+  "homepage": "https://github.com/jonschlinkert/toggle-array",
+  "keywords": [
+    "array",
+    "toggle"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "toggle-array",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/toggle-array.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "arr-flatten",
+        "array-unique",
+        "prompt-choices"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.0.1"
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/LICENSE b/input_devices/mag/node_modules/tunnel-agent/LICENSE
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/LICENSE
rename to input_devices/mag/node_modules/tunnel-agent/LICENSE
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/README.md b/input_devices/mag/node_modules/tunnel-agent/README.md
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/request/node_modules/tunnel-agent/README.md
rename to input_devices/mag/node_modules/tunnel-agent/README.md
diff --git a/input_devices/mag/node_modules/tunnel-agent/index.js b/input_devices/mag/node_modules/tunnel-agent/index.js
new file mode 100644
index 00000000..3ee9abc5
--- /dev/null
+++ b/input_devices/mag/node_modules/tunnel-agent/index.js
@@ -0,0 +1,244 @@
+'use strict'
+
+var net = require('net')
+  , tls = require('tls')
+  , http = require('http')
+  , https = require('https')
+  , events = require('events')
+  , assert = require('assert')
+  , util = require('util')
+  , Buffer = require('safe-buffer').Buffer
+  ;
+
+exports.httpOverHttp = httpOverHttp
+exports.httpsOverHttp = httpsOverHttp
+exports.httpOverHttps = httpOverHttps
+exports.httpsOverHttps = httpsOverHttps
+
+
+function httpOverHttp(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = http.request
+  return agent
+}
+
+function httpsOverHttp(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = http.request
+  agent.createSocket = createSecureSocket
+  agent.defaultPort = 443
+  return agent
+}
+
+function httpOverHttps(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = https.request
+  return agent
+}
+
+function httpsOverHttps(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = https.request
+  agent.createSocket = createSecureSocket
+  agent.defaultPort = 443
+  return agent
+}
+
+
+function TunnelingAgent(options) {
+  var self = this
+  self.options = options || {}
+  self.proxyOptions = self.options.proxy || {}
+  self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets
+  self.requests = []
+  self.sockets = []
+
+  self.on('free', function onFree(socket, host, port) {
+    for (var i = 0, len = self.requests.length; i < len; ++i) {
+      var pending = self.requests[i]
+      if (pending.host === host && pending.port === port) {
+        // Detect the request to connect same origin server,
+        // reuse the connection.
+        self.requests.splice(i, 1)
+        pending.request.onSocket(socket)
+        return
+      }
+    }
+    socket.destroy()
+    self.removeSocket(socket)
+  })
+}
+util.inherits(TunnelingAgent, events.EventEmitter)
+
+TunnelingAgent.prototype.addRequest = function addRequest(req, options) {
+  var self = this
+
+   // Legacy API: addRequest(req, host, port, path)
+  if (typeof options === 'string') {
+    options = {
+      host: options,
+      port: arguments[2],
+      path: arguments[3]
+    };
+  }
+
+  if (self.sockets.length >= this.maxSockets) {
+    // We are over limit so we'll add it to the queue.
+    self.requests.push({host: options.host, port: options.port, request: req})
+    return
+  }
+
+  // If we are under maxSockets create a new one.
+  self.createConnection({host: options.host, port: options.port, request: req})
+}
+
+TunnelingAgent.prototype.createConnection = function createConnection(pending) {
+  var self = this
+
+  self.createSocket(pending, function(socket) {
+    socket.on('free', onFree)
+    socket.on('close', onCloseOrRemove)
+    socket.on('agentRemove', onCloseOrRemove)
+    pending.request.onSocket(socket)
+
+    function onFree() {
+      self.emit('free', socket, pending.host, pending.port)
+    }
+
+    function onCloseOrRemove(err) {
+      self.removeSocket(socket)
+      socket.removeListener('free', onFree)
+      socket.removeListener('close', onCloseOrRemove)
+      socket.removeListener('agentRemove', onCloseOrRemove)
+    }
+  })
+}
+
+TunnelingAgent.prototype.createSocket = function createSocket(options, cb) {
+  var self = this
+  var placeholder = {}
+  self.sockets.push(placeholder)
+
+  var connectOptions = mergeOptions({}, self.proxyOptions,
+    { method: 'CONNECT'
+    , path: options.host + ':' + options.port
+    , agent: false
+    }
+  )
+  if (connectOptions.proxyAuth) {
+    connectOptions.headers = connectOptions.headers || {}
+    connectOptions.headers['Proxy-Authorization'] = 'Basic ' +
+        Buffer.from(connectOptions.proxyAuth).toString('base64')
+  }
+
+  debug('making CONNECT request')
+  var connectReq = self.request(connectOptions)
+  connectReq.useChunkedEncodingByDefault = false // for v0.6
+  connectReq.once('response', onResponse) // for v0.6
+  connectReq.once('upgrade', onUpgrade)   // for v0.6
+  connectReq.once('connect', onConnect)   // for v0.7 or later
+  connectReq.once('error', onError)
+  connectReq.end()
+
+  function onResponse(res) {
+    // Very hacky. This is necessary to avoid http-parser leaks.
+    res.upgrade = true
+  }
+
+  function onUpgrade(res, socket, head) {
+    // Hacky.
+    process.nextTick(function() {
+      onConnect(res, socket, head)
+    })
+  }
+
+  function onConnect(res, socket, head) {
+    connectReq.removeAllListeners()
+    socket.removeAllListeners()
+
+    if (res.statusCode === 200) {
+      assert.equal(head.length, 0)
+      debug('tunneling connection has established')
+      self.sockets[self.sockets.indexOf(placeholder)] = socket
+      cb(socket)
+    } else {
+      debug('tunneling socket could not be established, statusCode=%d', res.statusCode)
+      var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode)
+      error.code = 'ECONNRESET'
+      options.request.emit('error', error)
+      self.removeSocket(placeholder)
+    }
+  }
+
+  function onError(cause) {
+    connectReq.removeAllListeners()
+
+    debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack)
+    var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message)
+    error.code = 'ECONNRESET'
+    options.request.emit('error', error)
+    self.removeSocket(placeholder)
+  }
+}
+
+TunnelingAgent.prototype.removeSocket = function removeSocket(socket) {
+  var pos = this.sockets.indexOf(socket)
+  if (pos === -1) return
+
+  this.sockets.splice(pos, 1)
+
+  var pending = this.requests.shift()
+  if (pending) {
+    // If we have pending requests and a socket gets closed a new one
+    // needs to be created to take over in the pool for the one that closed.
+    this.createConnection(pending)
+  }
+}
+
+function createSecureSocket(options, cb) {
+  var self = this
+  TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
+    // 0 is dummy port for v0.6
+    var secureSocket = tls.connect(0, mergeOptions({}, self.options,
+      { servername: options.host
+      , socket: socket
+      }
+    ))
+    self.sockets[self.sockets.indexOf(socket)] = secureSocket
+    cb(secureSocket)
+  })
+}
+
+
+function mergeOptions(target) {
+  for (var i = 1, len = arguments.length; i < len; ++i) {
+    var overrides = arguments[i]
+    if (typeof overrides === 'object') {
+      var keys = Object.keys(overrides)
+      for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {
+        var k = keys[j]
+        if (overrides[k] !== undefined) {
+          target[k] = overrides[k]
+        }
+      }
+    }
+  }
+  return target
+}
+
+
+var debug
+if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
+  debug = function() {
+    var args = Array.prototype.slice.call(arguments)
+    if (typeof args[0] === 'string') {
+      args[0] = 'TUNNEL: ' + args[0]
+    } else {
+      args.unshift('TUNNEL:')
+    }
+    console.error.apply(console, args)
+  }
+} else {
+  debug = function() {}
+}
+exports.debug = debug // for test
diff --git a/input_devices/mag/node_modules/tunnel-agent/package.json b/input_devices/mag/node_modules/tunnel-agent/package.json
new file mode 100644
index 00000000..81dc75f8
--- /dev/null
+++ b/input_devices/mag/node_modules/tunnel-agent/package.json
@@ -0,0 +1,94 @@
+{
+  "_args": [
+    [
+      "tunnel-agent@^0.6.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "tunnel-agent@>=0.6.0 <0.7.0",
+  "_id": "tunnel-agent@0.6.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/tunnel-agent",
+  "_nodeVersion": "6.9.2",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/tunnel-agent-0.6.0.tgz_1488673799706_0.16846991260536015"
+  },
+  "_npmUser": {
+    "email": "mikeal.rogers@gmail.com",
+    "name": "mikeal"
+  },
+  "_npmVersion": "3.10.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "tunnel-agent",
+    "raw": "tunnel-agent@^0.6.0",
+    "rawSpec": "^0.6.0",
+    "scope": null,
+    "spec": ">=0.6.0 <0.7.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+  "_shasum": "27a5dea06b36b04a0a9966774b290868f0fc40fd",
+  "_shrinkwrap": null,
+  "_spec": "tunnel-agent@^0.6.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "email": "mikeal.rogers@gmail.com",
+    "name": "Mikeal Rogers",
+    "url": "http://www.futurealoof.com"
+  },
+  "bugs": {
+    "url": "https://github.com/mikeal/tunnel-agent/issues"
+  },
+  "dependencies": {
+    "safe-buffer": "^5.0.1"
+  },
+  "description": "HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "shasum": "27a5dea06b36b04a0a9966774b290868f0fc40fd",
+    "tarball": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz"
+  },
+  "engines": {
+    "node": "*"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "67df643033258e7cb1388f648ee5f141cd66101b",
+  "homepage": "https://github.com/mikeal/tunnel-agent#readme",
+  "license": "Apache-2.0",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "mikeal",
+      "email": "mikeal.rogers@gmail.com"
+    },
+    {
+      "name": "nylen",
+      "email": "jnylen@gmail.com"
+    },
+    {
+      "name": "fredkschott",
+      "email": "fkschott@gmail.com"
+    },
+    {
+      "name": "simov",
+      "email": "simeonvelichkov@gmail.com"
+    }
+  ],
+  "name": "tunnel-agent",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "url": "git+https://github.com/mikeal/tunnel-agent.git"
+  },
+  "scripts": {},
+  "version": "0.6.0"
+}
diff --git a/input_devices/mag/node_modules/util-deprecate/History.md b/input_devices/mag/node_modules/util-deprecate/History.md
new file mode 100644
index 00000000..acc86753
--- /dev/null
+++ b/input_devices/mag/node_modules/util-deprecate/History.md
@@ -0,0 +1,16 @@
+
+1.0.2 / 2015-10-07
+==================
+
+  * use try/catch when checking `localStorage` (#3, @kumavis)
+
+1.0.1 / 2014-11-25
+==================
+
+  * browser: use `console.warn()` for deprecation calls
+  * browser: more jsdocs
+
+1.0.0 / 2014-04-30
+==================
+
+  * initial commit
diff --git a/input_devices/mag/node_modules/util-deprecate/LICENSE b/input_devices/mag/node_modules/util-deprecate/LICENSE
new file mode 100644
index 00000000..6a60e8c2
--- /dev/null
+++ b/input_devices/mag/node_modules/util-deprecate/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
+
+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/input_devices/mag/node_modules/util-deprecate/README.md b/input_devices/mag/node_modules/util-deprecate/README.md
new file mode 100644
index 00000000..75622fa7
--- /dev/null
+++ b/input_devices/mag/node_modules/util-deprecate/README.md
@@ -0,0 +1,53 @@
+util-deprecate
+==============
+### The Node.js `util.deprecate()` function with browser support
+
+In Node.js, this module simply re-exports the `util.deprecate()` function.
+
+In the web browser (i.e. via browserify), a browser-specific implementation
+of the `util.deprecate()` function is used.
+
+
+## API
+
+A `deprecate()` function is the only thing exposed by this module.
+
+``` javascript
+// setup:
+exports.foo = deprecate(foo, 'foo() is deprecated, use bar() instead');
+
+
+// users see:
+foo();
+// foo() is deprecated, use bar() instead
+foo();
+foo();
+```
+
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
+
+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/input_devices/mag/node_modules/util-deprecate/browser.js b/input_devices/mag/node_modules/util-deprecate/browser.js
new file mode 100644
index 00000000..549ae2f0
--- /dev/null
+++ b/input_devices/mag/node_modules/util-deprecate/browser.js
@@ -0,0 +1,67 @@
+
+/**
+ * Module exports.
+ */
+
+module.exports = deprecate;
+
+/**
+ * Mark that a method should not be used.
+ * Returns a modified function which warns once by default.
+ *
+ * If `localStorage.noDeprecation = true` is set, then it is a no-op.
+ *
+ * If `localStorage.throwDeprecation = true` is set, then deprecated functions
+ * will throw an Error when invoked.
+ *
+ * If `localStorage.traceDeprecation = true` is set, then deprecated functions
+ * will invoke `console.trace()` instead of `console.error()`.
+ *
+ * @param {Function} fn - the function to deprecate
+ * @param {String} msg - the string to print to the console when `fn` is invoked
+ * @returns {Function} a new "deprecated" version of `fn`
+ * @api public
+ */
+
+function deprecate (fn, msg) {
+  if (config('noDeprecation')) {
+    return fn;
+  }
+
+  var warned = false;
+  function deprecated() {
+    if (!warned) {
+      if (config('throwDeprecation')) {
+        throw new Error(msg);
+      } else if (config('traceDeprecation')) {
+        console.trace(msg);
+      } else {
+        console.warn(msg);
+      }
+      warned = true;
+    }
+    return fn.apply(this, arguments);
+  }
+
+  return deprecated;
+}
+
+/**
+ * Checks `localStorage` for boolean values for the given `name`.
+ *
+ * @param {String} name
+ * @returns {Boolean}
+ * @api private
+ */
+
+function config (name) {
+  // accessing global.localStorage can trigger a DOMException in sandboxed iframes
+  try {
+    if (!global.localStorage) return false;
+  } catch (_) {
+    return false;
+  }
+  var val = global.localStorage[name];
+  if (null == val) return false;
+  return String(val).toLowerCase() === 'true';
+}
diff --git a/input_devices/mag/node_modules/util-deprecate/node.js b/input_devices/mag/node_modules/util-deprecate/node.js
new file mode 100644
index 00000000..5e6fcff5
--- /dev/null
+++ b/input_devices/mag/node_modules/util-deprecate/node.js
@@ -0,0 +1,6 @@
+
+/**
+ * For Node.js, simply re-export the core `util.deprecate` function.
+ */
+
+module.exports = require('util').deprecate;
diff --git a/input_devices/mag/node_modules/util-deprecate/package.json b/input_devices/mag/node_modules/util-deprecate/package.json
new file mode 100644
index 00000000..1ce90dba
--- /dev/null
+++ b/input_devices/mag/node_modules/util-deprecate/package.json
@@ -0,0 +1,81 @@
+{
+  "_args": [
+    [
+      "util-deprecate@~1.0.1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream"
+    ]
+  ],
+  "_from": "util-deprecate@>=1.0.1 <1.1.0",
+  "_id": "util-deprecate@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/util-deprecate",
+  "_nodeVersion": "4.1.2",
+  "_npmUser": {
+    "email": "nathan@tootallnate.net",
+    "name": "tootallnate"
+  },
+  "_npmVersion": "2.14.4",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "util-deprecate",
+    "raw": "util-deprecate@~1.0.1",
+    "rawSpec": "~1.0.1",
+    "scope": null,
+    "spec": ">=1.0.1 <1.1.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readable-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+  "_shasum": "450d4dc9fa70de732762fbd2d4a28981419a0ccf",
+  "_shrinkwrap": null,
+  "_spec": "util-deprecate@~1.0.1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readable-stream",
+  "author": {
+    "email": "nathan@tootallnate.net",
+    "name": "Nathan Rajlich",
+    "url": "http://n8.io/"
+  },
+  "browser": "browser.js",
+  "bugs": {
+    "url": "https://github.com/TooTallNate/util-deprecate/issues"
+  },
+  "dependencies": {},
+  "description": "The Node.js `util.deprecate()` function with browser support",
+  "devDependencies": {},
+  "directories": {},
+  "dist": {
+    "shasum": "450d4dc9fa70de732762fbd2d4a28981419a0ccf",
+    "tarball": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
+  },
+  "gitHead": "475fb6857cd23fafff20c1be846c1350abf8e6d4",
+  "homepage": "https://github.com/TooTallNate/util-deprecate",
+  "keywords": [
+    "browser",
+    "browserify",
+    "deprecate",
+    "node",
+    "util"
+  ],
+  "license": "MIT",
+  "main": "node.js",
+  "maintainers": [
+    {
+      "name": "tootallnate",
+      "email": "nathan@tootallnate.net"
+    }
+  ],
+  "name": "util-deprecate",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/TooTallNate/util-deprecate.git"
+  },
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/warning-symbol/LICENSE b/input_devices/mag/node_modules/warning-symbol/LICENSE
new file mode 100644
index 00000000..65f90aca
--- /dev/null
+++ b/input_devices/mag/node_modules/warning-symbol/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015, Jon Schlinkert.
+
+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/input_devices/mag/node_modules/warning-symbol/README.md b/input_devices/mag/node_modules/warning-symbol/README.md
new file mode 100644
index 00000000..8c277fd9
--- /dev/null
+++ b/input_devices/mag/node_modules/warning-symbol/README.md
@@ -0,0 +1,53 @@
+# warning-symbol [![NPM version](https://badge.fury.io/js/warning-symbol.svg)](http://badge.fury.io/js/warning-symbol)
+
+> Cross-platform warning symbol.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/)
+
+```sh
+$ npm i warning-symbol --save
+```
+
+## Usage
+
+```js
+var warning = require('warning-symbol');
+// if windows => '‼' else '⚠'
+```
+
+## Related projects
+
+* [success-symbol](https://github.com/jonschlinkert/success-symbol)
+* [warning-symbol](https://github.com/jonschlinkert/warning-symbol)
+* [error-symbol](https://github.com/jonschlinkert/error-symbol)
+* [info-symbol](https://github.com/jonschlinkert/info-symbol)
+
+## Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm i -d && npm test
+```
+
+## Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/warning-symbol/issues/new)
+
+## Author
+
+**Jon Schlinkert**
+
++ [github/jonschlinkert](https://github.com/jonschlinkert)
++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+## License
+
+Copyright © 2015 Jon Schlinkert
+Released under the MIT license.
+
+***
+
+_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on May 27, 2015._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/warning-symbol/index.js b/input_devices/mag/node_modules/warning-symbol/index.js
new file mode 100644
index 00000000..7ab1aaa1
--- /dev/null
+++ b/input_devices/mag/node_modules/warning-symbol/index.js
@@ -0,0 +1 @@
+module.exports = process.platform === 'win32' ? '‼' : '⚠';
diff --git a/input_devices/mag/node_modules/warning-symbol/package.json b/input_devices/mag/node_modules/warning-symbol/package.json
new file mode 100644
index 00000000..916981fa
--- /dev/null
+++ b/input_devices/mag/node_modules/warning-symbol/package.json
@@ -0,0 +1,106 @@
+{
+  "_args": [
+    [
+      "warning-symbol@^0.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils"
+    ]
+  ],
+  "_from": "warning-symbol@>=0.1.0 <0.2.0",
+  "_id": "warning-symbol@0.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/warning-symbol",
+  "_nodeVersion": "0.12.0",
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "2.5.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "warning-symbol",
+    "raw": "warning-symbol@^0.1.0",
+    "rawSpec": "^0.1.0",
+    "scope": null,
+    "spec": ">=0.1.0 <0.2.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/log-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/warning-symbol/-/warning-symbol-0.1.0.tgz",
+  "_shasum": "bb31dd11b7a0f9d67ab2ed95f457b65825bbad21",
+  "_shrinkwrap": null,
+  "_spec": "warning-symbol@^0.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/log-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/warning-symbol/issues"
+  },
+  "dependencies": {},
+  "description": "Cross-platform warning symbol.",
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "bb31dd11b7a0f9d67ab2ed95f457b65825bbad21",
+    "tarball": "https://registry.npmjs.org/warning-symbol/-/warning-symbol-0.1.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "homepage": "https://github.com/jonschlinkert/warning-symbol",
+  "keywords": [
+    "256",
+    "ansi",
+    "cli",
+    "colour",
+    "command",
+    "command-line",
+    "console",
+    "format",
+    "formatting",
+    "iterm",
+    "log",
+    "logging",
+    "rgb",
+    "shell",
+    "string",
+    "style",
+    "styles",
+    "styling",
+    "symbol",
+    "symbols",
+    "terminal",
+    "text",
+    "tty",
+    "warning",
+    "xterm"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "warning-symbol",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/warning-symbol.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "version": "0.1.0"
+}
diff --git a/input_devices/mag/node_modules/which-pm-runs/LICENSE b/input_devices/mag/node_modules/which-pm-runs/LICENSE
new file mode 100644
index 00000000..7413e1f0
--- /dev/null
+++ b/input_devices/mag/node_modules/which-pm-runs/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Zoltan Kochan
+
+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.
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/which-pm-runs/README.md b/input_devices/mag/node_modules/which-pm-runs/README.md
new file mode 100644
index 00000000..d1a27553
--- /dev/null
+++ b/input_devices/mag/node_modules/which-pm-runs/README.md
@@ -0,0 +1,29 @@
+# which-pm-runs
+
+> Detects what package manager executes the process
+
+[![npm version](https://img.shields.io/npm/v/which-pm-runs.svg)](https://www.npmjs.com/package/which-pm-runs) [![Build Status](https://img.shields.io/travis/zkochan/which-pm-runs/master.svg)](https://travis-ci.org/zkochan/which-pm-runs)
+
+## Installation
+
+```
+npm i which-pm-runs
+```
+
+## Usage
+
+```js
+'use strict'
+const whichPMRuns = require('which-pm-runs')
+
+whichPMRuns()
+//> {name: "pnpm", version: "0.64.2"}
+```
+
+## Related
+
+* [which-pm](https://github.com/zkochan/which-pm) - Detects what package manager was used for installation
+
+## License
+
+[MIT](LICENSE) © [Zoltan Kochan](http://kochan.io)
diff --git a/input_devices/mag/node_modules/which-pm-runs/index.js b/input_devices/mag/node_modules/which-pm-runs/index.js
new file mode 100644
index 00000000..6bc0b21e
--- /dev/null
+++ b/input_devices/mag/node_modules/which-pm-runs/index.js
@@ -0,0 +1,17 @@
+'use strict'
+
+module.exports = function () {
+  if (!process.env.npm_config_user_agent) {
+    return undefined
+  }
+  return pmFromUserAgent(process.env.npm_config_user_agent)
+}
+
+function pmFromUserAgent (userAgent) {
+  const pmSpec = userAgent.split(' ')[0]
+  const separatorPos = pmSpec.lastIndexOf('/')
+  return {
+    name: pmSpec.substr(0, separatorPos),
+    version: pmSpec.substr(separatorPos + 1)
+  }
+}
diff --git a/input_devices/mag/node_modules/which-pm-runs/package.json b/input_devices/mag/node_modules/which-pm-runs/package.json
new file mode 100644
index 00000000..ddc2279a
--- /dev/null
+++ b/input_devices/mag/node_modules/which-pm-runs/package.json
@@ -0,0 +1,89 @@
+{
+  "_args": [
+    [
+      "which-pm-runs@^1.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install"
+    ]
+  ],
+  "_from": "which-pm-runs@>=1.0.0 <2.0.0",
+  "_id": "which-pm-runs@1.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/which-pm-runs",
+  "_nodeVersion": "6.9.1",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/which-pm-runs-1.0.0.tgz_1491658470712_0.22999512730166316"
+  },
+  "_npmUser": {
+    "email": "zoltan.kochan@gmail.com",
+    "name": "zkochan"
+  },
+  "_npmVersion": "3.10.9",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "which-pm-runs",
+    "raw": "which-pm-runs@^1.0.0",
+    "rawSpec": "^1.0.0",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/prebuild-install"
+  ],
+  "_resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
+  "_shasum": "670b3afbc552e0b55df6b7780ca74615f23ad1cb",
+  "_shrinkwrap": null,
+  "_spec": "which-pm-runs@^1.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/prebuild-install",
+  "author": {
+    "name": "Zoltan Kochan"
+  },
+  "bugs": {
+    "url": "https://github.com/zkochan/which-pm-runs/issues"
+  },
+  "dependencies": {},
+  "description": "Detects what package manager executes the process",
+  "devDependencies": {
+    "execa": "^0.6.3",
+    "npm": "^4.4.4",
+    "pnpm": "^0.64.3",
+    "tape": "^4.6.3",
+    "yarn": "^0.22.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "670b3afbc552e0b55df6b7780ca74615f23ad1cb",
+    "tarball": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "0a72e9f1e73f95153629312c9f4935ef0866d7fe",
+  "homepage": "https://github.com/zkochan/which-pm-runs#readme",
+  "keywords": [
+    "npm",
+    "pnpm",
+    "yarn"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "zkochan",
+      "email": "zoltan.kochan@gmail.com"
+    }
+  ],
+  "name": "which-pm-runs",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zkochan/which-pm-runs.git"
+  },
+  "scripts": {
+    "test": "tape test"
+  },
+  "version": "1.0.0"
+}
diff --git a/input_devices/mag/node_modules/wide-align/LICENSE b/input_devices/mag/node_modules/wide-align/LICENSE
new file mode 100644
index 00000000..f4be44d8
--- /dev/null
+++ b/input_devices/mag/node_modules/wide-align/LICENSE
@@ -0,0 +1,14 @@
+Copyright (c) 2015, Rebecca Turner <me@re-becca.org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/input_devices/mag/node_modules/wide-align/README.md b/input_devices/mag/node_modules/wide-align/README.md
new file mode 100644
index 00000000..32f1be04
--- /dev/null
+++ b/input_devices/mag/node_modules/wide-align/README.md
@@ -0,0 +1,47 @@
+wide-align
+----------
+
+A wide-character aware text alignment function for use in terminals / on the
+console.
+
+### Usage
+
+```
+var align = require('wide-align')
+
+// Note that if you view this on a unicode console, all of the slashes are
+// aligned. This is because on a console, all narrow characters are
+// an en wide and all wide characters are an em. In browsers, this isn't
+// held to and wide characters like "古" can be less than two narrow
+// characters even with a fixed width font.
+
+console.log(align.center('abc', 10))     // '   abc    '
+console.log(align.center('古古古', 10))  // '  古古古  '
+console.log(align.left('abc', 10))       // 'abc       '
+console.log(align.left('古古古', 10))    // '古古古    '
+console.log(align.right('abc', 10))      // '       abc'
+console.log(align.right('古古古', 10))   // '    古古古'
+```
+
+### Functions
+
+#### `align.center(str, length)` → `str`
+
+Returns *str* with spaces added to both sides such that that it is *length*
+chars long and centered in the spaces.
+
+#### `align.left(str, length)` → `str`
+
+Returns *str* with spaces to the right such that it is *length* chars long.
+
+### `align.right(str, length)` → `str`
+
+Returns *str* with spaces to the left such that it is *length* chars long.
+
+### Origins
+
+These functions were originally taken from 
+[cliui](https://npmjs.com/package/cliui). Changes include switching to the
+MUCH faster pad generation function from
+[lodash](https://npmjs.com/package/lodash), making center alignment pad
+both sides and adding left alignment.
diff --git a/input_devices/mag/node_modules/wide-align/align.js b/input_devices/mag/node_modules/wide-align/align.js
new file mode 100644
index 00000000..4f94ca4c
--- /dev/null
+++ b/input_devices/mag/node_modules/wide-align/align.js
@@ -0,0 +1,65 @@
+'use strict'
+var stringWidth = require('string-width')
+
+exports.center = alignCenter
+exports.left = alignLeft
+exports.right = alignRight
+
+// lodash's way of generating pad characters.
+
+function createPadding (width) {
+  var result = ''
+  var string = ' '
+  var n = width
+  do {
+    if (n % 2) {
+      result += string;
+    }
+    n = Math.floor(n / 2);
+    string += string;
+  } while (n);
+
+  return result;
+}
+
+function alignLeft (str, width) {
+  var trimmed = str.trimRight()
+  if (trimmed.length === 0 && str.length >= width) return str
+  var padding = ''
+  var strWidth = stringWidth(trimmed)
+
+  if (strWidth < width) {
+    padding = createPadding(width - strWidth)
+  }
+
+  return trimmed + padding
+}
+
+function alignRight (str, width) {
+  var trimmed = str.trimLeft()
+  if (trimmed.length === 0 && str.length >= width) return str
+  var padding = ''
+  var strWidth = stringWidth(trimmed)
+
+  if (strWidth < width) {
+    padding = createPadding(width - strWidth)
+  }
+
+  return padding + trimmed
+}
+
+function alignCenter (str, width) {
+  var trimmed = str.trim()
+  if (trimmed.length === 0 && str.length >= width) return str
+  var padLeft = ''
+  var padRight = ''
+  var strWidth = stringWidth(trimmed)
+
+  if (strWidth < width) {
+    var padLeftBy = parseInt((width - strWidth) / 2, 10) 
+    padLeft = createPadding(padLeftBy)
+    padRight = createPadding(width - (strWidth + padLeftBy))
+  }
+
+  return padLeft + trimmed + padRight
+}
diff --git a/input_devices/mag/node_modules/wide-align/package.json b/input_devices/mag/node_modules/wide-align/package.json
new file mode 100644
index 00000000..13de6e34
--- /dev/null
+++ b/input_devices/mag/node_modules/wide-align/package.json
@@ -0,0 +1,97 @@
+{
+  "_args": [
+    [
+      "wide-align@^1.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge"
+    ]
+  ],
+  "_from": "wide-align@>=1.1.0 <2.0.0",
+  "_id": "wide-align@1.1.3",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/wide-align",
+  "_nodeVersion": "9.3.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/wide-align_1.1.3_1527197810643_0.006292446790612027"
+  },
+  "_npmUser": {
+    "email": "me@re-becca.org",
+    "name": "iarna"
+  },
+  "_npmVersion": "6.1.0",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "wide-align",
+    "raw": "wide-align@^1.1.0",
+    "rawSpec": "^1.1.0",
+    "scope": null,
+    "spec": ">=1.1.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/gauge"
+  ],
+  "_resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+  "_shasum": "ae074e6bdc0c14a431e804e624549c633b000457",
+  "_shrinkwrap": null,
+  "_spec": "wide-align@^1.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/gauge",
+  "author": {
+    "email": "me@re-becca.org",
+    "name": "Rebecca Turner",
+    "url": "http://re-becca.org/"
+  },
+  "bugs": {
+    "url": "https://github.com/iarna/wide-align/issues"
+  },
+  "dependencies": {
+    "string-width": "^1.0.2 || 2"
+  },
+  "description": "A wide-character aware text alignment function for use on the console or with fixed width fonts.",
+  "devDependencies": {
+    "tap": "10 || 11 || 12"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 4,
+    "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbBzBzCRA9TVsSAnZWagAAxeYP/1L3tYrqfB/llIclGJJM\ns3DfFOyKiZgjsOMKrRXJcqEryc1YPQWJ3BqMj0viqaYNXOoOpMihGVFqGP6b\nb+PlmX9INOi7hU7q6Wb/ICXnLDVOn83Ye8uQN/aKlCJ/s1cIz27A6dL7u2d2\nmP5a/Eaxok9JjgFipBwxm5d93ZiZ1rOoILaiXCTlvzSCNpbdsZVDbOuEC9Bz\nkLRRXuG3dd8t8g9xi24VT5VFEiztVlvTgTGfcain+dZccQpNUtgDdFxX0Zco\niAjwt0n1L1lip3n40GHEz8lzPYULz3qAvt07bBFevSWNfPDGF4+n9eN91TAQ\nTqpY1kIgqhwz+QsTVC/w13yL4RKbuRqmWNshIAz7xqM2gvyzU/Zawead3MsC\naP3tdu6PA5KZxosBzozwzw1KRBmkg4EFQZTj+3yu6tL4En5jVS2VzznyLlrM\n1/J7NWeCub+yoKCUTNNnr1pGTMMEOIzsfU8NhvjHb3TxVcFkabdITveOVPf+\n5cElAiJ3yvxY/I1V/0hXl0EAgQEsghdRuDcXN3E1PsE0TwAyreOl4QJWyHU5\nILJhOb2wk9IL0aPKlun6tacPehAqu2EWV5TiGISM9HNgaArY9D3mU0iHmnTy\nADsKuTPcnY00KHtxuZT6a3QgCvrvtmxHL6zm1521mru3V1+7oGkrk5c6Hlzk\nYbx2\r\n=w9c6\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "ae074e6bdc0c14a431e804e624549c633b000457",
+    "tarball": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+    "unpackedSize": 4551
+  },
+  "files": [
+    "align.js"
+  ],
+  "gitHead": "6b766c9874a1e5157eda2ac75b90ccc01b313620",
+  "homepage": "https://github.com/iarna/wide-align#readme",
+  "keywords": [
+    "align",
+    "cjkv",
+    "double",
+    "pad",
+    "unicode",
+    "wide"
+  ],
+  "license": "ISC",
+  "main": "align.js",
+  "maintainers": [
+    {
+      "name": "iarna",
+      "email": "me@re-becca.org"
+    }
+  ],
+  "name": "wide-align",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/iarna/wide-align.git"
+  },
+  "scripts": {
+    "test": "tap --coverage test/*.js",
+    "version": "perl -pi -e 's/^(  \"version\": $ENV{npm_config_node_version}\").*?\",/$1abc\",/' package-lock.json ; git add package-lock.json"
+  },
+  "version": "1.1.3"
+}
diff --git a/input_devices/mag/node_modules/window-size/LICENSE b/input_devices/mag/node_modules/window-size/LICENSE
new file mode 100644
index 00000000..83b56e70
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2017, Jon Schlinkert
+
+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/input_devices/mag/node_modules/window-size/README.md b/input_devices/mag/node_modules/window-size/README.md
new file mode 100644
index 00000000..2803583c
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/README.md
@@ -0,0 +1,166 @@
+# window-size [![NPM version](https://img.shields.io/npm/v/window-size.svg?style=flat)](https://www.npmjs.com/package/window-size) [![NPM monthly downloads](https://img.shields.io/npm/dm/window-size.svg?style=flat)](https://npmjs.org/package/window-size)  [![NPM total downloads](https://img.shields.io/npm/dt/window-size.svg?style=flat)](https://npmjs.org/package/window-size) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/window-size.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/window-size) [![Windows Build Status](https://img.shields.io/appveyor/ci/jonschlinkert/window-size.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/jonschlinkert/window-size)
+
+> Reliable way to get the height and width of terminal/console, since it's not calculated or updated the same way on all platforms, environments and node.js versions.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save window-size
+```
+
+## Usage
+
+```js
+var size = require('window-size');
+```
+
+## CLI
+
+```sh
+$ window-size
+# height: 40
+# width : 145
+```
+
+## API
+
+### windowSize
+
+The main export is either an object with `width` and `height` properties, or `undefined` if unable to get width and height.
+
+```js
+var size = require('window-size');
+console.log(size); 
+//=> {width: 80, height: 25}
+```
+
+### .get
+
+Calls the main function to get the up-to-date window size.
+
+```js
+console.log(size.get());
+//=> {width: 80, height: 25}
+```
+
+**Example**
+
+See [example.js](example.js) for the code used in the below gif.
+
+```js
+process.stdout.on('resize', function() {
+  console.log(size.get());
+});
+```
+
+![resize event example](https://github.com/jonschlinkert/window-size/blob/master/resize.gif)
+
+**HEADS UP!**
+
+Note that some platforms only provide the initial terminal size, not the actual size after it has been resized by the user.
+
+### .env
+
+Get `process.env.COLUMNS` and `process.env.ROWS`, if defined. Called by the main function if for some reason size was not available from `process.stdout` and `process.stderr`.
+
+```js
+console.log(size.env());
+```
+
+### .tty
+
+Attempts to get the size from `tty`. Called by the main function if for some reason size was not available from `process.stdout`, `process.stderr` or `process.env`.
+
+```js
+console.log(size.tty());
+```
+
+### .win
+
+Get the terminal size in Windows 10+.
+
+```js
+console.log(size.win());
+```
+
+Note that this method calls [execSync](https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options) to get the size, and must be called directly, as it **is not** called by the main function.
+
+### .tput
+
+Get the terminal size by calling the unix `$ tput` command.
+
+```js
+console.log(size.tput());
+```
+
+Note that this method calls [execSync](https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options) to get the size, and must be called directly, as it **is not** called by the main function.
+
+### utils
+
+In some environments the main export may not be able to find a window size using the default methods. In this case, `size` will be `undefined` and the functions will not be exported.
+
+Because of this, the functions have been exported in a separate file and can be required directly.
+
+```js
+var utils = require('window-size/utils');
+console.log(utils.win());
+```
+
+## About
+
+### Related projects
+
+* [base-cli](https://www.npmjs.com/package/base-cli): Plugin for base-methods that maps built-in methods to CLI args (also supports methods from a… [more](https://github.com/node-base/base-cli) | [homepage](https://github.com/node-base/base-cli "Plugin for base-methods that maps built-in methods to CLI args (also supports methods from a few plugins, like 'base-store', 'base-options' and 'base-data'.")
+* [lint-deps](https://www.npmjs.com/package/lint-deps): CLI tool that tells you when dependencies are missing from package.json and offers you a… [more](https://github.com/jonschlinkert/lint-deps) | [homepage](https://github.com/jonschlinkert/lint-deps "CLI tool that tells you when dependencies are missing from package.json and offers you a choice to install them. Also tells you when dependencies are listed in package.json but are not being used anywhere in your project. Node.js command line tool and API")
+* [yargs](https://www.npmjs.com/package/yargs): yargs the modern, pirate-themed, successor to optimist. | [homepage](http://yargs.js.org/ "yargs the modern, pirate-themed, successor to optimist.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Contributors
+
+| **Commits** | **Contributor** |  
+| --- | --- |  
+| 23 | [jonschlinkert](https://github.com/jonschlinkert) |  
+| 11 | [doowb](https://github.com/doowb) |  
+| 4  | [bcoe](https://github.com/bcoe) |  
+| 3  | [icyflame](https://github.com/icyflame) |  
+| 2  | [derhuerst](https://github.com/derhuerst) |  
+| 1  | [karliky](https://github.com/karliky) |  
+
+### Building docs
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+### Running tests
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.7.0, on July 27, 2018._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/window-size/cli.js b/input_devices/mag/node_modules/window-size/cli.js
new file mode 100755
index 00000000..ef9ecfd3
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/cli.js
@@ -0,0 +1,30 @@
+#!/usr/bin/env node
+
+var size = require('./');
+var helpText = [
+  'Usage',
+  '  $ window-size',
+  '',
+  'Example',
+  '  $ window-size',
+  '  height: 40 ',
+  '  width : 145',
+  ''
+].join('\n');
+
+function showSize() {
+  console.log('height: ' + size.height);
+  console.log('width : ' + size.width);
+}
+
+switch (process.argv[2]) {
+  case 'help':
+  case '--help':
+  case '-h':
+    console.log(helpText);
+    break;
+  default: {
+    showSize();
+    break;
+  }
+}
diff --git a/input_devices/mag/node_modules/window-size/index.js b/input_devices/mag/node_modules/window-size/index.js
new file mode 100644
index 00000000..a3313b18
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/index.js
@@ -0,0 +1,35 @@
+/*!
+ * window-size <https://github.com/jonschlinkert/window-size>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var define = require('define-property');
+var utils = require('./utils');
+
+/**
+ * Expose `windowSize`
+ */
+
+module.exports = utils.get();
+
+if (module.exports) {
+  /**
+   * Expose `windowSize.get` method
+   */
+
+  define(module.exports, 'get', utils.get);
+
+  /**
+   * Expose methods for unit tests
+   */
+
+  define(module.exports, 'env', utils.env);
+  define(module.exports, 'tty', utils.tty);
+  define(module.exports, 'tput', utils.tput);
+  define(module.exports, 'win', utils.win);
+}
+
diff --git a/input_devices/mag/node_modules/window-size/node_modules/is-number/LICENSE b/input_devices/mag/node_modules/window-size/node_modules/is-number/LICENSE
new file mode 100644
index 00000000..842218cf
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/node_modules/is-number/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2016, Jon Schlinkert
+
+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/input_devices/mag/node_modules/window-size/node_modules/is-number/README.md b/input_devices/mag/node_modules/window-size/node_modules/is-number/README.md
new file mode 100644
index 00000000..281165dc
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/node_modules/is-number/README.md
@@ -0,0 +1,115 @@
+# is-number [![NPM version](https://img.shields.io/npm/v/is-number.svg?style=flat)](https://www.npmjs.com/package/is-number) [![NPM downloads](https://img.shields.io/npm/dm/is-number.svg?style=flat)](https://npmjs.org/package/is-number) [![Build Status](https://img.shields.io/travis/jonschlinkert/is-number.svg?style=flat)](https://travis-ci.org/jonschlinkert/is-number)
+
+> Returns true if the value is a number. comprehensive tests.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save is-number
+```
+
+## Usage
+
+To understand some of the rationale behind the decisions made in this library (and to learn about some oddities of number evaluation in JavaScript), [see this gist](https://gist.github.com/jonschlinkert/e30c70c713da325d0e81).
+
+```js
+var isNumber = require('is-number');
+```
+
+### true
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber(5e3)      //=> 'true'
+isNumber(0xff)     //=> 'true'
+isNumber(-1.1)     //=> 'true'
+isNumber(0)        //=> 'true'
+isNumber(1)        //=> 'true'
+isNumber(1.1)      //=> 'true'
+isNumber(10)       //=> 'true'
+isNumber(10.10)    //=> 'true'
+isNumber(100)      //=> 'true'
+isNumber('-1.1')   //=> 'true'
+isNumber('0')      //=> 'true'
+isNumber('012')    //=> 'true'
+isNumber('0xff')   //=> 'true'
+isNumber('1')      //=> 'true'
+isNumber('1.1')    //=> 'true'
+isNumber('10')     //=> 'true'
+isNumber('10.10')  //=> 'true'
+isNumber('100')    //=> 'true'
+isNumber('5e3')    //=> 'true'
+isNumber(parseInt('012'))   //=> 'true'
+isNumber(parseFloat('012')) //=> 'true'
+```
+
+### False
+
+See the [tests](./test.js) for more examples.
+
+```js
+isNumber('foo')             //=> 'false'
+isNumber([1])               //=> 'false'
+isNumber([])                //=> 'false'
+isNumber(function () {})    //=> 'false'
+isNumber(Infinity)          //=> 'false'
+isNumber(NaN)               //=> 'false'
+isNumber(new Array('abc'))  //=> 'false'
+isNumber(new Array(2))      //=> 'false'
+isNumber(new Buffer('abc')) //=> 'false'
+isNumber(null)              //=> 'false'
+isNumber(undefined)         //=> 'false'
+isNumber({abc: 'abc'})      //=> 'false'
+```
+
+## About
+
+### Related projects
+
+* [even](https://www.npmjs.com/package/even): Get the even numbered items from an array. | [homepage](https://github.com/jonschlinkert/even "Get the even numbered items from an array.")
+* [is-even](https://www.npmjs.com/package/is-even): Return true if the given number is even. | [homepage](https://github.com/jonschlinkert/is-even "Return true if the given number is even.")
+* [is-odd](https://www.npmjs.com/package/is-odd): Returns true if the given number is odd. | [homepage](https://github.com/jonschlinkert/is-odd "Returns true if the given number is odd.")
+* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive.  | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ")
+* [kind-of](https://www.npmjs.com/package/kind-of): Get the native type of a value. | [homepage](https://github.com/jonschlinkert/kind-of "Get the native type of a value.")
+* [odd](https://www.npmjs.com/package/odd): Get the odd numbered items from an array. | [homepage](https://github.com/jonschlinkert/odd "Get the odd numbered items from an array.")
+
+### Contributing
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+### Building docs
+
+_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
+
+To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
+
+```sh
+$ npm install -g verb verb-generate-readme && verb
+```
+
+### Running tests
+
+Install dev dependencies:
+
+```sh
+$ npm install -d && npm test
+```
+
+### Author
+
+**Jon Schlinkert**
+
+* [github/jonschlinkert](https://github.com/jonschlinkert)
+* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+
+### License
+
+Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT license](https://github.com/jonschlinkert/is-number/blob/master/LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.30, on September 10, 2016._
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/window-size/node_modules/is-number/index.js b/input_devices/mag/node_modules/window-size/node_modules/is-number/index.js
new file mode 100644
index 00000000..7a2a45be
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/node_modules/is-number/index.js
@@ -0,0 +1,22 @@
+/*!
+ * is-number <https://github.com/jonschlinkert/is-number>
+ *
+ * Copyright (c) 2014-2015, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+var typeOf = require('kind-of');
+
+module.exports = function isNumber(num) {
+  var type = typeOf(num);
+
+  if (type === 'string') {
+    if (!num.trim()) return false;
+  } else if (type !== 'number') {
+    return false;
+  }
+
+  return (num - num + 1) >= 0;
+};
diff --git a/input_devices/mag/node_modules/window-size/node_modules/is-number/package.json b/input_devices/mag/node_modules/window-size/node_modules/is-number/package.json
new file mode 100644
index 00000000..905c7b2f
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/node_modules/is-number/package.json
@@ -0,0 +1,152 @@
+{
+  "_args": [
+    [
+      "is-number@^3.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/window-size"
+    ]
+  ],
+  "_from": "is-number@>=3.0.0 <4.0.0",
+  "_id": "is-number@3.0.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/window-size/is-number",
+  "_nodeVersion": "6.3.0",
+  "_npmOperationalInternal": {
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/is-number-3.0.0.tgz_1473555089490_0.21388969756662846"
+  },
+  "_npmUser": {
+    "email": "github@sellside.com",
+    "name": "jonschlinkert"
+  },
+  "_npmVersion": "3.10.3",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "is-number",
+    "raw": "is-number@^3.0.0",
+    "rawSpec": "^3.0.0",
+    "scope": null,
+    "spec": ">=3.0.0 <4.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/window-size"
+  ],
+  "_resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+  "_shasum": "24fd6201a4782cf50561c810276afc7d12d71195",
+  "_shrinkwrap": null,
+  "_spec": "is-number@^3.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/window-size",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/is-number/issues"
+  },
+  "contributors": [
+    {
+      "name": "Charlike Mike Reagent",
+      "url": "http://www.tunnckocore.tk"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "email": "jon.schlinkert@sellside.com",
+      "url": "http://twitter.com/jonschlinkert"
+    }
+  ],
+  "dependencies": {
+    "kind-of": "^3.0.2"
+  },
+  "description": "Returns true if the value is a number. comprehensive tests.",
+  "devDependencies": {
+    "benchmarked": "^0.2.5",
+    "chalk": "^1.1.3",
+    "gulp-format-md": "^0.1.10",
+    "mocha": "^3.0.2"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "24fd6201a4782cf50561c810276afc7d12d71195",
+    "tarball": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "index.js"
+  ],
+  "gitHead": "af885e2e890b9ef0875edd2b117305119ee5bdc5",
+  "homepage": "https://github.com/jonschlinkert/is-number",
+  "keywords": [
+    "check",
+    "coerce",
+    "coercion",
+    "integer",
+    "is",
+    "is-nan",
+    "is-num",
+    "is-number",
+    "istype",
+    "kind",
+    "math",
+    "nan",
+    "num",
+    "number",
+    "numeric",
+    "test",
+    "type",
+    "typeof",
+    "value"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    },
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    }
+  ],
+  "name": "is-number",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/is-number.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "reflinks": [
+      "verb",
+      "verb-generate-readme"
+    ],
+    "related": {
+      "list": [
+        "even",
+        "is-even",
+        "is-odd",
+        "is-primitive",
+        "kind-of",
+        "odd"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "3.0.0"
+}
diff --git a/input_devices/mag/node_modules/window-size/package.json b/input_devices/mag/node_modules/window-size/package.json
new file mode 100644
index 00000000..df11752d
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/package.json
@@ -0,0 +1,170 @@
+{
+  "_args": [
+    [
+      "window-size@^1.1.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-utils"
+    ]
+  ],
+  "_from": "window-size@>=1.1.0 <2.0.0",
+  "_id": "window-size@1.1.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/window-size",
+  "_nodeVersion": "10.3.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/window-size_1.1.1_1532722870764_0.8558392465584159"
+  },
+  "_npmUser": {
+    "email": "brian.woodward@gmail.com",
+    "name": "doowb"
+  },
+  "_npmVersion": "6.1.0",
+  "_phantomChildren": {
+    "kind-of": "3.2.2"
+  },
+  "_requested": {
+    "name": "window-size",
+    "raw": "window-size@^1.1.0",
+    "rawSpec": "^1.1.0",
+    "scope": null,
+    "spec": ">=1.1.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/readline-utils"
+  ],
+  "_resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.1.tgz",
+  "_shasum": "9858586580ada78ab26ecd6978a6e03115c1af20",
+  "_shrinkwrap": null,
+  "_spec": "window-size@^1.1.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/readline-utils",
+  "author": {
+    "name": "Jon Schlinkert",
+    "url": "https://github.com/jonschlinkert"
+  },
+  "bin": {
+    "window-size": "cli.js"
+  },
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/window-size/issues"
+  },
+  "contributors": [
+    {
+      "name": "Benjamin E. Coe",
+      "url": "https://twitter.com/benjamincoe"
+    },
+    {
+      "name": "Brian Woodward",
+      "url": "https://twitter.com/doowb"
+    },
+    {
+      "name": "Carlos Hernández Gómez",
+      "url": "http://www.twitter.com/k4rliky"
+    },
+    {
+      "name": "Jannis Redmann",
+      "url": "http://jannisr.de"
+    },
+    {
+      "name": "Jon Schlinkert",
+      "url": "http://twitter.com/jonschlinkert"
+    },
+    {
+      "name": "Siddharth Kannan",
+      "url": "http://icyflame.github.io"
+    }
+  ],
+  "dependencies": {
+    "define-property": "^1.0.0",
+    "is-number": "^3.0.0"
+  },
+  "description": "Reliable way to get the height and width of terminal/console, since it's not calculated or updated the same way on all platforms, environments and node.js versions.",
+  "devDependencies": {
+    "gulp-format-md": "^0.1.12",
+    "justified": "^0.2.1",
+    "mocha": "^3.3.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 6,
+    "integrity": "sha512-5D/9vujkmVQ7pSmc0SCBmHXbkv6eaHwXEx65MywhmUMsI8sGqJ972APq1lotfcwMKPFLuCFfL8xGHLIp7jaBmA==",
+    "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbW362CRA9TVsSAnZWagAAyiMQAKRjQV07wf4HYVmWOgth\ncWuJHa/JKnEVGwDwQ50P+hyr88ItzQWvIleW2psXfWlbfvvIPyL1W2eKdqb0\nLMgpCLOwjHZACE2pWkBhvx2U1aZMPiKy4epFhGqZhgAdI0JtakmPbNq80VFP\n7RDpBVtaCvdiGMYwiBHnwRKP61mcGgSH/AvG0lGrfOty0cEOIPpK5Y9UE2kx\n4/PyVmc5etmCCYtnJQNWxNi7RtEEDdxaORGn09rVM/xBok++OrZ/fzbaWPi8\n6lV8oYwgDrpjU8J29iC3uEF5uTkfpUEBtz7HTB5hd/pnm1SQ71EOXU5NlXQ+\nfN36G0A0GUvr1o2QQLrY+J6mYRrGG0zVZToSNMDz8RCGuExXWEEZuEakBb96\nqAT8NOMUQ7BHDpGTNa+JssBMCL3KeKd3QFK5wbkZuQbUXv6WN7EVanJTyebE\nZiV8N4KUkAQpHKCjSyGohd/63ROqUXIN5iSOe+yfhX/cRbn1kB3y0QQu5poQ\nHrFINMKuh9AZ7Zups2zkbtwZetuSXmdPNy4aZvMH1bPqxm+/qSVxzl88JdNG\nQI5Yf/74fjmKuKsdKrdHb9Yxz6k0A9vtr2e0+UYfyrjfIwjUmtUzdRiBEz5h\nAGs9njtPBCAyGDCaFQTD89if/OJmE3p+UqAO1jKcjFlrqu2Arww5qSQKCRU7\n4Xsb\r\n=KcA1\r\n-----END PGP SIGNATURE-----\r\n",
+    "shasum": "9858586580ada78ab26ecd6978a6e03115c1af20",
+    "tarball": "https://registry.npmjs.org/window-size/-/window-size-1.1.1.tgz",
+    "unpackedSize": 12638
+  },
+  "engines": {
+    "node": ">= 0.10.0"
+  },
+  "files": [
+    "cli.js",
+    "index.js",
+    "utils.js"
+  ],
+  "gitHead": "28f3e0ffba18846d5db4919a65804aa076e4ffc5",
+  "homepage": "https://github.com/jonschlinkert/window-size",
+  "keywords": [
+    "columns",
+    "console",
+    "darwin",
+    "height",
+    "lines",
+    "redirected",
+    "resize",
+    "rows",
+    "size",
+    "term",
+    "term-size",
+    "terminal",
+    "tty",
+    "unix",
+    "width",
+    "win",
+    "window",
+    "windows"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "doowb",
+      "email": "brian.woodward@gmail.com"
+    },
+    {
+      "name": "jonschlinkert",
+      "email": "github@sellside.com"
+    }
+  ],
+  "name": "window-size",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/jonschlinkert/window-size.git"
+  },
+  "scripts": {
+    "test": "mocha"
+  },
+  "verb": {
+    "layout": "default",
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "related": {
+      "list": [
+        "base-cli",
+        "lint-deps",
+        "yargs"
+      ]
+    },
+    "tasks": [
+      "readme"
+    ],
+    "toc": false
+  },
+  "version": "1.1.1"
+}
diff --git a/input_devices/mag/node_modules/window-size/utils.js b/input_devices/mag/node_modules/window-size/utils.js
new file mode 100644
index 00000000..41dc10e9
--- /dev/null
+++ b/input_devices/mag/node_modules/window-size/utils.js
@@ -0,0 +1,124 @@
+/*!
+ * window-size <https://github.com/jonschlinkert/window-size>
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+'use strict';
+
+var os = require('os');
+var isNumber = require('is-number');
+var cp = require('child_process');
+
+function windowSize(options) {
+  options = options || {};
+  return streamSize(options, 'stdout') ||
+    streamSize(options, 'stderr') ||
+    envSize() ||
+    ttySize(options);
+}
+
+function streamSize(options, name) {
+  var stream = (process && process[name]) || options[name];
+  var size;
+
+  if (!stream) return;
+  if (typeof stream.getWindowSize === 'function') {
+    size = stream.getWindowSize();
+    if (isSize(size)) {
+      return {
+        width: size[0],
+        height: size[1],
+        type: name
+      };
+    }
+  }
+
+  size = [stream.columns, stream.rows];
+  if (isSize(size)) {
+    return {
+      width: Number(size[0]),
+      height: Number(size[1]),
+      type: name
+    };
+  }
+}
+
+function envSize() {
+  if (process && process.env) {
+    var size = [process.env.COLUMNS, process.env.ROWS];
+    if (isSize(size)) {
+      return {
+        width: Number(size[0]),
+        height: Number(size[1]),
+        type: 'process.env'
+      };
+    }
+  }
+}
+
+function ttySize(options, stdout) {
+  var tty = options.tty || require('tty');
+  if (tty && typeof tty.getWindowSize === 'function') {
+    var size = tty.getWindowSize(stdout);
+    if (isSize(size)) {
+      return {
+        width: Number(size[1]),
+        height: Number(size[0]),
+        type: 'tty'
+      };
+    }
+  }
+}
+
+function winSize() {
+  if (os.release().startsWith('10')) {
+    var cmd = 'wmic path Win32_VideoController get CurrentHorizontalResolution,CurrentVerticalResolution';
+    var numberPattern = /\d+/g;
+    var code = cp.execSync(cmd).toString();
+    var size = code.match(numberPattern);
+    if (isSize(size)) {
+      return {
+        width: Number(size[0]),
+        height: Number(size[1]),
+        type: 'windows'
+      };
+    }
+  }
+}
+
+function tputSize() {
+  try {
+    var buf = cp.execSync('tput cols && tput lines', {stdio: ['ignore', 'pipe', process.stderr]});
+    var size = buf.toString().trim().split('\n');
+    if (isSize(size)) {
+      return {
+        width: Number(size[0]),
+        height: Number(size[1]),
+        type: 'tput'
+      };
+    }
+  } catch (err) {}
+}
+
+/**
+ * Returns true if the given size array has
+ * valid height and width values.
+ */
+
+function isSize(size) {
+  return Array.isArray(size) && isNumber(size[0]) && isNumber(size[1]);
+}
+
+/**
+ * Expose `windowSize`
+ */
+
+module.exports = {
+  get: windowSize,
+  env: envSize,
+  tty: ttySize,
+  tput: tputSize,
+  win: winSize
+};
diff --git a/input_devices/mag/node_modules/wrappy/LICENSE b/input_devices/mag/node_modules/wrappy/LICENSE
new file mode 100644
index 00000000..19129e31
--- /dev/null
+++ b/input_devices/mag/node_modules/wrappy/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/input_devices/mag/node_modules/wrappy/README.md b/input_devices/mag/node_modules/wrappy/README.md
new file mode 100644
index 00000000..98eab252
--- /dev/null
+++ b/input_devices/mag/node_modules/wrappy/README.md
@@ -0,0 +1,36 @@
+# wrappy
+
+Callback wrapping utility
+
+## USAGE
+
+```javascript
+var wrappy = require("wrappy")
+
+// var wrapper = wrappy(wrapperFunction)
+
+// make sure a cb is called only once
+// See also: http://npm.im/once for this specific use case
+var once = wrappy(function (cb) {
+  var called = false
+  return function () {
+    if (called) return
+    called = true
+    return cb.apply(this, arguments)
+  }
+})
+
+function printBoo () {
+  console.log('boo')
+}
+// has some rando property
+printBoo.iAmBooPrinter = true
+
+var onlyPrintOnce = once(printBoo)
+
+onlyPrintOnce() // prints 'boo'
+onlyPrintOnce() // does nothing
+
+// random property is retained!
+assert.equal(onlyPrintOnce.iAmBooPrinter, true)
+```
diff --git a/input_devices/mag/node_modules/wrappy/package.json b/input_devices/mag/node_modules/wrappy/package.json
new file mode 100644
index 00000000..f54c657b
--- /dev/null
+++ b/input_devices/mag/node_modules/wrappy/package.json
@@ -0,0 +1,88 @@
+{
+  "_args": [
+    [
+      "wrappy@1",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/once"
+    ]
+  ],
+  "_from": "wrappy@>=1.0.0 <2.0.0",
+  "_id": "wrappy@1.0.2",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/wrappy",
+  "_nodeVersion": "5.10.1",
+  "_npmOperationalInternal": {
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/wrappy-1.0.2.tgz_1463527848281_0.037129373755306005"
+  },
+  "_npmUser": {
+    "email": "kat@sykosomatic.org",
+    "name": "zkat"
+  },
+  "_npmVersion": "3.9.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "wrappy",
+    "raw": "wrappy@1",
+    "rawSpec": "1",
+    "scope": null,
+    "spec": ">=1.0.0 <2.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/once"
+  ],
+  "_resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+  "_shasum": "b5243d8f3ec1aa35f1364605bc0d1036e30ab69f",
+  "_shrinkwrap": null,
+  "_spec": "wrappy@1",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/once",
+  "author": {
+    "email": "i@izs.me",
+    "name": "Isaac Z. Schlueter",
+    "url": "http://blog.izs.me/"
+  },
+  "bugs": {
+    "url": "https://github.com/npm/wrappy/issues"
+  },
+  "dependencies": {},
+  "description": "Callback wrapping utility",
+  "devDependencies": {
+    "tap": "^2.3.1"
+  },
+  "directories": {
+    "test": "test"
+  },
+  "dist": {
+    "shasum": "b5243d8f3ec1aa35f1364605bc0d1036e30ab69f",
+    "tarball": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
+  },
+  "files": [
+    "wrappy.js"
+  ],
+  "gitHead": "71d91b6dc5bdeac37e218c2cf03f9ab55b60d214",
+  "homepage": "https://github.com/npm/wrappy",
+  "license": "ISC",
+  "main": "wrappy.js",
+  "maintainers": [
+    {
+      "name": "isaacs",
+      "email": "i@izs.me"
+    },
+    {
+      "name": "zkat",
+      "email": "kat@sykosomatic.org"
+    }
+  ],
+  "name": "wrappy",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/npm/wrappy.git"
+  },
+  "scripts": {
+    "test": "tap --coverage test/*.js"
+  },
+  "version": "1.0.2"
+}
diff --git a/input_devices/mag/node_modules/wrappy/wrappy.js b/input_devices/mag/node_modules/wrappy/wrappy.js
new file mode 100644
index 00000000..bb7e7d6f
--- /dev/null
+++ b/input_devices/mag/node_modules/wrappy/wrappy.js
@@ -0,0 +1,33 @@
+// Returns a wrapper function that returns a wrapped callback
+// The wrapper function should do some stuff, and return a
+// presumably different callback function.
+// This makes sure that own properties are retained, so that
+// decorations and such are not lost along the way.
+module.exports = wrappy
+function wrappy (fn, cb) {
+  if (fn && cb) return wrappy(fn)(cb)
+
+  if (typeof fn !== 'function')
+    throw new TypeError('need wrapper function')
+
+  Object.keys(fn).forEach(function (k) {
+    wrapper[k] = fn[k]
+  })
+
+  return wrapper
+
+  function wrapper() {
+    var args = new Array(arguments.length)
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i]
+    }
+    var ret = fn.apply(this, args)
+    var cb = args[args.length-1]
+    if (typeof ret === 'function' && ret !== cb) {
+      Object.keys(cb).forEach(function (k) {
+        ret[k] = cb[k]
+      })
+    }
+    return ret
+  }
+}
diff --git a/input_devices/mag/node_modules/ws/.npmignore b/input_devices/mag/node_modules/ws/.npmignore
deleted file mode 100644
index 1eba800f..00000000
--- a/input_devices/mag/node_modules/ws/.npmignore
+++ /dev/null
@@ -1,11 +0,0 @@
-npm-debug.log
-node_modules
-.*.swp
-.lock-*
-build
-
-bench
-doc
-examples
-test
-
diff --git a/input_devices/mag/node_modules/ws/.travis.yml b/input_devices/mag/node_modules/ws/.travis.yml
deleted file mode 100644
index 97358668..00000000
--- a/input_devices/mag/node_modules/ws/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: node_js
-npm_args: --ws:native
-node_js:
-  - "0.8"
-  - "0.10"
diff --git a/input_devices/mag/node_modules/ws/LICENSE b/input_devices/mag/node_modules/ws/LICENSE
new file mode 100644
index 00000000..a145cd1d
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
+
+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/input_devices/mag/node_modules/ws/Makefile b/input_devices/mag/node_modules/ws/Makefile
deleted file mode 100644
index 00f19fa0..00000000
--- a/input_devices/mag/node_modules/ws/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-ALL_TESTS = $(shell find test/ -name '*.test.js')
-ALL_INTEGRATION = $(shell find test/ -name '*.integration.js')
-
-all:
-	node-gyp configure build
-
-clean:
-	node-gyp clean
-
-run-tests:
-	@./node_modules/.bin/mocha \
-		-t 5000 \
-		-s 2400 \
-		$(TESTFLAGS) \
-		$(TESTS)
-
-run-integrationtests:
-	@./node_modules/.bin/mocha \
-		-t 5000 \
-		-s 6000 \
-		$(TESTFLAGS) \
-		$(TESTS)
-
-test:
-	@$(MAKE) NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests
-
-integrationtest:
-	@$(MAKE) NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_PATH=lib TESTS="$(ALL_INTEGRATION)" run-integrationtests
-
-benchmark:
-	@node bench/sender.benchmark.js
-	@node bench/parser.benchmark.js
-
-autobahn:
-	@NODE_PATH=lib node test/autobahn.js
-
-autobahn-server:
-	@NODE_PATH=lib node test/autobahn-server.js
-
-.PHONY: test
diff --git a/input_devices/mag/node_modules/ws/README.md b/input_devices/mag/node_modules/ws/README.md
index fef2fe66..3fd9a8cc 100644
--- a/input_devices/mag/node_modules/ws/README.md
+++ b/input_devices/mag/node_modules/ws/README.md
@@ -1,69 +1,181 @@
-# ws: a node.js websocket library
-
-[![Build Status](https://travis-ci.org/einaros/ws.svg?branch=master)](https://travis-ci.org/einaros/ws)
-
-`ws` is a simple to use WebSocket implementation, up-to-date against RFC-6455,
-and [probably the fastest WebSocket library for node.js][archive].
-
-Passes the quite extensive Autobahn test suite. See http://einaros.github.com/ws
-for the full reports.
+# ws: a Node.js WebSocket library
+
+[![Version npm](https://img.shields.io/npm/v/ws.svg)](https://www.npmjs.com/package/ws)
+[![Linux Build](https://img.shields.io/travis/websockets/ws/master.svg)](https://travis-ci.org/websockets/ws)
+[![Windows Build](https://ci.appveyor.com/api/projects/status/github/websockets/ws?branch=master&svg=true)](https://ci.appveyor.com/project/lpinca/ws)
+[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg)](https://coveralls.io/r/websockets/ws?branch=master)
+
+ws is a simple to use, blazing fast, and thoroughly tested WebSocket client
+and server implementation.
+
+Passes the quite extensive Autobahn test suite: [server][server-report],
+[client][client-report].
+
+**Note**: This module does not work in the browser. The client in the docs is a
+reference to a back end with the role of a client in the WebSocket
+communication. Browser clients must use the native
+[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) object.
+To make the same code work seamlessly on Node.js and the browser, you can use
+one of the many wrappers available on npm, like
+[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws).
+
+## Table of Contents
+
+* [Protocol support](#protocol-support)
+* [Installing](#installing)
+  + [Opt-in for performance and spec compliance](#opt-in-for-performance-and-spec-compliance)
+* [API docs](#api-docs)
+* [WebSocket compression](#websocket-compression)
+* [Usage examples](#usage-examples)
+  + [Sending and receiving text data](#sending-and-receiving-text-data)
+  + [Sending binary data](#sending-binary-data)
+  + [Simple server](#simple-server)
+  + [External HTTP/S server](#external-https-server)
+  + [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server)
+  + [Server broadcast](#server-broadcast)
+  + [echo.websocket.org demo](#echowebsocketorg-demo)
+  + [Other examples](#other-examples)
+* [Error handling best practices](#error-handling-best-practices)
+* [FAQ](#faq)
+  + [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client)
+  + [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections)
+  + [How to connect via a proxy?](#how-to-connect-via-a-proxy)
+* [Changelog](#changelog)
+* [License](#license)
 
 ## Protocol support
 
-* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera.
-  Added to ws version 0.4.2, but server only. Can be disabled by setting the
-  `disableHixie` option to true.)
 * **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)
 * **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`)
 
-### Installing
+## Installing
 
 ```
 npm install --save ws
 ```
 
+### Opt-in for performance and spec compliance
+
+There are 2 optional modules that can be installed along side with the ws
+module. These modules are binary addons which improve certain operations.
+Prebuilt binaries are available for the most popular platforms so you don't
+necessarily need to have a C++ compiler installed on your machine.
+
+- `npm install --save-optional bufferutil`: Allows to efficiently perform
+  operations such as masking and unmasking the data payload of the WebSocket
+  frames.
+- `npm install --save-optional utf-8-validate`: Allows to efficiently check
+  if a message contains valid UTF-8 as required by the spec.
+
+## API docs
+
+See [`/doc/ws.md`](./doc/ws.md) for Node.js-like docs for the ws classes.
+
+## WebSocket compression
+
+ws supports the [permessage-deflate extension][permessage-deflate] which
+enables the client and server to negotiate a compression algorithm and its
+parameters, and then selectively apply it to the data payloads of each
+WebSocket message.
+
+The extension is disabled by default on the server and enabled by default on
+the client. It adds a significant overhead in terms of performance and memory
+consumption so we suggest to enable it only if it is really needed.
+
+Note that Node.js has a variety of issues with high-performance compression,
+where increased concurrency, especially on Linux, can lead to
+[catastrophic memory fragmentation][node-zlib-bug] and slow performance.
+If you intend to use permessage-deflate in production, it is worthwhile to set
+up a test representative of your workload and ensure Node.js/zlib will handle
+it with acceptable performance and memory usage.
+
+Tuning of permessage-deflate can be done via the options defined below. You can
+also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly
+into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs].
+
+See [the docs][ws-server-options] for more options.
+
+```js
+const WebSocket = require('ws');
+
+const wss = new WebSocket.Server({
+  port: 8080,
+  perMessageDeflate: {
+    zlibDeflateOptions: { // See zlib defaults.
+      chunkSize: 1024,
+      memLevel: 7,
+      level: 3,
+    },
+    zlibInflateOptions: {
+      chunkSize: 10 * 1024
+    },
+    // Other options settable:
+    clientNoContextTakeover: true, // Defaults to negotiated value.
+    serverNoContextTakeover: true, // Defaults to negotiated value.
+    clientMaxWindowBits: 10,       // Defaults to negotiated value.
+    serverMaxWindowBits: 10,       // Defaults to negotiated value.
+    // Below options specified as default values.
+    concurrencyLimit: 10,          // Limits zlib concurrency for perf.
+    threshold: 1024,               // Size (in bytes) below which messages
+                                   // should not be compressed.
+  }
+});
+```
+
+The client will only use the extension if it is supported and enabled on the
+server. To always disable the extension on the client set the
+`perMessageDeflate` option to `false`.
+
+```js
+const WebSocket = require('ws');
+
+const ws = new WebSocket('ws://www.host.com/path', {
+  perMessageDeflate: false
+});
+```
+
+## Usage examples
+
 ### Sending and receiving text data
 
 ```js
-var WebSocket = require('ws');
-var ws = new WebSocket('ws://www.host.com/path');
+const WebSocket = require('ws');
+
+const ws = new WebSocket('ws://www.host.com/path');
 
 ws.on('open', function open() {
   ws.send('something');
 });
 
-ws.on('message', function(data, flags) {
-  // flags.binary will be set if a binary data is received.
-  // flags.masked will be set if the data was masked.
+ws.on('message', function incoming(data) {
+  console.log(data);
 });
 ```
 
 ### Sending binary data
 
 ```js
-var WebSocket = require('ws');
-var ws = new WebSocket('ws://www.host.com/path');
+const WebSocket = require('ws');
+
+const ws = new WebSocket('ws://www.host.com/path');
 
 ws.on('open', function open() {
-  var array = new Float32Array(5);
+  const array = new Float32Array(5);
 
   for (var i = 0; i < array.length; ++i) {
     array[i] = i / 2;
   }
 
-  ws.send(array, { binary: true, mask: true });
+  ws.send(array);
 });
 ```
 
-Setting `mask`, as done for the send options above, will cause the data to be
-masked according to the WebSocket protocol. The same option applies for text
-data.
-
-### Server example
+### Simple server
 
 ```js
-var WebSocketServer = require('ws').Server
-  , wss = new WebSocketServer({ port: 8080 });
+const WebSocket = require('ws');
+
+const wss = new WebSocket.Server({ port: 8080 });
 
 wss.on('connection', function connection(ws) {
   ws.on('message', function incoming(message) {
@@ -74,63 +186,118 @@ wss.on('connection', function connection(ws) {
 });
 ```
 
-### Server sending broadcast data
+### External HTTP/S server
 
 ```js
-var WebSocketServer = require('ws').Server
-  , wss = new WebSocketServer({ port: 8080 });
+const fs = require('fs');
+const https = require('https');
+const WebSocket = require('ws');
 
-wss.broadcast = function broadcast(data) {
-  wss.clients.forEach(function each(client) {
-    client.send(data);
+const server = new https.createServer({
+  cert: fs.readFileSync('/path/to/cert.pem'),
+  key: fs.readFileSync('/path/to/key.pem')
+});
+const wss = new WebSocket.Server({ server });
+
+wss.on('connection', function connection(ws) {
+  ws.on('message', function incoming(message) {
+    console.log('received: %s', message);
   });
-};
+
+  ws.send('something');
+});
+
+server.listen(8080);
 ```
 
-### Error handling best practices
+### Multiple servers sharing a single HTTP/S server
 
 ```js
-// If the WebSocket is closed before the following send is attempted
-ws.send('something');
+const http = require('http');
+const WebSocket = require('ws');
 
-// Errors (both immediate and async write errors) can be detected in an optional
-// callback. The callback is also the only way of being notified that data has
-// actually been sent.
-ws.send('something', function ack(error) {
-  // if error is not defined, the send has been completed,
-  // otherwise the error object will indicate what failed.
+const server = http.createServer();
+const wss1 = new WebSocket.Server({ noServer: true });
+const wss2 = new WebSocket.Server({ noServer: true });
+
+wss1.on('connection', function connection(ws) {
+  // ...
 });
 
-// Immediate errors can also be handled with try/catch-blocks, but **note** that
-// since sends are inherently asynchronous, socket write failures will *not* be
-// captured when this technique is used.
-try { ws.send('something'); }
-catch (e) { /* handle error */ }
+wss2.on('connection', function connection(ws) {
+  // ...
+});
+
+server.on('upgrade', function upgrade(request, socket, head) {
+  const pathname = url.parse(request.url).pathname;
+
+  if (pathname === '/foo') {
+    wss1.handleUpgrade(request, socket, head, function done(ws) {
+      wss1.emit('connection', ws, request);
+    });
+  } else if (pathname === '/bar') {
+    wss2.handleUpgrade(request, socket, head, function done(ws) {
+      wss2.emit('connection', ws, request);
+    });
+  } else {
+    socket.destroy();
+  }
+});
+
+server.listen(8080);
+```
+
+### Server broadcast
+
+```js
+const WebSocket = require('ws');
+
+const wss = new WebSocket.Server({ port: 8080 });
+
+// Broadcast to all.
+wss.broadcast = function broadcast(data) {
+  wss.clients.forEach(function each(client) {
+    if (client.readyState === WebSocket.OPEN) {
+      client.send(data);
+    }
+  });
+};
+
+wss.on('connection', function connection(ws) {
+  ws.on('message', function incoming(data) {
+    // Broadcast to everyone else.
+    wss.clients.forEach(function each(client) {
+      if (client !== ws && client.readyState === WebSocket.OPEN) {
+        client.send(data);
+      }
+    });
+  });
+});
 ```
 
 ### echo.websocket.org demo
 
 ```js
-var WebSocket = require('ws');
-var ws = new WebSocket('ws://echo.websocket.org/', {
-  protocolVersion: 8, 
-  origin: 'http://websocket.org'
+const WebSocket = require('ws');
+
+const ws = new WebSocket('wss://echo.websocket.org/', {
+  origin: 'https://websocket.org'
 });
 
 ws.on('open', function open() {
   console.log('connected');
-  ws.send(Date.now().toString(), {mask: true});
+  ws.send(Date.now());
 });
 
 ws.on('close', function close() {
   console.log('disconnected');
 });
 
-ws.on('message', function message(data, flags) {
-  console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags);
+ws.on('message', function incoming(data) {
+  console.log(`Roundtrip time: ${Date.now() - data} ms`);
 
   setTimeout(function timeout() {
-    ws.send(Date.now().toString(), {mask: true});
+    ws.send(Date.now());
   }, 500);
 });
 ```
@@ -140,48 +307,111 @@ ws.on('message', function message(data, flags) {
 For a full example with a browser client communicating with a ws server, see the
 examples folder.
 
-Note that the usage together with Express 3.0 is quite different from Express
-2.x. The difference is expressed in the two different serverstats-examples.
-
 Otherwise, see the test cases.
 
-### Running the tests
+## Error handling best practices
+
+```js
+// If the WebSocket is closed before the following send is attempted
+ws.send('something');
+
+// Errors (both immediate and async write errors) can be detected in an optional
+// callback. The callback is also the only way of being notified that data has
+// actually been sent.
+ws.send('something', function ack(error) {
+  // If error is not defined, the send has been completed, otherwise the error
+  // object will indicate what failed.
+});
+
+// Immediate errors can also be handled with `try...catch`, but **note** that
+// since sends are inherently asynchronous, socket write failures will *not* be
+// captured when this technique is used.
+try { ws.send('something'); }
+catch (e) { /* handle error */ }
+```
+
+## FAQ
+
+### How to get the IP address of the client?
+
+The remote IP address can be obtained from the raw socket.
+
+```js
+const WebSocket = require('ws');
 
+const wss = new WebSocket.Server({ port: 8080 });
+
+wss.on('connection', function connection(ws, req) {
+  const ip = req.connection.remoteAddress;
+});
 ```
-make test
+
+When the server runs behind a proxy like NGINX, the de-facto standard is to use
+the `X-Forwarded-For` header.
+
+```js
+wss.on('connection', function connection(ws, req) {
+  const ip = req.headers['x-forwarded-for'].split(/\s*,\s*/)[0];
+});
 ```
 
-## API Docs
+### How to detect and close broken connections?
 
-See the doc/ directory for Node.js-like docs for the ws classes.
+Sometimes the link between the server and the client can be interrupted in a
+way that keeps both the server and the client unaware of the broken state of the
+connection (e.g. when pulling the cord).
 
-## Changelog
+In these cases ping messages can be used as a means to verify that the remote
+endpoint is still responsive.
 
-We're using the GitHub `releases` for changelog entries.
+```js
+const WebSocket = require('ws');
 
-## License
+const wss = new WebSocket.Server({ port: 8080 });
+
+function noop() {}
+
+function heartbeat() {
+  this.isAlive = true;
+}
+
+wss.on('connection', function connection(ws) {
+  ws.isAlive = true;
+  ws.on('pong', heartbeat);
+});
 
-(The MIT License)
+const interval = setInterval(function ping() {
+  wss.clients.forEach(function each(ws) {
+    if (ws.isAlive === false) return ws.terminate();
 
-Copyright (c) 2011 Einar Otto Stangvik &lt;einaros@gmail.com&gt;
+    ws.isAlive = false;
+    ws.ping(noop);
+  });
+}, 30000);
+```
 
-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:
+Pong messages are automatically sent in response to ping messages as required
+by the spec.
 
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
+### How to connect via a proxy?
 
-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.
+Use a custom `http.Agent` implementation like [https-proxy-agent][] or
+[socks-proxy-agent][].
+
+## Changelog
+
+We're using the GitHub [releases][changelog] for changelog entries.
+
+## License
 
-[archive]: http://web.archive.org/web/20130314230536/http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs
+[MIT](LICENSE)
+
+[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
+[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
+[client-report]: http://websockets.github.io/ws/autobahn/clients/
+[server-report]: http://websockets.github.io/ws/autobahn/servers/
+[permessage-deflate]: https://tools.ietf.org/html/rfc7692
+[changelog]: https://github.com/websockets/ws/releases
+[node-zlib-bug]: https://github.com/nodejs/node/issues/8871
+[node-zlib-deflaterawdocs]: https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options
+[ws-server-options]: https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback
diff --git a/input_devices/mag/node_modules/ws/browser.js b/input_devices/mag/node_modules/ws/browser.js
new file mode 100644
index 00000000..ca4f628a
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/browser.js
@@ -0,0 +1,8 @@
+'use strict';
+
+module.exports = function () {
+  throw new Error(
+    'ws does not work in the browser. Browser clients must use the native ' +
+      'WebSocket object'
+  );
+};
diff --git a/input_devices/mag/node_modules/ws/index.js b/input_devices/mag/node_modules/ws/index.js
index a7e8644b..b8d6be1c 100644
--- a/input_devices/mag/node_modules/ws/index.js
+++ b/input_devices/mag/node_modules/ws/index.js
@@ -1,49 +1,9 @@
 'use strict';
 
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
+const WebSocket = require('./lib/websocket');
 
-var WS = module.exports = require('./lib/WebSocket');
+WebSocket.Server = require('./lib/websocket-server');
+WebSocket.Receiver = require('./lib/receiver');
+WebSocket.Sender = require('./lib/sender');
 
-WS.Server = require('./lib/WebSocketServer');
-WS.Sender = require('./lib/Sender');
-WS.Receiver = require('./lib/Receiver');
-
-/**
- * Create a new WebSocket server.
- *
- * @param {Object} options Server options
- * @param {Function} fn Optional connection listener.
- * @returns {WS.Server}
- * @api public
- */
-WS.createServer = function createServer(options, fn) {
-  var server = new WS.Server(options);
-
-  if (typeof fn === 'function') {
-    server.on('connection', fn);
-  }
-
-  return server;
-};
-
-/**
- * Create a new WebSocket connection.
- *
- * @param {String} address The URL/address we need to connect to.
- * @param {Function} fn Open listener.
- * @returns {WS}
- * @api public
- */
-WS.connect = WS.createConnection = function connect(address, fn) {
-  var client = new WS(address);
-
-  if (typeof fn === 'function') {
-    client.on('open', fn);
-  }
-
-  return client;
-};
+module.exports = WebSocket;
diff --git a/input_devices/mag/node_modules/ws/lib/BufferPool.js b/input_devices/mag/node_modules/ws/lib/BufferPool.js
deleted file mode 100644
index faf8637c..00000000
--- a/input_devices/mag/node_modules/ws/lib/BufferPool.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var util = require('util');
-
-function BufferPool(initialSize, growStrategy, shrinkStrategy) {
-  if (typeof initialSize === 'function') {
-    shrinkStrategy = growStrategy;
-    growStrategy = initialSize;
-    initialSize = 0;
-  }
-  else if (typeof initialSize === 'undefined') {
-    initialSize = 0;
-  }
-  this._growStrategy = (growStrategy || function(db, size) {
-    return db.used + size;
-  }).bind(null, this);
-  this._shrinkStrategy = (shrinkStrategy || function(db) {
-    return initialSize;
-  }).bind(null, this);
-  this._buffer = initialSize ? new Buffer(initialSize) : null;
-  this._offset = 0;
-  this._used = 0;
-  this._changeFactor = 0;
-  this.__defineGetter__('size', function(){
-    return this._buffer == null ? 0 : this._buffer.length;
-  });
-  this.__defineGetter__('used', function(){
-    return this._used;
-  });
-}
-
-BufferPool.prototype.get = function(length) {
-  if (this._buffer == null || this._offset + length > this._buffer.length) {
-    var newBuf = new Buffer(this._growStrategy(length));
-    this._buffer = newBuf;
-    this._offset = 0;
-  }
-  this._used += length;
-  var buf = this._buffer.slice(this._offset, this._offset + length);
-  this._offset += length;
-  return buf;
-}
-
-BufferPool.prototype.reset = function(forceNewBuffer) {
-  var len = this._shrinkStrategy();
-  if (len < this.size) this._changeFactor -= 1;
-  if (forceNewBuffer || this._changeFactor < -2) {
-    this._changeFactor = 0;
-    this._buffer = len ? new Buffer(len) : null;
-  }
-  this._offset = 0;
-  this._used = 0;
-}
-
-module.exports = BufferPool;
diff --git a/input_devices/mag/node_modules/ws/lib/BufferUtil.fallback.js b/input_devices/mag/node_modules/ws/lib/BufferUtil.fallback.js
deleted file mode 100644
index 508542c9..00000000
--- a/input_devices/mag/node_modules/ws/lib/BufferUtil.fallback.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-module.exports.BufferUtil = {
-  merge: function(mergedBuffer, buffers) {
-    var offset = 0;
-    for (var i = 0, l = buffers.length; i < l; ++i) {
-      var buf = buffers[i];
-      buf.copy(mergedBuffer, offset);
-      offset += buf.length;
-    }
-  },
-  mask: function(source, mask, output, offset, length) {
-    var maskNum = mask.readUInt32LE(0, true);
-    var i = 0;
-    for (; i < length - 3; i += 4) {
-      var num = maskNum ^ source.readUInt32LE(i, true);
-      if (num < 0) num = 4294967296 + num;
-      output.writeUInt32LE(num, offset + i, true);
-    }
-    switch (length % 4) {
-      case 3: output[offset + i + 2] = source[i + 2] ^ mask[2];
-      case 2: output[offset + i + 1] = source[i + 1] ^ mask[1];
-      case 1: output[offset + i] = source[i] ^ mask[0];
-      case 0:;
-    }
-  },
-  unmask: function(data, mask) {
-    var maskNum = mask.readUInt32LE(0, true);
-    var length = data.length;
-    var i = 0;
-    for (; i < length - 3; i += 4) {
-      var num = maskNum ^ data.readUInt32LE(i, true);
-      if (num < 0) num = 4294967296 + num;
-      data.writeUInt32LE(num, i, true);
-    }
-    switch (length % 4) {
-      case 3: data[i + 2] = data[i + 2] ^ mask[2];
-      case 2: data[i + 1] = data[i + 1] ^ mask[1];
-      case 1: data[i] = data[i] ^ mask[0];
-      case 0:;
-    }
-  }
-}
diff --git a/input_devices/mag/node_modules/ws/lib/BufferUtil.js b/input_devices/mag/node_modules/ws/lib/BufferUtil.js
deleted file mode 100644
index 18c69989..00000000
--- a/input_devices/mag/node_modules/ws/lib/BufferUtil.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict';
-
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-try {
-  module.exports = require('bufferutil');
-} catch (e) {
-  module.exports = require('./BufferUtil.fallback');
-}
diff --git a/input_devices/mag/node_modules/ws/lib/ErrorCodes.js b/input_devices/mag/node_modules/ws/lib/ErrorCodes.js
deleted file mode 100644
index 55ebd529..00000000
--- a/input_devices/mag/node_modules/ws/lib/ErrorCodes.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-module.exports = {
-  isValidErrorCode: function(code) {
-    return (code >= 1000 && code <= 1011 && code != 1004 && code != 1005 && code != 1006) ||
-         (code >= 3000 && code <= 4999);
-  },
-  1000: 'normal',
-  1001: 'going away',
-  1002: 'protocol error',
-  1003: 'unsupported data',
-  1004: 'reserved',
-  1005: 'reserved for extensions',
-  1006: 'reserved for extensions',
-  1007: 'inconsistent or invalid data',
-  1008: 'policy violation',
-  1009: 'message too big',
-  1010: 'extension handshake missing',
-  1011: 'an unexpected condition prevented the request from being fulfilled',
-};
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/ws/lib/Extensions.js b/input_devices/mag/node_modules/ws/lib/Extensions.js
deleted file mode 100644
index a465ace2..00000000
--- a/input_devices/mag/node_modules/ws/lib/Extensions.js
+++ /dev/null
@@ -1,70 +0,0 @@
-
-var util = require('util');
-
-/**
- * Module exports.
- */
-
-exports.parse = parse;
-exports.format = format;
-
-/**
- * Parse extensions header value
- */
-
-function parse(value) {
-  value = value || '';
-
-  var extensions = {};
-
-  value.split(',').forEach(function(v) {
-    var params = v.split(';');
-    var token = params.shift().trim();
-    var paramsList = extensions[token] = extensions[token] || [];
-    var parsedParams = {};
-
-    params.forEach(function(param) {
-      var parts = param.trim().split('=');
-      var key = parts[0];
-      var value = parts[1];
-      if (typeof value === 'undefined') {
-        value = true;
-      } else {
-        // unquote value
-        if (value[0] === '"') {
-          value = value.slice(1);
-        }
-        if (value[value.length - 1] === '"') {
-          value = value.slice(0, value.length - 1);
-        }
-      }
-      (parsedParams[key] = parsedParams[key] || []).push(value);
-    });
-
-    paramsList.push(parsedParams);
-  });
-
-  return extensions;
-}
-
-/**
- * Format extensions header value
- */
-
-function format(value) {
-  return Object.keys(value).map(function(token) {
-    var paramsList = value[token];
-    if (!util.isArray(paramsList)) {
-      paramsList = [paramsList];
-    }
-    return paramsList.map(function(params) {
-      return [token].concat(Object.keys(params).map(function(k) {
-        var p = params[k];
-        if (!util.isArray(p)) p = [p];
-        return p.map(function(v) {
-          return v === true ? k : k + '=' + v;
-        }).join('; ');
-      })).join('; ');
-    }).join(', ');
-  }).join(', ');
-}
diff --git a/input_devices/mag/node_modules/ws/lib/PerMessageDeflate.js b/input_devices/mag/node_modules/ws/lib/PerMessageDeflate.js
deleted file mode 100644
index f7359779..00000000
--- a/input_devices/mag/node_modules/ws/lib/PerMessageDeflate.js
+++ /dev/null
@@ -1,289 +0,0 @@
-
-var zlib = require('zlib');
-
-var AVAILABLE_WINDOW_BITS = [8, 9, 10, 11, 12, 13, 14, 15];
-var DEFAULT_WINDOW_BITS = 15;
-var DEFAULT_MEM_LEVEL = 8;
-
-PerMessageDeflate.extensionName = 'permessage-deflate';
-
-/**
- * Per-message Compression Extensions implementation
- */
-
-function PerMessageDeflate(options, isServer) {
-  this._options = options || {};
-  this._isServer = !!isServer;
-  this._inflate = null;
-  this._deflate = null;
-  this.params = null;
-}
-
-/**
- * Create extension parameters offer
- *
- * @api public
- */
-
-PerMessageDeflate.prototype.offer = function() {
-  var params = {};
-  if (this._options.serverNoContextTakeover) {
-    params.server_no_context_takeover = true;
-  }
-  if (this._options.clientNoContextTakeover) {
-    params.client_no_context_takeover = true;
-  }
-  if (this._options.serverMaxWindowBits) {
-    params.server_max_window_bits = this._options.serverMaxWindowBits;
-  }
-  if (this._options.clientMaxWindowBits) {
-    params.client_max_window_bits = this._options.clientMaxWindowBits;
-  } else if (this._options.clientMaxWindowBits == null) {
-    params.client_max_window_bits = true;
-  }
-  return params;
-};
-
-/**
- * Accept extension offer
- *
- * @api public
- */
-
-PerMessageDeflate.prototype.accept = function(paramsList) {
-  paramsList = this.normalizeParams(paramsList);
-
-  var params;
-  if (this._isServer) {
-    params = this.acceptAsServer(paramsList);
-  } else {
-    params = this.acceptAsClient(paramsList);
-  }
-
-  this.params = params;
-  return params;
-};
-
-/**
- * Accept extension offer from client
- *
- * @api private
- */
-
-PerMessageDeflate.prototype.acceptAsServer = function(paramsList) {
-  var accepted = {};
-  var result = paramsList.some(function(params) {
-    accepted = {};
-    if (this._options.serverNoContextTakeover === false && params.server_no_context_takeover) {
-      return;
-    }
-    if (this._options.serverMaxWindowBits === false && params.server_max_window_bits) {
-      return;
-    }
-    if (typeof this._options.serverMaxWindowBits === 'number' &&
-        typeof params.server_max_window_bits === 'number' &&
-        this._options.serverMaxWindowBits > params.server_max_window_bits) {
-      return;
-    }
-    if (typeof this._options.clientMaxWindowBits === 'number' && !params.client_max_window_bits) {
-      return;
-    }
-
-    if (this._options.serverNoContextTakeover || params.server_no_context_takeover) {
-      accepted.server_no_context_takeover = true;
-    }
-    if (this._options.clientNoContextTakeover) {
-      accepted.client_no_context_takeover = true;
-    }
-    if (this._options.clientNoContextTakeover !== false && params.client_no_context_takeover) {
-      accepted.client_no_context_takeover = true;
-    }
-    if (typeof this._options.serverMaxWindowBits === 'number') {
-      accepted.server_max_window_bits = this._options.serverMaxWindowBits;
-    } else if (typeof params.server_max_window_bits === 'number') {
-      accepted.server_max_window_bits = params.server_max_window_bits;
-    }
-    if (typeof this._options.clientMaxWindowBits === 'number') {
-      accepted.client_max_window_bits = this._options.clientMaxWindowBits;
-    } else if (this._options.clientMaxWindowBits !== false && typeof params.client_max_window_bits === 'number') {
-      accepted.client_max_window_bits = params.client_max_window_bits;
-    }
-    return true;
-  }, this);
-
-  if (!result) {
-    throw new Error('Doesn\'t support the offered configuration');
-  }
-
-  return accepted;
-};
-
-/**
- * Accept extension response from server
- *
- * @api privaye
- */
-
-PerMessageDeflate.prototype.acceptAsClient = function(paramsList) {
-  var params = paramsList[0];
-  if (this._options.clientNoContextTakeover != null) {
-    if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) {
-      throw new Error('Invalid value for "client_no_context_takeover"');
-    }
-  }
-  if (this._options.clientMaxWindowBits != null) {
-    if (this._options.clientMaxWindowBits === false && params.client_max_window_bits) {
-      throw new Error('Invalid value for "client_max_window_bits"');
-    }
-    if (typeof this._options.clientMaxWindowBits === 'number' &&
-        (!params.client_max_window_bits || params.client_max_window_bits > this._options.clientMaxWindowBits)) {
-      throw new Error('Invalid value for "client_max_window_bits"');
-    }
-  }
-  return params;
-};
-
-/**
- * Normalize extensions parameters
- *
- * @api private
- */
-
-PerMessageDeflate.prototype.normalizeParams = function(paramsList) {
-  return paramsList.map(function(params) {
-    Object.keys(params).forEach(function(key) {
-      var value = params[key];
-      if (value.length > 1) {
-        throw new Error('Multiple extension parameters for ' + key);
-      }
-
-      value = value[0];
-
-      switch (key) {
-      case 'server_no_context_takeover':
-      case 'client_no_context_takeover':
-        if (value !== true) {
-          throw new Error('invalid extension parameter value for ' + key + ' (' + value + ')');
-        }
-        params[key] = true;
-        break;
-      case 'server_max_window_bits':
-      case 'client_max_window_bits':
-        if (typeof value === 'string') {
-          value = parseInt(value, 10);
-          if (!~AVAILABLE_WINDOW_BITS.indexOf(value)) {
-            throw new Error('invalid extension parameter value for ' + key + ' (' + value + ')');
-          }
-        }
-        if (!this._isServer && value === true) {
-          throw new Error('Missing extension parameter value for ' + key);
-        }
-        params[key] = value;
-        break;
-      default:
-        throw new Error('Not defined extension parameter (' + key + ')');
-      }
-    }, this);
-    return params;
-  }, this);
-};
-
-/**
- * Decompress message
- *
- * @api public
- */
-
-PerMessageDeflate.prototype.decompress = function (data, fin, callback) {
-  var endpoint = this._isServer ? 'client' : 'server';
-
-  if (!this._inflate) {
-    var maxWindowBits = this.params[endpoint + '_max_window_bits'];
-    this._inflate = zlib.createInflateRaw({
-      windowBits: 'number' === typeof maxWindowBits ? maxWindowBits : DEFAULT_WINDOW_BITS
-    });
-  }
-
-  var self = this;
-  var buffers = [];
-
-  this._inflate.on('error', onError).on('data', onData);
-  this._inflate.write(data);
-  if (fin) {
-    this._inflate.write(new Buffer([0x00, 0x00, 0xff, 0xff]));
-  }
-  this._inflate.flush(function() {
-    cleanup();
-    callback(null, Buffer.concat(buffers));
-  });
-
-  function onError(err) {
-    cleanup();
-    callback(err);
-  }
-
-  function onData(data) {
-    buffers.push(data);
-  }
-
-  function cleanup() {
-    self._inflate.removeListener('error', onError);
-    self._inflate.removeListener('data', onData);
-    if (fin && self.params[endpoint + '_no_context_takeover']) {
-      self._inflate = null;
-    }
-  }
-};
-
-/**
- * Compress message
- *
- * @api public
- */
-
-PerMessageDeflate.prototype.compress = function (data, fin, callback) {
-  var endpoint = this._isServer ? 'server' : 'client';
-
-  if (!this._deflate) {
-    var maxWindowBits = this.params[endpoint + '_max_window_bits'];
-    this._deflate = zlib.createDeflateRaw({
-      flush: zlib.Z_SYNC_FLUSH,
-      windowBits: 'number' === typeof maxWindowBits ? maxWindowBits : DEFAULT_WINDOW_BITS,
-      memLevel: this._options.memLevel || DEFAULT_MEM_LEVEL
-    });
-  }
-
-  var self = this;
-  var buffers = [];
-
-  this._deflate.on('error', onError).on('data', onData);
-  this._deflate.write(data);
-  this._deflate.flush(function() {
-    cleanup();
-    var data = Buffer.concat(buffers);
-    if (fin) {
-      data = data.slice(0, data.length - 4);
-    }
-    callback(null, data);
-  });
-
-  function onError(err) {
-    cleanup();
-    callback(err);
-  }
-
-  function onData(data) {
-    buffers.push(data);
-  }
-
-  function cleanup() {
-    self._deflate.removeListener('error', onError);
-    self._deflate.removeListener('data', onData);
-    if (fin && self.params[endpoint + '_no_context_takeover']) {
-      self._deflate = null;
-    }
-  }
-};
-
-module.exports = PerMessageDeflate;
-
diff --git a/input_devices/mag/node_modules/ws/lib/Receiver.hixie.js b/input_devices/mag/node_modules/ws/lib/Receiver.hixie.js
deleted file mode 100644
index a8e41c47..00000000
--- a/input_devices/mag/node_modules/ws/lib/Receiver.hixie.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var util = require('util');
-
-/**
- * State constants
- */
-
-var EMPTY = 0
-  , BODY = 1;
-var BINARYLENGTH = 2
-  , BINARYBODY = 3;
-
-/**
- * Hixie Receiver implementation
- */
-
-function Receiver () {
-  this.state = EMPTY;
-  this.buffers = [];
-  this.messageEnd = -1;
-  this.spanLength = 0;
-  this.dead = false;
-
-  this.onerror = function() {};
-  this.ontext = function() {};
-  this.onbinary = function() {};
-  this.onclose = function() {};
-  this.onping = function() {};
-  this.onpong = function() {};
-}
-
-module.exports = Receiver;
-
-/**
- * Add new data to the parser.
- *
- * @api public
- */
-
-Receiver.prototype.add = function(data) {
-  var self = this;
-  function doAdd() {
-    if (self.state === EMPTY) {
-      if (data.length == 2 && data[0] == 0xFF && data[1] == 0x00) {
-        self.reset();
-        self.onclose();
-        return;
-      }
-      if (data[0] === 0x80) {
-        self.messageEnd = 0;
-        self.state = BINARYLENGTH;
-        data = data.slice(1);
-      } else {
-
-      if (data[0] !== 0x00) {
-        self.error('payload must start with 0x00 byte', true);
-        return;
-      }
-      data = data.slice(1);
-      self.state = BODY;
-
-      }
-    }
-    if (self.state === BINARYLENGTH) {
-      var i = 0;
-      while ((i < data.length) && (data[i] & 0x80)) {
-        self.messageEnd = 128 * self.messageEnd + (data[i] & 0x7f);
-        ++i;
-      }
-      if (i < data.length) {
-        self.messageEnd = 128 * self.messageEnd + (data[i] & 0x7f);
-        self.state = BINARYBODY;
-        ++i;
-      }
-      if (i > 0)
-        data = data.slice(i);
-    }
-    if (self.state === BINARYBODY) {
-      var dataleft = self.messageEnd - self.spanLength;
-      if (data.length >= dataleft) {
-        // consume the whole buffer to finish the frame
-        self.buffers.push(data);
-        self.spanLength += dataleft;
-        self.messageEnd = dataleft;
-        return self.parse();
-      }
-      // frame's not done even if we consume it all
-      self.buffers.push(data);
-      self.spanLength += data.length;
-      return;
-    }
-    self.buffers.push(data);
-    if ((self.messageEnd = bufferIndex(data, 0xFF)) != -1) {
-      self.spanLength += self.messageEnd;
-      return self.parse();
-    }
-    else self.spanLength += data.length;
-  }
-  while(data) data = doAdd();
-};
-
-/**
- * Releases all resources used by the receiver.
- *
- * @api public
- */
-
-Receiver.prototype.cleanup = function() {
-  this.dead = true;
-  this.state = EMPTY;
-  this.buffers = [];
-};
-
-/**
- * Process buffered data.
- *
- * @api public
- */
-
-Receiver.prototype.parse = function() {
-  var output = new Buffer(this.spanLength);
-  var outputIndex = 0;
-  for (var bi = 0, bl = this.buffers.length; bi < bl - 1; ++bi) {
-    var buffer = this.buffers[bi];
-    buffer.copy(output, outputIndex);
-    outputIndex += buffer.length;
-  }
-  var lastBuffer = this.buffers[this.buffers.length - 1];
-  if (this.messageEnd > 0) lastBuffer.copy(output, outputIndex, 0, this.messageEnd);
-  if (this.state !== BODY) --this.messageEnd;
-  var tail = null;
-  if (this.messageEnd < lastBuffer.length - 1) {
-    tail = lastBuffer.slice(this.messageEnd + 1);
-  }
-  this.reset();
-  this.ontext(output.toString('utf8'));
-  return tail;
-};
-
-/**
- * Handles an error
- *
- * @api private
- */
-
-Receiver.prototype.error = function (reason, terminate) {
-  this.reset();
-  this.onerror(reason, terminate);
-  return this;
-};
-
-/**
- * Reset parser state
- *
- * @api private
- */
-
-Receiver.prototype.reset = function (reason) {
-  if (this.dead) return;
-  this.state = EMPTY;
-  this.buffers = [];
-  this.messageEnd = -1;
-  this.spanLength = 0;
-};
-
-/**
- * Internal api
- */
-
-function bufferIndex(buffer, byte) {
-  for (var i = 0, l = buffer.length; i < l; ++i) {
-    if (buffer[i] === byte) return i;
-  }
-  return -1;
-}
diff --git a/input_devices/mag/node_modules/ws/lib/Receiver.js b/input_devices/mag/node_modules/ws/lib/Receiver.js
deleted file mode 100644
index 1ae1c4e8..00000000
--- a/input_devices/mag/node_modules/ws/lib/Receiver.js
+++ /dev/null
@@ -1,698 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var util = require('util')
-  , Validation = require('./Validation').Validation
-  , ErrorCodes = require('./ErrorCodes')
-  , BufferPool = require('./BufferPool')
-  , bufferUtil = require('./BufferUtil').BufferUtil
-  , PerMessageDeflate = require('./PerMessageDeflate');
-
-/**
- * HyBi Receiver implementation
- */
-
-function Receiver (extensions) {
-  // memory pool for fragmented messages
-  var fragmentedPoolPrevUsed = -1;
-  this.fragmentedBufferPool = new BufferPool(1024, function(db, length) {
-    return db.used + length;
-  }, function(db) {
-    return fragmentedPoolPrevUsed = fragmentedPoolPrevUsed >= 0 ?
-      (fragmentedPoolPrevUsed + db.used) / 2 :
-      db.used;
-  });
-
-  // memory pool for unfragmented messages
-  var unfragmentedPoolPrevUsed = -1;
-  this.unfragmentedBufferPool = new BufferPool(1024, function(db, length) {
-    return db.used + length;
-  }, function(db) {
-    return unfragmentedPoolPrevUsed = unfragmentedPoolPrevUsed >= 0 ?
-      (unfragmentedPoolPrevUsed + db.used) / 2 :
-      db.used;
-  });
-
-  this.extensions = extensions || {};
-  this.state = {
-    activeFragmentedOperation: null,
-    lastFragment: false,
-    masked: false,
-    opcode: 0,
-    fragmentedOperation: false
-  };
-  this.overflow = [];
-  this.headerBuffer = new Buffer(10);
-  this.expectOffset = 0;
-  this.expectBuffer = null;
-  this.expectHandler = null;
-  this.currentMessage = [];
-  this.messageHandlers = [];
-  this.expectHeader(2, this.processPacket);
-  this.dead = false;
-  this.processing = false;
-
-  this.onerror = function() {};
-  this.ontext = function() {};
-  this.onbinary = function() {};
-  this.onclose = function() {};
-  this.onping = function() {};
-  this.onpong = function() {};
-}
-
-module.exports = Receiver;
-
-/**
- * Add new data to the parser.
- *
- * @api public
- */
-
-Receiver.prototype.add = function(data) {
-  var dataLength = data.length;
-  if (dataLength == 0) return;
-  if (this.expectBuffer == null) {
-    this.overflow.push(data);
-    return;
-  }
-  var toRead = Math.min(dataLength, this.expectBuffer.length - this.expectOffset);
-  fastCopy(toRead, data, this.expectBuffer, this.expectOffset);
-  this.expectOffset += toRead;
-  if (toRead < dataLength) {
-    this.overflow.push(data.slice(toRead));
-  }
-  while (this.expectBuffer && this.expectOffset == this.expectBuffer.length) {
-    var bufferForHandler = this.expectBuffer;
-    this.expectBuffer = null;
-    this.expectOffset = 0;
-    this.expectHandler.call(this, bufferForHandler);
-  }
-};
-
-/**
- * Releases all resources used by the receiver.
- *
- * @api public
- */
-
-Receiver.prototype.cleanup = function() {
-  this.dead = true;
-  this.overflow = null;
-  this.headerBuffer = null;
-  this.expectBuffer = null;
-  this.expectHandler = null;
-  this.unfragmentedBufferPool = null;
-  this.fragmentedBufferPool = null;
-  this.state = null;
-  this.currentMessage = null;
-  this.onerror = null;
-  this.ontext = null;
-  this.onbinary = null;
-  this.onclose = null;
-  this.onping = null;
-  this.onpong = null;
-};
-
-/**
- * Waits for a certain amount of header bytes to be available, then fires a callback.
- *
- * @api private
- */
-
-Receiver.prototype.expectHeader = function(length, handler) {
-  if (length == 0) {
-    handler(null);
-    return;
-  }
-  this.expectBuffer = this.headerBuffer.slice(this.expectOffset, this.expectOffset + length);
-  this.expectHandler = handler;
-  var toRead = length;
-  while (toRead > 0 && this.overflow.length > 0) {
-    var fromOverflow = this.overflow.pop();
-    if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead));
-    var read = Math.min(fromOverflow.length, toRead);
-    fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset);
-    this.expectOffset += read;
-    toRead -= read;
-  }
-};
-
-/**
- * Waits for a certain amount of data bytes to be available, then fires a callback.
- *
- * @api private
- */
-
-Receiver.prototype.expectData = function(length, handler) {
-  if (length == 0) {
-    handler(null);
-    return;
-  }
-  this.expectBuffer = this.allocateFromPool(length, this.state.fragmentedOperation);
-  this.expectHandler = handler;
-  var toRead = length;
-  while (toRead > 0 && this.overflow.length > 0) {
-    var fromOverflow = this.overflow.pop();
-    if (toRead < fromOverflow.length) this.overflow.push(fromOverflow.slice(toRead));
-    var read = Math.min(fromOverflow.length, toRead);
-    fastCopy(read, fromOverflow, this.expectBuffer, this.expectOffset);
-    this.expectOffset += read;
-    toRead -= read;
-  }
-};
-
-/**
- * Allocates memory from the buffer pool.
- *
- * @api private
- */
-
-Receiver.prototype.allocateFromPool = function(length, isFragmented) {
-  return (isFragmented ? this.fragmentedBufferPool : this.unfragmentedBufferPool).get(length);
-};
-
-/**
- * Start processing a new packet.
- *
- * @api private
- */
-
-Receiver.prototype.processPacket = function (data) {
-  if (this.extensions[PerMessageDeflate.extensionName]) {
-    if ((data[0] & 0x30) != 0) {
-      this.error('reserved fields (2, 3) must be empty', 1002);
-      return;
-    }
-  } else {
-    if ((data[0] & 0x70) != 0) {
-      this.error('reserved fields must be empty', 1002);
-      return;
-    }
-  }
-  this.state.lastFragment = (data[0] & 0x80) == 0x80;
-  this.state.masked = (data[1] & 0x80) == 0x80;
-  var compressed = (data[0] & 0x40) == 0x40;
-  var opcode = data[0] & 0xf;
-  if (opcode === 0) {
-    if (compressed) {
-      this.error('continuation frame cannot have the Per-message Compressed bits', 1002);
-      return;
-    }
-    // continuation frame
-    this.state.fragmentedOperation = true;
-    this.state.opcode = this.state.activeFragmentedOperation;
-    if (!(this.state.opcode == 1 || this.state.opcode == 2)) {
-      this.error('continuation frame cannot follow current opcode', 1002);
-      return;
-    }
-  }
-  else {
-    if (opcode < 3 && this.state.activeFragmentedOperation != null) {
-      this.error('data frames after the initial data frame must have opcode 0', 1002);
-      return;
-    }
-    if (opcode >= 8 && compressed) {
-      this.error('control frames cannot have the Per-message Compressed bits', 1002);
-      return;
-    }
-    this.state.compressed = compressed;
-    this.state.opcode = opcode;
-    if (this.state.lastFragment === false) {
-      this.state.fragmentedOperation = true;
-      this.state.activeFragmentedOperation = opcode;
-    }
-    else this.state.fragmentedOperation = false;
-  }
-  var handler = opcodes[this.state.opcode];
-  if (typeof handler == 'undefined') this.error('no handler for opcode ' + this.state.opcode, 1002);
-  else {
-    handler.start.call(this, data);
-  }
-};
-
-/**
- * Endprocessing a packet.
- *
- * @api private
- */
-
-Receiver.prototype.endPacket = function() {
-  if (!this.state.fragmentedOperation) this.unfragmentedBufferPool.reset(true);
-  else if (this.state.lastFragment) this.fragmentedBufferPool.reset(false);
-  this.expectOffset = 0;
-  this.expectBuffer = null;
-  this.expectHandler = null;
-  if (this.state.lastFragment && this.state.opcode === this.state.activeFragmentedOperation) {
-    // end current fragmented operation
-    this.state.activeFragmentedOperation = null;
-  }
-  this.state.lastFragment = false;
-  this.state.opcode = this.state.activeFragmentedOperation != null ? this.state.activeFragmentedOperation : 0;
-  this.state.masked = false;
-  this.expectHeader(2, this.processPacket);
-};
-
-/**
- * Reset the parser state.
- *
- * @api private
- */
-
-Receiver.prototype.reset = function() {
-  if (this.dead) return;
-  this.state = {
-    activeFragmentedOperation: null,
-    lastFragment: false,
-    masked: false,
-    opcode: 0,
-    fragmentedOperation: false
-  };
-  this.fragmentedBufferPool.reset(true);
-  this.unfragmentedBufferPool.reset(true);
-  this.expectOffset = 0;
-  this.expectBuffer = null;
-  this.expectHandler = null;
-  this.overflow = [];
-  this.currentMessage = [];
-  this.messageHandlers = [];
-};
-
-/**
- * Unmask received data.
- *
- * @api private
- */
-
-Receiver.prototype.unmask = function (mask, buf, binary) {
-  if (mask != null && buf != null) bufferUtil.unmask(buf, mask);
-  if (binary) return buf;
-  return buf != null ? buf.toString('utf8') : '';
-};
-
-/**
- * Concatenates a list of buffers.
- *
- * @api private
- */
-
-Receiver.prototype.concatBuffers = function(buffers) {
-  var length = 0;
-  for (var i = 0, l = buffers.length; i < l; ++i) length += buffers[i].length;
-  var mergedBuffer = new Buffer(length);
-  bufferUtil.merge(mergedBuffer, buffers);
-  return mergedBuffer;
-};
-
-/**
- * Handles an error
- *
- * @api private
- */
-
-Receiver.prototype.error = function (reason, protocolErrorCode) {
-  this.reset();
-  this.onerror(reason, protocolErrorCode);
-  return this;
-};
-
-/**
- * Execute message handler buffers
- *
- * @api private
- */
-
-Receiver.prototype.flush = function() {
-  if (this.processing || this.dead) return;
-
-  var handler = this.messageHandlers.shift();
-  if (!handler) return;
-
-  this.processing = true;
-  var self = this;
-
-  handler(function() {
-    self.processing = false;
-    self.flush();
-  });
-};
-
-/**
- * Apply extensions to message
- *
- * @api private
- */
-
-Receiver.prototype.applyExtensions = function(messageBuffer, fin, compressed, callback) {
-  var self = this;
-  if (compressed) {
-    this.extensions[PerMessageDeflate.extensionName].decompress(messageBuffer, fin, function(err, buffer) {
-      if (self.dead) return;
-      if (err) {
-        callback(new Error('invalid compressed data'));
-        return;
-      }
-      callback(null, buffer);
-    });
-  } else {
-    callback(null, messageBuffer);
-  }
-};
-
-/**
- * Buffer utilities
- */
-
-function readUInt16BE(start) {
-  return (this[start]<<8) +
-         this[start+1];
-}
-
-function readUInt32BE(start) {
-  return (this[start]<<24) +
-         (this[start+1]<<16) +
-         (this[start+2]<<8) +
-         this[start+3];
-}
-
-function fastCopy(length, srcBuffer, dstBuffer, dstOffset) {
-  switch (length) {
-    default: srcBuffer.copy(dstBuffer, dstOffset, 0, length); break;
-    case 16: dstBuffer[dstOffset+15] = srcBuffer[15];
-    case 15: dstBuffer[dstOffset+14] = srcBuffer[14];
-    case 14: dstBuffer[dstOffset+13] = srcBuffer[13];
-    case 13: dstBuffer[dstOffset+12] = srcBuffer[12];
-    case 12: dstBuffer[dstOffset+11] = srcBuffer[11];
-    case 11: dstBuffer[dstOffset+10] = srcBuffer[10];
-    case 10: dstBuffer[dstOffset+9] = srcBuffer[9];
-    case 9: dstBuffer[dstOffset+8] = srcBuffer[8];
-    case 8: dstBuffer[dstOffset+7] = srcBuffer[7];
-    case 7: dstBuffer[dstOffset+6] = srcBuffer[6];
-    case 6: dstBuffer[dstOffset+5] = srcBuffer[5];
-    case 5: dstBuffer[dstOffset+4] = srcBuffer[4];
-    case 4: dstBuffer[dstOffset+3] = srcBuffer[3];
-    case 3: dstBuffer[dstOffset+2] = srcBuffer[2];
-    case 2: dstBuffer[dstOffset+1] = srcBuffer[1];
-    case 1: dstBuffer[dstOffset] = srcBuffer[0];
-  }
-}
-
-function clone(obj) {
-  var cloned = {};
-  for (var k in obj) {
-    if (obj.hasOwnProperty(k)) {
-      cloned[k] = obj[k];
-    }
-  }
-  return cloned;
-}
-
-/**
- * Opcode handlers
- */
-
-var opcodes = {
-  // text
-  '1': {
-    start: function(data) {
-      var self = this;
-      // decode length
-      var firstLength = data[1] & 0x7f;
-      if (firstLength < 126) {
-        opcodes['1'].getData.call(self, firstLength);
-      }
-      else if (firstLength == 126) {
-        self.expectHeader(2, function(data) {
-          opcodes['1'].getData.call(self, readUInt16BE.call(data, 0));
-        });
-      }
-      else if (firstLength == 127) {
-        self.expectHeader(8, function(data) {
-          if (readUInt32BE.call(data, 0) != 0) {
-            self.error('packets with length spanning more than 32 bit is currently not supported', 1008);
-            return;
-          }
-          opcodes['1'].getData.call(self, readUInt32BE.call(data, 4));
-        });
-      }
-    },
-    getData: function(length) {
-      var self = this;
-      if (self.state.masked) {
-        self.expectHeader(4, function(data) {
-          var mask = data;
-          self.expectData(length, function(data) {
-            opcodes['1'].finish.call(self, mask, data);
-          });
-        });
-      }
-      else {
-        self.expectData(length, function(data) {
-          opcodes['1'].finish.call(self, null, data);
-        });
-      }
-    },
-    finish: function(mask, data) {
-      var self = this;
-      var packet = this.unmask(mask, data, true) || new Buffer(0);
-      var state = clone(this.state);
-      this.messageHandlers.push(function(callback) {
-        self.applyExtensions(packet, state.lastFragment, state.compressed, function(err, buffer) {
-          if (err) return self.error(err.message, 1007);
-          if (buffer != null) self.currentMessage.push(buffer);
-
-          if (state.lastFragment) {
-            var messageBuffer = self.concatBuffers(self.currentMessage);
-            self.currentMessage = [];
-            if (!Validation.isValidUTF8(messageBuffer)) {
-              self.error('invalid utf8 sequence', 1007);
-              return;
-            }
-            self.ontext(messageBuffer.toString('utf8'), {masked: state.masked, buffer: messageBuffer});
-          }
-          callback();
-        });
-      });
-      this.flush();
-      this.endPacket();
-    }
-  },
-  // binary
-  '2': {
-    start: function(data) {
-      var self = this;
-      // decode length
-      var firstLength = data[1] & 0x7f;
-      if (firstLength < 126) {
-        opcodes['2'].getData.call(self, firstLength);
-      }
-      else if (firstLength == 126) {
-        self.expectHeader(2, function(data) {
-          opcodes['2'].getData.call(self, readUInt16BE.call(data, 0));
-        });
-      }
-      else if (firstLength == 127) {
-        self.expectHeader(8, function(data) {
-          if (readUInt32BE.call(data, 0) != 0) {
-            self.error('packets with length spanning more than 32 bit is currently not supported', 1008);
-            return;
-          }
-          opcodes['2'].getData.call(self, readUInt32BE.call(data, 4, true));
-        });
-      }
-    },
-    getData: function(length) {
-      var self = this;
-      if (self.state.masked) {
-        self.expectHeader(4, function(data) {
-          var mask = data;
-          self.expectData(length, function(data) {
-            opcodes['2'].finish.call(self, mask, data);
-          });
-        });
-      }
-      else {
-        self.expectData(length, function(data) {
-          opcodes['2'].finish.call(self, null, data);
-        });
-      }
-    },
-    finish: function(mask, data) {
-      var self = this;
-      var packet = this.unmask(mask, data, true) || new Buffer(0);
-      var state = clone(this.state);
-      this.messageHandlers.push(function(callback) {
-        self.applyExtensions(packet, state.lastFragment, state.compressed, function(err, buffer) {
-          if (err) return self.error(err.message, 1007);
-          if (buffer != null) self.currentMessage.push(buffer);
-          if (state.lastFragment) {
-            var messageBuffer = self.concatBuffers(self.currentMessage);
-            self.currentMessage = [];
-            self.onbinary(messageBuffer, {masked: state.masked, buffer: messageBuffer});
-          }
-          callback();
-        });
-      });
-      this.flush();
-      this.endPacket();
-    }
-  },
-  // close
-  '8': {
-    start: function(data) {
-      var self = this;
-      if (self.state.lastFragment == false) {
-        self.error('fragmented close is not supported', 1002);
-        return;
-      }
-
-      // decode length
-      var firstLength = data[1] & 0x7f;
-      if (firstLength < 126) {
-        opcodes['8'].getData.call(self, firstLength);
-      }
-      else {
-        self.error('control frames cannot have more than 125 bytes of data', 1002);
-      }
-    },
-    getData: function(length) {
-      var self = this;
-      if (self.state.masked) {
-        self.expectHeader(4, function(data) {
-          var mask = data;
-          self.expectData(length, function(data) {
-            opcodes['8'].finish.call(self, mask, data);
-          });
-        });
-      }
-      else {
-        self.expectData(length, function(data) {
-          opcodes['8'].finish.call(self, null, data);
-        });
-      }
-    },
-    finish: function(mask, data) {
-      var self = this;
-      data = self.unmask(mask, data, true);
-
-      var state = clone(this.state);
-      this.messageHandlers.push(function() {
-        if (data && data.length == 1) {
-          self.error('close packets with data must be at least two bytes long', 1002);
-          return;
-        }
-        var code = data && data.length > 1 ? readUInt16BE.call(data, 0) : 1000;
-        if (!ErrorCodes.isValidErrorCode(code)) {
-          self.error('invalid error code', 1002);
-          return;
-        }
-        var message = '';
-        if (data && data.length > 2) {
-          var messageBuffer = data.slice(2);
-          if (!Validation.isValidUTF8(messageBuffer)) {
-            self.error('invalid utf8 sequence', 1007);
-            return;
-          }
-          message = messageBuffer.toString('utf8');
-        }
-        self.onclose(code, message, {masked: state.masked});
-        self.reset();
-      });
-      this.flush();
-    },
-  },
-  // ping
-  '9': {
-    start: function(data) {
-      var self = this;
-      if (self.state.lastFragment == false) {
-        self.error('fragmented ping is not supported', 1002);
-        return;
-      }
-
-      // decode length
-      var firstLength = data[1] & 0x7f;
-      if (firstLength < 126) {
-        opcodes['9'].getData.call(self, firstLength);
-      }
-      else {
-        self.error('control frames cannot have more than 125 bytes of data', 1002);
-      }
-    },
-    getData: function(length) {
-      var self = this;
-      if (self.state.masked) {
-        self.expectHeader(4, function(data) {
-          var mask = data;
-          self.expectData(length, function(data) {
-            opcodes['9'].finish.call(self, mask, data);
-          });
-        });
-      }
-      else {
-        self.expectData(length, function(data) {
-          opcodes['9'].finish.call(self, null, data);
-        });
-      }
-    },
-    finish: function(mask, data) {
-      var self = this;
-      data = this.unmask(mask, data, true);
-      var state = clone(this.state);
-      this.messageHandlers.push(function(callback) {
-        self.onping(data, {masked: state.masked, binary: true});
-        callback();
-      });
-      this.flush();
-      this.endPacket();
-    }
-  },
-  // pong
-  '10': {
-    start: function(data) {
-      var self = this;
-      if (self.state.lastFragment == false) {
-        self.error('fragmented pong is not supported', 1002);
-        return;
-      }
-
-      // decode length
-      var firstLength = data[1] & 0x7f;
-      if (firstLength < 126) {
-        opcodes['10'].getData.call(self, firstLength);
-      }
-      else {
-        self.error('control frames cannot have more than 125 bytes of data', 1002);
-      }
-    },
-    getData: function(length) {
-      var self = this;
-      if (this.state.masked) {
-        this.expectHeader(4, function(data) {
-          var mask = data;
-          self.expectData(length, function(data) {
-            opcodes['10'].finish.call(self, mask, data);
-          });
-        });
-      }
-      else {
-        this.expectData(length, function(data) {
-          opcodes['10'].finish.call(self, null, data);
-        });
-      }
-    },
-    finish: function(mask, data) {
-      var self = this;
-      data = self.unmask(mask, data, true);
-      var state = clone(this.state);
-      this.messageHandlers.push(function(callback) {
-        self.onpong(data, {masked: state.masked, binary: true});
-        callback();
-      });
-      this.flush();
-      this.endPacket();
-    }
-  }
-}
diff --git a/input_devices/mag/node_modules/ws/lib/Sender.hixie.js b/input_devices/mag/node_modules/ws/lib/Sender.hixie.js
deleted file mode 100644
index fd2fd250..00000000
--- a/input_devices/mag/node_modules/ws/lib/Sender.hixie.js
+++ /dev/null
@@ -1,120 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var events = require('events')
-  , util = require('util')
-  , EventEmitter = events.EventEmitter;
-
-/**
- * Hixie Sender implementation
- */
-
-function Sender(socket) {
-  events.EventEmitter.call(this);
-
-  this.socket = socket;
-  this.continuationFrame = false;
-  this.isClosed = false;
-}
-
-module.exports = Sender;
-
-/**
- * Inherits from EventEmitter.
- */
-
-util.inherits(Sender, events.EventEmitter);
-
-/**
- * Frames and writes data.
- *
- * @api public
- */
-
-Sender.prototype.send = function(data, options, cb) {
-  if (this.isClosed) return;
-
-  var isString = typeof data == 'string'
-    , length = isString ? Buffer.byteLength(data) : data.length
-    , lengthbytes = (length > 127) ? 2 : 1 // assume less than 2**14 bytes
-    , writeStartMarker = this.continuationFrame == false
-    , writeEndMarker = !options || !(typeof options.fin != 'undefined' && !options.fin)
-    , buffer = new Buffer((writeStartMarker ? ((options && options.binary) ? (1 + lengthbytes) : 1) : 0) + length + ((writeEndMarker && !(options && options.binary)) ? 1 : 0))
-    , offset = writeStartMarker ? 1 : 0;
-
-  if (writeStartMarker) {
-    if (options && options.binary) {
-      buffer.write('\x80', 'binary');
-      // assume length less than 2**14 bytes
-      if (lengthbytes > 1)
-        buffer.write(String.fromCharCode(128+length/128), offset++, 'binary');
-      buffer.write(String.fromCharCode(length&0x7f), offset++, 'binary');
-    } else
-      buffer.write('\x00', 'binary');
-  }
-
-  if (isString) buffer.write(data, offset, 'utf8');
-  else data.copy(buffer, offset, 0);
-
-  if (writeEndMarker) {
-    if (options && options.binary) {
-      // sending binary, not writing end marker
-    } else
-      buffer.write('\xff', offset + length, 'binary');
-    this.continuationFrame = false;
-  }
-  else this.continuationFrame = true;
-
-  try {
-    this.socket.write(buffer, 'binary', cb);
-  } catch (e) {
-    this.error(e.toString());
-  }
-};
-
-/**
- * Sends a close instruction to the remote party.
- *
- * @api public
- */
-
-Sender.prototype.close = function(code, data, mask, cb) {
-  if (this.isClosed) return;
-  this.isClosed = true;
-  try {
-    if (this.continuationFrame) this.socket.write(new Buffer([0xff], 'binary'));
-    this.socket.write(new Buffer([0xff, 0x00]), 'binary', cb);
-  } catch (e) {
-    this.error(e.toString());
-  }
-};
-
-/**
- * Sends a ping message to the remote party. Not available for hixie.
- *
- * @api public
- */
-
-Sender.prototype.ping = function(data, options) {};
-
-/**
- * Sends a pong message to the remote party. Not available for hixie.
- *
- * @api public
- */
-
-Sender.prototype.pong = function(data, options) {};
-
-/**
- * Handles an error
- *
- * @api private
- */
-
-Sender.prototype.error = function (reason) {
-  this.emit('error', reason);
-  return this;
-};
diff --git a/input_devices/mag/node_modules/ws/lib/Sender.js b/input_devices/mag/node_modules/ws/lib/Sender.js
deleted file mode 100644
index f3467480..00000000
--- a/input_devices/mag/node_modules/ws/lib/Sender.js
+++ /dev/null
@@ -1,309 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var events = require('events')
-  , util = require('util')
-  , EventEmitter = events.EventEmitter
-  , ErrorCodes = require('./ErrorCodes')
-  , bufferUtil = require('./BufferUtil').BufferUtil
-  , PerMessageDeflate = require('./PerMessageDeflate');
-
-/**
- * HyBi Sender implementation
- */
-
-function Sender(socket, extensions) {
-  events.EventEmitter.call(this);
-
-  this._socket = socket;
-  this.extensions = extensions || {};
-  this.firstFragment = true;
-  this.compress = false;
-  this.messageHandlers = [];
-  this.processing = false;
-}
-
-/**
- * Inherits from EventEmitter.
- */
-
-util.inherits(Sender, events.EventEmitter);
-
-/**
- * Sends a close instruction to the remote party.
- *
- * @api public
- */
-
-Sender.prototype.close = function(code, data, mask, cb) {
-  if (typeof code !== 'undefined') {
-    if (typeof code !== 'number' ||
-      !ErrorCodes.isValidErrorCode(code)) throw new Error('first argument must be a valid error code number');
-  }
-  code = code || 1000;
-  var dataBuffer = new Buffer(2 + (data ? Buffer.byteLength(data) : 0));
-  writeUInt16BE.call(dataBuffer, code, 0);
-  if (dataBuffer.length > 2) dataBuffer.write(data, 2);
-
-  var self = this;
-  this.messageHandlers.push(function(callback) {
-    self.frameAndSend(0x8, dataBuffer, true, mask);
-    callback();
-    if (typeof cb == 'function') cb();
-  });
-  this.flush();
-};
-
-/**
- * Sends a ping message to the remote party.
- *
- * @api public
- */
-
-Sender.prototype.ping = function(data, options) {
-  var mask = options && options.mask;
-  var self = this;
-  this.messageHandlers.push(function(callback) {
-    self.frameAndSend(0x9, data || '', true, mask);
-    callback();
-  });
-  this.flush();
-};
-
-/**
- * Sends a pong message to the remote party.
- *
- * @api public
- */
-
-Sender.prototype.pong = function(data, options) {
-  var mask = options && options.mask;
-  var self = this;
-  this.messageHandlers.push(function(callback) {
-    self.frameAndSend(0xa, data || '', true, mask);
-    callback();
-  });
-  this.flush();
-};
-
-/**
- * Sends text or binary data to the remote party.
- *
- * @api public
- */
-
-Sender.prototype.send = function(data, options, cb) {
-  var finalFragment = options && options.fin === false ? false : true;
-  var mask = options && options.mask;
-  var compress = options && options.compress;
-  var opcode = options && options.binary ? 2 : 1;
-  if (this.firstFragment === false) {
-    opcode = 0;
-    compress = false;
-  } else {
-    this.firstFragment = false;
-    this.compress = compress;
-  }
-  if (finalFragment) this.firstFragment = true
-
-  var compressFragment = this.compress;
-
-  var self = this;
-  this.messageHandlers.push(function(callback) {
-    self.applyExtensions(data, finalFragment, compressFragment, function(err, data) {
-      if (err) {
-        if (typeof cb == 'function') cb(err);
-        else self.emit('error', err);
-        return;
-      }
-      self.frameAndSend(opcode, data, finalFragment, mask, compress, cb);
-      callback();
-    });
-  });
-  this.flush();
-};
-
-/**
- * Frames and sends a piece of data according to the HyBi WebSocket protocol.
- *
- * @api private
- */
-
-Sender.prototype.frameAndSend = function(opcode, data, finalFragment, maskData, compressed, cb) {
-  var canModifyData = false;
-
-  if (!data) {
-    try {
-      this._socket.write(new Buffer([opcode | (finalFragment ? 0x80 : 0), 0 | (maskData ? 0x80 : 0)].concat(maskData ? [0, 0, 0, 0] : [])), 'binary', cb);
-    }
-    catch (e) {
-      if (typeof cb == 'function') cb(e);
-      else this.emit('error', e);
-    }
-    return;
-  }
-
-  if (!Buffer.isBuffer(data)) {
-    canModifyData = true;
-    if (data && (typeof data.byteLength !== 'undefined' || typeof data.buffer !== 'undefined')) {
-      data = getArrayBuffer(data);
-    } else {
-      data = new Buffer(data);
-    }
-  }
-
-  var dataLength = data.length
-    , dataOffset = maskData ? 6 : 2
-    , secondByte = dataLength;
-
-  if (dataLength >= 65536) {
-    dataOffset += 8;
-    secondByte = 127;
-  }
-  else if (dataLength > 125) {
-    dataOffset += 2;
-    secondByte = 126;
-  }
-
-  var mergeBuffers = dataLength < 32768 || (maskData && !canModifyData);
-  var totalLength = mergeBuffers ? dataLength + dataOffset : dataOffset;
-  var outputBuffer = new Buffer(totalLength);
-  outputBuffer[0] = finalFragment ? opcode | 0x80 : opcode;
-  if (compressed) outputBuffer[0] |= 0x40;
-
-  switch (secondByte) {
-    case 126:
-      writeUInt16BE.call(outputBuffer, dataLength, 2);
-      break;
-    case 127:
-      writeUInt32BE.call(outputBuffer, 0, 2);
-      writeUInt32BE.call(outputBuffer, dataLength, 6);
-  }
-
-  if (maskData) {
-    outputBuffer[1] = secondByte | 0x80;
-    var mask = this._randomMask || (this._randomMask = getRandomMask());
-    outputBuffer[dataOffset - 4] = mask[0];
-    outputBuffer[dataOffset - 3] = mask[1];
-    outputBuffer[dataOffset - 2] = mask[2];
-    outputBuffer[dataOffset - 1] = mask[3];
-    if (mergeBuffers) {
-      bufferUtil.mask(data, mask, outputBuffer, dataOffset, dataLength);
-      try {
-        this._socket.write(outputBuffer, 'binary', cb);
-      }
-      catch (e) {
-        if (typeof cb == 'function') cb(e);
-        else this.emit('error', e);
-      }
-    }
-    else {
-      bufferUtil.mask(data, mask, data, 0, dataLength);
-      try {
-        this._socket.write(outputBuffer, 'binary');
-        this._socket.write(data, 'binary', cb);
-      }
-      catch (e) {
-        if (typeof cb == 'function') cb(e);
-        else this.emit('error', e);
-      }
-    }
-  }
-  else {
-    outputBuffer[1] = secondByte;
-    if (mergeBuffers) {
-      data.copy(outputBuffer, dataOffset);
-      try {
-        this._socket.write(outputBuffer, 'binary', cb);
-      }
-      catch (e) {
-        if (typeof cb == 'function') cb(e);
-        else this.emit('error', e);
-      }
-    }
-    else {
-      try {
-        this._socket.write(outputBuffer, 'binary');
-        this._socket.write(data, 'binary', cb);
-      }
-      catch (e) {
-        if (typeof cb == 'function') cb(e);
-        else this.emit('error', e);
-      }
-    }
-  }
-};
-
-/**
- * Execute message handler buffers
- *
- * @api private
- */
-
-Sender.prototype.flush = function() {
-  if (this.processing) return;
-
-  var handler = this.messageHandlers.shift();
-  if (!handler) return;
-
-  this.processing = true;
-
-  var self = this;
-
-  handler(function() {
-    self.processing = false;
-    self.flush();
-  });
-};
-
-/**
- * Apply extensions to message
- *
- * @api private
- */
-
-Sender.prototype.applyExtensions = function(data, fin, compress, callback) {
-  if (compress && data) {
-    this.extensions[PerMessageDeflate.extensionName].compress(data, fin, callback);
-  } else {
-    callback(null, data);
-  }
-};
-
-module.exports = Sender;
-
-function writeUInt16BE(value, offset) {
-  this[offset] = (value & 0xff00)>>8;
-  this[offset+1] = value & 0xff;
-}
-
-function writeUInt32BE(value, offset) {
-  this[offset] = (value & 0xff000000)>>24;
-  this[offset+1] = (value & 0xff0000)>>16;
-  this[offset+2] = (value & 0xff00)>>8;
-  this[offset+3] = value & 0xff;
-}
-
-function getArrayBuffer(data) {
-  // data is either an ArrayBuffer or ArrayBufferView.
-  var array = new Uint8Array(data.buffer || data)
-    , l = data.byteLength || data.length
-    , o = data.byteOffset || 0
-    , buffer = new Buffer(l);
-  for (var i = 0; i < l; ++i) {
-    buffer[i] = array[o+i];
-  }
-  return buffer;
-}
-
-function getRandomMask() {
-  return new Buffer([
-    ~~(Math.random() * 255),
-    ~~(Math.random() * 255),
-    ~~(Math.random() * 255),
-    ~~(Math.random() * 255)
-  ]);
-}
diff --git a/input_devices/mag/node_modules/ws/lib/Validation.fallback.js b/input_devices/mag/node_modules/ws/lib/Validation.fallback.js
deleted file mode 100644
index 2c7c4fd4..00000000
--- a/input_devices/mag/node_modules/ws/lib/Validation.fallback.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
- 
-module.exports.Validation = {
-  isValidUTF8: function(buffer) {
-    return true;
-  }
-};
-
diff --git a/input_devices/mag/node_modules/ws/lib/Validation.js b/input_devices/mag/node_modules/ws/lib/Validation.js
deleted file mode 100644
index 0795fb7f..00000000
--- a/input_devices/mag/node_modules/ws/lib/Validation.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict';
-
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-try {
-  module.exports = require('utf-8-validate');
-} catch (e) {
-  module.exports = require('./Validation.fallback');
-}
diff --git a/input_devices/mag/node_modules/ws/lib/WebSocket.js b/input_devices/mag/node_modules/ws/lib/WebSocket.js
deleted file mode 100644
index bc3f84ad..00000000
--- a/input_devices/mag/node_modules/ws/lib/WebSocket.js
+++ /dev/null
@@ -1,937 +0,0 @@
-'use strict';
-
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var url = require('url')
-  , util = require('util')
-  , http = require('http')
-  , https = require('https')
-  , crypto = require('crypto')
-  , stream = require('stream')
-  , Ultron = require('ultron')
-  , Options = require('options')
-  , Sender = require('./Sender')
-  , Receiver = require('./Receiver')
-  , SenderHixie = require('./Sender.hixie')
-  , ReceiverHixie = require('./Receiver.hixie')
-  , Extensions = require('./Extensions')
-  , PerMessageDeflate = require('./PerMessageDeflate')
-  , EventEmitter = require('events').EventEmitter;
-
-/**
- * Constants
- */
-
-// Default protocol version
-
-var protocolVersion = 13;
-
-// Close timeout
-
-var closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly
-
-/**
- * WebSocket implementation
- *
- * @constructor
- * @param {String} address Connection address.
- * @param {String|Array} protocols WebSocket protocols.
- * @param {Object} options Additional connection options.
- * @api public
- */
-function WebSocket(address, protocols, options) {
-  EventEmitter.call(this);
-
-  if (protocols && !Array.isArray(protocols) && 'object' === typeof protocols) {
-    // accept the "options" Object as the 2nd argument
-    options = protocols;
-    protocols = null;
-  }
-
-  if ('string' === typeof protocols) {
-    protocols = [ protocols ];
-  }
-
-  if (!Array.isArray(protocols)) {
-    protocols = [];
-  }
-
-  this._socket = null;
-  this._ultron = null;
-  this._closeReceived = false;
-  this.bytesReceived = 0;
-  this.readyState = null;
-  this.supports = {};
-  this.extensions = {};
-
-  if (Array.isArray(address)) {
-    initAsServerClient.apply(this, address.concat(options));
-  } else {
-    initAsClient.apply(this, [address, protocols, options]);
-  }
-}
-
-/**
- * Inherits from EventEmitter.
- */
-util.inherits(WebSocket, EventEmitter);
-
-/**
- * Ready States
- */
-["CONNECTING", "OPEN", "CLOSING", "CLOSED"].forEach(function each(state, index) {
-    WebSocket.prototype[state] = WebSocket[state] = index;
-});
-
-/**
- * Gracefully closes the connection, after sending a description message to the server
- *
- * @param {Object} data to be sent to the server
- * @api public
- */
-WebSocket.prototype.close = function close(code, data) {
-  if (this.readyState === WebSocket.CLOSED) return;
-
-  if (this.readyState === WebSocket.CONNECTING) {
-    this.readyState = WebSocket.CLOSED;
-    return;
-  }
-
-  if (this.readyState === WebSocket.CLOSING) {
-    if (this._closeReceived && this._isServer) {
-      this.terminate();
-    }
-    return;
-  }
-
-  var self = this;
-  try {
-    this.readyState = WebSocket.CLOSING;
-    this._closeCode = code;
-    this._closeMessage = data;
-    var mask = !this._isServer;
-    this._sender.close(code, data, mask, function(err) {
-      if (err) self.emit('error', err);
-
-      if (self._closeReceived && self._isServer) {
-        self.terminate();
-      } else {
-        // ensure that the connection is cleaned up even when no response of closing handshake.
-        clearTimeout(self._closeTimer);
-        self._closeTimer = setTimeout(cleanupWebsocketResources.bind(self, true), closeTimeout);
-      }
-    });
-  } catch (e) {
-    this.emit('error', e);
-  }
-};
-
-/**
- * Pause the client stream
- *
- * @api public
- */
-WebSocket.prototype.pause = function pauser() {
-  if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
-
-  return this._socket.pause();
-};
-
-/**
- * Sends a ping
- *
- * @param {Object} data to be sent to the server
- * @param {Object} Members - mask: boolean, binary: boolean
- * @param {boolean} dontFailWhenClosed indicates whether or not to throw if the connection isnt open
- * @api public
- */
-WebSocket.prototype.ping = function ping(data, options, dontFailWhenClosed) {
-  if (this.readyState !== WebSocket.OPEN) {
-    if (dontFailWhenClosed === true) return;
-    throw new Error('not opened');
-  }
-
-  options = options || {};
-
-  if (typeof options.mask === 'undefined') options.mask = !this._isServer;
-
-  this._sender.ping(data, options);
-};
-
-/**
- * Sends a pong
- *
- * @param {Object} data to be sent to the server
- * @param {Object} Members - mask: boolean, binary: boolean
- * @param {boolean} dontFailWhenClosed indicates whether or not to throw if the connection isnt open
- * @api public
- */
-WebSocket.prototype.pong = function(data, options, dontFailWhenClosed) {
-  if (this.readyState !== WebSocket.OPEN) {
-    if (dontFailWhenClosed === true) return;
-    throw new Error('not opened');
-  }
-
-  options = options || {};
-
-  if (typeof options.mask === 'undefined') options.mask = !this._isServer;
-
-  this._sender.pong(data, options);
-};
-
-/**
- * Resume the client stream
- *
- * @api public
- */
-WebSocket.prototype.resume = function resume() {
-  if (this.readyState !== WebSocket.OPEN) throw new Error('not opened');
-
-  return this._socket.resume();
-};
-
-/**
- * Sends a piece of data
- *
- * @param {Object} data to be sent to the server
- * @param {Object} Members - mask: boolean, binary: boolean, compress: boolean
- * @param {function} Optional callback which is executed after the send completes
- * @api public
- */
-
-WebSocket.prototype.send = function send(data, options, cb) {
-  if (typeof options === 'function') {
-    cb = options;
-    options = {};
-  }
-
-  if (this.readyState !== WebSocket.OPEN) {
-    if (typeof cb === 'function') cb(new Error('not opened'));
-    else throw new Error('not opened');
-    return;
-  }
-
-  if (!data) data = '';
-  if (this._queue) {
-    var self = this;
-    this._queue.push(function() { self.send(data, options, cb); });
-    return;
-  }
-
-  options = options || {};
-  options.fin = true;
-
-  if (typeof options.binary === 'undefined') {
-    options.binary = (data instanceof ArrayBuffer || data instanceof Buffer ||
-      data instanceof Uint8Array ||
-      data instanceof Uint16Array ||
-      data instanceof Uint32Array ||
-      data instanceof Int8Array ||
-      data instanceof Int16Array ||
-      data instanceof Int32Array ||
-      data instanceof Float32Array ||
-      data instanceof Float64Array);
-  }
-
-  if (typeof options.mask === 'undefined') options.mask = !this._isServer;
-  if (typeof options.compress === 'undefined') options.compress = true;
-  if (!this.extensions[PerMessageDeflate.extensionName]) {
-    options.compress = false;
-  }
-
-  var readable = typeof stream.Readable === 'function'
-    ? stream.Readable
-    : stream.Stream;
-
-  if (data instanceof readable) {
-    startQueue(this);
-    var self = this;
-
-    sendStream(this, data, options, function send(error) {
-      process.nextTick(function tock() {
-        executeQueueSends(self);
-      });
-
-      if (typeof cb === 'function') cb(error);
-    });
-  } else {
-    this._sender.send(data, options, cb);
-  }
-};
-
-/**
- * Streams data through calls to a user supplied function
- *
- * @param {Object} Members - mask: boolean, binary: boolean, compress: boolean
- * @param {function} 'function (error, send)' which is executed on successive ticks of which send is 'function (data, final)'.
- * @api public
- */
-WebSocket.prototype.stream = function stream(options, cb) {
-  if (typeof options === 'function') {
-    cb = options;
-    options = {};
-  }
-
-  var self = this;
-
-  if (typeof cb !== 'function') throw new Error('callback must be provided');
-
-  if (this.readyState !== WebSocket.OPEN) {
-    if (typeof cb === 'function') cb(new Error('not opened'));
-    else throw new Error('not opened');
-    return;
-  }
-
-  if (this._queue) {
-    this._queue.push(function () { self.stream(options, cb); });
-    return;
-  }
-
-  options = options || {};
-
-  if (typeof options.mask === 'undefined') options.mask = !this._isServer;
-  if (typeof options.compress === 'undefined') options.compress = true;
-  if (!this.extensions[PerMessageDeflate.extensionName]) {
-    options.compress = false;
-  }
-
-  startQueue(this);
-
-  function send(data, final) {
-    try {
-      if (self.readyState !== WebSocket.OPEN) throw new Error('not opened');
-      options.fin = final === true;
-      self._sender.send(data, options);
-      if (!final) process.nextTick(cb.bind(null, null, send));
-      else executeQueueSends(self);
-    } catch (e) {
-      if (typeof cb === 'function') cb(e);
-      else {
-        delete self._queue;
-        self.emit('error', e);
-      }
-    }
-  }
-
-  process.nextTick(cb.bind(null, null, send));
-};
-
-/**
- * Immediately shuts down the connection
- *
- * @api public
- */
-WebSocket.prototype.terminate = function terminate() {
-  if (this.readyState === WebSocket.CLOSED) return;
-
-  if (this._socket) {
-    this.readyState = WebSocket.CLOSING;
-
-    // End the connection
-    try { this._socket.end(); }
-    catch (e) {
-      // Socket error during end() call, so just destroy it right now
-      cleanupWebsocketResources.call(this, true);
-      return;
-    }
-
-    // Add a timeout to ensure that the connection is completely
-    // cleaned up within 30 seconds, even if the clean close procedure
-    // fails for whatever reason
-    // First cleanup any pre-existing timeout from an earlier "terminate" call,
-    // if one exists.  Otherwise terminate calls in quick succession will leak timeouts
-    // and hold the program open for `closeTimout` time.
-    if (this._closeTimer) { clearTimeout(this._closeTimer); }
-    this._closeTimer = setTimeout(cleanupWebsocketResources.bind(this, true), closeTimeout);
-  } else if (this.readyState === WebSocket.CONNECTING) {
-    cleanupWebsocketResources.call(this, true);
-  }
-};
-
-/**
- * Expose bufferedAmount
- *
- * @api public
- */
-Object.defineProperty(WebSocket.prototype, 'bufferedAmount', {
-  get: function get() {
-    var amount = 0;
-    if (this._socket) {
-      amount = this._socket.bufferSize || 0;
-    }
-    return amount;
-  }
-});
-
-/**
- * Emulates the W3C Browser based WebSocket interface using function members.
- *
- * @see http://dev.w3.org/html5/websockets/#the-websocket-interface
- * @api public
- */
-['open', 'error', 'close', 'message'].forEach(function(method) {
-  Object.defineProperty(WebSocket.prototype, 'on' + method, {
-    /**
-     * Returns the current listener
-     *
-     * @returns {Mixed} the set function or undefined
-     * @api public
-     */
-    get: function get() {
-      var listener = this.listeners(method)[0];
-      return listener ? (listener._listener ? listener._listener : listener) : undefined;
-    },
-
-    /**
-     * Start listening for events
-     *
-     * @param {Function} listener the listener
-     * @returns {Mixed} the set function or undefined
-     * @api public
-     */
-    set: function set(listener) {
-      this.removeAllListeners(method);
-      this.addEventListener(method, listener);
-    }
-  });
-});
-
-/**
- * Emulates the W3C Browser based WebSocket interface using addEventListener.
- *
- * @see https://developer.mozilla.org/en/DOM/element.addEventListener
- * @see http://dev.w3.org/html5/websockets/#the-websocket-interface
- * @api public
- */
-WebSocket.prototype.addEventListener = function(method, listener) {
-  var target = this;
-
-  function onMessage (data, flags) {
-    listener.call(target, new MessageEvent(data, flags.binary ? 'Binary' : 'Text', target));
-  }
-
-  function onClose (code, message) {
-    listener.call(target, new CloseEvent(code, message, target));
-  }
-
-  function onError (event) {
-    event.target = target;
-    listener.call(target, event);
-  }
-
-  function onOpen () {
-    listener.call(target, new OpenEvent(target));
-  }
-
-  if (typeof listener === 'function') {
-    if (method === 'message') {
-      // store a reference so we can return the original function from the
-      // addEventListener hook
-      onMessage._listener = listener;
-      this.on(method, onMessage);
-    } else if (method === 'close') {
-      // store a reference so we can return the original function from the
-      // addEventListener hook
-      onClose._listener = listener;
-      this.on(method, onClose);
-    } else if (method === 'error') {
-      // store a reference so we can return the original function from the
-      // addEventListener hook
-      onError._listener = listener;
-      this.on(method, onError);
-    } else if (method === 'open') {
-      // store a reference so we can return the original function from the
-      // addEventListener hook
-      onOpen._listener = listener;
-      this.on(method, onOpen);
-    } else {
-      this.on(method, listener);
-    }
-  }
-};
-
-module.exports = WebSocket;
-
-/**
- * W3C MessageEvent
- *
- * @see http://www.w3.org/TR/html5/comms.html
- * @constructor
- * @api private
- */
-function MessageEvent(dataArg, typeArg, target) {
-  this.data = dataArg;
-  this.type = typeArg;
-  this.target = target;
-}
-
-/**
- * W3C CloseEvent
- *
- * @see http://www.w3.org/TR/html5/comms.html
- * @constructor
- * @api private
- */
-function CloseEvent(code, reason, target) {
-  this.wasClean = (typeof code === 'undefined' || code === 1000);
-  this.code = code;
-  this.reason = reason;
-  this.target = target;
-}
-
-/**
- * W3C OpenEvent
- *
- * @see http://www.w3.org/TR/html5/comms.html
- * @constructor
- * @api private
- */
-function OpenEvent(target) {
-  this.target = target;
-}
-
-/**
- * Entirely private apis,
- * which may or may not be bound to a sepcific WebSocket instance.
- */
-function initAsServerClient(req, socket, upgradeHead, options) {
-  options = new Options({
-    protocolVersion: protocolVersion,
-    protocol: null,
-    extensions: {}
-  }).merge(options);
-
-  // expose state properties
-  this.protocol = options.value.protocol;
-  this.protocolVersion = options.value.protocolVersion;
-  this.extensions = options.value.extensions;
-  this.supports.binary = (this.protocolVersion !== 'hixie-76');
-  this.upgradeReq = req;
-  this.readyState = WebSocket.CONNECTING;
-  this._isServer = true;
-
-  // establish connection
-  if (options.value.protocolVersion === 'hixie-76') {
-    establishConnection.call(this, ReceiverHixie, SenderHixie, socket, upgradeHead);
-  } else {
-    establishConnection.call(this, Receiver, Sender, socket, upgradeHead);
-  }
-}
-
-function initAsClient(address, protocols, options) {
-  options = new Options({
-    origin: null,
-    protocolVersion: protocolVersion,
-    host: null,
-    headers: null,
-    protocol: protocols.join(','),
-    agent: null,
-
-    // ssl-related options
-    pfx: null,
-    key: null,
-    passphrase: null,
-    cert: null,
-    ca: null,
-    ciphers: null,
-    rejectUnauthorized: null,
-    perMessageDeflate: true
-  }).merge(options);
-
-  if (options.value.protocolVersion !== 8 && options.value.protocolVersion !== 13) {
-    throw new Error('unsupported protocol version');
-  }
-
-  // verify URL and establish http class
-  var serverUrl = url.parse(address);
-  var isUnixSocket = serverUrl.protocol === 'ws+unix:';
-  if (!serverUrl.host && !isUnixSocket) throw new Error('invalid url');
-  var isSecure = serverUrl.protocol === 'wss:' || serverUrl.protocol === 'https:';
-  var httpObj = isSecure ? https : http;
-  var port = serverUrl.port || (isSecure ? 443 : 80);
-  var auth = serverUrl.auth;
-
-  // prepare extensions
-  var extensionsOffer = {};
-  var perMessageDeflate;
-  if (options.value.perMessageDeflate) {
-    perMessageDeflate = new PerMessageDeflate(typeof options.value.perMessageDeflate !== true ? options.value.perMessageDeflate : {}, false);
-    extensionsOffer[PerMessageDeflate.extensionName] = perMessageDeflate.offer();
-  }
-
-  // expose state properties
-  this._isServer = false;
-  this.url = address;
-  this.protocolVersion = options.value.protocolVersion;
-  this.supports.binary = (this.protocolVersion !== 'hixie-76');
-
-  // begin handshake
-  var key = new Buffer(options.value.protocolVersion + '-' + Date.now()).toString('base64');
-  var shasum = crypto.createHash('sha1');
-  shasum.update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11');
-  var expectedServerKey = shasum.digest('base64');
-
-  var agent = options.value.agent;
-
-  var headerHost = serverUrl.hostname;
-  // Append port number to Host and Origin header, only if specified in the url
-  // and non-default
-  if (serverUrl.port) {
-    if ((isSecure && (port !== 443)) || (!isSecure && (port !== 80))){
-      headerHost = headerHost + ':' + port;
-    }
-  }
-
-  var requestOptions = {
-    port: port,
-    host: serverUrl.hostname,
-    headers: {
-      'Connection': 'Upgrade',
-      'Upgrade': 'websocket',
-      'Host': headerHost,
-      'Origin': headerHost,
-      'Sec-WebSocket-Version': options.value.protocolVersion,
-      'Sec-WebSocket-Key': key
-    }
-  };
-
-  // If we have basic auth.
-  if (auth) {
-    requestOptions.headers.Authorization = 'Basic ' + new Buffer(auth).toString('base64');
-  }
-
-  if (options.value.protocol) {
-    requestOptions.headers['Sec-WebSocket-Protocol'] = options.value.protocol;
-  }
-
-  if (options.value.host) {
-    requestOptions.headers.Host = options.value.host;
-  }
-
-  if (options.value.headers) {
-    for (var header in options.value.headers) {
-       if (options.value.headers.hasOwnProperty(header)) {
-        requestOptions.headers[header] = options.value.headers[header];
-       }
-    }
-  }
-
-  if (Object.keys(extensionsOffer).length) {
-    requestOptions.headers['Sec-WebSocket-Extensions'] = Extensions.format(extensionsOffer);
-  }
-
-  if (options.isDefinedAndNonNull('pfx')
-   || options.isDefinedAndNonNull('key')
-   || options.isDefinedAndNonNull('passphrase')
-   || options.isDefinedAndNonNull('cert')
-   || options.isDefinedAndNonNull('ca')
-   || options.isDefinedAndNonNull('ciphers')
-   || options.isDefinedAndNonNull('rejectUnauthorized')) {
-
-    if (options.isDefinedAndNonNull('pfx')) requestOptions.pfx = options.value.pfx;
-    if (options.isDefinedAndNonNull('key')) requestOptions.key = options.value.key;
-    if (options.isDefinedAndNonNull('passphrase')) requestOptions.passphrase = options.value.passphrase;
-    if (options.isDefinedAndNonNull('cert')) requestOptions.cert = options.value.cert;
-    if (options.isDefinedAndNonNull('ca')) requestOptions.ca = options.value.ca;
-    if (options.isDefinedAndNonNull('ciphers')) requestOptions.ciphers = options.value.ciphers;
-    if (options.isDefinedAndNonNull('rejectUnauthorized')) requestOptions.rejectUnauthorized = options.value.rejectUnauthorized;
-
-    if (!agent) {
-        // global agent ignores client side certificates
-        agent = new httpObj.Agent(requestOptions);
-    }
-  }
-
-  requestOptions.path = serverUrl.path || '/';
-
-  if (agent) {
-    requestOptions.agent = agent;
-  }
-
-  if (isUnixSocket) {
-    requestOptions.socketPath = serverUrl.pathname;
-  }
-  if (options.value.origin) {
-    if (options.value.protocolVersion < 13) requestOptions.headers['Sec-WebSocket-Origin'] = options.value.origin;
-    else requestOptions.headers.Origin = options.value.origin;
-  }
-
-  var self = this;
-  var req = httpObj.request(requestOptions);
-
-  req.on('error', function onerror(error) {
-    self.emit('error', error);
-    cleanupWebsocketResources.call(this, error);
-  });
-
-  req.once('response', function response(res) {
-    var error;
-
-    if (!self.emit('unexpected-response', req, res)) {
-      error = new Error('unexpected server response (' + res.statusCode + ')');
-      req.abort();
-      self.emit('error', error);
-    }
-
-    cleanupWebsocketResources.call(this, error);
-  });
-
-  req.once('upgrade', function upgrade(res, socket, upgradeHead) {
-    if (self.readyState === WebSocket.CLOSED) {
-      // client closed before server accepted connection
-      self.emit('close');
-      self.removeAllListeners();
-      socket.end();
-      return;
-    }
-
-    var serverKey = res.headers['sec-websocket-accept'];
-    if (typeof serverKey === 'undefined' || serverKey !== expectedServerKey) {
-      self.emit('error', 'invalid server key');
-      self.removeAllListeners();
-      socket.end();
-      return;
-    }
-
-    var serverProt = res.headers['sec-websocket-protocol'];
-    var protList = (options.value.protocol || "").split(/, */);
-    var protError = null;
-
-    if (!options.value.protocol && serverProt) {
-      protError = 'server sent a subprotocol even though none requested';
-    } else if (options.value.protocol && !serverProt) {
-      protError = 'server sent no subprotocol even though requested';
-    } else if (serverProt && protList.indexOf(serverProt) === -1) {
-      protError = 'server responded with an invalid protocol';
-    }
-
-    if (protError) {
-      self.emit('error', protError);
-      self.removeAllListeners();
-      socket.end();
-      return;
-    } else if (serverProt) {
-      self.protocol = serverProt;
-    }
-
-    var serverExtensions = Extensions.parse(res.headers['sec-websocket-extensions']);
-    if (perMessageDeflate && serverExtensions[PerMessageDeflate.extensionName]) {
-      try {
-        perMessageDeflate.accept(serverExtensions[PerMessageDeflate.extensionName]);
-      } catch (err) {
-        self.emit('error', 'invalid extension parameter');
-        self.removeAllListeners();
-        socket.end();
-        return;
-      }
-      self.extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
-    }
-
-    establishConnection.call(self, Receiver, Sender, socket, upgradeHead);
-
-    // perform cleanup on http resources
-    req.removeAllListeners();
-    req = null;
-    agent = null;
-  });
-
-  req.end();
-  this.readyState = WebSocket.CONNECTING;
-}
-
-function establishConnection(ReceiverClass, SenderClass, socket, upgradeHead) {
-  var ultron = this._ultron = new Ultron(socket);
-  this._socket = socket;
-
-  socket.setTimeout(0);
-  socket.setNoDelay(true);
-  var self = this;
-  this._receiver = new ReceiverClass(this.extensions);
-
-  // socket cleanup handlers
-  ultron.on('end', cleanupWebsocketResources.bind(this));
-  ultron.on('close', cleanupWebsocketResources.bind(this));
-  ultron.on('error', cleanupWebsocketResources.bind(this));
-
-  // ensure that the upgradeHead is added to the receiver
-  function firstHandler(data) {
-    if (self.readyState !== WebSocket.OPEN && self.readyState !== WebSocket.CLOSING) return;
-
-    if (upgradeHead && upgradeHead.length > 0) {
-      self.bytesReceived += upgradeHead.length;
-      var head = upgradeHead;
-      upgradeHead = null;
-      self._receiver.add(head);
-    }
-
-    dataHandler = realHandler;
-
-    if (data) {
-      self.bytesReceived += data.length;
-      self._receiver.add(data);
-    }
-  }
-
-  // subsequent packets are pushed straight to the receiver
-  function realHandler(data) {
-    if (data) self.bytesReceived += data.length;
-    self._receiver.add(data);
-  }
-
-  var dataHandler = firstHandler;
-
-  // if data was passed along with the http upgrade,
-  // this will schedule a push of that on to the receiver.
-  // this has to be done on next tick, since the caller
-  // hasn't had a chance to set event handlers on this client
-  // object yet.
-  process.nextTick(firstHandler);
-
-  // receiver event handlers
-  self._receiver.ontext = function ontext(data, flags) {
-    flags = flags || {};
-
-    self.emit('message', data, flags);
-  };
-
-  self._receiver.onbinary = function onbinary(data, flags) {
-    flags = flags || {};
-
-    flags.binary = true;
-    self.emit('message', data, flags);
-  };
-
-  self._receiver.onping = function onping(data, flags) {
-    flags = flags || {};
-
-    self.pong(data, {
-      mask: !self._isServer,
-      binary: flags.binary === true
-    }, true);
-
-    self.emit('ping', data, flags);
-  };
-
-  self._receiver.onpong = function onpong(data, flags) {
-    self.emit('pong', data, flags || {});
-  };
-
-  self._receiver.onclose = function onclose(code, data, flags) {
-    flags = flags || {};
-
-    self._closeReceived = true;
-    self.close(code, data);
-  };
-
-  self._receiver.onerror = function onerror(reason, errorCode) {
-    // close the connection when the receiver reports a HyBi error code
-    self.close(typeof errorCode !== 'undefined' ? errorCode : 1002, '');
-    self.emit('error', reason, errorCode);
-  };
-
-  // finalize the client
-  this._sender = new SenderClass(socket, this.extensions);
-  this._sender.on('error', function onerror(error) {
-    self.close(1002, '');
-    self.emit('error', error);
-  });
-
-  this.readyState = WebSocket.OPEN;
-  this.emit('open');
-
-  ultron.on('data', dataHandler);
-}
-
-function startQueue(instance) {
-  instance._queue = instance._queue || [];
-}
-
-function executeQueueSends(instance) {
-  var queue = instance._queue;
-  if (typeof queue === 'undefined') return;
-
-  delete instance._queue;
-  for (var i = 0, l = queue.length; i < l; ++i) {
-    queue[i]();
-  }
-}
-
-function sendStream(instance, stream, options, cb) {
-  stream.on('data', function incoming(data) {
-    if (instance.readyState !== WebSocket.OPEN) {
-      if (typeof cb === 'function') cb(new Error('not opened'));
-      else {
-        delete instance._queue;
-        instance.emit('error', new Error('not opened'));
-      }
-      return;
-    }
-
-    options.fin = false;
-    instance._sender.send(data, options);
-  });
-
-  stream.on('end', function end() {
-    if (instance.readyState !== WebSocket.OPEN) {
-      if (typeof cb === 'function') cb(new Error('not opened'));
-      else {
-        delete instance._queue;
-        instance.emit('error', new Error('not opened'));
-      }
-      return;
-    }
-
-    options.fin = true;
-    instance._sender.send(null, options);
-
-    if (typeof cb === 'function') cb(null);
-  });
-}
-
-function cleanupWebsocketResources(error) {
-  if (this.readyState === WebSocket.CLOSED) return;
-
-  var emitClose = this.readyState !== WebSocket.CONNECTING;
-  this.readyState = WebSocket.CLOSED;
-
-  clearTimeout(this._closeTimer);
-  this._closeTimer = null;
-
-  if (emitClose) {
-    this.emit('close', this._closeCode || 1000, this._closeMessage || '');
-  }
-
-  if (this._socket) {
-    if (this._ultron) this._ultron.destroy();
-    this._socket.on('error', function onerror() {
-      try { this.destroy(); }
-      catch (e) {}
-    });
-
-    try {
-      if (!error) this._socket.end();
-      else this._socket.destroy();
-    } catch (e) { /* Ignore termination errors */ }
-
-    this._socket = null;
-    this._ultron = null;
-  }
-
-  if (this._sender) {
-    this._sender.removeAllListeners();
-    this._sender = null;
-  }
-
-  if (this._receiver) {
-    this._receiver.cleanup();
-    this._receiver = null;
-  }
-
-  this.removeAllListeners();
-  this.on('error', function onerror() {}); // catch all errors after this
-  delete this._queue;
-}
diff --git a/input_devices/mag/node_modules/ws/lib/WebSocketServer.js b/input_devices/mag/node_modules/ws/lib/WebSocketServer.js
deleted file mode 100644
index a2f3a618..00000000
--- a/input_devices/mag/node_modules/ws/lib/WebSocketServer.js
+++ /dev/null
@@ -1,501 +0,0 @@
-/*!
- * ws: a node.js websocket client
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var util = require('util')
-  , events = require('events')
-  , http = require('http')
-  , crypto = require('crypto')
-  , Options = require('options')
-  , WebSocket = require('./WebSocket')
-  , Extensions = require('./Extensions')
-  , PerMessageDeflate = require('./PerMessageDeflate')
-  , tls = require('tls')
-  , url = require('url');
-
-/**
- * WebSocket Server implementation
- */
-
-function WebSocketServer(options, callback) {
-  events.EventEmitter.call(this);
-
-  options = new Options({
-    host: '0.0.0.0',
-    port: null,
-    server: null,
-    verifyClient: null,
-    handleProtocols: null,
-    path: null,
-    noServer: false,
-    disableHixie: false,
-    clientTracking: true,
-    perMessageDeflate: true
-  }).merge(options);
-
-  if (!options.isDefinedAndNonNull('port') && !options.isDefinedAndNonNull('server') && !options.value.noServer) {
-    throw new TypeError('`port` or a `server` must be provided');
-  }
-
-  var self = this;
-
-  if (options.isDefinedAndNonNull('port')) {
-    this._server = http.createServer(function (req, res) {
-      res.writeHead(200, {'Content-Type': 'text/plain'});
-      res.end('Not implemented');
-    });
-    this._server.listen(options.value.port, options.value.host, callback);
-    this._closeServer = function() { if (self._server) self._server.close(); };
-  }
-  else if (options.value.server) {
-    this._server = options.value.server;
-    if (options.value.path) {
-      // take note of the path, to avoid collisions when multiple websocket servers are
-      // listening on the same http server
-      if (this._server._webSocketPaths && options.value.server._webSocketPaths[options.value.path]) {
-        throw new Error('two instances of WebSocketServer cannot listen on the same http server path');
-      }
-      if (typeof this._server._webSocketPaths !== 'object') {
-        this._server._webSocketPaths = {};
-      }
-      this._server._webSocketPaths[options.value.path] = 1;
-    }
-  }
-  if (this._server) this._server.once('listening', function() { self.emit('listening'); });
-
-  if (typeof this._server != 'undefined') {
-    this._server.on('error', function(error) {
-      self.emit('error', error)
-    });
-    this._server.on('upgrade', function(req, socket, upgradeHead) {
-      //copy upgradeHead to avoid retention of large slab buffers used in node core
-      var head = new Buffer(upgradeHead.length);
-      upgradeHead.copy(head);
-
-      self.handleUpgrade(req, socket, head, function(client) {
-        self.emit('connection'+req.url, client);
-        self.emit('connection', client);
-      });
-    });
-  }
-
-  this.options = options.value;
-  this.path = options.value.path;
-  this.clients = [];
-}
-
-/**
- * Inherits from EventEmitter.
- */
-
-util.inherits(WebSocketServer, events.EventEmitter);
-
-/**
- * Immediately shuts down the connection.
- *
- * @api public
- */
-
-WebSocketServer.prototype.close = function() {
-  // terminate all associated clients
-  var error = null;
-  try {
-    for (var i = 0, l = this.clients.length; i < l; ++i) {
-      this.clients[i].terminate();
-    }
-  }
-  catch (e) {
-    error = e;
-  }
-
-  // remove path descriptor, if any
-  if (this.path && this._server._webSocketPaths) {
-    delete this._server._webSocketPaths[this.path];
-    if (Object.keys(this._server._webSocketPaths).length == 0) {
-      delete this._server._webSocketPaths;
-    }
-  }
-
-  // close the http server if it was internally created
-  try {
-    if (typeof this._closeServer !== 'undefined') {
-      this._closeServer();
-    }
-  }
-  finally {
-    delete this._server;
-  }
-  if (error) throw error;
-}
-
-/**
- * Handle a HTTP Upgrade request.
- *
- * @api public
- */
-
-WebSocketServer.prototype.handleUpgrade = function(req, socket, upgradeHead, cb) {
-  // check for wrong path
-  if (this.options.path) {
-    var u = url.parse(req.url);
-    if (u && u.pathname !== this.options.path) return;
-  }
-
-  if (typeof req.headers.upgrade === 'undefined' || req.headers.upgrade.toLowerCase() !== 'websocket') {
-    abortConnection(socket, 400, 'Bad Request');
-    return;
-  }
-
-  if (req.headers['sec-websocket-key1']) handleHixieUpgrade.apply(this, arguments);
-  else handleHybiUpgrade.apply(this, arguments);
-}
-
-module.exports = WebSocketServer;
-
-/**
- * Entirely private apis,
- * which may or may not be bound to a sepcific WebSocket instance.
- */
-
-function handleHybiUpgrade(req, socket, upgradeHead, cb) {
-  // handle premature socket errors
-  var errorHandler = function() {
-    try { socket.destroy(); } catch (e) {}
-  }
-  socket.on('error', errorHandler);
-
-  // verify key presence
-  if (!req.headers['sec-websocket-key']) {
-    abortConnection(socket, 400, 'Bad Request');
-    return;
-  }
-
-  // verify version
-  var version = parseInt(req.headers['sec-websocket-version']);
-  if ([8, 13].indexOf(version) === -1) {
-    abortConnection(socket, 400, 'Bad Request');
-    return;
-  }
-
-  // verify protocol
-  var protocols = req.headers['sec-websocket-protocol'];
-
-  // verify client
-  var origin = version < 13 ?
-    req.headers['sec-websocket-origin'] :
-    req.headers['origin'];
-
-  // handle extensions offer
-  var extensionsOffer = Extensions.parse(req.headers['sec-websocket-extensions']);
-
-  // handler to call when the connection sequence completes
-  var self = this;
-  var completeHybiUpgrade2 = function(protocol) {
-
-    // calc key
-    var key = req.headers['sec-websocket-key'];
-    var shasum = crypto.createHash('sha1');
-    shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
-    key = shasum.digest('base64');
-
-    var headers = [
-        'HTTP/1.1 101 Switching Protocols'
-      , 'Upgrade: websocket'
-      , 'Connection: Upgrade'
-      , 'Sec-WebSocket-Accept: ' + key
-    ];
-
-    if (typeof protocol != 'undefined') {
-      headers.push('Sec-WebSocket-Protocol: ' + protocol);
-    }
-
-    var extensions = {};
-    try {
-      extensions = acceptExtensions.call(self, extensionsOffer);
-    } catch (err) {
-      abortConnection(socket, 400, 'Bad Request');
-      return;
-    }
-
-    if (Object.keys(extensions).length) {
-      var serverExtensions = {};
-      Object.keys(extensions).forEach(function(token) {
-        serverExtensions[token] = [extensions[token].params]
-      });
-      headers.push('Sec-WebSocket-Extensions: ' + Extensions.format(serverExtensions));
-    }
-
-    // allows external modification/inspection of handshake headers
-    self.emit('headers', headers);
-
-    socket.setTimeout(0);
-    socket.setNoDelay(true);
-    try {
-      socket.write(headers.concat('', '').join('\r\n'));
-    }
-    catch (e) {
-      // if the upgrade write fails, shut the connection down hard
-      try { socket.destroy(); } catch (e) {}
-      return;
-    }
-
-    var client = new WebSocket([req, socket, upgradeHead], {
-      protocolVersion: version,
-      protocol: protocol,
-      extensions: extensions
-    });
-
-    if (self.options.clientTracking) {
-      self.clients.push(client);
-      client.on('close', function() {
-        var index = self.clients.indexOf(client);
-        if (index != -1) {
-          self.clients.splice(index, 1);
-        }
-      });
-    }
-
-    // signal upgrade complete
-    socket.removeListener('error', errorHandler);
-    cb(client);
-  }
-
-  // optionally call external protocol selection handler before
-  // calling completeHybiUpgrade2
-  var completeHybiUpgrade1 = function() {
-    // choose from the sub-protocols
-    if (typeof self.options.handleProtocols == 'function') {
-        var protList = (protocols || "").split(/, */);
-        var callbackCalled = false;
-        var res = self.options.handleProtocols(protList, function(result, protocol) {
-          callbackCalled = true;
-          if (!result) abortConnection(socket, 401, 'Unauthorized');
-          else completeHybiUpgrade2(protocol);
-        });
-        if (!callbackCalled) {
-            // the handleProtocols handler never called our callback
-            abortConnection(socket, 501, 'Could not process protocols');
-        }
-        return;
-    } else {
-        if (typeof protocols !== 'undefined') {
-            completeHybiUpgrade2(protocols.split(/, */)[0]);
-        }
-        else {
-            completeHybiUpgrade2();
-        }
-    }
-  }
-
-  // optionally call external client verification handler
-  if (typeof this.options.verifyClient == 'function') {
-    var info = {
-      origin: origin,
-      secure: typeof req.connection.authorized !== 'undefined' || typeof req.connection.encrypted !== 'undefined',
-      req: req
-    };
-    if (this.options.verifyClient.length == 2) {
-      this.options.verifyClient(info, function(result, code, name) {
-        if (typeof code === 'undefined') code = 401;
-        if (typeof name === 'undefined') name = http.STATUS_CODES[code];
-
-        if (!result) abortConnection(socket, code, name);
-        else completeHybiUpgrade1();
-      });
-      return;
-    }
-    else if (!this.options.verifyClient(info)) {
-      abortConnection(socket, 401, 'Unauthorized');
-      return;
-    }
-  }
-
-  completeHybiUpgrade1();
-}
-
-function handleHixieUpgrade(req, socket, upgradeHead, cb) {
-  // handle premature socket errors
-  var errorHandler = function() {
-    try { socket.destroy(); } catch (e) {}
-  }
-  socket.on('error', errorHandler);
-
-  // bail if options prevent hixie
-  if (this.options.disableHixie) {
-    abortConnection(socket, 401, 'Hixie support disabled');
-    return;
-  }
-
-  // verify key presence
-  if (!req.headers['sec-websocket-key2']) {
-    abortConnection(socket, 400, 'Bad Request');
-    return;
-  }
-
-  var origin = req.headers['origin']
-    , self = this;
-
-  // setup handshake completion to run after client has been verified
-  var onClientVerified = function() {
-    var wshost;
-    if (!req.headers['x-forwarded-host'])
-        wshost = req.headers.host;
-    else
-        wshost = req.headers['x-forwarded-host'];
-    var location = ((req.headers['x-forwarded-proto'] === 'https' || socket.encrypted) ? 'wss' : 'ws') + '://' + wshost + req.url
-      , protocol = req.headers['sec-websocket-protocol'];
-
-    // handshake completion code to run once nonce has been successfully retrieved
-    var completeHandshake = function(nonce, rest) {
-      // calculate key
-      var k1 = req.headers['sec-websocket-key1']
-        , k2 = req.headers['sec-websocket-key2']
-        , md5 = crypto.createHash('md5');
-
-      [k1, k2].forEach(function (k) {
-        var n = parseInt(k.replace(/[^\d]/g, ''))
-          , spaces = k.replace(/[^ ]/g, '').length;
-        if (spaces === 0 || n % spaces !== 0){
-          abortConnection(socket, 400, 'Bad Request');
-          return;
-        }
-        n /= spaces;
-        md5.update(String.fromCharCode(
-          n >> 24 & 0xFF,
-          n >> 16 & 0xFF,
-          n >> 8  & 0xFF,
-          n       & 0xFF));
-      });
-      md5.update(nonce.toString('binary'));
-
-      var headers = [
-          'HTTP/1.1 101 Switching Protocols'
-        , 'Upgrade: WebSocket'
-        , 'Connection: Upgrade'
-        , 'Sec-WebSocket-Location: ' + location
-      ];
-      if (typeof protocol != 'undefined') headers.push('Sec-WebSocket-Protocol: ' + protocol);
-      if (typeof origin != 'undefined') headers.push('Sec-WebSocket-Origin: ' + origin);
-
-      socket.setTimeout(0);
-      socket.setNoDelay(true);
-      try {
-        // merge header and hash buffer
-        var headerBuffer = new Buffer(headers.concat('', '').join('\r\n'));
-        var hashBuffer = new Buffer(md5.digest('binary'), 'binary');
-        var handshakeBuffer = new Buffer(headerBuffer.length + hashBuffer.length);
-        headerBuffer.copy(handshakeBuffer, 0);
-        hashBuffer.copy(handshakeBuffer, headerBuffer.length);
-
-        // do a single write, which - upon success - causes a new client websocket to be setup
-        socket.write(handshakeBuffer, 'binary', function(err) {
-          if (err) return; // do not create client if an error happens
-          var client = new WebSocket([req, socket, rest], {
-            protocolVersion: 'hixie-76',
-            protocol: protocol
-          });
-          if (self.options.clientTracking) {
-            self.clients.push(client);
-            client.on('close', function() {
-              var index = self.clients.indexOf(client);
-              if (index != -1) {
-                self.clients.splice(index, 1);
-              }
-            });
-          }
-
-          // signal upgrade complete
-          socket.removeListener('error', errorHandler);
-          cb(client);
-        });
-      }
-      catch (e) {
-        try { socket.destroy(); } catch (e) {}
-        return;
-      }
-    }
-
-    // retrieve nonce
-    var nonceLength = 8;
-    if (upgradeHead && upgradeHead.length >= nonceLength) {
-      var nonce = upgradeHead.slice(0, nonceLength);
-      var rest = upgradeHead.length > nonceLength ? upgradeHead.slice(nonceLength) : null;
-      completeHandshake.call(self, nonce, rest);
-    }
-    else {
-      // nonce not present in upgradeHead, so we must wait for enough data
-      // data to arrive before continuing
-      var nonce = new Buffer(nonceLength);
-      upgradeHead.copy(nonce, 0);
-      var received = upgradeHead.length;
-      var rest = null;
-      var handler = function (data) {
-        var toRead = Math.min(data.length, nonceLength - received);
-        if (toRead === 0) return;
-        data.copy(nonce, received, 0, toRead);
-        received += toRead;
-        if (received == nonceLength) {
-          socket.removeListener('data', handler);
-          if (toRead < data.length) rest = data.slice(toRead);
-          completeHandshake.call(self, nonce, rest);
-        }
-      }
-      socket.on('data', handler);
-    }
-  }
-
-  // verify client
-  if (typeof this.options.verifyClient == 'function') {
-    var info = {
-      origin: origin,
-      secure: typeof req.connection.authorized !== 'undefined' || typeof req.connection.encrypted !== 'undefined',
-      req: req
-    };
-    if (this.options.verifyClient.length == 2) {
-      var self = this;
-      this.options.verifyClient(info, function(result, code, name) {
-        if (typeof code === 'undefined') code = 401;
-        if (typeof name === 'undefined') name = http.STATUS_CODES[code];
-
-        if (!result) abortConnection(socket, code, name);
-        else onClientVerified.apply(self);
-      });
-      return;
-    }
-    else if (!this.options.verifyClient(info)) {
-      abortConnection(socket, 401, 'Unauthorized');
-      return;
-    }
-  }
-
-  // no client verification required
-  onClientVerified();
-}
-
-function acceptExtensions(offer) {
-  var extensions = {};
-  var options = this.options.perMessageDeflate;
-  if (options && offer[PerMessageDeflate.extensionName]) {
-    var perMessageDeflate = new PerMessageDeflate(options !== true ? options : {}, true);
-    perMessageDeflate.accept(offer[PerMessageDeflate.extensionName]);
-    extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
-  }
-  return extensions;
-}
-
-function abortConnection(socket, code, name) {
-  try {
-    var response = [
-      'HTTP/1.1 ' + code + ' ' + name,
-      'Content-type: text/html'
-    ];
-    socket.write(response.concat('', '').join('\r\n'));
-  }
-  catch (e) { /* ignore errors - we've aborted this connection */ }
-  finally {
-    // ensure that an early aborted connection is shut down completely
-    try { socket.destroy(); } catch (e) {}
-  }
-}
diff --git a/input_devices/mag/node_modules/ws/lib/browser.js b/input_devices/mag/node_modules/ws/lib/browser.js
deleted file mode 100644
index 8d3a755c..00000000
--- a/input_devices/mag/node_modules/ws/lib/browser.js
+++ /dev/null
@@ -1,43 +0,0 @@
-
-/**
- * Module dependencies.
- */
-
-var global = (function() { return this; })();
-
-/**
- * WebSocket constructor.
- */
-
-var WebSocket = global.WebSocket || global.MozWebSocket;
-
-/**
- * Module exports.
- */
-
-module.exports = WebSocket ? ws : null;
-
-/**
- * WebSocket constructor.
- *
- * The third `opts` options object gets ignored in web browsers, since it's
- * non-standard, and throws a TypeError if passed to the constructor.
- * See: https://github.com/einaros/ws/issues/227
- *
- * @param {String} uri
- * @param {Array} protocols (optional)
- * @param {Object) opts (optional)
- * @api public
- */
-
-function ws(uri, protocols, opts) {
-  var instance;
-  if (protocols) {
-    instance = new WebSocket(uri, protocols);
-  } else {
-    instance = new WebSocket(uri);
-  }
-  return instance;
-}
-
-if (WebSocket) ws.prototype = WebSocket.prototype;
diff --git a/input_devices/mag/node_modules/ws/lib/buffer-util.js b/input_devices/mag/node_modules/ws/lib/buffer-util.js
new file mode 100644
index 00000000..6974dd6a
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/buffer-util.js
@@ -0,0 +1,72 @@
+'use strict';
+
+/**
+ * Merges an array of buffers into a new buffer.
+ *
+ * @param {Buffer[]} list The array of buffers to concat
+ * @param {Number} totalLength The total length of buffers in the list
+ * @return {Buffer} The resulting buffer
+ * @public
+ */
+function concat (list, totalLength) {
+  const target = Buffer.allocUnsafe(totalLength);
+  var offset = 0;
+
+  for (var i = 0; i < list.length; i++) {
+    const buf = list[i];
+    buf.copy(target, offset);
+    offset += buf.length;
+  }
+
+  return target;
+}
+
+/**
+ * Masks a buffer using the given mask.
+ *
+ * @param {Buffer} source The buffer to mask
+ * @param {Buffer} mask The mask to use
+ * @param {Buffer} output The buffer where to store the result
+ * @param {Number} offset The offset at which to start writing
+ * @param {Number} length The number of bytes to mask.
+ * @public
+ */
+function _mask (source, mask, output, offset, length) {
+  for (var i = 0; i < length; i++) {
+    output[offset + i] = source[i] ^ mask[i & 3];
+  }
+}
+
+/**
+ * Unmasks a buffer using the given mask.
+ *
+ * @param {Buffer} buffer The buffer to unmask
+ * @param {Buffer} mask The mask to use
+ * @public
+ */
+function _unmask (buffer, mask) {
+  // Required until https://github.com/nodejs/node/issues/9006 is resolved.
+  const length = buffer.length;
+  for (var i = 0; i < length; i++) {
+    buffer[i] ^= mask[i & 3];
+  }
+}
+
+try {
+  const bufferUtil = require('bufferutil');
+  const bu = bufferUtil.BufferUtil || bufferUtil;
+
+  module.exports = {
+    mask (source, mask, output, offset, length) {
+      if (length < 48) _mask(source, mask, output, offset, length);
+      else bu.mask(source, mask, output, offset, length);
+    },
+    unmask (buffer, mask) {
+      if (buffer.length < 32) _unmask(buffer, mask);
+      else bu.unmask(buffer, mask);
+    },
+    concat
+  };
+} catch (e) /* istanbul ignore next */ {
+  module.exports = { concat, mask: _mask, unmask: _unmask };
+}
diff --git a/input_devices/mag/node_modules/ws/lib/constants.js b/input_devices/mag/node_modules/ws/lib/constants.js
new file mode 100644
index 00000000..4082981f
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/constants.js
@@ -0,0 +1,10 @@
+'use strict';
+
+module.exports = {
+  BINARY_TYPES: ['nodebuffer', 'arraybuffer', 'fragments'],
+  GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
+  kStatusCode: Symbol('status-code'),
+  kWebSocket: Symbol('websocket'),
+  EMPTY_BUFFER: Buffer.alloc(0),
+  NOOP: () => {}
+};
diff --git a/input_devices/mag/node_modules/ws/lib/event-target.js b/input_devices/mag/node_modules/ws/lib/event-target.js
new file mode 100644
index 00000000..574e9080
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/event-target.js
@@ -0,0 +1,170 @@
+'use strict';
+
+/**
+ * Class representing an event.
+ *
+ * @private
+ */
+class Event {
+  /**
+   * Create a new `Event`.
+   *
+   * @param {String} type The name of the event
+   * @param {Object} target A reference to the target to which the event was dispatched
+   */
+  constructor (type, target) {
+    this.target = target;
+    this.type = type;
+  }
+}
+
+/**
+ * Class representing a message event.
+ *
+ * @extends Event
+ * @private
+ */
+class MessageEvent extends Event {
+  /**
+   * Create a new `MessageEvent`.
+   *
+   * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The received data
+   * @param {WebSocket} target A reference to the target to which the event was dispatched
+   */
+  constructor (data, target) {
+    super('message', target);
+
+    this.data = data;
+  }
+}
+
+/**
+ * Class representing a close event.
+ *
+ * @extends Event
+ * @private
+ */
+class CloseEvent extends Event {
+  /**
+   * Create a new `CloseEvent`.
+   *
+   * @param {Number} code The status code explaining why the connection is being closed
+   * @param {String} reason A human-readable string explaining why the connection is closing
+   * @param {WebSocket} target A reference to the target to which the event was dispatched
+   */
+  constructor (code, reason, target) {
+    super('close', target);
+
+    this.wasClean = target._closeFrameReceived && target._closeFrameSent;
+    this.reason = reason;
+    this.code = code;
+  }
+}
+
+/**
+ * Class representing an open event.
+ *
+ * @extends Event
+ * @private
+ */
+class OpenEvent extends Event {
+  /**
+   * Create a new `OpenEvent`.
+   *
+   * @param {WebSocket} target A reference to the target to which the event was dispatched
+   */
+  constructor (target) {
+    super('open', target);
+  }
+}
+
+/**
+ * Class representing an error event.
+ *
+ * @extends Event
+ * @private
+ */
+class ErrorEvent extends Event {
+  /**
+   * Create a new `ErrorEvent`.
+   *
+   * @param {Object} error The error that generated this event
+   * @param {WebSocket} target A reference to the target to which the event was dispatched
+   */
+  constructor (error, target) {
+    super('error', target);
+
+    this.message = error.message;
+    this.error = error;
+  }
+}
+
+/**
+ * This provides methods for emulating the `EventTarget` interface. It's not
+ * meant to be used directly.
+ *
+ * @mixin
+ */
+const EventTarget = {
+  /**
+   * Register an event listener.
+   *
+   * @param {String} method A string representing the event type to listen for
+   * @param {Function} listener The listener to add
+   * @public
+   */
+  addEventListener (method, listener) {
+    if (typeof listener !== 'function') return;
+
+    function onMessage (data) {
+      listener.call(this, new MessageEvent(data, this));
+    }
+
+    function onClose (code, message) {
+      listener.call(this, new CloseEvent(code, message, this));
+    }
+
+    function onError (error) {
+      listener.call(this, new ErrorEvent(error, this));
+    }
+
+    function onOpen () {
+      listener.call(this, new OpenEvent(this));
+    }
+
+    if (method === 'message') {
+      onMessage._listener = listener;
+      this.on(method, onMessage);
+    } else if (method === 'close') {
+      onClose._listener = listener;
+      this.on(method, onClose);
+    } else if (method === 'error') {
+      onError._listener = listener;
+      this.on(method, onError);
+    } else if (method === 'open') {
+      onOpen._listener = listener;
+      this.on(method, onOpen);
+    } else {
+      this.on(method, listener);
+    }
+  },
+
+  /**
+   * Remove an event listener.
+   *
+   * @param {String} method A string representing the event type to remove
+   * @param {Function} listener The listener to remove
+   * @public
+   */
+  removeEventListener (method, listener) {
+    const listeners = this.listeners(method);
+
+    for (var i = 0; i < listeners.length; i++) {
+      if (listeners[i] === listener || listeners[i]._listener === listener) {
+        this.removeListener(method, listeners[i]);
+      }
+    }
+  }
+};
+
+module.exports = EventTarget;
diff --git a/input_devices/mag/node_modules/ws/lib/extension.js b/input_devices/mag/node_modules/ws/lib/extension.js
new file mode 100644
index 00000000..3f48d751
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/extension.js
@@ -0,0 +1,211 @@
+'use strict';
+
+//
+// Allowed token characters:
+//
+// '!', '#', '$', '%', '&', ''', '*', '+', '-',
+// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
+//
+// tokenChars[32] === 0 // ' '
+// tokenChars[33] === 1 // '!'
+// tokenChars[34] === 0 // '"'
+// ...
+//
+const tokenChars = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
+  0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
+  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
+];
+
+/**
+ * Adds an offer to the map of extension offers or a parameter to the map of
+ * parameters.
+ *
+ * @param {Object} dest The map of extension offers or parameters
+ * @param {String} name The extension or parameter name
+ * @param {(Object|Boolean|String)} elem The extension parameters or the
+ *     parameter value
+ * @private
+ */
+function push (dest, name, elem) {
+  if (Object.prototype.hasOwnProperty.call(dest, name)) dest[name].push(elem);
+  else dest[name] = [elem];
+}
+
+/**
+ * Parses the `Sec-WebSocket-Extensions` header into an object.
+ *
+ * @param {String} header The field value of the header
+ * @return {Object} The parsed object
+ * @public
+ */
+function parse (header) {
+  const offers = {};
+
+  if (header === undefined || header === '') return offers;
+
+  var params = {};
+  var mustUnescape = false;
+  var isEscaping = false;
+  var inQuotes = false;
+  var extensionName;
+  var paramName;
+  var start = -1;
+  var end = -1;
+
+  for (var i = 0; i < header.length; i++) {
+    const code = header.charCodeAt(i);
+
+    if (extensionName === undefined) {
+      if (end === -1 && tokenChars[code] === 1) {
+        if (start === -1) start = i;
+      } else if (code === 0x20/* ' ' */|| code === 0x09/* '\t' */) {
+        if (end === -1 && start !== -1) end = i;
+      } else if (code === 0x3b/* ';' */ || code === 0x2c/* ',' */) {
+        if (start === -1) {
+          throw new SyntaxError(`Unexpected character at index ${i}`);
+        }
+
+        if (end === -1) end = i;
+        const name = header.slice(start, end);
+        if (code === 0x2c) {
+          push(offers, name, params);
+          params = {};
+        } else {
+          extensionName = name;
+        }
+
+        start = end = -1;
+      } else {
+        throw new SyntaxError(`Unexpected character at index ${i}`);
+      }
+    } else if (paramName === undefined) {
+      if (end === -1 && tokenChars[code] === 1) {
+        if (start === -1) start = i;
+      } else if (code === 0x20 || code === 0x09) {
+        if (end === -1 && start !== -1) end = i;
+      } else if (code === 0x3b || code === 0x2c) {
+        if (start === -1) {
+          throw new SyntaxError(`Unexpected character at index ${i}`);
+        }
+
+        if (end === -1) end = i;
+        push(params, header.slice(start, end), true);
+        if (code === 0x2c) {
+          push(offers, extensionName, params);
+          params = {};
+          extensionName = undefined;
+        }
+
+        start = end = -1;
+      } else if (code === 0x3d/* '=' */&& start !== -1 && end === -1) {
+        paramName = header.slice(start, i);
+        start = end = -1;
+      } else {
+        throw new SyntaxError(`Unexpected character at index ${i}`);
+      }
+    } else {
+      //
+      // The value of a quoted-string after unescaping must conform to the
+      // token ABNF, so only token characters are valid.
+      // Ref: https://tools.ietf.org/html/rfc6455#section-9.1
+      //
+      if (isEscaping) {
+        if (tokenChars[code] !== 1) {
+          throw new SyntaxError(`Unexpected character at index ${i}`);
+        }
+        if (start === -1) start = i;
+        else if (!mustUnescape) mustUnescape = true;
+        isEscaping = false;
+      } else if (inQuotes) {
+        if (tokenChars[code] === 1) {
+          if (start === -1) start = i;
+        } else if (code === 0x22/* '"' */ && start !== -1) {
+          inQuotes = false;
+          end = i;
+        } else if (code === 0x5c/* '\' */) {
+          isEscaping = true;
+        } else {
+          throw new SyntaxError(`Unexpected character at index ${i}`);
+        }
+      } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
+        inQuotes = true;
+      } else if (end === -1 && tokenChars[code] === 1) {
+        if (start === -1) start = i;
+      } else if (start !== -1 && (code === 0x20 || code === 0x09)) {
+        if (end === -1) end = i;
+      } else if (code === 0x3b || code === 0x2c) {
+        if (start === -1) {
+          throw new SyntaxError(`Unexpected character at index ${i}`);
+        }
+
+        if (end === -1) end = i;
+        var value = header.slice(start, end);
+        if (mustUnescape) {
+          value = value.replace(/\\/g, '');
+          mustUnescape = false;
+        }
+        push(params, paramName, value);
+        if (code === 0x2c) {
+          push(offers, extensionName, params);
+          params = {};
+          extensionName = undefined;
+        }
+
+        paramName = undefined;
+        start = end = -1;
+      } else {
+        throw new SyntaxError(`Unexpected character at index ${i}`);
+      }
+    }
+  }
+
+  if (start === -1 || inQuotes) {
+    throw new SyntaxError('Unexpected end of input');
+  }
+
+  if (end === -1) end = i;
+  const token = header.slice(start, end);
+  if (extensionName === undefined) {
+    push(offers, token, {});
+  } else {
+    if (paramName === undefined) {
+      push(params, token, true);
+    } else if (mustUnescape) {
+      push(params, paramName, token.replace(/\\/g, ''));
+    } else {
+      push(params, paramName, token);
+    }
+    push(offers, extensionName, params);
+  }
+
+  return offers;
+}
+
+/**
+ * Builds the `Sec-WebSocket-Extensions` header field value.
+ *
+ * @param {Object} extensions The map of extensions and parameters to format
+ * @return {String} A string representing the given object
+ * @public
+ */
+function format (extensions) {
+  return Object.keys(extensions).map((extension) => {
+    var configurations = extensions[extension];
+    if (!Array.isArray(configurations)) configurations = [configurations];
+    return configurations.map((params) => {
+      return [extension].concat(Object.keys(params).map((k) => {
+        var values = params[k];
+        if (!Array.isArray(values)) values = [values];
+        return values.map((v) => v === true ? k : `${k}=${v}`).join('; ');
+      })).join('; ');
+    }).join(', ');
+  }).join(', ');
+}
+
+module.exports = { format, parse };
diff --git a/input_devices/mag/node_modules/ws/lib/permessage-deflate.js b/input_devices/mag/node_modules/ws/lib/permessage-deflate.js
new file mode 100644
index 00000000..d4ec149c
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/permessage-deflate.js
@@ -0,0 +1,508 @@
+'use strict';
+
+const Limiter = require('async-limiter');
+const zlib = require('zlib');
+
+const bufferUtil = require('./buffer-util');
+const constants = require('./constants');
+
+const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
+const EMPTY_BLOCK = Buffer.from([0x00]);
+
+const kPerMessageDeflate = Symbol('permessage-deflate');
+const kWriteInProgress = Symbol('write-in-progress');
+const kPendingClose = Symbol('pending-close');
+const kTotalLength = Symbol('total-length');
+const kCallback = Symbol('callback');
+const kBuffers = Symbol('buffers');
+const kError = Symbol('error');
+
+//
+// We limit zlib concurrency, which prevents severe memory fragmentation
+// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913
+// and https://github.com/websockets/ws/issues/1202
+//
+// Intentionally global; it's the global thread pool that's an issue.
+//
+let zlibLimiter;
+
+/**
+ * permessage-deflate implementation.
+ */
+class PerMessageDeflate {
+  /**
+   * Creates a PerMessageDeflate instance.
+   *
+   * @param {Object} options Configuration options
+   * @param {Boolean} options.serverNoContextTakeover Request/accept disabling
+   *     of server context takeover
+   * @param {Boolean} options.clientNoContextTakeover Advertise/acknowledge
+   *     disabling of client context takeover
+   * @param {(Boolean|Number)} options.serverMaxWindowBits Request/confirm the
+   *     use of a custom server window size
+   * @param {(Boolean|Number)} options.clientMaxWindowBits Advertise support
+   *     for, or request, a custom client window size
+   * @param {Object} options.zlibDeflateOptions Options to pass to zlib on deflate
+   * @param {Object} options.zlibInflateOptions Options to pass to zlib on inflate
+   * @param {Number} options.threshold Size (in bytes) below which messages
+   *     should not be compressed
+   * @param {Number} options.concurrencyLimit The number of concurrent calls to
+   *     zlib
+   * @param {Boolean} isServer Create the instance in either server or client
+   *     mode
+   * @param {Number} maxPayload The maximum allowed message length
+   */
+  constructor (options, isServer, maxPayload) {
+    this._maxPayload = maxPayload | 0;
+    this._options = options || {};
+    this._threshold = this._options.threshold !== undefined
+      ? this._options.threshold
+      : 1024;
+    this._isServer = !!isServer;
+    this._deflate = null;
+    this._inflate = null;
+
+    this.params = null;
+
+    if (!zlibLimiter) {
+      const concurrency = this._options.concurrencyLimit !== undefined
+        ? this._options.concurrencyLimit
+        : 10;
+      zlibLimiter = new Limiter({ concurrency });
+    }
+  }
+
+  /**
+   * @type {String}
+   */
+  static get extensionName () {
+    return 'permessage-deflate';
+  }
+
+  /**
+   * Create an extension negotiation offer.
+   *
+   * @return {Object} Extension parameters
+   * @public
+   */
+  offer () {
+    const params = {};
+
+    if (this._options.serverNoContextTakeover) {
+      params.server_no_context_takeover = true;
+    }
+    if (this._options.clientNoContextTakeover) {
+      params.client_no_context_takeover = true;
+    }
+    if (this._options.serverMaxWindowBits) {
+      params.server_max_window_bits = this._options.serverMaxWindowBits;
+    }
+    if (this._options.clientMaxWindowBits) {
+      params.client_max_window_bits = this._options.clientMaxWindowBits;
+    } else if (this._options.clientMaxWindowBits == null) {
+      params.client_max_window_bits = true;
+    }
+
+    return params;
+  }
+
+  /**
+   * Accept an extension negotiation offer/response.
+   *
+   * @param {Array} configurations The extension negotiation offers/reponse
+   * @return {Object} Accepted configuration
+   * @public
+   */
+  accept (configurations) {
+    configurations = this.normalizeParams(configurations);
+
+    this.params = this._isServer
+      ? this.acceptAsServer(configurations)
+      : this.acceptAsClient(configurations);
+
+    return this.params;
+  }
+
+  /**
+   * Releases all resources used by the extension.
+   *
+   * @public
+   */
+  cleanup () {
+    if (this._inflate) {
+      if (this._inflate[kWriteInProgress]) {
+        this._inflate[kPendingClose] = true;
+      } else {
+        this._inflate.close();
+        this._inflate = null;
+      }
+    }
+    if (this._deflate) {
+      if (this._deflate[kWriteInProgress]) {
+        this._deflate[kPendingClose] = true;
+      } else {
+        this._deflate.close();
+        this._deflate = null;
+      }
+    }
+  }
+
+  /**
+   *  Accept an extension negotiation offer.
+   *
+   * @param {Array} offers The extension negotiation offers
+   * @return {Object} Accepted configuration
+   * @private
+   */
+  acceptAsServer (offers) {
+    const opts = this._options;
+    const accepted = offers.find((params) => {
+      if (
+        (opts.serverNoContextTakeover === false &&
+          params.server_no_context_takeover) ||
+        (params.server_max_window_bits &&
+          (opts.serverMaxWindowBits === false ||
+            (typeof opts.serverMaxWindowBits === 'number' &&
+              opts.serverMaxWindowBits > params.server_max_window_bits))) ||
+        (typeof opts.clientMaxWindowBits === 'number' &&
+          !params.client_max_window_bits)
+      ) {
+        return false;
+      }
+
+      return true;
+    });
+
+    if (!accepted) {
+      throw new Error('None of the extension offers can be accepted');
+    }
+
+    if (opts.serverNoContextTakeover) {
+      accepted.server_no_context_takeover = true;
+    }
+    if (opts.clientNoContextTakeover) {
+      accepted.client_no_context_takeover = true;
+    }
+    if (typeof opts.serverMaxWindowBits === 'number') {
+      accepted.server_max_window_bits = opts.serverMaxWindowBits;
+    }
+    if (typeof opts.clientMaxWindowBits === 'number') {
+      accepted.client_max_window_bits = opts.clientMaxWindowBits;
+    } else if (
+      accepted.client_max_window_bits === true ||
+      opts.clientMaxWindowBits === false
+    ) {
+      delete accepted.client_max_window_bits;
+    }
+
+    return accepted;
+  }
+
+  /**
+   * Accept the extension negotiation response.
+   *
+   * @param {Array} response The extension negotiation response
+   * @return {Object} Accepted configuration
+   * @private
+   */
+  acceptAsClient (response) {
+    const params = response[0];
+
+    if (
+      this._options.clientNoContextTakeover === false &&
+      params.client_no_context_takeover
+    ) {
+      throw new Error('Unexpected parameter "client_no_context_takeover"');
+    }
+
+    if (!params.client_max_window_bits) {
+      if (typeof this._options.clientMaxWindowBits === 'number') {
+        params.client_max_window_bits = this._options.clientMaxWindowBits;
+      }
+    } else if (
+      this._options.clientMaxWindowBits === false ||
+      (typeof this._options.clientMaxWindowBits === 'number' &&
+        params.client_max_window_bits > this._options.clientMaxWindowBits)
+    ) {
+      throw new Error(
+        'Unexpected or invalid parameter "client_max_window_bits"'
+      );
+    }
+
+    return params;
+  }
+
+  /**
+   * Normalize parameters.
+   *
+   * @param {Array} configurations The extension negotiation offers/reponse
+   * @return {Array} The offers/response with normalized parameters
+   * @private
+   */
+  normalizeParams (configurations) {
+    configurations.forEach((params) => {
+      Object.keys(params).forEach((key) => {
+        var value = params[key];
+
+        if (value.length > 1) {
+          throw new Error(`Parameter "${key}" must have only a single value`);
+        }
+
+        value = value[0];
+
+        if (key === 'client_max_window_bits') {
+          if (value !== true) {
+            const num = +value;
+            if (!Number.isInteger(num) || num < 8 || num > 15) {
+              throw new TypeError(
+                `Invalid value for parameter "${key}": ${value}`
+              );
+            }
+            value = num;
+          } else if (!this._isServer) {
+            throw new TypeError(
+              `Invalid value for parameter "${key}": ${value}`
+            );
+          }
+        } else if (key === 'server_max_window_bits') {
+          const num = +value;
+          if (!Number.isInteger(num) || num < 8 || num > 15) {
+            throw new TypeError(
+              `Invalid value for parameter "${key}": ${value}`
+            );
+          }
+          value = num;
+        } else if (
+          key === 'client_no_context_takeover' ||
+          key === 'server_no_context_takeover'
+        ) {
+          if (value !== true) {
+            throw new TypeError(
+              `Invalid value for parameter "${key}": ${value}`
+            );
+          }
+        } else {
+          throw new Error(`Unknown parameter "${key}"`);
+        }
+
+        params[key] = value;
+      });
+    });
+
+    return configurations;
+  }
+
+  /**
+   * Decompress data. Concurrency limited by async-limiter.
+   *
+   * @param {Buffer} data Compressed data
+   * @param {Boolean} fin Specifies whether or not this is the last fragment
+   * @param {Function} callback Callback
+   * @public
+   */
+  decompress (data, fin, callback) {
+    zlibLimiter.push((done) => {
+      this._decompress(data, fin, (err, result) => {
+        done();
+        callback(err, result);
+      });
+    });
+  }
+
+  /**
+   * Compress data. Concurrency limited by async-limiter.
+   *
+   * @param {Buffer} data Data to compress
+   * @param {Boolean} fin Specifies whether or not this is the last fragment
+   * @param {Function} callback Callback
+   * @public
+   */
+  compress (data, fin, callback) {
+    zlibLimiter.push((done) => {
+      this._compress(data, fin, (err, result) => {
+        done();
+        callback(err, result);
+      });
+    });
+  }
+
+  /**
+   * Decompress data.
+   *
+   * @param {Buffer} data Compressed data
+   * @param {Boolean} fin Specifies whether or not this is the last fragment
+   * @param {Function} callback Callback
+   * @private
+   */
+  _decompress (data, fin, callback) {
+    const endpoint = this._isServer ? 'client' : 'server';
+
+    if (!this._inflate) {
+      const key = `${endpoint}_max_window_bits`;
+      const windowBits = typeof this.params[key] !== 'number'
+        ? zlib.Z_DEFAULT_WINDOWBITS
+        : this.params[key];
+
+      this._inflate = zlib.createInflateRaw(
+        Object.assign({}, this._options.zlibInflateOptions, { windowBits })
+      );
+      this._inflate[kPerMessageDeflate] = this;
+      this._inflate[kTotalLength] = 0;
+      this._inflate[kBuffers] = [];
+      this._inflate.on('error', inflateOnError);
+      this._inflate.on('data', inflateOnData);
+    }
+
+    this._inflate[kCallback] = callback;
+    this._inflate[kWriteInProgress] = true;
+
+    this._inflate.write(data);
+    if (fin) this._inflate.write(TRAILER);
+
+    this._inflate.flush(() => {
+      const err = this._inflate[kError];
+
+      if (err) {
+        this._inflate.close();
+        this._inflate = null;
+        callback(err);
+        return;
+      }
+
+      const data = bufferUtil.concat(
+        this._inflate[kBuffers],
+        this._inflate[kTotalLength]
+      );
+
+      if (
+        (fin && this.params[`${endpoint}_no_context_takeover`]) ||
+        this._inflate[kPendingClose]
+      ) {
+        this._inflate.close();
+        this._inflate = null;
+      } else {
+        this._inflate[kWriteInProgress] = false;
+        this._inflate[kTotalLength] = 0;
+        this._inflate[kBuffers] = [];
+      }
+
+      callback(null, data);
+    });
+  }
+
+  /**
+   * Compress data.
+   *
+   * @param {Buffer} data Data to compress
+   * @param {Boolean} fin Specifies whether or not this is the last fragment
+   * @param {Function} callback Callback
+   * @private
+   */
+  _compress (data, fin, callback) {
+    if (!data || data.length === 0) {
+      process.nextTick(callback, null, EMPTY_BLOCK);
+      return;
+    }
+
+    const endpoint = this._isServer ? 'server' : 'client';
+
+    if (!this._deflate) {
+      const key = `${endpoint}_max_window_bits`;
+      const windowBits = typeof this.params[key] !== 'number'
+        ? zlib.Z_DEFAULT_WINDOWBITS
+        : this.params[key];
+
+      this._deflate = zlib.createDeflateRaw(
+        Object.assign({}, this._options.zlibDeflateOptions, { windowBits })
+      );
+
+      this._deflate[kTotalLength] = 0;
+      this._deflate[kBuffers] = [];
+
+      //
+      // `zlib.DeflateRaw` emits an `'error'` event only when an attempt to use
+      // it is made after it has already been closed. This cannot happen here,
+      // so we only add a listener for the `'data'` event.
+      //
+      this._deflate.on('data', deflateOnData);
+    }
+
+    this._deflate[kWriteInProgress] = true;
+
+    this._deflate.write(data);
+    this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
+      var data = bufferUtil.concat(
+        this._deflate[kBuffers],
+        this._deflate[kTotalLength]
+      );
+
+      if (fin) data = data.slice(0, data.length - 4);
+
+      if (
+        (fin && this.params[`${endpoint}_no_context_takeover`]) ||
+        this._deflate[kPendingClose]
+      ) {
+        this._deflate.close();
+        this._deflate = null;
+      } else {
+        this._deflate[kWriteInProgress] = false;
+        this._deflate[kTotalLength] = 0;
+        this._deflate[kBuffers] = [];
+      }
+
+      callback(null, data);
+    });
+  }
+}
+
+module.exports = PerMessageDeflate;
+
+/**
+ * The listener of the `zlib.DeflateRaw` stream `'data'` event.
+ *
+ * @param {Buffer} chunk A chunk of data
+ * @private
+ */
+function deflateOnData (chunk) {
+  this[kBuffers].push(chunk);
+  this[kTotalLength] += chunk.length;
+}
+
+/**
+ * The listener of the `zlib.InflateRaw` stream `'data'` event.
+ *
+ * @param {Buffer} chunk A chunk of data
+ * @private
+ */
+function inflateOnData (chunk) {
+  this[kTotalLength] += chunk.length;
+
+  if (
+    this[kPerMessageDeflate]._maxPayload < 1 ||
+    this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload
+  ) {
+    this[kBuffers].push(chunk);
+    return;
+  }
+
+  this[kError] = new RangeError('Max payload size exceeded');
+  this[kError][constants.kStatusCode] = 1009;
+  this.removeListener('data', inflateOnData);
+  this.reset();
+}
+
+/**
+ * The listener of the `zlib.InflateRaw` stream `'error'` event.
+ *
+ * @param {Error} err The emitted error
+ * @private
+ */
+function inflateOnError (err) {
+  //
+  // There is no need to call `Zlib#close()` as the handle is automatically
+  // closed when an error is emitted.
+  //
+  this[kPerMessageDeflate]._inflate = null;
+  err[constants.kStatusCode] = 1007;
+  this[kCallback](err);
+}
diff --git a/input_devices/mag/node_modules/ws/lib/receiver.js b/input_devices/mag/node_modules/ws/lib/receiver.js
new file mode 100644
index 00000000..81dc0bf8
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/receiver.js
@@ -0,0 +1,513 @@
+'use strict';
+
+const stream = require('stream');
+
+const PerMessageDeflate = require('./permessage-deflate');
+const bufferUtil = require('./buffer-util');
+const validation = require('./validation');
+const constants = require('./constants');
+
+const GET_INFO = 0;
+const GET_PAYLOAD_LENGTH_16 = 1;
+const GET_PAYLOAD_LENGTH_64 = 2;
+const GET_MASK = 3;
+const GET_DATA = 4;
+const INFLATING = 5;
+
+/**
+ * HyBi Receiver implementation.
+ *
+ * @extends stream.Writable
+ */
+class Receiver extends stream.Writable {
+  /**
+   * Creates a Receiver instance.
+   *
+   * @param {String} binaryType The type for binary data
+   * @param {Object} extensions An object containing the negotiated extensions
+   * @param {Number} maxPayload The maximum allowed message length
+   */
+  constructor (binaryType, extensions, maxPayload) {
+    super();
+
+    this._binaryType = binaryType || constants.BINARY_TYPES[0];
+    this[constants.kWebSocket] = undefined;
+    this._extensions = extensions || {};
+    this._maxPayload = maxPayload | 0;
+
+    this._bufferedBytes = 0;
+    this._buffers = [];
+
+    this._compressed = false;
+    this._payloadLength = 0;
+    this._mask = undefined;
+    this._fragmented = 0;
+    this._masked = false;
+    this._fin = false;
+    this._opcode = 0;
+
+    this._totalPayloadLength = 0;
+    this._messageLength = 0;
+    this._fragments = [];
+
+    this._state = GET_INFO;
+    this._loop = false;
+  }
+
+  /**
+   * Implements `Writable.prototype._write()`.
+   *
+   * @param {Buffer} chunk The chunk of data to write
+   * @param {String} encoding The character encoding of `chunk`
+   * @param {Function} cb Callback
+   */
+  _write (chunk, encoding, cb) {
+    if (this._opcode === 0x08) return cb();
+
+    this._bufferedBytes += chunk.length;
+    this._buffers.push(chunk);
+    this.startLoop(cb);
+  }
+
+  /**
+   * Consumes `n` bytes from the buffered data.
+   *
+   * @param {Number} n The number of bytes to consume
+   * @return {Buffer} The consumed bytes
+   * @private
+   */
+  consume (n) {
+    this._bufferedBytes -= n;
+
+    if (n === this._buffers[0].length) return this._buffers.shift();
+
+    if (n < this._buffers[0].length) {
+      const buf = this._buffers[0];
+      this._buffers[0] = buf.slice(n);
+      return buf.slice(0, n);
+    }
+
+    const dst = Buffer.allocUnsafe(n);
+
+    do {
+      const buf = this._buffers[0];
+
+      if (n >= buf.length) {
+        this._buffers.shift().copy(dst, dst.length - n);
+      } else {
+        buf.copy(dst, dst.length - n, 0, n);
+        this._buffers[0] = buf.slice(n);
+      }
+
+      n -= buf.length;
+    } while (n > 0);
+
+    return dst;
+  }
+
+  /**
+   * Starts the parsing loop.
+   *
+   * @param {Function} cb Callback
+   * @private
+   */
+  startLoop (cb) {
+    var err;
+    this._loop = true;
+
+    do {
+      switch (this._state) {
+        case GET_INFO:
+          err = this.getInfo();
+          break;
+        case GET_PAYLOAD_LENGTH_16:
+          err = this.getPayloadLength16();
+          break;
+        case GET_PAYLOAD_LENGTH_64:
+          err = this.getPayloadLength64();
+          break;
+        case GET_MASK:
+          this.getMask();
+          break;
+        case GET_DATA:
+          err = this.getData(cb);
+          break;
+        default: // `INFLATING`
+          this._loop = false;
+          return;
+      }
+    } while (this._loop);
+
+    cb(err);
+  }
+
+  /**
+   * Reads the first two bytes of a frame.
+   *
+   * @return {(RangeError|undefined)} A possible error
+   * @private
+   */
+  getInfo () {
+    if (this._bufferedBytes < 2) {
+      this._loop = false;
+      return;
+    }
+
+    const buf = this.consume(2);
+
+    if ((buf[0] & 0x30) !== 0x00) {
+      this._loop = false;
+      return error(RangeError, 'RSV2 and RSV3 must be clear', true, 1002);
+    }
+
+    const compressed = (buf[0] & 0x40) === 0x40;
+
+    if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
+      this._loop = false;
+      return error(RangeError, 'RSV1 must be clear', true, 1002);
+    }
+
+    this._fin = (buf[0] & 0x80) === 0x80;
+    this._opcode = buf[0] & 0x0f;
+    this._payloadLength = buf[1] & 0x7f;
+
+    if (this._opcode === 0x00) {
+      if (compressed) {
+        this._loop = false;
+        return error(RangeError, 'RSV1 must be clear', true, 1002);
+      }
+
+      if (!this._fragmented) {
+        this._loop = false;
+        return error(RangeError, 'invalid opcode 0', true, 1002);
+      }
+
+      this._opcode = this._fragmented;
+    } else if (this._opcode === 0x01 || this._opcode === 0x02) {
+      if (this._fragmented) {
+        this._loop = false;
+        return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002);
+      }
+
+      this._compressed = compressed;
+    } else if (this._opcode > 0x07 && this._opcode < 0x0b) {
+      if (!this._fin) {
+        this._loop = false;
+        return error(RangeError, 'FIN must be set', true, 1002);
+      }
+
+      if (compressed) {
+        this._loop = false;
+        return error(RangeError, 'RSV1 must be clear', true, 1002);
+      }
+
+      if (this._payloadLength > 0x7d) {
+        this._loop = false;
+        return error(
+          RangeError,
+          `invalid payload length ${this._payloadLength}`,
+          true,
+          1002
+        );
+      }
+    } else {
+      this._loop = false;
+      return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002);
+    }
+
+    if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
+    this._masked = (buf[1] & 0x80) === 0x80;
+
+    if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
+    else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
+    else return this.haveLength();
+  }
+
+  /**
+   * Gets extended payload length (7+16).
+   *
+   * @return {(RangeError|undefined)} A possible error
+   * @private
+   */
+  getPayloadLength16 () {
+    if (this._bufferedBytes < 2) {
+      this._loop = false;
+      return;
+    }
+
+    this._payloadLength = this.consume(2).readUInt16BE(0);
+    return this.haveLength();
+  }
+
+  /**
+   * Gets extended payload length (7+64).
+   *
+   * @return {(RangeError|undefined)} A possible error
+   * @private
+   */
+  getPayloadLength64 () {
+    if (this._bufferedBytes < 8) {
+      this._loop = false;
+      return;
+    }
+
+    const buf = this.consume(8);
+    const num = buf.readUInt32BE(0);
+
+    //
+    // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned
+    // if payload length is greater than this number.
+    //
+    if (num > Math.pow(2, 53 - 32) - 1) {
+      this._loop = false;
+      return error(
+        RangeError,
+        'Unsupported WebSocket frame: payload length > 2^53 - 1',
+        false,
+        1009
+      );
+    }
+
+    this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
+    return this.haveLength();
+  }
+
+  /**
+   * Payload length has been read.
+   *
+   * @return {(RangeError|undefined)} A possible error
+   * @private
+   */
+  haveLength () {
+    if (this._payloadLength && this._opcode < 0x08) {
+      this._totalPayloadLength += this._payloadLength;
+      if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
+        this._loop = false;
+        return error(RangeError, 'Max payload size exceeded', false, 1009);
+      }
+    }
+
+    if (this._masked) this._state = GET_MASK;
+    else this._state = GET_DATA;
+  }
+
+  /**
+   * Reads mask bytes.
+   *
+   * @private
+   */
+  getMask () {
+    if (this._bufferedBytes < 4) {
+      this._loop = false;
+      return;
+    }
+
+    this._mask = this.consume(4);
+    this._state = GET_DATA;
+  }
+
+  /**
+   * Reads data bytes.
+   *
+   * @param {Function} cb Callback
+   * @return {(Error|RangeError|undefined)} A possible error
+   * @private
+   */
+  getData (cb) {
+    var data = constants.EMPTY_BUFFER;
+
+    if (this._payloadLength) {
+      if (this._bufferedBytes < this._payloadLength) {
+        this._loop = false;
+        return;
+      }
+
+      data = this.consume(this._payloadLength);
+      if (this._masked) bufferUtil.unmask(data, this._mask);
+    }
+
+    if (this._opcode > 0x07) return this.controlMessage(data);
+
+    if (this._compressed) {
+      this._state = INFLATING;
+      this.decompress(data, cb);
+      return;
+    }
+
+    if (data.length) {
+      //
+      // This message is not compressed so its lenght is the sum of the payload
+      // length of all fragments.
+      //
+      this._messageLength = this._totalPayloadLength;
+      this._fragments.push(data);
+    }
+
+    return this.dataMessage();
+  }
+
+  /**
+   * Decompresses data.
+   *
+   * @param {Buffer} data Compressed data
+   * @param {Function} cb Callback
+   * @private
+   */
+  decompress (data, cb) {
+    const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
+
+    perMessageDeflate.decompress(data, this._fin, (err, buf) => {
+      if (err) return cb(err);
+
+      if (buf.length) {
+        this._messageLength += buf.length;
+        if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
+          return cb(error(RangeError, 'Max payload size exceeded', false, 1009));
+        }
+
+        this._fragments.push(buf);
+      }
+
+      const er = this.dataMessage();
+      if (er) return cb(er);
+
+      this.startLoop(cb);
+    });
+  }
+
+  /**
+   * Handles a data message.
+   *
+   * @return {(Error|undefined)} A possible error
+   * @private
+   */
+  dataMessage () {
+    if (this._fin) {
+      const messageLength = this._messageLength;
+      const fragments = this._fragments;
+
+      this._totalPayloadLength = 0;
+      this._messageLength = 0;
+      this._fragmented = 0;
+      this._fragments = [];
+
+      if (this._opcode === 2) {
+        var data;
+
+        if (this._binaryType === 'nodebuffer') {
+          data = toBuffer(fragments, messageLength);
+        } else if (this._binaryType === 'arraybuffer') {
+          data = toArrayBuffer(toBuffer(fragments, messageLength));
+        } else {
+          data = fragments;
+        }
+
+        this.emit('message', data);
+      } else {
+        const buf = toBuffer(fragments, messageLength);
+
+        if (!validation.isValidUTF8(buf)) {
+          this._loop = false;
+          return error(Error, 'invalid UTF-8 sequence', true, 1007);
+        }
+
+        this.emit('message', buf.toString());
+      }
+    }
+
+    this._state = GET_INFO;
+  }
+
+  /**
+   * Handles a control message.
+   *
+   * @param {Buffer} data Data to handle
+   * @return {(Error|RangeError|undefined)} A possible error
+   * @private
+   */
+  controlMessage (data) {
+    if (this._opcode === 0x08) {
+      this._loop = false;
+
+      if (data.length === 0) {
+        this.emit('conclude', 1005, '');
+        this.end();
+      } else if (data.length === 1) {
+        return error(RangeError, 'invalid payload length 1', true, 1002);
+      } else {
+        const code = data.readUInt16BE(0);
+
+        if (!validation.isValidStatusCode(code)) {
+          return error(RangeError, `invalid status code ${code}`, true, 1002);
+        }
+
+        const buf = data.slice(2);
+
+        if (!validation.isValidUTF8(buf)) {
+          return error(Error, 'invalid UTF-8 sequence', true, 1007);
+        }
+
+        this.emit('conclude', code, buf.toString());
+        this.end();
+      }
+
+      return;
+    }
+
+    if (this._opcode === 0x09) this.emit('ping', data);
+    else this.emit('pong', data);
+
+    this._state = GET_INFO;
+  }
+}
+
+module.exports = Receiver;
+
+/**
+ * Builds an error object.
+ *
+ * @param {(Error|RangeError)} ErrorCtor The error constructor
+ * @param {String} message The error message
+ * @param {Boolean} prefix Specifies whether or not to add a default prefix to
+ *     `message`
+ * @param {Number} statusCode The status code
+ * @return {(Error|RangeError)} The error
+ * @private
+ */
+function error (ErrorCtor, message, prefix, statusCode) {
+  const err = new ErrorCtor(
+    prefix ? `Invalid WebSocket frame: ${message}` : message
+  );
+
+  Error.captureStackTrace(err, error);
+  err[constants.kStatusCode] = statusCode;
+  return err;
+}
+
+/**
+ * Makes a buffer from a list of fragments.
+ *
+ * @param {Buffer[]} fragments The list of fragments composing the message
+ * @param {Number} messageLength The length of the message
+ * @return {Buffer}
+ * @private
+ */
+function toBuffer (fragments, messageLength) {
+  if (fragments.length === 1) return fragments[0];
+  if (fragments.length > 1) return bufferUtil.concat(fragments, messageLength);
+  return constants.EMPTY_BUFFER;
+}
+
+/**
+ * Converts a buffer to an `ArrayBuffer`.
+ *
+ * @param {Buffer} The buffer to convert
+ * @return {ArrayBuffer} Converted buffer
+ */
+function toArrayBuffer (buf) {
+  if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
+    return buf.buffer;
+  }
+
+  return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
+}
diff --git a/input_devices/mag/node_modules/ws/lib/sender.js b/input_devices/mag/node_modules/ws/lib/sender.js
new file mode 100644
index 00000000..060e5539
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/sender.js
@@ -0,0 +1,401 @@
+'use strict';
+
+const crypto = require('crypto');
+
+const PerMessageDeflate = require('./permessage-deflate');
+const bufferUtil = require('./buffer-util');
+const validation = require('./validation');
+const constants = require('./constants');
+
+/**
+ * HyBi Sender implementation.
+ */
+class Sender {
+  /**
+   * Creates a Sender instance.
+   *
+   * @param {net.Socket} socket The connection socket
+   * @param {Object} extensions An object containing the negotiated extensions
+   */
+  constructor (socket, extensions) {
+    this._extensions = extensions || {};
+    this._socket = socket;
+
+    this._firstFragment = true;
+    this._compress = false;
+
+    this._bufferedBytes = 0;
+    this._deflating = false;
+    this._queue = [];
+  }
+
+  /**
+   * Frames a piece of data according to the HyBi WebSocket protocol.
+   *
+   * @param {Buffer} data The data to frame
+   * @param {Object} options Options object
+   * @param {Number} options.opcode The opcode
+   * @param {Boolean} options.readOnly Specifies whether `data` can be modified
+   * @param {Boolean} options.fin Specifies whether or not to set the FIN bit
+   * @param {Boolean} options.mask Specifies whether or not to mask `data`
+   * @param {Boolean} options.rsv1 Specifies whether or not to set the RSV1 bit
+   * @return {Buffer[]} The framed data as a list of `Buffer` instances
+   * @public
+   */
+  static frame (data, options) {
+    const merge = data.length < 1024 || (options.mask && options.readOnly);
+    var offset = options.mask ? 6 : 2;
+    var payloadLength = data.length;
+
+    if (data.length >= 65536) {
+      offset += 8;
+      payloadLength = 127;
+    } else if (data.length > 125) {
+      offset += 2;
+      payloadLength = 126;
+    }
+
+    const target = Buffer.allocUnsafe(merge ? data.length + offset : offset);
+
+    target[0] = options.fin ? options.opcode | 0x80 : options.opcode;
+    if (options.rsv1) target[0] |= 0x40;
+
+    if (payloadLength === 126) {
+      target.writeUInt16BE(data.length, 2);
+    } else if (payloadLength === 127) {
+      target.writeUInt32BE(0, 2);
+      target.writeUInt32BE(data.length, 6);
+    }
+
+    if (!options.mask) {
+      target[1] = payloadLength;
+      if (merge) {
+        data.copy(target, offset);
+        return [target];
+      }
+
+      return [target, data];
+    }
+
+    const mask = crypto.randomBytes(4);
+
+    target[1] = payloadLength | 0x80;
+    target[offset - 4] = mask[0];
+    target[offset - 3] = mask[1];
+    target[offset - 2] = mask[2];
+    target[offset - 1] = mask[3];
+
+    if (merge) {
+      bufferUtil.mask(data, mask, target, offset, data.length);
+      return [target];
+    }
+
+    bufferUtil.mask(data, mask, data, 0, data.length);
+    return [target, data];
+  }
+
+  /**
+   * Sends a close message to the other peer.
+   *
+   * @param {(Number|undefined)} code The status code component of the body
+   * @param {String} data The message component of the body
+   * @param {Boolean} mask Specifies whether or not to mask the message
+   * @param {Function} cb Callback
+   * @public
+   */
+  close (code, data, mask, cb) {
+    var buf;
+
+    if (code === undefined) {
+      buf = constants.EMPTY_BUFFER;
+    } else if (typeof code !== 'number' || !validation.isValidStatusCode(code)) {
+      throw new TypeError('First argument must be a valid error code number');
+    } else if (data === undefined || data === '') {
+      buf = Buffer.allocUnsafe(2);
+      buf.writeUInt16BE(code, 0);
+    } else {
+      buf = Buffer.allocUnsafe(2 + Buffer.byteLength(data));
+      buf.writeUInt16BE(code, 0);
+      buf.write(data, 2);
+    }
+
+    if (this._deflating) {
+      this.enqueue([this.doClose, buf, mask, cb]);
+    } else {
+      this.doClose(buf, mask, cb);
+    }
+  }
+
+  /**
+   * Frames and sends a close message.
+   *
+   * @param {Buffer} data The message to send
+   * @param {Boolean} mask Specifies whether or not to mask `data`
+   * @param {Function} cb Callback
+   * @private
+   */
+  doClose (data, mask, cb) {
+    this.sendFrame(Sender.frame(data, {
+      fin: true,
+      rsv1: false,
+      opcode: 0x08,
+      mask,
+      readOnly: false
+    }), cb);
+  }
+
+  /**
+   * Sends a ping message to the other peer.
+   *
+   * @param {*} data The message to send
+   * @param {Boolean} mask Specifies whether or not to mask `data`
+   * @param {Function} cb Callback
+   * @public
+   */
+  ping (data, mask, cb) {
+    var readOnly = true;
+
+    if (!Buffer.isBuffer(data)) {
+      if (data instanceof ArrayBuffer) {
+        data = Buffer.from(data);
+      } else if (ArrayBuffer.isView(data)) {
+        data = viewToBuffer(data);
+      } else {
+        data = Buffer.from(data);
+        readOnly = false;
+      }
+    }
+
+    if (this._deflating) {
+      this.enqueue([this.doPing, data, mask, readOnly, cb]);
+    } else {
+      this.doPing(data, mask, readOnly, cb);
+    }
+  }
+
+  /**
+   * Frames and sends a ping message.
+   *
+   * @param {*} data The message to send
+   * @param {Boolean} mask Specifies whether or not to mask `data`
+   * @param {Boolean} readOnly Specifies whether `data` can be modified
+   * @param {Function} cb Callback
+   * @private
+   */
+  doPing (data, mask, readOnly, cb) {
+    this.sendFrame(Sender.frame(data, {
+      fin: true,
+      rsv1: false,
+      opcode: 0x09,
+      mask,
+      readOnly
+    }), cb);
+  }
+
+  /**
+   * Sends a pong message to the other peer.
+   *
+   * @param {*} data The message to send
+   * @param {Boolean} mask Specifies whether or not to mask `data`
+   * @param {Function} cb Callback
+   * @public
+   */
+  pong (data, mask, cb) {
+    var readOnly = true;
+
+    if (!Buffer.isBuffer(data)) {
+      if (data instanceof ArrayBuffer) {
+        data = Buffer.from(data);
+      } else if (ArrayBuffer.isView(data)) {
+        data = viewToBuffer(data);
+      } else {
+        data = Buffer.from(data);
+        readOnly = false;
+      }
+    }
+
+    if (this._deflating) {
+      this.enqueue([this.doPong, data, mask, readOnly, cb]);
+    } else {
+      this.doPong(data, mask, readOnly, cb);
+    }
+  }
+
+  /**
+   * Frames and sends a pong message.
+   *
+   * @param {*} data The message to send
+   * @param {Boolean} mask Specifies whether or not to mask `data`
+   * @param {Boolean} readOnly Specifies whether `data` can be modified
+   * @param {Function} cb Callback
+   * @private
+   */
+  doPong (data, mask, readOnly, cb) {
+    this.sendFrame(Sender.frame(data, {
+      fin: true,
+      rsv1: false,
+      opcode: 0x0a,
+      mask,
+      readOnly
+    }), cb);
+  }
+
+  /**
+   * Sends a data message to the other peer.
+   *
+   * @param {*} data The message to send
+   * @param {Object} options Options object
+   * @param {Boolean} options.compress Specifies whether or not to compress `data`
+   * @param {Boolean} options.binary Specifies whether `data` is binary or text
+   * @param {Boolean} options.fin Specifies whether the fragment is the last one
+   * @param {Boolean} options.mask Specifies whether or not to mask `data`
+   * @param {Function} cb Callback
+   * @public
+   */
+  send (data, options, cb) {
+    var opcode = options.binary ? 2 : 1;
+    var rsv1 = options.compress;
+    var readOnly = true;
+
+    if (!Buffer.isBuffer(data)) {
+      if (data instanceof ArrayBuffer) {
+        data = Buffer.from(data);
+      } else if (ArrayBuffer.isView(data)) {
+        data = viewToBuffer(data);
+      } else {
+        data = Buffer.from(data);
+        readOnly = false;
+      }
+    }
+
+    const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
+
+    if (this._firstFragment) {
+      this._firstFragment = false;
+      if (rsv1 && perMessageDeflate) {
+        rsv1 = data.length >= perMessageDeflate._threshold;
+      }
+      this._compress = rsv1;
+    } else {
+      rsv1 = false;
+      opcode = 0;
+    }
+
+    if (options.fin) this._firstFragment = true;
+
+    if (perMessageDeflate) {
+      const opts = {
+        fin: options.fin,
+        rsv1,
+        opcode,
+        mask: options.mask,
+        readOnly
+      };
+
+      if (this._deflating) {
+        this.enqueue([this.dispatch, data, this._compress, opts, cb]);
+      } else {
+        this.dispatch(data, this._compress, opts, cb);
+      }
+    } else {
+      this.sendFrame(Sender.frame(data, {
+        fin: options.fin,
+        rsv1: false,
+        opcode,
+        mask: options.mask,
+        readOnly
+      }), cb);
+    }
+  }
+
+  /**
+   * Dispatches a data message.
+   *
+   * @param {Buffer} data The message to send
+   * @param {Boolean} compress Specifies whether or not to compress `data`
+   * @param {Object} options Options object
+   * @param {Number} options.opcode The opcode
+   * @param {Boolean} options.readOnly Specifies whether `data` can be modified
+   * @param {Boolean} options.fin Specifies whether or not to set the FIN bit
+   * @param {Boolean} options.mask Specifies whether or not to mask `data`
+   * @param {Boolean} options.rsv1 Specifies whether or not to set the RSV1 bit
+   * @param {Function} cb Callback
+   * @private
+   */
+  dispatch (data, compress, options, cb) {
+    if (!compress) {
+      this.sendFrame(Sender.frame(data, options), cb);
+      return;
+    }
+
+    const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
+
+    this._deflating = true;
+    perMessageDeflate.compress(data, options.fin, (_, buf) => {
+      options.readOnly = false;
+      this.sendFrame(Sender.frame(buf, options), cb);
+      this._deflating = false;
+      this.dequeue();
+    });
+  }
+
+  /**
+   * Executes queued send operations.
+   *
+   * @private
+   */
+  dequeue () {
+    while (!this._deflating && this._queue.length) {
+      const params = this._queue.shift();
+
+      this._bufferedBytes -= params[1].length;
+      params[0].apply(this, params.slice(1));
+    }
+  }
+
+  /**
+   * Enqueues a send operation.
+   *
+   * @param {Array} params Send operation parameters.
+   * @private
+   */
+  enqueue (params) {
+    this._bufferedBytes += params[1].length;
+    this._queue.push(params);
+  }
+
+  /**
+   * Sends a frame.
+   *
+   * @param {Buffer[]} list The frame to send
+   * @param {Function} cb Callback
+   * @private
+   */
+  sendFrame (list, cb) {
+    if (list.length === 2) {
+      this._socket.write(list[0]);
+      this._socket.write(list[1], cb);
+    } else {
+      this._socket.write(list[0], cb);
+    }
+  }
+}
+
+module.exports = Sender;
+
+/**
+ * Converts an `ArrayBuffer` view into a buffer.
+ *
+ * @param {(DataView|TypedArray)} view The view to convert
+ * @return {Buffer} Converted view
+ * @private
+ */
+function viewToBuffer (view) {
+  const buf = Buffer.from(view.buffer);
+
+  if (view.byteLength !== view.buffer.byteLength) {
+    return buf.slice(view.byteOffset, view.byteOffset + view.byteLength);
+  }
+
+  return buf;
+}
diff --git a/input_devices/mag/node_modules/ws/lib/validation.js b/input_devices/mag/node_modules/ws/lib/validation.js
new file mode 100644
index 00000000..06269fcf
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/validation.js
@@ -0,0 +1,29 @@
+'use strict';
+
+try {
+  const isValidUTF8 = require('utf-8-validate');
+
+  exports.isValidUTF8 = typeof isValidUTF8 === 'object'
+    ? isValidUTF8.Validation.isValidUTF8 // utf-8-validate@<3.0.0
+    : isValidUTF8;
+} catch (e) /* istanbul ignore next */ {
+  exports.isValidUTF8 = () => true;
+}
+
+/**
+ * Checks if a status code is allowed in a close frame.
+ *
+ * @param {Number} code The status code
+ * @return {Boolean} `true` if the status code is valid, else `false`
+ * @public
+ */
+exports.isValidStatusCode = (code) => {
+  return (
+    (code >= 1000 &&
+      code <= 1013 &&
+      code !== 1004 &&
+      code !== 1005 &&
+      code !== 1006) ||
+    (code >= 3000 && code <= 4999)
+  );
+};
diff --git a/input_devices/mag/node_modules/ws/lib/websocket-server.js b/input_devices/mag/node_modules/ws/lib/websocket-server.js
new file mode 100644
index 00000000..709f3885
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/websocket-server.js
@@ -0,0 +1,372 @@
+'use strict';
+
+const EventEmitter = require('events');
+const crypto = require('crypto');
+const http = require('http');
+const url = require('url');
+
+const PerMessageDeflate = require('./permessage-deflate');
+const extension = require('./extension');
+const constants = require('./constants');
+const WebSocket = require('./websocket');
+
+/**
+ * Class representing a WebSocket server.
+ *
+ * @extends EventEmitter
+ */
+class WebSocketServer extends EventEmitter {
+  /**
+   * Create a `WebSocketServer` instance.
+   *
+   * @param {Object} options Configuration options
+   * @param {String} options.host The hostname where to bind the server
+   * @param {Number} options.port The port where to bind the server
+   * @param {http.Server} options.server A pre-created HTTP/S server to use
+   * @param {Function} options.verifyClient An hook to reject connections
+   * @param {Function} options.handleProtocols An hook to handle protocols
+   * @param {String} options.path Accept only connections matching this path
+   * @param {Boolean} options.noServer Enable no server mode
+   * @param {Boolean} options.clientTracking Specifies whether or not to track clients
+   * @param {(Boolean|Object)} options.perMessageDeflate Enable/disable permessage-deflate
+   * @param {Number} options.maxPayload The maximum allowed message size
+   * @param {Function} callback A listener for the `listening` event
+   */
+  constructor (options, callback) {
+    super();
+
+    options = Object.assign({
+      maxPayload: 100 * 1024 * 1024,
+      perMessageDeflate: false,
+      handleProtocols: null,
+      clientTracking: true,
+      verifyClient: null,
+      noServer: false,
+      backlog: null, // use default (511 as implemented in net.js)
+      server: null,
+      host: null,
+      path: null,
+      port: null
+    }, options);
+
+    if (options.port == null && !options.server && !options.noServer) {
+      throw new TypeError(
+        'One of the "port", "server", or "noServer" options must be specified'
+      );
+    }
+
+    if (options.port != null) {
+      this._server = http.createServer((req, res) => {
+        const body = http.STATUS_CODES[426];
+
+        res.writeHead(426, {
+          'Content-Length': body.length,
+          'Content-Type': 'text/plain'
+        });
+        res.end(body);
+      });
+      this._server.listen(options.port, options.host, options.backlog, callback);
+    } else if (options.server) {
+      this._server = options.server;
+    }
+
+    if (this._server) {
+      this._removeListeners = addListeners(this._server, {
+        listening: this.emit.bind(this, 'listening'),
+        error: this.emit.bind(this, 'error'),
+        upgrade: (req, socket, head) => {
+          this.handleUpgrade(req, socket, head, (ws) => {
+            this.emit('connection', ws, req);
+          });
+        }
+      });
+    }
+
+    if (options.perMessageDeflate === true) options.perMessageDeflate = {};
+    if (options.clientTracking) this.clients = new Set();
+    this.options = options;
+  }
+
+  /**
+   * Returns the bound address, the address family name, and port of the server
+   * as reported by the operating system if listening on an IP socket.
+   * If the server is listening on a pipe or UNIX domain socket, the name is
+   * returned as a string.
+   *
+   * @return {(Object|String|null)} The address of the server
+   * @public
+   */
+  address () {
+    if (this.options.noServer) {
+      throw new Error('The server is operating in "noServer" mode');
+    }
+
+    if (!this._server) return null;
+    return this._server.address();
+  }
+
+  /**
+   * Close the server.
+   *
+   * @param {Function} cb Callback
+   * @public
+   */
+  close (cb) {
+    if (cb) this.once('close', cb);
+
+    //
+    // Terminate all associated clients.
+    //
+    if (this.clients) {
+      for (const client of this.clients) client.terminate();
+    }
+
+    const server = this._server;
+
+    if (server) {
+      this._removeListeners();
+      this._removeListeners = this._server = null;
+
+      //
+      // Close the http server if it was internally created.
+      //
+      if (this.options.port != null) {
+        server.close(() => this.emit('close'));
+        return;
+      }
+    }
+
+    process.nextTick(emitClose, this);
+  }
+
+  /**
+   * See if a given request should be handled by this server instance.
+   *
+   * @param {http.IncomingMessage} req Request object to inspect
+   * @return {Boolean} `true` if the request is valid, else `false`
+   * @public
+   */
+  shouldHandle (req) {
+    if (this.options.path && url.parse(req.url).pathname !== this.options.path) {
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Handle a HTTP Upgrade request.
+   *
+   * @param {http.IncomingMessage} req The request object
+   * @param {net.Socket} socket The network socket between the server and client
+   * @param {Buffer} head The first packet of the upgraded stream
+   * @param {Function} cb Callback
+   * @public
+   */
+  handleUpgrade (req, socket, head, cb) {
+    socket.on('error', socketOnError);
+
+    const version = +req.headers['sec-websocket-version'];
+    const extensions = {};
+
+    if (
+      req.method !== 'GET' || req.headers.upgrade.toLowerCase() !== 'websocket' ||
+      !req.headers['sec-websocket-key'] || (version !== 8 && version !== 13) ||
+      !this.shouldHandle(req)
+    ) {
+      return abortHandshake(socket, 400);
+    }
+
+    if (this.options.perMessageDeflate) {
+      const perMessageDeflate = new PerMessageDeflate(
+        this.options.perMessageDeflate,
+        true,
+        this.options.maxPayload
+      );
+
+      try {
+        const offers = extension.parse(
+          req.headers['sec-websocket-extensions']
+        );
+
+        if (offers[PerMessageDeflate.extensionName]) {
+          perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
+          extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
+        }
+      } catch (err) {
+        return abortHandshake(socket, 400);
+      }
+    }
+
+    //
+    // Optionally call external client verification handler.
+    //
+    if (this.options.verifyClient) {
+      const info = {
+        origin: req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],
+        secure: !!(req.connection.authorized || req.connection.encrypted),
+        req
+      };
+
+      if (this.options.verifyClient.length === 2) {
+        this.options.verifyClient(info, (verified, code, message, headers) => {
+          if (!verified) {
+            return abortHandshake(socket, code || 401, message, headers);
+          }
+
+          this.completeUpgrade(extensions, req, socket, head, cb);
+        });
+        return;
+      }
+
+      if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
+    }
+
+    this.completeUpgrade(extensions, req, socket, head, cb);
+  }
+
+  /**
+   * Upgrade the connection to WebSocket.
+   *
+   * @param {Object} extensions The accepted extensions
+   * @param {http.IncomingMessage} req The request object
+   * @param {net.Socket} socket The network socket between the server and client
+   * @param {Buffer} head The first packet of the upgraded stream
+   * @param {Function} cb Callback
+   * @private
+   */
+  completeUpgrade (extensions, req, socket, head, cb) {
+    //
+    // Destroy the socket if the client has already sent a FIN packet.
+    //
+    if (!socket.readable || !socket.writable) return socket.destroy();
+
+    const key = crypto.createHash('sha1')
+      .update(req.headers['sec-websocket-key'] + constants.GUID, 'binary')
+      .digest('base64');
+
+    const headers = [
+      'HTTP/1.1 101 Switching Protocols',
+      'Upgrade: websocket',
+      'Connection: Upgrade',
+      `Sec-WebSocket-Accept: ${key}`
+    ];
+
+    const ws = new WebSocket(null);
+    var protocol = req.headers['sec-websocket-protocol'];
+
+    if (protocol) {
+      protocol = protocol.trim().split(/ *, */);
+
+      //
+      // Optionally call external protocol selection handler.
+      //
+      if (this.options.handleProtocols) {
+        protocol = this.options.handleProtocols(protocol, req);
+      } else {
+        protocol = protocol[0];
+      }
+
+      if (protocol) {
+        headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
+        ws.protocol = protocol;
+      }
+    }
+
+    if (extensions[PerMessageDeflate.extensionName]) {
+      const params = extensions[PerMessageDeflate.extensionName].params;
+      const value = extension.format({
+        [PerMessageDeflate.extensionName]: [params]
+      });
+      headers.push(`Sec-WebSocket-Extensions: ${value}`);
+      ws._extensions = extensions;
+    }
+
+    //
+    // Allow external modification/inspection of handshake headers.
+    //
+    this.emit('headers', headers, req);
+
+    socket.write(headers.concat('\r\n').join('\r\n'));
+    socket.removeListener('error', socketOnError);
+
+    ws.setSocket(socket, head, this.options.maxPayload);
+
+    if (this.clients) {
+      this.clients.add(ws);
+      ws.on('close', () => this.clients.delete(ws));
+    }
+
+    cb(ws);
+  }
+}
+
+module.exports = WebSocketServer;
+
+/**
+ * Add event listeners on an `EventEmitter` using a map of <event, listener>
+ * pairs.
+ *
+ * @param {EventEmitter} server The event emitter
+ * @param {Object.<String, Function>} map The listeners to add
+ * @return {Function} A function that will remove the added listeners when called
+ * @private
+ */
+function addListeners (server, map) {
+  for (const event of Object.keys(map)) server.on(event, map[event]);
+
+  return function removeListeners () {
+    for (const event of Object.keys(map)) {
+      server.removeListener(event, map[event]);
+    }
+  };
+}
+
+/**
+ * Emit a `'close'` event on an `EventEmitter`.
+ *
+ * @param {EventEmitter} server The event emitter
+ * @private
+ */
+function emitClose (server) {
+  server.emit('close');
+}
+
+/**
+ * Handle premature socket errors.
+ *
+ * @private
+ */
+function socketOnError () {
+  this.destroy();
+}
+
+/**
+ * Close the connection when preconditions are not fulfilled.
+ *
+ * @param {net.Socket} socket The socket of the upgrade request
+ * @param {Number} code The HTTP response status code
+ * @param {String} [message] The HTTP response body
+ * @param {Object} [headers] Additional HTTP response headers
+ * @private
+ */
+function abortHandshake (socket, code, message, headers) {
+  if (socket.writable) {
+    message = message || http.STATUS_CODES[code];
+    headers = Object.assign({
+      'Connection': 'close',
+      'Content-type': 'text/html',
+      'Content-Length': Buffer.byteLength(message)
+    }, headers);
+
+    socket.write(
+      `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
+      Object.keys(headers).map(h => `${h}: ${headers[h]}`).join('\r\n') +
+      '\r\n\r\n' +
+      message
+    );
+  }
+
+  socket.removeListener('error', socketOnError);
+  socket.destroy();
+}
diff --git a/input_devices/mag/node_modules/ws/lib/websocket.js b/input_devices/mag/node_modules/ws/lib/websocket.js
new file mode 100644
index 00000000..92cb0f89
--- /dev/null
+++ b/input_devices/mag/node_modules/ws/lib/websocket.js
@@ -0,0 +1,827 @@
+'use strict';
+
+const EventEmitter = require('events');
+const crypto = require('crypto');
+const https = require('https');
+const http = require('http');
+const net = require('net');
+const tls = require('tls');
+const url = require('url');
+
+const PerMessageDeflate = require('./permessage-deflate');
+const EventTarget = require('./event-target');
+const extension = require('./extension');
+const constants = require('./constants');
+const Receiver = require('./receiver');
+const Sender = require('./sender');
+
+const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+const kWebSocket = constants.kWebSocket;
+const protocolVersions = [8, 13];
+const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly.
+
+/**
+ * Class representing a WebSocket.
+ *
+ * @extends EventEmitter
+ */
+class WebSocket extends EventEmitter {
+  /**
+   * Create a new `WebSocket`.
+   *
+   * @param {(String|url.Url|url.URL)} address The URL to which to connect
+   * @param {(String|String[])} protocols The subprotocols
+   * @param {Object} options Connection options
+   */
+  constructor (address, protocols, options) {
+    super();
+
+    this.readyState = WebSocket.CONNECTING;
+    this.protocol = '';
+
+    this._binaryType = constants.BINARY_TYPES[0];
+    this._closeFrameReceived = false;
+    this._closeFrameSent = false;
+    this._closeMessage = '';
+    this._closeTimer = null;
+    this._closeCode = 1006;
+    this._extensions = {};
+    this._isServer = true;
+    this._receiver = null;
+    this._sender = null;
+    this._socket = null;
+
+    if (address !== null) {
+      if (Array.isArray(protocols)) {
+        protocols = protocols.join(', ');
+      } else if (typeof protocols === 'object' && protocols !== null) {
+        options = protocols;
+        protocols = undefined;
+      }
+
+      initAsClient.call(this, address, protocols, options);
+    }
+  }
+
+  get CONNECTING () { return WebSocket.CONNECTING; }
+  get CLOSING () { return WebSocket.CLOSING; }
+  get CLOSED () { return WebSocket.CLOSED; }
+  get OPEN () { return WebSocket.OPEN; }
+
+  /**
+   * This deviates from the WHATWG interface since ws doesn't support the required
+   * default "blob" type (instead we define a custom "nodebuffer" type).
+   *
+   * @type {String}
+   */
+  get binaryType () {
+    return this._binaryType;
+  }
+
+  set binaryType (type) {
+    if (constants.BINARY_TYPES.indexOf(type) < 0) return;
+
+    this._binaryType = type;
+
+    //
+    // Allow to change `binaryType` on the fly.
+    //
+    if (this._receiver) this._receiver._binaryType = type;
+  }
+
+  /**
+   * @type {Number}
+   */
+  get bufferedAmount () {
+    if (!this._socket) return 0;
+
+    //
+    // `socket.bufferSize` is `undefined` if the socket is closed.
+    //
+    return (this._socket.bufferSize || 0) + this._sender._bufferedBytes;
+  }
+
+  /**
+   * @type {String}
+   */
+  get extensions () {
+    return Object.keys(this._extensions).join();
+  }
+
+  /**
+   * Set up the socket and the internal resources.
+   *
+   * @param {net.Socket} socket The network socket between the server and client
+   * @param {Buffer} head The first packet of the upgraded stream
+   * @param {Number} maxPayload The maximum allowed message size
+   * @private
+   */
+  setSocket (socket, head, maxPayload) {
+    const receiver = new Receiver(
+      this._binaryType,
+      this._extensions,
+      maxPayload
+    );
+
+    this._sender = new Sender(socket, this._extensions);
+    this._receiver = receiver;
+    this._socket = socket;
+
+    receiver[kWebSocket] = this;
+    socket[kWebSocket] = this;
+
+    receiver.on('conclude', receiverOnConclude);
+    receiver.on('drain', receiverOnDrain);
+    receiver.on('error', receiverOnError);
+    receiver.on('message', receiverOnMessage);
+    receiver.on('ping', receiverOnPing);
+    receiver.on('pong', receiverOnPong);
+
+    socket.setTimeout(0);
+    socket.setNoDelay();
+
+    if (head.length > 0) socket.unshift(head);
+
+    socket.on('close', socketOnClose);
+    socket.on('data', socketOnData);
+    socket.on('end', socketOnEnd);
+    socket.on('error', socketOnError);
+
+    this.readyState = WebSocket.OPEN;
+    this.emit('open');
+  }
+
+  /**
+   * Emit the `'close'` event.
+   *
+   * @private
+   */
+  emitClose () {
+    this.readyState = WebSocket.CLOSED;
+
+    if (!this._socket) {
+      this.emit('close', this._closeCode, this._closeMessage);
+      return;
+    }
+
+    if (this._extensions[PerMessageDeflate.extensionName]) {
+      this._extensions[PerMessageDeflate.extensionName].cleanup();
+    }
+
+    this._receiver.removeAllListeners();
+    this.emit('close', this._closeCode, this._closeMessage);
+  }
+
+  /**
+   * Start a closing handshake.
+   *
+   *          +----------+   +-----------+   +----------+
+   *     - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
+   *    |     +----------+   +-----------+   +----------+     |
+   *          +----------+   +-----------+         |
+   * CLOSING  |ws.close()|<--|close frame|<--+-----+       CLOSING
+   *          +----------+   +-----------+   |
+   *    |           |                        |   +---+        |
+   *                +------------------------+-->|fin| - - - -
+   *    |         +---+                      |   +---+
+   *     - - - - -|fin|<---------------------+
+   *              +---+
+   *
+   * @param {Number} code Status code explaining why the connection is closing
+   * @param {String} data A string explaining why the connection is closing
+   * @public
+   */
+  close (code, data) {
+    if (this.readyState === WebSocket.CLOSED) return;
+    if (this.readyState === WebSocket.CONNECTING) {
+      const msg = 'WebSocket was closed before the connection was established';
+      return abortHandshake(this, this._req, msg);
+    }
+
+    if (this.readyState === WebSocket.CLOSING) {
+      if (this._closeFrameSent && this._closeFrameReceived) this._socket.end();
+      return;
+    }
+
+    this.readyState = WebSocket.CLOSING;
+    this._sender.close(code, data, !this._isServer, (err) => {
+      //
+      // This error is handled by the `'error'` listener on the socket. We only
+      // want to know if the close frame has been sent here.
+      //
+      if (err) return;
+
+      this._closeFrameSent = true;
+
+      if (this._socket.writable) {
+        if (this._closeFrameReceived) this._socket.end();
+
+        //
+        // Ensure that the connection is closed even if the closing handshake
+        // fails.
+        //
+        this._closeTimer = setTimeout(
+          this._socket.destroy.bind(this._socket),
+          closeTimeout
+        );
+      }
+    });
+  }
+
+  /**
+   * Send a ping.
+   *
+   * @param {*} data The data to send
+   * @param {Boolean} mask Indicates whether or not to mask `data`
+   * @param {Function} cb Callback which is executed when the ping is sent
+   * @public
+   */
+  ping (data, mask, cb) {
+    if (typeof data === 'function') {
+      cb = data;
+      data = mask = undefined;
+    } else if (typeof mask === 'function') {
+      cb = mask;
+      mask = undefined;
+    }
+
+    if (this.readyState !== WebSocket.OPEN) {
+      const err = new Error(
+        `WebSocket is not open: readyState ${this.readyState} ` +
+          `(${readyStates[this.readyState]})`
+      );
+
+      if (cb) return cb(err);
+      throw err;
+    }
+
+    if (typeof data === 'number') data = data.toString();
+    if (mask === undefined) mask = !this._isServer;
+    this._sender.ping(data || constants.EMPTY_BUFFER, mask, cb);
+  }
+
+  /**
+   * Send a pong.
+   *
+   * @param {*} data The data to send
+   * @param {Boolean} mask Indicates whether or not to mask `data`
+   * @param {Function} cb Callback which is executed when the pong is sent
+   * @public
+   */
+  pong (data, mask, cb) {
+    if (typeof data === 'function') {
+      cb = data;
+      data = mask = undefined;
+    } else if (typeof mask === 'function') {
+      cb = mask;
+      mask = undefined;
+    }
+
+    if (this.readyState !== WebSocket.OPEN) {
+      const err = new Error(
+        `WebSocket is not open: readyState ${this.readyState} ` +
+          `(${readyStates[this.readyState]})`
+      );
+
+      if (cb) return cb(err);
+      throw err;
+    }
+
+    if (typeof data === 'number') data = data.toString();
+    if (mask === undefined) mask = !this._isServer;
+    this._sender.pong(data || constants.EMPTY_BUFFER, mask, cb);
+  }
+
+  /**
+   * Send a data message.
+   *
+   * @param {*} data The message to send
+   * @param {Object} options Options object
+   * @param {Boolean} options.compress Specifies whether or not to compress `data`
+   * @param {Boolean} options.binary Specifies whether `data` is binary or text
+   * @param {Boolean} options.fin Specifies whether the fragment is the last one
+   * @param {Boolean} options.mask Specifies whether or not to mask `data`
+   * @param {Function} cb Callback which is executed when data is written out
+   * @public
+   */
+  send (data, options, cb) {
+    if (typeof options === 'function') {
+      cb = options;
+      options = {};
+    }
+
+    if (this.readyState !== WebSocket.OPEN) {
+      const err = new Error(
+        `WebSocket is not open: readyState ${this.readyState} ` +
+          `(${readyStates[this.readyState]})`
+      );
+
+      if (cb) return cb(err);
+      throw err;
+    }
+
+    if (typeof data === 'number') data = data.toString();
+
+    const opts = Object.assign({
+      binary: typeof data !== 'string',
+      mask: !this._isServer,
+      compress: true,
+      fin: true
+    }, options);
+
+    if (!this._extensions[PerMessageDeflate.extensionName]) {
+      opts.compress = false;
+    }
+
+    this._sender.send(data || constants.EMPTY_BUFFER, opts, cb);
+  }
+
+  /**
+   * Forcibly close the connection.
+   *
+   * @public
+   */
+  terminate () {
+    if (this.readyState === WebSocket.CLOSED) return;
+    if (this.readyState === WebSocket.CONNECTING) {
+      const msg = 'WebSocket was closed before the connection was established';
+      return abortHandshake(this, this._req, msg);
+    }
+
+    if (this._socket) {
+      this.readyState = WebSocket.CLOSING;
+      this._socket.destroy();
+    }
+  }
+}
+
+readyStates.forEach((readyState, i) => {
+  WebSocket[readyStates[i]] = i;
+});
+
+//
+// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.
+// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface
+//
+['open', 'error', 'close', 'message'].forEach((method) => {
+  Object.defineProperty(WebSocket.prototype, `on${method}`, {
+    /**
+     * Return the listener of the event.
+     *
+     * @return {(Function|undefined)} The event listener or `undefined`
+     * @public
+     */
+    get () {
+      const listeners = this.listeners(method);
+      for (var i = 0; i < listeners.length; i++) {
+        if (listeners[i]._listener) return listeners[i]._listener;
+      }
+    },
+    /**
+     * Add a listener for the event.
+     *
+     * @param {Function} listener The listener to add
+     * @public
+     */
+    set (listener) {
+      const listeners = this.listeners(method);
+      for (var i = 0; i < listeners.length; i++) {
+        //
+        // Remove only the listeners added via `addEventListener`.
+        //
+        if (listeners[i]._listener) this.removeListener(method, listeners[i]);
+      }
+      this.addEventListener(method, listener);
+    }
+  });
+});
+
+WebSocket.prototype.addEventListener = EventTarget.addEventListener;
+WebSocket.prototype.removeEventListener = EventTarget.removeEventListener;
+
+module.exports = WebSocket;
+
+/**
+ * Initialize a WebSocket client.
+ *
+ * @param {(String|url.Url|url.URL)} address The URL to which to connect
+ * @param {String} protocols The subprotocols
+ * @param {Object} options Connection options
+ * @param {(Boolean|Object)} options.perMessageDeflate Enable/disable permessage-deflate
+ * @param {Number} options.handshakeTimeout Timeout in milliseconds for the handshake request
+ * @param {Number} options.protocolVersion Value of the `Sec-WebSocket-Version` header
+ * @param {String} options.origin Value of the `Origin` or `Sec-WebSocket-Origin` header
+ * @param {Number} options.maxPayload The maximum allowed message size
+ * @private
+ */
+function initAsClient (address, protocols, options) {
+  options = Object.assign({
+    protocolVersion: protocolVersions[1],
+    perMessageDeflate: true,
+    maxPayload: 100 * 1024 * 1024
+  }, options, {
+    createConnection: undefined,
+    socketPath: undefined,
+    hostname: undefined,
+    protocol: undefined,
+    timeout: undefined,
+    method: undefined,
+    auth: undefined,
+    host: undefined,
+    path: undefined,
+    port: undefined
+  });
+
+  if (protocolVersions.indexOf(options.protocolVersion) === -1) {
+    throw new RangeError(
+      `Unsupported protocol version: ${options.protocolVersion} ` +
+        `(supported versions: ${protocolVersions.join(', ')})`
+    );
+  }
+
+  this._isServer = false;
+
+  var parsedUrl;
+
+  if (typeof address === 'object' && address.href !== undefined) {
+    parsedUrl = address;
+    this.url = address.href;
+  } else {
+    parsedUrl = url.parse(address);
+    this.url = address;
+  }
+
+  const isUnixSocket = parsedUrl.protocol === 'ws+unix:';
+
+  if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) {
+    throw new Error(`Invalid URL: ${this.url}`);
+  }
+
+  const isSecure = parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:';
+  const key = crypto.randomBytes(16).toString('base64');
+  const httpObj = isSecure ? https : http;
+  const path = parsedUrl.search
+    ? `${parsedUrl.pathname || '/'}${parsedUrl.search}`
+    : parsedUrl.pathname || '/';
+  var perMessageDeflate;
+
+  options.createConnection = isSecure ? tlsConnect : netConnect;
+  options.port = parsedUrl.port || (isSecure ? 443 : 80);
+  options.host = parsedUrl.hostname.startsWith('[')
+    ? parsedUrl.hostname.slice(1, -1)
+    : parsedUrl.hostname;
+  options.headers = Object.assign({
+    'Sec-WebSocket-Version': options.protocolVersion,
+    'Sec-WebSocket-Key': key,
+    'Connection': 'Upgrade',
+    'Upgrade': 'websocket'
+  }, options.headers);
+  options.path = path;
+
+  if (options.perMessageDeflate) {
+    perMessageDeflate = new PerMessageDeflate(
+      options.perMessageDeflate !== true ? options.perMessageDeflate : {},
+      false,
+      options.maxPayload
+    );
+    options.headers['Sec-WebSocket-Extensions'] = extension.format({
+      [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
+    });
+  }
+  if (protocols) {
+    options.headers['Sec-WebSocket-Protocol'] = protocols;
+  }
+  if (options.origin) {
+    if (options.protocolVersion < 13) {
+      options.headers['Sec-WebSocket-Origin'] = options.origin;
+    } else {
+      options.headers.Origin = options.origin;
+    }
+  }
+  if (parsedUrl.auth) {
+    options.auth = parsedUrl.auth;
+  } else if (parsedUrl.username || parsedUrl.password) {
+    options.auth = `${parsedUrl.username}:${parsedUrl.password}`;
+  }
+
+  if (isUnixSocket) {
+    const parts = path.split(':');
+
+    options.socketPath = parts[0];
+    options.path = parts[1];
+  }
+
+  var req = this._req = httpObj.get(options);
+
+  if (options.handshakeTimeout) {
+    req.setTimeout(
+      options.handshakeTimeout,
+      () => abortHandshake(this, req, 'Opening handshake has timed out')
+    );
+  }
+
+  req.on('error', (err) => {
+    if (this._req.aborted) return;
+
+    req = this._req = null;
+    this.readyState = WebSocket.CLOSING;
+    this.emit('error', err);
+    this.emitClose();
+  });
+
+  req.on('response', (res) => {
+    if (this.emit('unexpected-response', req, res)) return;
+
+    abortHandshake(this, req, `Unexpected server response: ${res.statusCode}`);
+  });
+
+  req.on('upgrade', (res, socket, head) => {
+    this.emit('upgrade', res);
+
+    //
+    // The user may have closed the connection from a listener of the `upgrade`
+    // event.
+    //
+    if (this.readyState !== WebSocket.CONNECTING) return;
+
+    req = this._req = null;
+
+    const digest = crypto.createHash('sha1')
+      .update(key + constants.GUID, 'binary')
+      .digest('base64');
+
+    if (res.headers['sec-websocket-accept'] !== digest) {
+      abortHandshake(this, socket, 'Invalid Sec-WebSocket-Accept header');
+      return;
+    }
+
+    const serverProt = res.headers['sec-websocket-protocol'];
+    const protList = (protocols || '').split(/, */);
+    var protError;
+
+    if (!protocols && serverProt) {
+      protError = 'Server sent a subprotocol but none was requested';
+    } else if (protocols && !serverProt) {
+      protError = 'Server sent no subprotocol';
+    } else if (serverProt && protList.indexOf(serverProt) === -1) {
+      protError = 'Server sent an invalid subprotocol';
+    }
+
+    if (protError) {
+      abortHandshake(this, socket, protError);
+      return;
+    }
+
+    if (serverProt) this.protocol = serverProt;
+
+    if (perMessageDeflate) {
+      try {
+        const extensions = extension.parse(
+          res.headers['sec-websocket-extensions']
+        );
+
+        if (extensions[PerMessageDeflate.extensionName]) {
+          perMessageDeflate.accept(
+            extensions[PerMessageDeflate.extensionName]
+          );
+          this._extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
+        }
+      } catch (err) {
+        abortHandshake(this, socket, 'Invalid Sec-WebSocket-Extensions header');
+        return;
+      }
+    }
+
+    this.setSocket(socket, head, options.maxPayload);
+  });
+}
+
+/**
+ * Create a `net.Socket` and initiate a connection.
+ *
+ * @param {Object} options Connection options
+ * @return {net.Socket} The newly created socket used to start the connection
+ * @private
+ */
+function netConnect (options) {
+  //
+  // Override `options.path` only if `options` is a copy of the original options
+  // object. This is always true on Node.js >= 8 but not on Node.js 6 where
+  // `options.socketPath` might be `undefined` even if the `socketPath` option
+  // was originally set.
+  //
+  if (options.protocolVersion) options.path = options.socketPath;
+  return net.connect(options);
+}
+
+/**
+ * Create a `tls.TLSSocket` and initiate a connection.
+ *
+ * @param {Object} options Connection options
+ * @return {tls.TLSSocket} The newly created socket used to start the connection
+ * @private
+ */
+function tlsConnect (options) {
+  options.path = undefined;
+  options.servername = options.servername || options.host;
+  return tls.connect(options);
+}
+
+/**
+ * Abort the handshake and emit an error.
+ *
+ * @param {WebSocket} websocket The WebSocket instance
+ * @param {(http.ClientRequest|net.Socket)} stream The request to abort or the
+ *     socket to destroy
+ * @param {String} message The error message
+ * @private
+ */
+function abortHandshake (websocket, stream, message) {
+  websocket.readyState = WebSocket.CLOSING;
+
+  const err = new Error(message);
+  Error.captureStackTrace(err, abortHandshake);
+
+  if (stream.setHeader) {
+    stream.abort();
+    stream.once('abort', websocket.emitClose.bind(websocket));
+    websocket.emit('error', err);
+  } else {
+    stream.destroy(err);
+    stream.once('error', websocket.emit.bind(websocket, 'error'));
+    stream.once('close', websocket.emitClose.bind(websocket));
+  }
+}
+
+/**
+ * The listener of the `Receiver` `'conclude'` event.
+ *
+ * @param {Number} code The status code
+ * @param {String} reason The reason for closing
+ * @private
+ */
+function receiverOnConclude (code, reason) {
+  const websocket = this[kWebSocket];
+
+  websocket._socket.removeListener('data', socketOnData);
+  websocket._socket.resume();
+
+  websocket._closeFrameReceived = true;
+  websocket._closeMessage = reason;
+  websocket._closeCode = code;
+
+  if (code === 1005) websocket.close();
+  else websocket.close(code, reason);
+}
+
+/**
+ * The listener of the `Receiver` `'drain'` event.
+ *
+ * @private
+ */
+function receiverOnDrain () {
+  this[kWebSocket]._socket.resume();
+}
+
+/**
+ * The listener of the `Receiver` `'error'` event.
+ *
+ * @param {(RangeError|Error)} err The emitted error
+ * @private
+ */
+function receiverOnError (err) {
+  const websocket = this[kWebSocket];
+
+  websocket._socket.removeListener('data', socketOnData);
+
+  websocket.readyState = WebSocket.CLOSING;
+  websocket._closeCode = err[constants.kStatusCode];
+  websocket.emit('error', err);
+  websocket._socket.destroy();
+}
+
+/**
+ * The listener of the `Receiver` `'finish'` event.
+ *
+ * @private
+ */
+function receiverOnFinish () {
+  this[kWebSocket].emitClose();
+}
+
+/**
+ * The listener of the `Receiver` `'message'` event.
+ *
+ * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The message
+ * @private
+ */
+function receiverOnMessage (data) {
+  this[kWebSocket].emit('message', data);
+}
+
+/**
+ * The listener of the `Receiver` `'ping'` event.
+ *
+ * @param {Buffer} data The data included in the ping frame
+ * @private
+ */
+function receiverOnPing (data) {
+  const websocket = this[kWebSocket];
+
+  websocket.pong(data, !websocket._isServer, constants.NOOP);
+  websocket.emit('ping', data);
+}
+
+/**
+ * The listener of the `Receiver` `'pong'` event.
+ *
+ * @param {Buffer} data The data included in the pong frame
+ * @private
+ */
+function receiverOnPong (data) {
+  this[kWebSocket].emit('pong', data);
+}
+
+/**
+ * The listener of the `net.Socket` `'close'` event.
+ *
+ * @private
+ */
+function socketOnClose () {
+  const websocket = this[kWebSocket];
+
+  this.removeListener('close', socketOnClose);
+  this.removeListener('end', socketOnEnd);
+
+  websocket.readyState = WebSocket.CLOSING;
+
+  //
+  // The close frame might not have been received or the `'end'` event emitted,
+  // for example, if the socket was destroyed due to an error. Ensure that the
+  // `receiver` stream is closed after writing any remaining buffered data to
+  // it. If the readable side of the socket is in flowing mode then there is no
+  // buffered data as everything has been already written and `readable.read()`
+  // will return `null`. If instead, the socket is paused, any possible buffered
+  // data will be read as a single chunk and emitted synchronously in a single
+  // `'data'` event.
+  //
+  websocket._socket.read();
+  websocket._receiver.end();
+
+  this.removeListener('data', socketOnData);
+  this[kWebSocket] = undefined;
+
+  clearTimeout(websocket._closeTimer);
+
+  if (
+    websocket._receiver._writableState.finished ||
+    websocket._receiver._writableState.errorEmitted
+  ) {
+    websocket.emitClose();
+  } else {
+    websocket._receiver.on('error', receiverOnFinish);
+    websocket._receiver.on('finish', receiverOnFinish);
+  }
+}
+
+/**
+ * The listener of the `net.Socket` `'data'` event.
+ *
+ * @param {Buffer} chunk A chunk of data
+ * @private
+ */
+function socketOnData (chunk) {
+  if (!this[kWebSocket]._receiver.write(chunk)) {
+    this.pause();
+  }
+}
+
+/**
+ * The listener of the `net.Socket` `'end'` event.
+ *
+ * @private
+ */
+function socketOnEnd () {
+  const websocket = this[kWebSocket];
+
+  websocket.readyState = WebSocket.CLOSING;
+  websocket._receiver.end();
+  this.end();
+}
+
+/**
+ * The listener of the `net.Socket` `'error'` event.
+ *
+ * @private
+ */
+function socketOnError () {
+  const websocket = this[kWebSocket];
+
+  this.removeListener('error', socketOnError);
+  this.on('error', constants.NOOP);
+
+  if (websocket) {
+    websocket.readyState = WebSocket.CLOSING;
+    this.destroy();
+  }
+}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/.npmignore b/input_devices/mag/node_modules/ws/node_modules/bufferutil/.npmignore
deleted file mode 100644
index 0c90f673..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-npm-debug.log
-node_modules
-build
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/binding.gyp b/input_devices/mag/node_modules/ws/node_modules/bufferutil/binding.gyp
deleted file mode 100644
index 31f41a65..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/binding.gyp
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  'targets': [
-    {
-      'target_name': 'bufferutil',
-      'include_dirs': ["<!(node -e \"require('nan')\")"],
-      'cflags': [ '-O3' ],
-      'sources': [ 'src/bufferutil.cc' ]
-    }
-  ]
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Makefile b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Makefile
deleted file mode 100644
index 2184b31f..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Makefile
+++ /dev/null
@@ -1,332 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ..
-abs_srcdir := $(abspath $(srcdir))
-
-# The name of the builddir.
-builddir_name ?= .
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Release
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS) $(CPPFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS)
-AR.target ?= $(AR)
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= flock $(builddir)/linker.lock $(CXX.target)
-
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= $(CXX.host)
-LDFLAGS.host ?=
-AR.host ?= ar
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = AR($(TOOLSET)) $@
-cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
-
-quiet_cmd_alink_thin = AR($(TOOLSET)) $@
-cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
-
-# Due to circular dependencies between libraries :(, we wrap the
-# special "figure out circular dependencies" flags around the entire
-# input list during linking.
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
-
-# We support two kinds of shared objects (.so):
-# 1) shared_library, which is just bundling together many dependent libraries
-# into a link line.
-# 2) loadable_module, which is generating a module intended for dlopen().
-#
-# They differ only slightly:
-# In the former case, we want to package all dependent code into the .so.
-# In the latter case, we want to package just the API exposed by the
-# outermost module.
-# This means shared_library uses --whole-archive, while loadable_module doesn't.
-# (Note that --whole-archive is incompatible with the --start-group used in
-# normal linking.)
-
-# Other shared-object link notes:
-# - Set SONAME to the library filename so our binaries don't reference
-# the local, absolute paths used on the link command-line.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds until one fails.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    E=$$?;\
-    if [ $$E -ne 0 ]; then\
-      break;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 1,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare the "all" target first so it is the default,
-# even though we don't have the deps yet.
-.PHONY: all
-all:
-
-# make looks for ways to re-generate included makefiles, but in our case, we
-# don't have a direct way. Explicitly telling make that it has nothing to do
-# for them makes it go faster.
-%.d: ;
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,bufferutil.target.mk)))),)
-  include bufferutil.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = cd $(srcdir); /usr/share/node-gyp/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -I/home/neilg/hg/academy.classes/Web/classes/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/config.gypi -I/usr/share/node-gyp/addon.gypi -I/usr/include/nodejs/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/usr/include/nodejs" "-Dmodule_root_dir=/home/neilg/hg/academy.classes/Web/classes/input_devices/mag/node_modules/ws/node_modules/bufferutil" binding.gyp
-Makefile: $(srcdir)/../../../../../../../../../../../../usr/share/node-gyp/addon.gypi $(srcdir)/../../../../../../../../../../../../usr/include/nodejs/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp
-	$(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  include $(d_files)
-endif
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/bufferutil.node.d b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/bufferutil.node.d
deleted file mode 100644
index 0695fcc3..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/bufferutil.node.d
+++ /dev/null
@@ -1 +0,0 @@
-cmd_Release/bufferutil.node := ln -f "Release/obj.target/bufferutil.node" "Release/bufferutil.node" 2>/dev/null || (rm -rf "Release/bufferutil.node" && cp -af "Release/obj.target/bufferutil.node" "Release/bufferutil.node")
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil.node.d b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil.node.d
deleted file mode 100644
index c329bd59..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil.node.d
+++ /dev/null
@@ -1 +0,0 @@
-cmd_Release/obj.target/bufferutil.node := flock ./Release/linker.lock g++ -shared -pthread -rdynamic -m64  -Wl,-soname=bufferutil.node -o Release/obj.target/bufferutil.node -Wl,--start-group Release/obj.target/bufferutil/src/bufferutil.o -Wl,--end-group 
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d
deleted file mode 100644
index 4458d7f2..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d
+++ /dev/null
@@ -1,30 +0,0 @@
-cmd_Release/obj.target/bufferutil/src/bufferutil.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -I../node_modules/nan  -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d.raw   -c -o Release/obj.target/bufferutil/src/bufferutil.o ../src/bufferutil.cc
-Release/obj.target/bufferutil/src/bufferutil.o: ../src/bufferutil.cc \
- /usr/include/nodejs/deps/v8/include/v8.h \
- /usr/include/nodejs/deps/v8/include/v8stdint.h \
- /usr/include/nodejs/src/node.h /usr/include/nodejs/deps/uv/include/uv.h \
- /usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h \
- /usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h \
- /usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h \
- /usr/include/nodejs/src/node_object_wrap.h \
- /usr/include/nodejs/src/node.h /usr/include/nodejs/src/node_version.h \
- /usr/include/nodejs/src/node_buffer.h \
- /usr/include/nodejs/src/node_object_wrap.h ../node_modules/nan/nan.h \
- ../node_modules/nan/nan_new.h \
- ../node_modules/nan/nan_implementation_pre_12_inl.h
-../src/bufferutil.cc:
-/usr/include/nodejs/deps/v8/include/v8.h:
-/usr/include/nodejs/deps/v8/include/v8stdint.h:
-/usr/include/nodejs/src/node.h:
-/usr/include/nodejs/deps/uv/include/uv.h:
-/usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h:
-/usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h:
-/usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h:
-/usr/include/nodejs/src/node_object_wrap.h:
-/usr/include/nodejs/src/node.h:
-/usr/include/nodejs/src/node_version.h:
-/usr/include/nodejs/src/node_buffer.h:
-/usr/include/nodejs/src/node_object_wrap.h:
-../node_modules/nan/nan.h:
-../node_modules/nan/nan_new.h:
-../node_modules/nan/nan_implementation_pre_12_inl.h:
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/bufferutil.node b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/bufferutil.node
deleted file mode 100755
index a7c95fbfe5acf2bf8ac2a893699542df680bdaa8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 24762
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

diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/obj.target/bufferutil.node b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/obj.target/bufferutil.node
deleted file mode 100755
index a7c95fbfe5acf2bf8ac2a893699542df680bdaa8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 24762
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

diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/obj.target/bufferutil/src/bufferutil.o b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/Release/obj.target/bufferutil/src/bufferutil.o
deleted file mode 100644
index 358623e58913c54821c64baeea3da9f02974c3b5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 20232
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
VfCQlKM64!ZV2D8yhcZFR833(XG{*n{

diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/binding.Makefile b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/binding.Makefile
deleted file mode 100644
index 9d16809d..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/binding.Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-export builddir_name ?= build/./.
-.PHONY: all
-all:
-	$(MAKE) bufferutil
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/bufferutil.target.mk b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/bufferutil.target.mk
deleted file mode 100644
index 757fe5e8..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/bufferutil.target.mk
+++ /dev/null
@@ -1,133 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := bufferutil
-DEFS_Debug := \
-	'-D_LARGEFILE_SOURCE' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DBUILDING_NODE_EXTENSION' \
-	'-DDEBUG' \
-	'-D_DEBUG'
-
-# Flags passed to all source files.
-CFLAGS_Debug := \
-	-fPIC \
-	-Wall \
-	-Wextra \
-	-Wno-unused-parameter \
-	-pthread \
-	-m64 \
-	-O3 \
-	-g \
-	-O0
-
-# Flags passed to only C files.
-CFLAGS_C_Debug :=
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Debug := \
-	-fno-rtti \
-	-fno-exceptions
-
-INCS_Debug := \
-	-I/usr/include/nodejs/src \
-	-I/usr/include/nodejs/deps/uv/include \
-	-I/usr/include/nodejs/deps/v8/include \
-	-I$(srcdir)/node_modules/nan
-
-DEFS_Release := \
-	'-D_LARGEFILE_SOURCE' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DBUILDING_NODE_EXTENSION'
-
-# Flags passed to all source files.
-CFLAGS_Release := \
-	-fPIC \
-	-Wall \
-	-Wextra \
-	-Wno-unused-parameter \
-	-pthread \
-	-m64 \
-	-O2 \
-	-fno-strict-aliasing \
-	-fno-tree-vrp \
-	-fno-omit-frame-pointer
-
-# Flags passed to only C files.
-CFLAGS_C_Release :=
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Release := \
-	-fno-rtti \
-	-fno-exceptions
-
-INCS_Release := \
-	-I/usr/include/nodejs/src \
-	-I/usr/include/nodejs/deps/uv/include \
-	-I/usr/include/nodejs/deps/v8/include \
-	-I$(srcdir)/node_modules/nan
-
-OBJS := \
-	$(obj).target/$(TARGET)/src/bufferutil.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Debug := \
-	-pthread \
-	-rdynamic \
-	-m64
-
-LDFLAGS_Release := \
-	-pthread \
-	-rdynamic \
-	-m64
-
-LIBS :=
-
-$(obj).target/bufferutil.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(obj).target/bufferutil.node: LIBS := $(LIBS)
-$(obj).target/bufferutil.node: TOOLSET := $(TOOLSET)
-$(obj).target/bufferutil.node: $(OBJS) FORCE_DO_CMD
-	$(call do_cmd,solink_module)
-
-all_deps += $(obj).target/bufferutil.node
-# Add target alias
-.PHONY: bufferutil
-bufferutil: $(builddir)/bufferutil.node
-
-# Copy this to the executable output path.
-$(builddir)/bufferutil.node: TOOLSET := $(TOOLSET)
-$(builddir)/bufferutil.node: $(obj).target/bufferutil.node FORCE_DO_CMD
-	$(call do_cmd,copy)
-
-all_deps += $(builddir)/bufferutil.node
-# Short alias for building this executable.
-.PHONY: bufferutil.node
-bufferutil.node: $(obj).target/bufferutil.node $(builddir)/bufferutil.node
-
-# Add executable to "all" target.
-.PHONY: all
-all: $(builddir)/bufferutil.node
-
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/config.gypi b/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/config.gypi
deleted file mode 100644
index 8515666f..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/build/config.gypi
+++ /dev/null
@@ -1,116 +0,0 @@
-# Do not edit. File was generated by node-gyp's "configure" step
-{
-  "target_defaults": {
-    "cflags": [],
-    "default_configuration": "Release",
-    "defines": [],
-    "include_dirs": [],
-    "libraries": []
-  },
-  "variables": {
-    "clang": 0,
-    "gcc_version": 48,
-    "host_arch": "x64",
-    "node_byteorder": "little",
-    "node_install_npm": "false",
-    "node_prefix": "/usr",
-    "node_shared_cares": "true",
-    "node_shared_http_parser": "false",
-    "node_shared_libuv": "false",
-    "node_shared_openssl": "true",
-    "node_shared_v8": "true",
-    "node_shared_zlib": "true",
-    "node_tag": "",
-    "node_unsafe_optimizations": 0,
-    "node_use_dtrace": "false",
-    "node_use_etw": "false",
-    "node_use_openssl": "true",
-    "node_use_perfctr": "false",
-    "node_use_systemtap": "false",
-    "python": "/usr/bin/python",
-    "target_arch": "x64",
-    "v8_enable_gdbjit": 0,
-    "v8_no_strict_aliasing": 1,
-    "v8_use_snapshot": "false",
-    "nodedir": "/usr/include/nodejs",
-    "copy_dev_lib": "true",
-    "standalone_static_library": 1,
-    "cache_lock_stale": "60000",
-    "pre": "",
-    "sign_git_tag": "",
-    "always_auth": "",
-    "user_agent": "node/v0.10.25 linux x64",
-    "bin_links": "true",
-    "description": "true",
-    "fetch_retries": "2",
-    "init_version": "0.0.0",
-    "user": "",
-    "force": "",
-    "ignore": "",
-    "cache_min": "10",
-    "editor": "emacs",
-    "rollback": "true",
-    "cache_max": "null",
-    "userconfig": "/home/neilg/.npmrc",
-    "coverage": "",
-    "engine_strict": "",
-    "init_author_name": "",
-    "init_author_url": "",
-    "tmp": "/home/neilg/tmp",
-    "userignorefile": "/home/neilg/.npmignore",
-    "yes": "",
-    "depth": "null",
-    "save_dev": "",
-    "usage": "",
-    "https_proxy": "",
-    "onload_script": "",
-    "rebuild_bundle": "true",
-    "save_bundle": "",
-    "shell": "/bin/bash",
-    "prefix": "/usr/local",
-    "registry": "http://registry.npmjs.org/",
-    "__DO_NOT_MODIFY_THIS_FILE___use__etc_npmrc_instead_": "true",
-    "browser": "",
-    "cache_lock_wait": "10000",
-    "save_optional": "",
-    "searchopts": "",
-    "versions": "",
-    "cache": "/home/neilg/.npm",
-    "npaturl": "http://npat.npmjs.org/",
-    "searchsort": "name",
-    "version": "",
-    "viewer": "man",
-    "color": "true",
-    "fetch_retry_mintimeout": "10000",
-    "umask": "18",
-    "fetch_retry_maxtimeout": "60000",
-    "message": "%s",
-    "global": "",
-    "link": "",
-    "save": "",
-    "unicode": "true",
-    "long": "",
-    "production": "",
-    "unsafe_perm": "true",
-    "node_version": "v0.10.25",
-    "tag": "latest",
-    "shrinkwrap": "true",
-    "fetch_retry_factor": "10",
-    "npat": "",
-    "proprietary_attribs": "true",
-    "strict_ssl": "true",
-    "username": "",
-    "globalconfig": "/etc/npmrc",
-    "dev": "",
-    "init_module": "/home/neilg/.npm-init.js",
-    "parseable": "",
-    "globalignorefile": "/etc/npmignore",
-    "cache_lock_retries": "10",
-    "group": "1000",
-    "init_author_email": "",
-    "searchexclude": "",
-    "git": "git",
-    "optional": "true",
-    "json": ""
-  }
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/fallback.js b/input_devices/mag/node_modules/ws/node_modules/bufferutil/fallback.js
deleted file mode 100644
index ef4658b0..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/fallback.js
+++ /dev/null
@@ -1,52 +0,0 @@
-'use strict';
-
-/*!
- * bufferutil: WebSocket buffer utils
- * Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-module.exports.BufferUtil = {
-  merge: function(mergedBuffer, buffers) {
-    var offset = 0;
-
-    for (var i = 0, l = buffers.length; i < l; ++i) {
-      var buf = buffers[i];
-      buf.copy(mergedBuffer, offset);
-      offset += buf.length;
-    }
-  },
-  mask: function(source, mask, output, offset, length) {
-    var maskNum = mask.readUInt32LE(0, true);
-    var i = 0;
-
-    for (; i < length - 3; i += 4) {
-      var num = maskNum ^ source.readUInt32LE(i, true);
-      if (num < 0) num = 4294967296 + num;
-      output.writeUInt32LE(num, offset + i, true);
-    }
-
-    switch (length % 4) {
-      case 3: output[offset + i + 2] = source[i + 2] ^ mask[2];
-      case 2: output[offset + i + 1] = source[i + 1] ^ mask[1];
-      case 1: output[offset + i] = source[i] ^ mask[0];
-    }
-  },
-  unmask: function(data, mask) {
-    var maskNum = mask.readUInt32LE(0, true);
-    var length = data.length;
-    var i = 0;
-
-    for (; i < length - 3; i += 4) {
-      var num = maskNum ^ data.readUInt32LE(i, true);
-      if (num < 0) num = 4294967296 + num;
-      data.writeUInt32LE(num, i, true);
-    }
-
-    switch (length % 4) {
-      case 3: data[i + 2] = data[i + 2] ^ mask[2];
-      case 2: data[i + 1] = data[i + 1] ^ mask[1];
-      case 1: data[i] = data[i] ^ mask[0];
-    }
-  }
-};
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/index.js b/input_devices/mag/node_modules/ws/node_modules/bufferutil/index.js
deleted file mode 100644
index 00c607c6..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-'use strict';
-
-try {
-  module.exports = require('bindings')('bufferutil');
-} catch (e) {
-  module.exports = require('./fallback');
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/README.md b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/README.md
deleted file mode 100644
index 585cf512..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/README.md
+++ /dev/null
@@ -1,97 +0,0 @@
-node-bindings
-=============
-### Helper module for loading your native module's .node file
-
-This is a helper module for authors of Node.js native addon modules.
-It is basically the "swiss army knife" of `require()`ing your native module's
-`.node` file.
-
-Throughout the course of Node's native addon history, addons have ended up being
-compiled in a variety of different places, depending on which build tool and which
-version of node was used. To make matters worse, now the _gyp_ build tool can
-produce either a _Release_ or _Debug_ build, each being built into different
-locations.
-
-This module checks _all_ the possible locations that a native addon would be built
-at, and returns the first one that loads successfully.
-
-
-Installation
-------------
-
-Install with `npm`:
-
-``` bash
-$ npm install bindings
-```
-
-Or add it to the `"dependencies"` section of your _package.json_ file.
-
-
-Example
--------
-
-`require()`ing the proper bindings file for the current node version, platform
-and architecture is as simple as:
-
-``` js
-var bindings = require('bindings')('binding.node')
-
-// Use your bindings defined in your C files
-bindings.your_c_function()
-```
-
-
-Nice Error Output
------------------
-
-When the `.node` file could not be loaded, `node-bindings` throws an Error with
-a nice error message telling you exactly what was tried. You can also check the
-`err.tries` Array property.
-
-```
-Error: Could not load the bindings file. Tried:
- → /Users/nrajlich/ref/build/binding.node
- → /Users/nrajlich/ref/build/Debug/binding.node
- → /Users/nrajlich/ref/build/Release/binding.node
- → /Users/nrajlich/ref/out/Debug/binding.node
- → /Users/nrajlich/ref/Debug/binding.node
- → /Users/nrajlich/ref/out/Release/binding.node
- → /Users/nrajlich/ref/Release/binding.node
- → /Users/nrajlich/ref/build/default/binding.node
- → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node
-    at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)
-    at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)
-    at Module._compile (module.js:449:26)
-    at Object.Module._extensions..js (module.js:467:10)
-    at Module.load (module.js:356:32)
-    at Function.Module._load (module.js:312:12)
-    ...
-```
-
-
-License
--------
-
-(The MIT License)
-
-Copyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
-
-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/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/bindings.js b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/bindings.js
deleted file mode 100644
index 93dcf85a..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/bindings.js
+++ /dev/null
@@ -1,166 +0,0 @@
-
-/**
- * Module dependencies.
- */
-
-var fs = require('fs')
-  , path = require('path')
-  , join = path.join
-  , dirname = path.dirname
-  , exists = fs.existsSync || path.existsSync
-  , defaults = {
-        arrow: process.env.NODE_BINDINGS_ARROW || ' → '
-      , compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled'
-      , platform: process.platform
-      , arch: process.arch
-      , version: process.versions.node
-      , bindings: 'bindings.node'
-      , try: [
-          // node-gyp's linked version in the "build" dir
-          [ 'module_root', 'build', 'bindings' ]
-          // node-waf and gyp_addon (a.k.a node-gyp)
-        , [ 'module_root', 'build', 'Debug', 'bindings' ]
-        , [ 'module_root', 'build', 'Release', 'bindings' ]
-          // Debug files, for development (legacy behavior, remove for node v0.9)
-        , [ 'module_root', 'out', 'Debug', 'bindings' ]
-        , [ 'module_root', 'Debug', 'bindings' ]
-          // Release files, but manually compiled (legacy behavior, remove for node v0.9)
-        , [ 'module_root', 'out', 'Release', 'bindings' ]
-        , [ 'module_root', 'Release', 'bindings' ]
-          // Legacy from node-waf, node <= 0.4.x
-        , [ 'module_root', 'build', 'default', 'bindings' ]
-          // Production "Release" buildtype binary (meh...)
-        , [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ]
-        ]
-    }
-
-/**
- * The main `bindings()` function loads the compiled bindings for a given module.
- * It uses V8's Error API to determine the parent filename that this function is
- * being invoked from, which is then used to find the root directory.
- */
-
-function bindings (opts) {
-
-  // Argument surgery
-  if (typeof opts == 'string') {
-    opts = { bindings: opts }
-  } else if (!opts) {
-    opts = {}
-  }
-  opts.__proto__ = defaults
-
-  // Get the module root
-  if (!opts.module_root) {
-    opts.module_root = exports.getRoot(exports.getFileName())
-  }
-
-  // Ensure the given bindings name ends with .node
-  if (path.extname(opts.bindings) != '.node') {
-    opts.bindings += '.node'
-  }
-
-  var tries = []
-    , i = 0
-    , l = opts.try.length
-    , n
-    , b
-    , err
-
-  for (; i<l; i++) {
-    n = join.apply(null, opts.try[i].map(function (p) {
-      return opts[p] || p
-    }))
-    tries.push(n)
-    try {
-      b = opts.path ? require.resolve(n) : require(n)
-      if (!opts.path) {
-        b.path = n
-      }
-      return b
-    } catch (e) {
-      if (!/not find/i.test(e.message)) {
-        throw e
-      }
-    }
-  }
-
-  err = new Error('Could not locate the bindings file. Tried:\n'
-    + tries.map(function (a) { return opts.arrow + a }).join('\n'))
-  err.tries = tries
-  throw err
-}
-module.exports = exports = bindings
-
-
-/**
- * Gets the filename of the JavaScript file that invokes this function.
- * Used to help find the root directory of a module.
- * Optionally accepts an filename argument to skip when searching for the invoking filename
- */
-
-exports.getFileName = function getFileName (calling_file) {
-  var origPST = Error.prepareStackTrace
-    , origSTL = Error.stackTraceLimit
-    , dummy = {}
-    , fileName
-
-  Error.stackTraceLimit = 10
-
-  Error.prepareStackTrace = function (e, st) {
-    for (var i=0, l=st.length; i<l; i++) {
-      fileName = st[i].getFileName()
-      if (fileName !== __filename) {
-        if (calling_file) {
-            if (fileName !== calling_file) {
-              return
-            }
-        } else {
-          return
-        }
-      }
-    }
-  }
-
-  // run the 'prepareStackTrace' function above
-  Error.captureStackTrace(dummy)
-  dummy.stack
-
-  // cleanup
-  Error.prepareStackTrace = origPST
-  Error.stackTraceLimit = origSTL
-
-  return fileName
-}
-
-/**
- * Gets the root directory of a module, given an arbitrary filename
- * somewhere in the module tree. The "root directory" is the directory
- * containing the `package.json` file.
- *
- *   In:  /home/nate/node-native-module/lib/index.js
- *   Out: /home/nate/node-native-module
- */
-
-exports.getRoot = function getRoot (file) {
-  var dir = dirname(file)
-    , prev
-  while (true) {
-    if (dir === '.') {
-      // Avoids an infinite loop in rare cases, like the REPL
-      dir = process.cwd()
-    }
-    if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
-      // Found the 'package.json' file or 'node_modules' dir; we're done
-      return dir
-    }
-    if (prev === dir) {
-      // Got to the top
-      throw new Error('Could not find module root given file: "' + file
-                    + '". Do you have a `package.json` file? ')
-    }
-    // Try the parent dir next
-    prev = dir
-    dir = join(dir, '..')
-  }
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/package.json b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/package.json
deleted file mode 100644
index 6ecf3a43..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/bindings/package.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "name": "bindings",
-  "description": "Helper module for loading your native module's .node file",
-  "keywords": [
-    "native",
-    "addon",
-    "bindings",
-    "gyp",
-    "waf",
-    "c",
-    "c++"
-  ],
-  "version": "1.2.1",
-  "author": {
-    "name": "Nathan Rajlich",
-    "email": "nathan@tootallnate.net",
-    "url": "http://tootallnate.net"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/TooTallNate/node-bindings.git"
-  },
-  "main": "./bindings.js",
-  "bugs": {
-    "url": "https://github.com/TooTallNate/node-bindings/issues"
-  },
-  "homepage": "https://github.com/TooTallNate/node-bindings",
-  "license": "MIT",
-  "readme": "node-bindings\n=============\n### Helper module for loading your native module's .node file\n\nThis is a helper module for authors of Node.js native addon modules.\nIt is basically the \"swiss army knife\" of `require()`ing your native module's\n`.node` file.\n\nThroughout the course of Node's native addon history, addons have ended up being\ncompiled in a variety of different places, depending on which build tool and which\nversion of node was used. To make matters worse, now the _gyp_ build tool can\nproduce either a _Release_ or _Debug_ build, each being built into different\nlocations.\n\nThis module checks _all_ the possible locations that a native addon would be built\nat, and returns the first one that loads successfully.\n\n\nInstallation\n------------\n\nInstall with `npm`:\n\n``` bash\n$ npm install bindings\n```\n\nOr add it to the `\"dependencies\"` section of your _package.json_ file.\n\n\nExample\n-------\n\n`require()`ing the proper bindings file for the current node version, platform\nand architecture is as simple as:\n\n``` js\nvar bindings = require('bindings')('binding.node')\n\n// Use your bindings defined in your C files\nbindings.your_c_function()\n```\n\n\nNice Error Output\n-----------------\n\nWhen the `.node` file could not be loaded, `node-bindings` throws an Error with\na nice error message telling you exactly what was tried. You can also check the\n`err.tries` Array property.\n\n```\nError: Could not load the bindings file. Tried:\n → /Users/nrajlich/ref/build/binding.node\n → /Users/nrajlich/ref/build/Debug/binding.node\n → /Users/nrajlich/ref/build/Release/binding.node\n → /Users/nrajlich/ref/out/Debug/binding.node\n → /Users/nrajlich/ref/Debug/binding.node\n → /Users/nrajlich/ref/out/Release/binding.node\n → /Users/nrajlich/ref/Release/binding.node\n → /Users/nrajlich/ref/build/default/binding.node\n → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node\n    at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)\n    at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)\n    at Module._compile (module.js:449:26)\n    at Object.Module._extensions..js (module.js:467:10)\n    at Module.load (module.js:356:32)\n    at Function.Module._load (module.js:312:12)\n    ...\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
-  "readmeFilename": "README.md",
-  "_id": "bindings@1.2.1",
-  "_from": "bindings@1.2.x"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/.dntrc b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/.dntrc
deleted file mode 100644
index 47971da6..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/.dntrc
+++ /dev/null
@@ -1,30 +0,0 @@
-## DNT config file
-## see https://github.com/rvagg/dnt
-
-NODE_VERSIONS="\
-  master   \
-  v0.11.13 \
-  v0.10.30 \
-  v0.10.29 \
-  v0.10.28 \
-  v0.10.26 \
-  v0.10.25 \
-  v0.10.24 \
-  v0.10.23 \
-  v0.10.22 \
-  v0.10.21 \
-  v0.10.20 \
-  v0.10.19 \
-  v0.8.28  \
-  v0.8.27  \
-  v0.8.26  \
-  v0.8.24  \
-"
-OUTPUT_PREFIX="nan-"
-TEST_CMD="                                                                        \
-  cd /dnt/ &&                                                                     \
-  npm install &&                                                                  \
-  node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \
-  node_modules/.bin/tap --gc test/js/*-test.js                                    \
-"
-
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/CHANGELOG.md b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/CHANGELOG.md
deleted file mode 100644
index de0ac02a..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/CHANGELOG.md
+++ /dev/null
@@ -1,265 +0,0 @@
-# NAN ChangeLog
-
-**Version 1.6.2: current Node unstable: 0.11.16, Node stable: 0.10.36, io.js: 1.1.0**
-
-### 1.6.2 Feb 6 2015
-
-  - Bugfix: NanEncode: fix argument type for node::Encode on io.js 2be8639
-
-### 1.6.1 Jan 23 2015
-
-  - Build: version bump
-
-### 1.5.3 Jan 23 2015
-
-  - Build: repackage
-
-### 1.6.0 Jan 23 2015
-
- - Deprecated `NanNewContextHandle` in favor of `NanNew<Context>` 49259af
- - Support utility functions moved in newer v8 versions (Node 0.11.15, io.js 1.0) a0aa179
- - Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite` 75e6fb9
-
-### 1.5.2 Jan 23 2015
-
-  - Bugfix: Fix non-inline definition build error with clang++ 21d96a1, 60fadd4
-  - Bugfix: Readded missing String constructors 18d828f
-  - Bugfix: Add overload handling NanNew<FunctionTemplate>(..) 5ef813b
-  - Bugfix: Fix uv_work_cb versioning 997e4ae
-  - Bugfix: Add function factory and test 4eca89c
-  - Bugfix: Add object template factory and test cdcb951
-  - Correctness: Lifted an io.js related typedef c9490be
-  - Correctness: Make explicit downcasts of String lengths 00074e6
-  - Windows: Limit the scope of disabled warning C4530 83d7deb
-
-### 1.5.1 Jan 15 2015
-
-  - Build: version bump
-
-### 1.4.3 Jan 15 2015
-
-  - Build: version bump
-
-### 1.4.2 Jan 15 2015
-
-  - Feature: Support io.js 0dbc5e8
-
-### 1.5.0 Jan 14 2015
-
- - Feature: Support io.js b003843
- - Correctness: Improved NanNew internals 9cd4f6a
- - Feature: Implement progress to NanAsyncWorker 8d6a160
-
-### 1.4.1 Nov 8 2014
-
- - Bugfix: Handle DEBUG definition correctly
- - Bugfix: Accept int as Boolean
-
-### 1.4.0 Nov 1 2014
-
- - Feature: Added NAN_GC_CALLBACK 6a5c245
- - Performance: Removed unnecessary local handle creation 18a7243, 41fe2f8
- - Correctness: Added constness to references in NanHasInstance 02c61cd
- - Warnings: Fixed spurious warnings from -Wundef and -Wshadow, 541b122, 99d8cb6
- - Windoze: Shut Visual Studio up when compiling 8d558c1
- - License: Switch to plain MIT from custom hacked MIT license 11de983
- - Build: Added test target to Makefile e232e46
- - Performance: Removed superfluous scope in NanAsyncWorker f4b7821
- - Sugar/Feature: Added NanReturnThis() and NanReturnHolder() shorthands 237a5ff, d697208
- - Feature: Added suitable overload of NanNew for v8::Integer::NewFromUnsigned b27b450
-
-### 1.3.0 Aug 2 2014
-
- - Added NanNew<v8::String, std::string>(std::string)
- - Added NanNew<v8::String, std::string&>(std::string&)
- - Added NanAsciiString helper class
- - Added NanUtf8String helper class
- - Added NanUcs2String helper class
- - Deprecated NanRawString()
- - Deprecated NanCString()
- - Added NanGetIsolateData(v8::Isolate *isolate)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value>* argv)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::String> symbol, int argc, v8::Handle<v8::Value>* argv)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, const char* method, int argc, v8::Handle<v8::Value>* argv)
- - Added NanSetTemplate(v8::Handle<v8::Template> templ, v8::Handle<v8::String> name , v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- - Added NanSetPrototypeTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, const char *name, v8::Handle<v8::Data> value)
- - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
-
-### 1.2.0 Jun 5 2014
-
- - Add NanSetPrototypeTemplate
- - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class,
-     introduced _NanWeakCallbackDispatcher
- - Removed -Wno-unused-local-typedefs from test builds
- - Made test builds Windows compatible ('Sleep()')
-
-### 1.1.2 May 28 2014
-
- - Release to fix more stuff-ups in 1.1.1
-
-### 1.1.1 May 28 2014
-
- - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0
-
-### 1.1.0 May 25 2014
-
- - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead
- - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]),
-     (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*,
-     v8::String::ExternalAsciiStringResource*
- - Deprecate NanSymbol()
- - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker
-
-### 1.0.0 May 4 2014
-
- - Heavy API changes for V8 3.25 / Node 0.11.13
- - Use cpplint.py
- - Removed NanInitPersistent
- - Removed NanPersistentToLocal
- - Removed NanFromV8String
- - Removed NanMakeWeak
- - Removed NanNewLocal
- - Removed NAN_WEAK_CALLBACK_OBJECT
- - Removed NAN_WEAK_CALLBACK_DATA
- - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions
- - Introduce NanUndefined, NanNull, NanTrue and NanFalse
- - Introduce NanEscapableScope and NanEscapeScope
- - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node)
- - Introduce NanMakeCallback for node::MakeCallback
- - Introduce NanSetTemplate
- - Introduce NanGetCurrentContext
- - Introduce NanCompileScript and NanRunScript
- - Introduce NanAdjustExternalMemory
- - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback
- - Introduce NanGetHeapStatistics
- - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent()
-
-### 0.8.0 Jan 9 2014
-
- - NanDispose -> NanDisposePersistent, deprecate NanDispose
- - Extract _NAN_*_RETURN_TYPE, pull up NAN_*()
-
-### 0.7.1 Jan 9 2014
-
- - Fixes to work against debug builds of Node
- - Safer NanPersistentToLocal (avoid reinterpret_cast)
- - Speed up common NanRawString case by only extracting flattened string when necessary
-
-### 0.7.0 Dec 17 2013
-
- - New no-arg form of NanCallback() constructor.
- - NanCallback#Call takes Handle rather than Local
- - Removed deprecated NanCallback#Run method, use NanCallback#Call instead
- - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS
- - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call()
- - Introduce NanRawString() for char* (or appropriate void*) from v8::String
-     (replacement for NanFromV8String)
- - Introduce NanCString() for null-terminated char* from v8::String
-
-### 0.6.0 Nov 21 2013
-
- - Introduce NanNewLocal<T>(v8::Handle<T> value) for use in place of
-     v8::Local<T>::New(...) since v8 started requiring isolate in Node 0.11.9
-
-### 0.5.2 Nov 16 2013
-
- - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public
-
-### 0.5.1 Nov 12 2013
-
- - Use node::MakeCallback() instead of direct v8::Function::Call()
-
-### 0.5.0 Nov 11 2013
-
- - Added @TooTallNate as collaborator
- - New, much simpler, "include_dirs" for binding.gyp
- - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros
-
-### 0.4.4 Nov 2 2013
-
- - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+
-
-### 0.4.3 Nov 2 2013
-
- - Include node_object_wrap.h, removed from node.h for Node 0.11.8.
-
-### 0.4.2 Nov 2 2013
-
- - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for
-     Node 0.11.8 release.
-
-### 0.4.1 Sep 16 2013
-
- - Added explicit `#include <uv.h>` as it was removed from node.h for v0.11.8
-
-### 0.4.0 Sep 2 2013
-
- - Added NAN_INLINE and NAN_DEPRECATED and made use of them
- - Added NanError, NanTypeError and NanRangeError
- - Cleaned up code
-
-### 0.3.2 Aug 30 2013
-
- - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent
-     in NanAsyncWorker
-
-### 0.3.1 Aug 20 2013
-
- - fix "not all control paths return a value" compile warning on some platforms
-
-### 0.3.0 Aug 19 2013
-
- - Made NAN work with NPM
- - Lots of fixes to NanFromV8String, pulling in features from new Node core
- - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API
- - Added optional error number argument for NanThrowError()
- - Added NanInitPersistent()
- - Added NanReturnNull() and NanReturnEmptyString()
- - Added NanLocker and NanUnlocker
- - Added missing scopes
- - Made sure to clear disposed Persistent handles
- - Changed NanAsyncWorker to allocate error messages on the heap
- - Changed NanThrowError(Local<Value>) to NanThrowError(Handle<Value>)
- - Fixed leak in NanAsyncWorker when errmsg is used
-
-### 0.2.2 Aug 5 2013
-
- - Fixed usage of undefined variable with node::BASE64 in NanFromV8String()
-
-### 0.2.1 Aug 5 2013
-
- - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for
-     NanFromV8String()
-
-### 0.2.0 Aug 5 2013
-
- - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR,
-     NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY
- - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS,
-     _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS,
-     _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS,
-     _NAN_PROPERTY_QUERY_ARGS
- - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer
- - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT,
-     NAN_WEAK_CALLBACK_DATA, NanMakeWeak
- - Renamed THROW_ERROR to _NAN_THROW_ERROR
- - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*)
- - Added NanBufferUse(char*, uint32_t)
- - Added NanNewContextHandle(v8::ExtensionConfiguration*,
-       v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
- - Fixed broken NanCallback#GetFunction()
- - Added optional encoding and size arguments to NanFromV8String()
- - Added NanGetPointerSafe() and NanSetPointerSafe()
- - Added initial test suite (to be expanded)
- - Allow NanUInt32OptionValue to convert any Number object
-
-### 0.1.0 Jul 21 2013
-
- - Added `NAN_GETTER`, `NAN_SETTER`
- - Added `NanThrowError` with single Local<Value> argument
- - Added `NanNewBufferHandle` with single uint32_t argument
- - Added `NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)`
- - Added `Local<Function> NanCallback#GetFunction()`
- - Added `NanCallback#Call(int, Local<Value>[])`
- - Deprecated `NanCallback#Run(int, Local<Value>[])` in favour of Call
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/LICENSE.md b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/LICENSE.md
deleted file mode 100644
index 95c2eb5f..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/LICENSE.md
+++ /dev/null
@@ -1,13 +0,0 @@
-The MIT License (MIT)
-=====================
-
-Copyright (c) 2015 NAN contributors
------------------------------------
-
-*NAN contributors listed at <https://github.com/rvagg/nan#contributors>*
-
-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/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/appveyor.yml b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/appveyor.yml
deleted file mode 100644
index 17771078..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/appveyor.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-# http://www.appveyor.com/docs/appveyor-yml
-
-# Test against these versions of Io.js and Node.js.
-environment:
-  matrix:
-  # node.js
-    - nodejs_version: "0.8"
-    - nodejs_version: "0.10"
-    - nodejs_version: "0.11"
-  # io.js
-    - nodejs_version: "1"
-
-# Install scripts. (runs after repo cloning)
-install:
-  # Get the latest stable version of Node 0.STABLE.latest
-  - ps: if($env:nodejs_version -eq "0.8") {Install-Product node $env:nodejs_version}
-  - ps: if($env:nodejs_version -ne "0.8") {Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)}
-  - IF NOT %nodejs_version% == 1 npm -g install npm
-  - IF NOT %nodejs_version% == 1 set PATH=%APPDATA%\npm;%PATH%
-  # Typical npm stuff.
-  - npm install
-  - IF %nodejs_version% == 0.8 node node_modules\node-gyp\bin\node-gyp.js rebuild --directory test
-  - IF NOT %nodejs_version% == 0.8 npm run rebuild-tests
-
-# Post-install test scripts.
-test_script:
-  # Output useful info for debugging.
-  - node --version
-  - npm --version
-  # run tests
-  - npm test
-
-# Don't actually build.
-build: off
-
-# Set build version format here instead of in the admin panel.
-version: "{build}"
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/include_dirs.js b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/include_dirs.js
deleted file mode 100644
index 4f1dfb41..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/include_dirs.js
+++ /dev/null
@@ -1 +0,0 @@
-console.log(require('path').relative('.', __dirname));
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan.h b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan.h
deleted file mode 100644
index e95a3b3e..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan.h
+++ /dev/null
@@ -1,2174 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors:
- *   - Rod Vagg <https://github.com/rvagg>
- *   - Benjamin Byholm <https://github.com/kkoopa>
- *   - Trevor Norris <https://github.com/trevnorris>
- *   - Nathan Rajlich <https://github.com/TooTallNate>
- *   - Brett Lawson <https://github.com/brett19>
- *   - Ben Noordhuis <https://github.com/bnoordhuis>
- *   - David Siegel <https://github.com/agnat>
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- *
- * Version 1.6.2: current Node unstable: 0.11.16, Node stable: 0.10.36, io.js: 1.1.0
- *
- * See https://github.com/rvagg/nan for the latest update to this file
- **********************************************************************************/
-
-#ifndef NAN_H_
-#define NAN_H_
-
-#include <uv.h>
-#include <node.h>
-#include <node_buffer.h>
-#include <node_version.h>
-#include <node_object_wrap.h>
-#include <cstring>
-#include <climits>
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-#if defined(__GNUC__) && !(defined(DEBUG) && DEBUG)
-# define NAN_INLINE inline __attribute__((always_inline))
-#elif defined(_MSC_VER) && !(defined(DEBUG) && DEBUG)
-# define NAN_INLINE __forceinline
-#else
-# define NAN_INLINE inline
-#endif
-
-#if defined(__GNUC__) && \
-    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
-# define NAN_DEPRECATED __attribute__((deprecated))
-#elif defined(_MSC_VER) && \
-    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
-# define NAN_DEPRECATED __declspec(deprecated)
-#else
-# define NAN_DEPRECATED
-#endif
-
-#if (NODE_MODULE_VERSION < 12)
-typedef v8::InvocationCallback NanFunctionCallback;
-typedef v8::Script             NanUnboundScript;
-typedef v8::Script             NanBoundScript;
-#else
-typedef v8::FunctionCallback   NanFunctionCallback;
-typedef v8::UnboundScript      NanUnboundScript;
-typedef v8::Script             NanBoundScript;
-#endif
-
-#if (NODE_MODULE_VERSION < 42)
-typedef v8::String::ExternalAsciiStringResource
-    NanExternalOneByteStringResource;
-#else  // io.js v1.0.0
-typedef v8::String::ExternalOneByteStringResource
-    NanExternalOneByteStringResource;
-#endif
-
-#include "nan_new.h"  // NOLINT(build/include)
-
-// uv helpers
-#ifdef UV_VERSION_MAJOR
-#ifndef UV_VERSION_PATCH
-#define UV_VERSION_PATCH 0
-#endif
-#define NAUV_UVVERSION  ((UV_VERSION_MAJOR << 16) | \
-                     (UV_VERSION_MINOR <<  8) | \
-                     (UV_VERSION_PATCH))
-#else
-#define NAUV_UVVERSION 0x000b00
-#endif
-
-
-#if NAUV_UVVERSION < 0x000b17
-#define NAUV_WORK_CB(func) \
-    void func(uv_async_t *async, int)
-#else
-#define NAUV_WORK_CB(func) \
-    void func(uv_async_t *async)
-#endif
-
-// some generic helpers
-
-template<typename T> NAN_INLINE bool NanSetPointerSafe(
-    T *var
-  , T val
-) {
-  if (var) {
-    *var = val;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-template<typename T> NAN_INLINE T NanGetPointerSafe(
-    T *var
-  , T fallback = reinterpret_cast<T>(0)
-) {
-  if (var) {
-    return *var;
-  } else {
-    return fallback;
-  }
-}
-
-NAN_INLINE bool NanBooleanOptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt, bool def
-) {
-  if (def) {
-    return optionsObj.IsEmpty()
-      || !optionsObj->Has(opt)
-      || optionsObj->Get(opt)->BooleanValue();
-  } else {
-    return !optionsObj.IsEmpty()
-      && optionsObj->Has(opt)
-      && optionsObj->Get(opt)->BooleanValue();
-  }
-}
-
-NAN_INLINE bool NanBooleanOptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt
-) {
-  return NanBooleanOptionValue(optionsObj, opt, false);
-}
-
-NAN_INLINE uint32_t NanUInt32OptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt
-  , uint32_t def
-) {
-  return !optionsObj.IsEmpty()
-    && optionsObj->Has(opt)
-    && optionsObj->Get(opt)->IsNumber()
-      ? optionsObj->Get(opt)->Uint32Value()
-      : def;
-}
-
-template<typename T>
-v8::Local<T> NanNew(v8::Handle<T>);
-
-template<typename T>
-NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
-  return NanNew(val);
-}
-
-template<typename T>
-NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
-  return val;
-}
-
-/* io.js 1.0  */
-#if NODE_MODULE_VERSION >= 42 || NODE_VERSION_AT_LEAST(0, 11, 15)
-  NAN_INLINE
-  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
-    v8::Isolate::GetCurrent()->SetCounterFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
-    v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
-    v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb);
-  }
-
-  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
-    return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
-  }
-
-  NAN_INLINE void NanLowMemoryNotification() {
-    v8::Isolate::GetCurrent()->LowMemoryNotification();
-  }
-
-  NAN_INLINE void NanContextDisposedNotification() {
-    v8::Isolate::GetCurrent()->ContextDisposedNotification();
-  }
-#else
-  NAN_INLINE
-  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
-    v8::V8::SetCounterFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
-    v8::V8::SetCreateHistogramFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
-    v8::V8::SetAddHistogramSampleFunction(cb);
-  }
-
-  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
-    return v8::V8::IdleNotification(idle_time_in_ms);
-  }
-
-  NAN_INLINE void NanLowMemoryNotification() {
-    v8::V8::LowMemoryNotification();
-  }
-
-  NAN_INLINE void NanContextDisposedNotification() {
-    v8::V8::ContextDisposedNotification();
-  }
-#endif
-
-#if (NODE_MODULE_VERSION > 0x000B)
-// Node 0.11+ (0.11.12 and below won't compile with these)
-
-# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo<v8::Value>&
-# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args
-# define _NAN_METHOD_RETURN_TYPE void
-
-# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args
-# define _NAN_GETTER_RETURN_TYPE void
-
-# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo<void>&
-# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args
-# define _NAN_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_GETTER_ARGS_TYPE                                        \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_GETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_SETTER_ARGS_TYPE                                        \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE                                    \
-    const v8::PropertyCallbackInfo<v8::Array>&
-# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args
-# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void
-
-# define _NAN_PROPERTY_DELETER_ARGS_TYPE                                       \
-    const v8::PropertyCallbackInfo<v8::Boolean>&
-# define _NAN_PROPERTY_DELETER_ARGS                                            \
-    _NAN_PROPERTY_DELETER_ARGS_TYPE args
-# define _NAN_PROPERTY_DELETER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_QUERY_ARGS_TYPE                                         \
-    const v8::PropertyCallbackInfo<v8::Integer>&
-# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args
-# define _NAN_PROPERTY_QUERY_RETURN_TYPE void
-
-# define _NAN_INDEX_GETTER_ARGS_TYPE                                           \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args
-# define _NAN_INDEX_GETTER_RETURN_TYPE void
-
-# define _NAN_INDEX_SETTER_ARGS_TYPE                                           \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args
-# define _NAN_INDEX_SETTER_RETURN_TYPE void
-
-# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE                                       \
-    const v8::PropertyCallbackInfo<v8::Array>&
-# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args
-# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void
-
-# define _NAN_INDEX_DELETER_ARGS_TYPE                                          \
-    const v8::PropertyCallbackInfo<v8::Boolean>&
-# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args
-# define _NAN_INDEX_DELETER_RETURN_TYPE void
-
-# define _NAN_INDEX_QUERY_ARGS_TYPE                                            \
-    const v8::PropertyCallbackInfo<v8::Integer>&
-# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
-# define _NAN_INDEX_QUERY_RETURN_TYPE void
-
-# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent())
-# define NanEscapableScope()                                                   \
-  v8::EscapableHandleScope scope(v8::Isolate::GetCurrent())
-
-# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
-# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent())
-# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent())
-# define NanReturnValue(value) return args.GetReturnValue().Set(value)
-# define NanReturnUndefined() return
-# define NanReturnHolder() NanReturnValue(args.Holder())
-# define NanReturnThis() NanReturnValue(args.This())
-# define NanReturnNull() return args.GetReturnValue().SetNull()
-# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString()
-
-# define NanObjectWrapHandle(obj) obj->handle()
-
-  NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Primitive> NanNull() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanTrue() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanFalse() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE int NanAdjustExternalMemory(int bc) {
-    return static_cast<int>(
-        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc));
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , const char *name
-    , v8::Handle<v8::Data> value) {
-    templ->Set(v8::Isolate::GetCurrent(), name, value);
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , v8::Handle<v8::String> name
-    , v8::Handle<v8::Data> value
-    , v8::PropertyAttribute attributes) {
-    templ->Set(name, value, attributes);
-  }
-
-  NAN_INLINE v8::Local<v8::Context> NanGetCurrentContext() {
-    return v8::Isolate::GetCurrent()->GetCurrentContext();
-  }
-
-  NAN_INLINE void* NanGetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index) {
-    return object->GetAlignedPointerFromInternalField(index);
-  }
-
-  NAN_INLINE void NanSetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index
-    , void* value) {
-    object->SetAlignedPointerInInternalField(index, value);
-  }
-
-# define NAN_GC_CALLBACK(name)                                                 \
-    void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags)
-
-  NAN_INLINE void NanAddGCEpilogueCallback(
-      v8::Isolate::GCEpilogueCallback callback
-    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter);
-  }
-
-  NAN_INLINE void NanRemoveGCEpilogueCallback(
-      v8::Isolate::GCEpilogueCallback callback) {
-    v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback);
-  }
-
-  NAN_INLINE void NanAddGCPrologueCallback(
-      v8::Isolate::GCPrologueCallback callback
-    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter);
-  }
-
-  NAN_INLINE void NanRemoveGCPrologueCallback(
-      v8::Isolate::GCPrologueCallback callback) {
-    v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback);
-  }
-
-  NAN_INLINE void NanGetHeapStatistics(
-      v8::HeapStatistics *heap_statistics) {
-    v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::String> NanSymbol(
-      const char* data, int length = -1) {
-    return NanNew<v8::String>(data, length);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , v8::Handle<T> obj) {
-      handle.Reset(v8::Isolate::GetCurrent(), obj);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , const v8::Persistent<T>& obj) {
-      handle.Reset(v8::Isolate::GetCurrent(), obj);
-  }
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData;
-
-  template<typename T, typename P>
-  struct _NanWeakCallbackInfo {
-    typedef void (*Callback)(const _NanWeakCallbackData<T, P>& data);
-    NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
-      : parameter(param), callback(cb) {
-       NanAssignPersistent(persistent, handle);
-    }
-
-    NAN_INLINE ~_NanWeakCallbackInfo() {
-      persistent.Reset();
-    }
-
-    P* const parameter;
-    Callback const callback;
-    v8::Persistent<T> persistent;
-  };
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData {
-   public:
-    NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
-      : info_(info) { }
-
-    NAN_INLINE v8::Local<T> GetValue() const {
-      return NanNew(info_->persistent);
-    }
-
-    NAN_INLINE P* GetParameter() const { return info_->parameter; }
-
-    NAN_INLINE bool IsNearDeath() const {
-      return info_->persistent.IsNearDeath();
-    }
-
-    NAN_INLINE void Revive() const;
-
-    NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
-      return info_;
-    }
-
-    NAN_DEPRECATED NAN_INLINE void Dispose() const {
-    }
-
-   private:
-    _NanWeakCallbackInfo<T, P>* info_;
-  };
-
-  template<typename T, typename P>
-  static void _NanWeakCallbackDispatcher(
-    const v8::WeakCallbackData<T, _NanWeakCallbackInfo<T, P> > &data) {
-      _NanWeakCallbackInfo<T, P> *info = data.GetParameter();
-      _NanWeakCallbackData<T, P> wcbd(info);
-      info->callback(wcbd);
-      if (wcbd.IsNearDeath()) {
-        delete wcbd.GetCallbackInfo();
-      }
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
-      info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher<T, P>);
-  }
-
-template<typename T, typename P>
-NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
-    v8::Handle<T> handle
-  , P* parameter
-  , typename _NanWeakCallbackInfo<T, P>::Callback callback) {
-    _NanWeakCallbackInfo<T, P> *cbinfo =
-     new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
-    cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher<T, P>);
-    return cbinfo;
-}
-
-# define NAN_WEAK_CALLBACK(name)                                               \
-    template<typename T, typename P>                                           \
-    static void name(const _NanWeakCallbackData<T, P> &data)
-
-# define _NAN_ERROR(fun, errmsg) fun(NanNew<v8::String>(errmsg))
-
-# define _NAN_THROW_ERROR(fun, errmsg)                                         \
-    do {                                                                       \
-      NanScope();                                                              \
-      v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg));      \
-    } while (0);
-
-  NAN_INLINE v8::Local<v8::Value> NanError(const char* errmsg) {
-    return  _NAN_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE void NanThrowError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE void NanThrowError(v8::Handle<v8::Value> error) {
-    NanScope();
-    v8::Isolate::GetCurrent()->ThrowException(error);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    v8::Local<v8::Value> err = v8::Exception::Error(NanNew<v8::String>(msg));
-    v8::Local<v8::Object> obj = err.As<v8::Object>();
-    obj->Set(NanNew<v8::String>("code"), NanNew<v8::Integer>(errorNumber));
-    return err;
-  }
-
-  NAN_INLINE void NanThrowError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    NanThrowError(NanError(msg, errorNumber));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanTypeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE void NanThrowTypeError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRangeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  NAN_INLINE void NanThrowRangeError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  template<typename T> NAN_INLINE void NanDisposePersistent(
-      v8::Persistent<T> &handle
-  ) {
-    handle.Reset();
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      char *data
-    , size_t length
-    , node::smalloc::FreeCallback callback
-    , void *hint
-  ) {
-    return node::Buffer::New(
-        v8::Isolate::GetCurrent(), data, length, callback, hint);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      const char *data
-    , uint32_t size
-  ) {
-    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
-    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanBufferUse(
-      char* data
-    , uint32_t size
-  ) {
-    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
-  }
-
-  NAN_INLINE bool NanHasInstance(
-      const v8::Persistent<v8::FunctionTemplate>& function_template
-    , v8::Handle<v8::Value> value
-  ) {
-    return NanNew(function_template)->HasInstance(value);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
-      v8::ExtensionConfiguration* extensions = NULL
-    , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-    , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
-  ) {
-    v8::Isolate* isolate = v8::Isolate::GetCurrent();
-    return v8::Local<v8::Context>::New(
-        isolate
-      , v8::Context::New(isolate, extensions, tmpl, obj)
-    );
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-    , const v8::ScriptOrigin& origin
-  ) {
-    v8::ScriptCompiler::Source source(s, origin);
-    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-  ) {
-    v8::ScriptCompiler::Source source(s);
-    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(
-      v8::Handle<NanUnboundScript> script
-  ) {
-    return script->BindToCurrentContext()->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(
-      v8::Handle<NanBoundScript> script
-  ) {
-    return script->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::Function> func
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, func, argc, argv));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::String> symbol
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, symbol, argc, argv));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , const char* method
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, method, argc, argv));
-  }
-
-  template<typename T>
-  NAN_INLINE void NanSetIsolateData(
-      v8::Isolate *isolate
-    , T *data
-  ) {
-      isolate->SetData(0, data);
-  }
-
-  template<typename T>
-  NAN_INLINE T *NanGetIsolateData(
-      v8::Isolate *isolate
-  ) {
-      return static_cast<T*>(isolate->GetData(0));
-  }
-
-  class NanAsciiString {
-   public:
-    NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new char[size + 1];
-      size = toStr->WriteOneByte(reinterpret_cast<unsigned char*>(buf));
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanAsciiString() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanAsciiString(const NanAsciiString&);
-    void operator=(const NanAsciiString&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUtf8String {
-   public:
-    NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Utf8Length();
-      buf = new char[size + 1];
-      toStr->WriteUtf8(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUtf8String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUtf8String(const NanUtf8String&);
-    void operator=(const NanUtf8String&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUcs2String {
-   public:
-    NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new uint16_t[size + 1];
-      toStr->Write(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE uint16_t* operator*() { return buf; }
-    NAN_INLINE const uint16_t* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUcs2String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUcs2String(const NanUcs2String&);
-    void operator=(const NanUcs2String&);
-
-    uint16_t *buf;
-    int size;
-  };
-
-#else
-// Node 0.8 and 0.10
-
-# define _NAN_METHOD_ARGS_TYPE const v8::Arguments&
-# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args
-# define _NAN_METHOD_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo &
-# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args
-# define _NAN_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo &
-# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args
-# define _NAN_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args
-# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle<v8::Array>
-
-# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args
-# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle<v8::Boolean>
-
-# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args
-# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle<v8::Integer>
-
-# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args
-# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args
-# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args
-# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle<v8::Array>
-
-# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args
-# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle<v8::Boolean>
-
-# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
-# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle<v8::Integer>
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::String> NanSymbol(
-      const char* data, int length = -1) {
-    return v8::String::NewSymbol(data, length);
-  }
-
-# define NanScope() v8::HandleScope scope
-# define NanEscapableScope() v8::HandleScope scope
-# define NanEscapeScope(val) scope.Close(val)
-# define NanLocker() v8::Locker locker
-# define NanUnlocker() v8::Unlocker unlocker
-# define NanReturnValue(value) return scope.Close(value)
-# define NanReturnHolder() NanReturnValue(args.Holder())
-# define NanReturnThis() NanReturnValue(args.This())
-# define NanReturnUndefined() return v8::Undefined()
-# define NanReturnNull() return v8::Null()
-# define NanReturnEmptyString() return v8::String::Empty()
-# define NanObjectWrapHandle(obj) v8::Local<v8::Object>::New(obj->handle_)
-
-  NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Undefined()));
-  }
-
-  NAN_INLINE v8::Local<v8::Primitive> NanNull() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Null()));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanTrue() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::True()));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanFalse() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::False()));
-  }
-
-  NAN_INLINE int NanAdjustExternalMemory(int bc) {
-    return static_cast<int>(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc));
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , const char *name
-    , v8::Handle<v8::Data> value) {
-    templ->Set(name, value);
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , v8::Handle<v8::String> name
-    , v8::Handle<v8::Data> value
-    , v8::PropertyAttribute attributes) {
-    templ->Set(name, value, attributes);
-  }
-
-  NAN_INLINE v8::Local<v8::Context> NanGetCurrentContext() {
-    return v8::Context::GetCurrent();
-  }
-
-  NAN_INLINE void* NanGetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index) {
-    return object->GetPointerFromInternalField(index);
-  }
-
-  NAN_INLINE void NanSetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index
-    , void* value) {
-    object->SetPointerInInternalField(index, value);
-  }
-
-# define NAN_GC_CALLBACK(name)                                                 \
-    void name(v8::GCType type, v8::GCCallbackFlags flags)
-
-  NAN_INLINE void NanAddGCEpilogueCallback(
-    v8::GCEpilogueCallback callback
-  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::V8::AddGCEpilogueCallback(callback, gc_type_filter);
-  }
-  NAN_INLINE void NanRemoveGCEpilogueCallback(
-    v8::GCEpilogueCallback callback) {
-    v8::V8::RemoveGCEpilogueCallback(callback);
-  }
-  NAN_INLINE void NanAddGCPrologueCallback(
-    v8::GCPrologueCallback callback
-  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::V8::AddGCPrologueCallback(callback, gc_type_filter);
-  }
-  NAN_INLINE void NanRemoveGCPrologueCallback(
-    v8::GCPrologueCallback callback) {
-    v8::V8::RemoveGCPrologueCallback(callback);
-  }
-  NAN_INLINE void NanGetHeapStatistics(
-    v8::HeapStatistics *heap_statistics) {
-    v8::V8::GetHeapStatistics(heap_statistics);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , v8::Handle<T> obj) {
-      handle.Dispose();
-      handle = v8::Persistent<T>::New(obj);
-  }
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData;
-
-  template<typename T, typename P>
-  struct _NanWeakCallbackInfo {
-    typedef void (*Callback)(const _NanWeakCallbackData<T, P> &data);
-    NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
-      : parameter(param)
-      , callback(cb)
-      , persistent(v8::Persistent<T>::New(handle)) { }
-
-    NAN_INLINE ~_NanWeakCallbackInfo() {
-      persistent.Dispose();
-      persistent.Clear();
-    }
-
-    P* const parameter;
-    Callback const callback;
-    v8::Persistent<T> persistent;
-  };
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData {
-   public:
-    NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
-      : info_(info) { }
-
-    NAN_INLINE v8::Local<T> GetValue() const {
-      return NanNew(info_->persistent);
-    }
-
-    NAN_INLINE P* GetParameter() const { return info_->parameter; }
-
-    NAN_INLINE bool IsNearDeath() const {
-      return info_->persistent.IsNearDeath();
-    }
-
-    NAN_INLINE void Revive() const;
-
-    NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
-      return info_;
-    }
-
-    NAN_DEPRECATED NAN_INLINE void Dispose() const {
-    }
-
-   private:
-    _NanWeakCallbackInfo<T, P>* info_;
-  };
-
-  template<typename T, typename P>
-  static void _NanWeakPersistentDispatcher(
-      v8::Persistent<v8::Value> object, void *data) {
-    _NanWeakCallbackInfo<T, P>* info =
-        static_cast<_NanWeakCallbackInfo<T, P>*>(data);
-    _NanWeakCallbackData<T, P> wcbd(info);
-    info->callback(wcbd);
-    if (wcbd.IsNearDeath()) {
-      delete wcbd.GetCallbackInfo();
-    }
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
-      info_->persistent.MakeWeak(
-          info_
-        , &_NanWeakPersistentDispatcher<T, P>);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
-    v8::Handle<T> handle
-  , P* parameter
-  , typename _NanWeakCallbackInfo<T, P>::Callback callback) {
-      _NanWeakCallbackInfo<T, P> *cbinfo =
-        new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
-      cbinfo->persistent.MakeWeak(
-          cbinfo
-        , &_NanWeakPersistentDispatcher<T, P>);
-      return cbinfo;
-  }
-
-# define NAN_WEAK_CALLBACK(name)                                               \
-    template<typename T, typename P>                                           \
-    static void name(const _NanWeakCallbackData<T, P> &data)
-
-# define _NAN_ERROR(fun, errmsg)                                               \
-    fun(v8::String::New(errmsg))
-
-# define _NAN_THROW_ERROR(fun, errmsg)                                         \
-    do {                                                                       \
-      NanScope();                                                              \
-      return v8::Local<v8::Value>::New(                                        \
-        v8::ThrowException(_NAN_ERROR(fun, errmsg)));                          \
-    } while (0);
-
-  NAN_INLINE v8::Local<v8::Value> NanError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(
-      v8::Handle<v8::Value> error
-  ) {
-    NanScope();
-    return v8::Local<v8::Value>::New(v8::ThrowException(error));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    v8::Local<v8::Value> err = v8::Exception::Error(v8::String::New(msg));
-    v8::Local<v8::Object> obj = err.As<v8::Object>();
-    obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber));
-    return err;
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    return NanThrowError(NanError(msg, errorNumber));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanTypeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowTypeError(
-      const char* errmsg
-  ) {
-    _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRangeError(
-      const char* errmsg
-  ) {
-    return _NAN_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowRangeError(
-      const char* errmsg
-  ) {
-    _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanDisposePersistent(
-      v8::Persistent<T> &handle) {  // NOLINT(runtime/references)
-    handle.Dispose();
-    handle.Clear();
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      char *data
-    , size_t length
-    , node::Buffer::free_callback callback
-    , void *hint
-  ) {
-    return NanNew(
-        node::Buffer::New(data, length, callback, hint)->handle_);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      const char *data
-    , uint32_t size
-  ) {
-#if NODE_MODULE_VERSION >= 0x000B
-    return NanNew(node::Buffer::New(data, size)->handle_);
-#else
-    return NanNew(
-      node::Buffer::New(const_cast<char*>(data), size)->handle_);
-#endif
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
-    return NanNew(node::Buffer::New(size)->handle_);
-  }
-
-  NAN_INLINE void FreeData(char *data, void *hint) {
-    delete[] data;
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanBufferUse(
-      char* data
-    , uint32_t size
-  ) {
-    return NanNew(
-        node::Buffer::New(data, size, FreeData, NULL)->handle_);
-  }
-
-  NAN_INLINE bool NanHasInstance(
-      const v8::Persistent<v8::FunctionTemplate>& function_template
-    , v8::Handle<v8::Value> value
-  ) {
-    return function_template->HasInstance(value);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
-      v8::ExtensionConfiguration* extensions = NULL
-    , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-    , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
-  ) {
-    v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
-    v8::Local<v8::Context> lctx = NanNew(ctx);
-    ctx.Dispose();
-    return lctx;
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-    , const v8::ScriptOrigin& origin
-  ) {
-    return v8::Script::Compile(s, const_cast<v8::ScriptOrigin *>(&origin));
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-    v8::Local<v8::String> s
-  ) {
-    return v8::Script::Compile(s);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(v8::Handle<v8::Script> script) {
-    return script->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::Function> func
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, func, argc, argv));
-# else
-    v8::TryCatch try_catch;
-    v8::Local<v8::Value> result = func->Call(target, argc, argv);
-    if (try_catch.HasCaught()) {
-        node::FatalException(try_catch);
-    }
-    return result;
-# endif
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::String> symbol
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, symbol, argc, argv));
-# else
-    v8::Local<v8::Function> callback = target->Get(symbol).As<v8::Function>();
-    return NanMakeCallback(target, callback, argc, argv);
-# endif
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , const char* method
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, method, argc, argv));
-# else
-    return NanMakeCallback(target, NanNew(method), argc, argv);
-# endif
-  }
-
-  template<typename T>
-  NAN_INLINE void NanSetIsolateData(
-      v8::Isolate *isolate
-    , T *data
-  ) {
-      isolate->SetData(data);
-  }
-
-  template<typename T>
-  NAN_INLINE T *NanGetIsolateData(
-      v8::Isolate *isolate
-  ) {
-      return static_cast<T*>(isolate->GetData());
-  }
-
-  class NanAsciiString {
-   public:
-    NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new char[size + 1];
-      size = toStr->WriteAscii(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanAsciiString() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanAsciiString(const NanAsciiString&);
-    void operator=(const NanAsciiString&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUtf8String {
-   public:
-    NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Utf8Length();
-      buf = new char[size + 1];
-      toStr->WriteUtf8(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUtf8String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUtf8String(const NanUtf8String&);
-    void operator=(const NanUtf8String&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUcs2String {
-   public:
-    NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new uint16_t[size + 1];
-      toStr->Write(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE uint16_t* operator*() { return buf; }
-    NAN_INLINE const uint16_t* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUcs2String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUcs2String(const NanUcs2String&);
-    void operator=(const NanUcs2String&);
-
-    uint16_t *buf;
-    int size;
-  };
-
-#endif  // NODE_MODULE_VERSION
-
-typedef void (*NanFreeCallback)(char *data, void *hint);
-
-#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS)
-#define NAN_GETTER(name)                                                       \
-    _NAN_GETTER_RETURN_TYPE name(                                              \
-        v8::Local<v8::String> property                                         \
-      , _NAN_GETTER_ARGS)
-#define NAN_SETTER(name)                                                       \
-    _NAN_SETTER_RETURN_TYPE name(                                              \
-        v8::Local<v8::String> property                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_SETTER_ARGS)
-#define NAN_PROPERTY_GETTER(name)                                              \
-    _NAN_PROPERTY_GETTER_RETURN_TYPE name(                                     \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_GETTER_ARGS)
-#define NAN_PROPERTY_SETTER(name)                                              \
-    _NAN_PROPERTY_SETTER_RETURN_TYPE name(                                     \
-        v8::Local<v8::String> property                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_PROPERTY_SETTER_ARGS)
-#define NAN_PROPERTY_ENUMERATOR(name)                                          \
-    _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS)
-#define NAN_PROPERTY_DELETER(name)                                             \
-    _NAN_PROPERTY_DELETER_RETURN_TYPE name(                                    \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_DELETER_ARGS)
-#define NAN_PROPERTY_QUERY(name)                                               \
-    _NAN_PROPERTY_QUERY_RETURN_TYPE name(                                      \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_QUERY_ARGS)
-# define NAN_INDEX_GETTER(name)                                                \
-    _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS)
-#define NAN_INDEX_SETTER(name)                                                 \
-    _NAN_INDEX_SETTER_RETURN_TYPE name(                                        \
-        uint32_t index                                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_INDEX_SETTER_ARGS)
-#define NAN_INDEX_ENUMERATOR(name)                                             \
-    _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS)
-#define NAN_INDEX_DELETER(name)                                                \
-    _NAN_INDEX_DELETER_RETURN_TYPE name(                                       \
-        uint32_t index                                                         \
-      , _NAN_INDEX_DELETER_ARGS)
-#define NAN_INDEX_QUERY(name)                                                  \
-    _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS)
-
-class NanCallback {
- public:
-  NanCallback() {
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(handle, obj);
-  }
-
-  explicit NanCallback(const v8::Handle<v8::Function> &fn) {
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(handle, obj);
-    SetFunction(fn);
-  }
-
-  ~NanCallback() {
-    if (handle.IsEmpty()) return;
-    NanDisposePersistent(handle);
-  }
-
-  NAN_INLINE void SetFunction(const v8::Handle<v8::Function> &fn) {
-    NanScope();
-    NanNew(handle)->Set(kCallbackIndex, fn);
-  }
-
-  NAN_INLINE v8::Local<v8::Function> GetFunction() const {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex)
-        .As<v8::Function>());
-  }
-
-  NAN_INLINE bool IsEmpty() const {
-    NanScope();
-    return NanNew(handle)->Get(kCallbackIndex)->IsUndefined();
-  }
-
-  v8::Handle<v8::Value> Call(int argc, v8::Handle<v8::Value> argv[]) const {
-    NanEscapableScope();
-#if (NODE_MODULE_VERSION > 0x000B)  // 0.11.12+
-    v8::Isolate* isolate = v8::Isolate::GetCurrent();
-    v8::Local<v8::Function> callback = NanNew(handle)->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(node::MakeCallback(
-        isolate
-      , isolate->GetCurrentContext()->Global()
-      , callback
-      , argc
-      , argv
-    ));
-#else
-#if NODE_VERSION_AT_LEAST(0, 8, 0)
-    v8::Local<v8::Function> callback = handle->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(node::MakeCallback(
-        v8::Context::GetCurrent()->Global()
-      , callback
-      , argc
-      , argv
-    ));
-#else
-    v8::Local<v8::Function> callback = handle->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(NanMakeCallback(
-        v8::Context::GetCurrent()->Global(), callback, argc, argv));
-#endif
-#endif
-  }
-
- private:
-  v8::Persistent<v8::Object> handle;
-  static const uint32_t kCallbackIndex = 0;
-};
-
-/* abstract */ class NanAsyncWorker {
- public:
-  explicit NanAsyncWorker(NanCallback *callback_)
-      : callback(callback_), errmsg_(NULL) {
-    request.data = this;
-
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(persistentHandle, obj);
-  }
-
-  virtual ~NanAsyncWorker() {
-    NanScope();
-
-    if (!persistentHandle.IsEmpty())
-      NanDisposePersistent(persistentHandle);
-    if (callback)
-      delete callback;
-    if (errmsg_)
-      delete[] errmsg_;
-  }
-
-  virtual void WorkComplete() {
-    NanScope();
-
-    if (errmsg_ == NULL)
-      HandleOKCallback();
-    else
-      HandleErrorCallback();
-    delete callback;
-    callback = NULL;
-  }
-
-  NAN_INLINE void SaveToPersistent(
-      const char *key, const v8::Local<v8::Object> &obj) {
-    v8::Local<v8::Object> handle = NanNew(persistentHandle);
-    handle->Set(NanNew<v8::String>(key), obj);
-  }
-
-  v8::Local<v8::Object> GetFromPersistent(const char *key) const {
-    NanEscapableScope();
-    v8::Local<v8::Object> handle = NanNew(persistentHandle);
-    return NanEscapeScope(handle->Get(NanNew(key)).As<v8::Object>());
-  }
-
-  virtual void Execute() = 0;
-
-  uv_work_t request;
-
-  virtual void Destroy() {
-      delete this;
-  }
-
- protected:
-  v8::Persistent<v8::Object> persistentHandle;
-  NanCallback *callback;
-
-  virtual void HandleOKCallback() {
-    callback->Call(0, NULL);
-  }
-
-  virtual void HandleErrorCallback() {
-    NanScope();
-
-    v8::Local<v8::Value> argv[] = {
-        v8::Exception::Error(NanNew<v8::String>(ErrorMessage()))
-    };
-    callback->Call(1, argv);
-  }
-
-  void SetErrorMessage(const char *msg) {
-    if (errmsg_) {
-      delete[] errmsg_;
-    }
-
-    size_t size = strlen(msg) + 1;
-    errmsg_ = new char[size];
-    memcpy(errmsg_, msg, size);
-  }
-
-  const char* ErrorMessage() const {
-    return errmsg_;
-  }
-
- private:
-  char *errmsg_;
-};
-
-/* abstract */ class NanAsyncProgressWorker : public NanAsyncWorker {
- public:
-  explicit NanAsyncProgressWorker(NanCallback *callback_)
-      : NanAsyncWorker(callback_), asyncdata_(NULL), asyncsize_(0) {
-    async = new uv_async_t;
-    uv_async_init(
-        uv_default_loop()
-      , async
-      , AsyncProgress_
-    );
-    async->data = this;
-
-    uv_mutex_init(&async_lock);
-  }
-
-  virtual ~NanAsyncProgressWorker() {
-    uv_mutex_destroy(&async_lock);
-
-    if (asyncdata_) {
-      delete[] asyncdata_;
-    }
-  }
-
-  void WorkProgress() {
-    uv_mutex_lock(&async_lock);
-    char *data = asyncdata_;
-    size_t size = asyncsize_;
-    asyncdata_ = NULL;
-    uv_mutex_unlock(&async_lock);
-
-    // Dont send progress events after we've already completed.
-    if (callback) {
-        HandleProgressCallback(data, size);
-    }
-    delete[] data;
-  }
-
-  class ExecutionProgress {
-    friend class NanAsyncProgressWorker;
-   public:
-    // You could do fancy generics with templates here.
-    void Send(const char* data, size_t size) const {
-        that_->SendProgress_(data, size);
-    }
-
-   private:
-    explicit ExecutionProgress(NanAsyncProgressWorker* that) : that_(that) {}
-    // Prohibit copying and assignment.
-    ExecutionProgress(const ExecutionProgress&);
-    void operator=(const ExecutionProgress&);
-  #if __cplusplus >= 201103L
-    // Prohibit C++11 move semantics.
-    ExecutionProgress(ExecutionProgress&&) = delete;
-    void operator=(ExecutionProgress&&) = delete;
-  #endif
-    NanAsyncProgressWorker* const that_;
-  };
-
-  virtual void Execute(const ExecutionProgress& progress) = 0;
-  virtual void HandleProgressCallback(const char *data, size_t size) = 0;
-
-  virtual void Destroy() {
-      uv_close(reinterpret_cast<uv_handle_t*>(async), AsyncClose_);
-  }
-
- private:
-  void Execute() /*final override*/ {
-      ExecutionProgress progress(this);
-      Execute(progress);
-  }
-
-  void SendProgress_(const char *data, size_t size) {
-    char *new_data = new char[size];
-    memcpy(new_data, data, size);
-
-    uv_mutex_lock(&async_lock);
-    char *old_data = asyncdata_;
-    asyncdata_ = new_data;
-    asyncsize_ = size;
-    uv_mutex_unlock(&async_lock);
-
-    if (old_data) {
-      delete[] old_data;
-    }
-    uv_async_send(async);
-  }
-
-  NAN_INLINE static NAUV_WORK_CB(AsyncProgress_) {
-    NanAsyncProgressWorker *worker =
-            static_cast<NanAsyncProgressWorker*>(async->data);
-    worker->WorkProgress();
-  }
-
-  NAN_INLINE static void AsyncClose_(uv_handle_t* handle) {
-    NanAsyncProgressWorker *worker =
-            static_cast<NanAsyncProgressWorker*>(handle->data);
-    delete reinterpret_cast<uv_async_t*>(handle);
-    delete worker;
-  }
-
-  uv_async_t *async;
-  uv_mutex_t async_lock;
-  char *asyncdata_;
-  size_t asyncsize_;
-};
-
-NAN_INLINE void NanAsyncExecute (uv_work_t* req) {
-  NanAsyncWorker *worker = static_cast<NanAsyncWorker*>(req->data);
-  worker->Execute();
-}
-
-NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) {
-  NanAsyncWorker* worker = static_cast<NanAsyncWorker*>(req->data);
-  worker->WorkComplete();
-  worker->Destroy();
-}
-
-NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) {
-  uv_queue_work(
-      uv_default_loop()
-    , &worker->request
-    , NanAsyncExecute
-    , (uv_after_work_cb)NanAsyncExecuteComplete
-  );
-}
-
-//// Base 64 ////
-
-#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
-
-// Doesn't check for padding at the end.  Can be 1-2 bytes over.
-NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) {
-  size_t remainder = size % 4;
-
-  size = (size / 4) * 3;
-  if (remainder) {
-    if (size == 0 && remainder == 1) {
-      // special case: 1-byte input cannot be decoded
-      size = 0;
-    } else {
-      // non-padded input, add 1 or 2 extra bytes
-      size += 1 + (remainder == 3);
-    }
-  }
-
-  return size;
-}
-
-template<typename T>
-NAN_INLINE size_t _nan_base64_decoded_size(
-    const T* src
-  , size_t size
-) {
-  if (size == 0)
-    return 0;
-
-  if (src[size - 1] == '=')
-    size--;
-  if (size > 0 && src[size - 1] == '=')
-    size--;
-
-  return _nan_base64_decoded_size_fast(size);
-}
-
-// supports regular and URL-safe base64
-static const int _nan_unbase64_table[] = {
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63
-  , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1
-  , -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14
-  , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63
-  , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
-  , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)]
-
-template<typename T> static size_t _nan_base64_decode(
-    char* buf
-  , size_t len
-  , const T* src
-  , const size_t srcLen
-) {
-  char* dst = buf;
-  char* dstEnd = buf + len;
-  const T* srcEnd = src + srcLen;
-
-  while (src < srcEnd && dst < dstEnd) {
-    ptrdiff_t remaining = srcEnd - src;
-    char a, b, c, d;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining == 0 || *src == '=') break;
-    a = _nan_unbase64(*src++);
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 1 || *src == '=') break;
-    b = _nan_unbase64(*src++);
-
-    *dst++ = (a << 2) | ((b & 0x30) >> 4);
-    if (dst == dstEnd) break;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 2 || *src == '=') break;
-    c = _nan_unbase64(*src++);
-
-    *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
-    if (dst == dstEnd) break;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 3 || *src == '=') break;
-    d = _nan_unbase64(*src++);
-
-    *dst++ = ((c & 0x03) << 6) | (d & 0x3F);
-  }
-
-  return dst - buf;
-}
-
-//// HEX ////
-
-template<typename T> unsigned _nan_hex2bin(T c) {
-  if (c >= '0' && c <= '9') return c - '0';
-  if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
-  if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
-  return static_cast<unsigned>(-1);
-}
-
-template<typename T> static size_t _nan_hex_decode(
-    char* buf
-  , size_t len
-  , const T* src
-  , const size_t srcLen
-) {
-  size_t i;
-  for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
-    unsigned a = _nan_hex2bin(src[i * 2 + 0]);
-    unsigned b = _nan_hex2bin(src[i * 2 + 1]);
-    if (!~a || !~b) return i;
-    buf[i] = a * 16 + b;
-  }
-
-  return i;
-}
-
-namespace NanIntern {
-
-inline
-NanExternalOneByteStringResource const*
-GetExternalResource(v8::Local<v8::String> str) {
-#if NODE_MODULE_VERSION < 42
-    return str->GetExternalAsciiStringResource();
-#else  // io.js v1.0.0
-    return str->GetExternalOneByteStringResource();
-#endif
-}
-
-inline
-bool
-IsExternal(v8::Local<v8::String> str) {
-#if NODE_MODULE_VERSION < 42
-    return str->IsExternalAscii();
-#else  // io.js v1.0.0
-    return str->IsExternalOneByte();
-#endif
-}
-
-}  // end of namespace NanIntern
-
-static bool _NanGetExternalParts(
-    v8::Handle<v8::Value> val
-  , const char** data
-  , size_t* len
-) {
-  if (node::Buffer::HasInstance(val)) {
-    *data = node::Buffer::Data(val.As<v8::Object>());
-    *len = node::Buffer::Length(val.As<v8::Object>());
-    return true;
-  }
-
-  assert(val->IsString());
-  v8::Local<v8::String> str = NanNew(val.As<v8::String>());
-
-  if (NanIntern::IsExternal(str)) {
-    const NanExternalOneByteStringResource* ext;
-    ext = NanIntern::GetExternalResource(str);
-    *data = ext->data();
-    *len = ext->length();
-    return true;
-  }
-
-  if (str->IsExternal()) {
-    const v8::String::ExternalStringResource* ext;
-    ext = str->GetExternalStringResource();
-    *data = reinterpret_cast<const char*>(ext->data());
-    *len = ext->length();
-    return true;
-  }
-
-  return false;
-}
-
-namespace Nan {
-  enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
-}
-
-#if !NODE_VERSION_AT_LEAST(0, 10, 0)
-# include "nan_string_bytes.h"  // NOLINT(build/include)
-#endif
-
-NAN_INLINE v8::Local<v8::Value> NanEncode(
-    const void *buf, size_t len, enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION >= 42)
-  v8::Isolate* isolate = v8::Isolate::GetCurrent();
-  node::encoding node_enc = static_cast<node::encoding>(encoding);
-
-  if (encoding == Nan::UCS2) {
-    return node::Encode(
-        isolate
-      , reinterpret_cast<const uint16_t *>(buf)
-      , len / 2);
-  } else {
-    return node::Encode(
-        isolate
-      , reinterpret_cast<const char *>(buf)
-      , len
-      , node_enc);
-  }
-#elif (NODE_MODULE_VERSION > 0x000B)
-  return node::Encode(
-      v8::Isolate::GetCurrent()
-    , buf, len
-    , static_cast<node::encoding>(encoding));
-#else
-# if NODE_VERSION_AT_LEAST(0, 10, 0)
-  return node::Encode(buf, len, static_cast<node::encoding>(encoding));
-# else
-  return NanIntern::Encode(reinterpret_cast<const char*>(buf), len, encoding);
-# endif
-#endif
-}
-
-NAN_INLINE ssize_t NanDecodeBytes(
-    v8::Handle<v8::Value> val, enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION > 0x000B)
-  return node::DecodeBytes(
-      v8::Isolate::GetCurrent()
-    , val
-    , static_cast<node::encoding>(encoding));
-#else
-# if (NODE_MODULE_VERSION < 0x000B)
-  if (encoding == Nan::BUFFER) {
-    return node::DecodeBytes(val, node::BINARY);
-  }
-# endif
-  return node::DecodeBytes(val, static_cast<node::encoding>(encoding));
-#endif
-}
-
-NAN_INLINE ssize_t NanDecodeWrite(
-    char *buf
-  , size_t len
-  , v8::Handle<v8::Value> val
-  , enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION > 0x000B)
-  return node::DecodeWrite(
-      v8::Isolate::GetCurrent()
-    , buf
-    , len
-    , val
-    , static_cast<node::encoding>(encoding));
-#else
-# if (NODE_MODULE_VERSION < 0x000B)
-  if (encoding == Nan::BUFFER) {
-    return node::DecodeWrite(buf, len, val, node::BINARY);
-  }
-# endif
-  return node::DecodeWrite(
-      buf
-    , len
-    , val
-    , static_cast<node::encoding>(encoding));
-#endif
-}
-
-/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString(
-    v8::Handle<v8::Value> from
-  , enum Nan::Encoding encoding
-  , size_t *datalen
-  , void *buf
-  , size_t buflen
-  , int flags
-) {
-  NanScope();
-
-  size_t sz_;
-  size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION);
-  char *data = NULL;
-  size_t len;
-  bool is_extern = _NanGetExternalParts(
-      from
-    , const_cast<const char**>(&data)
-    , &len);
-
-  if (is_extern && !term_len) {
-    NanSetPointerSafe(datalen, len);
-    return data;
-  }
-
-  v8::Local<v8::String> toStr = from->ToString();
-
-  char *to = static_cast<char *>(buf);
-
-  switch (encoding) {
-    case Nan::ASCII:
-#if NODE_MODULE_VERSION < 0x000C
-      sz_ = toStr->Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-      NanSetPointerSafe<size_t>(
-          datalen
-        , toStr->WriteAscii(to, 0, static_cast<int>(sz_ + term_len), flags));
-      return to;
-#endif
-    case Nan::BINARY:
-    case Nan::BUFFER:
-      sz_ = toStr->Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-#if NODE_MODULE_VERSION < 0x000C
-      {
-        uint16_t* twobytebuf = new uint16_t[sz_ + term_len];
-
-        size_t somelen = toStr->Write(twobytebuf, 0,
-          static_cast<int>(sz_ + term_len), flags);
-
-        for (size_t i = 0; i < sz_ + term_len && i < somelen + term_len; i++) {
-          unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
-          to[i] = *b;
-        }
-
-        NanSetPointerSafe<size_t>(datalen, somelen);
-
-        delete[] twobytebuf;
-        return to;
-      }
-#else
-      NanSetPointerSafe<size_t>(
-        datalen,
-        toStr->WriteOneByte(
-            reinterpret_cast<uint8_t *>(to)
-          , 0
-          , static_cast<int>(sz_ + term_len)
-          , flags));
-      return to;
-#endif
-    case Nan::UTF8:
-      sz_ = toStr->Utf8Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-      NanSetPointerSafe<size_t>(
-          datalen
-        , toStr->WriteUtf8(to, static_cast<int>(sz_ + term_len)
-            , NULL, flags)
-          - term_len);
-      return to;
-    case Nan::BASE64:
-      {
-        v8::String::Value value(toStr);
-        sz_ = _nan_base64_decoded_size(*value, value.length());
-        if (to == NULL) {
-          to = new char[sz_ + term_len];
-        } else {
-          assert(buflen >= sz_ + term_len);
-        }
-        NanSetPointerSafe<size_t>(
-            datalen
-          , _nan_base64_decode(to, sz_, *value, value.length()));
-        if (term_len) {
-          to[sz_] = '\0';
-        }
-        return to;
-      }
-    case Nan::UCS2:
-      {
-        sz_ = toStr->Length();
-        if (to == NULL) {
-          to = new char[(sz_ + term_len) * 2];
-        } else {
-          assert(buflen >= (sz_ + term_len) * 2 && "too small buffer");
-        }
-
-        int bc = 2 * toStr->Write(
-            reinterpret_cast<uint16_t *>(to)
-          , 0
-          , static_cast<int>(sz_ + term_len)
-          , flags);
-        NanSetPointerSafe<size_t>(datalen, bc);
-        return to;
-      }
-    case Nan::HEX:
-      {
-        v8::String::Value value(toStr);
-        sz_ = value.length();
-        assert(!(sz_ & 1) && "bad hex data");
-        if (to == NULL) {
-          to = new char[sz_ / 2 + term_len];
-        } else {
-          assert(buflen >= sz_ / 2 + term_len && "too small buffer");
-        }
-        NanSetPointerSafe<size_t>(
-            datalen
-          , _nan_hex_decode(to, sz_ / 2, *value, value.length()));
-      }
-      if (term_len) {
-        to[sz_ / 2] = '\0';
-      }
-      return to;
-    default:
-      assert(0 && "unknown encoding");
-  }
-  return to;
-}
-
-NAN_DEPRECATED NAN_INLINE void* NanRawString(
-    v8::Handle<v8::Value> from
-  , enum Nan::Encoding encoding
-  , size_t *datalen
-  , void *buf
-  , size_t buflen
-  , int flags
-) {
-  return _NanRawString(from, encoding, datalen, buf, buflen, flags);
-}
-
-
-NAN_DEPRECATED NAN_INLINE char* NanCString(
-    v8::Handle<v8::Value> from
-  , size_t *datalen
-  , char *buf = NULL
-  , size_t buflen = 0
-  , int flags = v8::String::NO_OPTIONS
-) {
-    return static_cast<char *>(
-      _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags)
-    );
-}
-
-NAN_INLINE void NanSetPrototypeTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , const char *name
-  , v8::Handle<v8::Data> value
-) {
-  NanSetTemplate(templ->PrototypeTemplate(), name, value);
-}
-
-NAN_INLINE void NanSetPrototypeTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , v8::Handle<v8::String> name
-  , v8::Handle<v8::Data> value
-  , v8::PropertyAttribute attributes
-) {
-  NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes);
-}
-
-NAN_INLINE void NanSetInstanceTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , const char *name
-  , v8::Handle<v8::Data> value
-) {
-  NanSetTemplate(templ->InstanceTemplate(), name, value);
-}
-
-NAN_INLINE void NanSetInstanceTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , v8::Handle<v8::String> name
-  , v8::Handle<v8::Data> value
-  , v8::PropertyAttribute attributes
-) {
-  NanSetTemplate(templ->InstanceTemplate(), name, value, attributes);
-}
-
-//=== Export ==================================================================
-
-inline
-void
-NanExport(v8::Handle<v8::Object> target, const char * name,
-    NanFunctionCallback f) {
-  target->Set(NanNew<v8::String>(name),
-      NanNew<v8::FunctionTemplate>(f)->GetFunction());
-}
-
-//=== Tap Reverse Binding =====================================================
-
-struct NanTap {
-  explicit NanTap(v8::Handle<v8::Value> t) : t_() {
-    NanAssignPersistent(t_, t->ToObject());
-  }
-
-  ~NanTap() { NanDisposePersistent(t_); }  // not sure if neccessary
-
-  inline void plan(int i) {
-    v8::Handle<v8::Value> arg = NanNew(i);
-    NanMakeCallback(NanNew(t_), "plan", 1, &arg);
-  }
-
-  inline void ok(bool isOk, const char * msg = NULL) {
-    v8::Handle<v8::Value> args[2];
-    args[0] = NanNew(isOk);
-    if (msg) args[1] = NanNew(msg);
-    NanMakeCallback(NanNew(t_), "ok", msg ? 2 : 1, args);
-  }
-
- private:
-  v8::Persistent<v8::Object> t_;
-};
-
-#define NAN_STRINGIZE2(x) #x
-#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x)
-#define NAN_TEST_EXPRESSION(expression) \
-  ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression
-
-#define return_NanValue(v) NanReturnValue(v)
-#define return_NanUndefined() NanReturnUndefined()
-#define NAN_EXPORT(target, function) NanExport(target, #function, function)
-
-#endif  // NAN_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_12_inl.h b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_12_inl.h
deleted file mode 100644
index ff63ec0c..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_12_inl.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_IMPLEMENTATION_12_INL_H_
-#define NAN_IMPLEMENTATION_12_INL_H_
-//==============================================================================
-// node v0.11 implementation
-//==============================================================================
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-namespace NanIntern {
-
-//=== Array ====================================================================
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New() {
-  return v8::Array::New(v8::Isolate::GetCurrent());
-}
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New(int length) {
-  return v8::Array::New(v8::Isolate::GetCurrent(), length);
-}
-
-//=== Boolean ==================================================================
-
-Factory<v8::Boolean>::return_t
-Factory<v8::Boolean>::New(bool value) {
-  return v8::Boolean::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Boolean Object ===========================================================
-
-Factory<v8::BooleanObject>::return_t
-Factory<v8::BooleanObject>::New(bool value) {
-  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-}
-
-//=== Context ==================================================================
-
-Factory<v8::Context>::return_t
-Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
-                         , v8::Handle<v8::ObjectTemplate> tmpl
-                         , v8::Handle<v8::Value> obj) {
-  return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj);
-}
-
-//=== Date =====================================================================
-
-Factory<v8::Date>::return_t
-Factory<v8::Date>::New(double value) {
-  return v8::Date::New(v8::Isolate::GetCurrent(), value).As<v8::Date>();
-}
-
-//=== External =================================================================
-
-Factory<v8::External>::return_t
-Factory<v8::External>::New(void * value) {
-  return v8::External::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Function =================================================================
-
-Factory<v8::Function>::return_t
-Factory<v8::Function>::New( NanFunctionCallback callback
-                          , v8::Handle<v8::Value> data) {
-  return v8::Function::New( v8::Isolate::GetCurrent()
-                          , callback
-                          , data);
-}
-
-//=== Function Template ========================================================
-
-Factory<v8::FunctionTemplate>::return_t
-Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
-                                  , v8::Handle<v8::Value> data
-                                  , v8::Handle<v8::Signature> signature) {
-  return v8::FunctionTemplate::New( v8::Isolate::GetCurrent()
-                                  , callback
-                                  , data
-                                  , signature);
-}
-
-//=== Number ===================================================================
-
-Factory<v8::Number>::return_t
-Factory<v8::Number>::New(double value) {
-  return v8::Number::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Number Object ============================================================
-
-Factory<v8::NumberObject>::return_t
-Factory<v8::NumberObject>::New(double value) {
-  return v8::NumberObject::New( v8::Isolate::GetCurrent()
-                              , value).As<v8::NumberObject>();
-}
-
-//=== Integer, Int32 and Uint32 ================================================
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(int32_t value) {
-  return To<T>(T::New(v8::Isolate::GetCurrent(), value));
-}
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(uint32_t value) {
-  return To<T>(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(int32_t value) {
-  return To<v8::Uint32>(
-      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(uint32_t value) {
-  return To<v8::Uint32>(
-      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-//=== Object ===================================================================
-
-Factory<v8::Object>::return_t
-Factory<v8::Object>::New() {
-  return v8::Object::New(v8::Isolate::GetCurrent());
-}
-
-//=== Object Template ==========================================================
-
-Factory<v8::ObjectTemplate>::return_t
-Factory<v8::ObjectTemplate>::New() {
-  return v8::ObjectTemplate::New(v8::Isolate::GetCurrent());
-}
-
-//=== RegExp ===================================================================
-
-Factory<v8::RegExp>::return_t
-Factory<v8::RegExp>::New(
-    v8::Handle<v8::String> pattern
-  , v8::RegExp::Flags flags) {
-  return v8::RegExp::New(pattern, flags);
-}
-
-//=== Script ===================================================================
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source) {
-  v8::ScriptCompiler::Source src(source);
-  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
-}
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source
-                        , v8::ScriptOrigin const& origin) {
-  v8::ScriptCompiler::Source src(source, origin);
-  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
-}
-
-//=== Signature ================================================================
-
-Factory<v8::Signature>::return_t
-Factory<v8::Signature>::New( Factory<v8::Signature>::FTH receiver
-                           , int argc
-                           , Factory<v8::Signature>::FTH argv[]) {
-  return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv);
-}
-
-//=== String ===================================================================
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New() {
-  return v8::String::Empty(v8::Isolate::GetCurrent());
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const char * value, int length) {
-  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value,
-      v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(std::string const& value) {
-  assert(value.size() <= INT_MAX && "string too long");
-  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(),
-      value.data(), v8::String::kNormalString, static_cast<int>(value.size()));
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint8_t * value, int length) {
-  return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
-        v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint16_t * value, int length) {
-  return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value,
-        v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
-  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(NanExternalOneByteStringResource * value) {
-  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
-}
-
-//=== String Object ============================================================
-
-Factory<v8::StringObject>::return_t
-Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
-  return v8::StringObject::New(value).As<v8::StringObject>();
-}
-
-//=== Unbound Script ===========================================================
-
-Factory<v8::UnboundScript>::return_t
-Factory<v8::UnboundScript>::New(v8::Local<v8::String> source) {
-  v8::ScriptCompiler::Source src(source);
-  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
-}
-
-Factory<v8::UnboundScript>::return_t
-Factory<v8::UnboundScript>::New( v8::Local<v8::String> source
-                               , v8::ScriptOrigin const& origin) {
-  v8::ScriptCompiler::Source src(source, origin);
-  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
-}
-
-}  // end of namespace NanIntern
-
-//=== Presistents and Handles ==================================================
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Handle<T> h) {
-  return v8::Local<T>::New(v8::Isolate::GetCurrent(), h);
-}
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
-  return v8::Local<T>::New(v8::Isolate::GetCurrent(), p);
-}
-
-#endif  // NAN_IMPLEMENTATION_12_INL_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_pre_12_inl.h b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_pre_12_inl.h
deleted file mode 100644
index 85dd2754..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_implementation_pre_12_inl.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_
-#define NAN_IMPLEMENTATION_PRE_12_INL_H_
-
-#include <algorithm>
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# include <vector>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-# include <vector>
-#endif
-
-//==============================================================================
-// node v0.10 implementation
-//==============================================================================
-
-namespace NanIntern {
-
-//=== Array ====================================================================
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New() {
-  return v8::Array::New();
-}
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New(int length) {
-  return v8::Array::New(length);
-}
-
-//=== Boolean ==================================================================
-
-Factory<v8::Boolean>::return_t
-Factory<v8::Boolean>::New(bool value) {
-  return v8::Boolean::New(value)->ToBoolean();
-}
-
-//=== Boolean Object ===========================================================
-
-Factory<v8::BooleanObject>::return_t
-Factory<v8::BooleanObject>::New(bool value) {
-  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-}
-
-//=== Context ==================================================================
-
-Factory<v8::Context>::return_t
-Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
-                         , v8::Handle<v8::ObjectTemplate> tmpl
-                         , v8::Handle<v8::Value> obj) {
-  v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
-  v8::Local<v8::Context> lctx = v8::Local<v8::Context>::New(ctx);
-  ctx.Dispose();
-  return lctx;
-}
-
-//=== Date =====================================================================
-
-Factory<v8::Date>::return_t
-Factory<v8::Date>::New(double value) {
-  return v8::Date::New(value).As<v8::Date>();
-}
-
-//=== External =================================================================
-
-Factory<v8::External>::return_t
-Factory<v8::External>::New(void * value) {
-  return v8::External::New(value);
-}
-
-//=== Function =================================================================
-
-Factory<v8::Function>::return_t
-Factory<v8::Function>::New( NanFunctionCallback callback
-                          , v8::Handle<v8::Value> data) {
-  return Factory<v8::FunctionTemplate>::New( callback
-                                           , data
-                                           , v8::Handle<v8::Signature>()
-                                           )->GetFunction();
-}
-
-
-//=== FunctionTemplate =========================================================
-
-Factory<v8::FunctionTemplate>::return_t
-Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
-                                  , v8::Handle<v8::Value> data
-                                  , v8::Handle<v8::Signature> signature) {
-  // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find
-  // a way. Have at it though...
-  return v8::FunctionTemplate::New( callback
-                                  , data
-                                  , signature);
-}
-
-//=== Number ===================================================================
-
-Factory<v8::Number>::return_t
-Factory<v8::Number>::New(double value) {
-  return v8::Number::New(value);
-}
-
-//=== Number Object ============================================================
-
-Factory<v8::NumberObject>::return_t
-Factory<v8::NumberObject>::New(double value) {
-  return v8::NumberObject::New(value).As<v8::NumberObject>();
-}
-
-//=== Integer, Int32 and Uint32 ================================================
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(int32_t value) {
-  return To<T>(T::New(value));
-}
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(uint32_t value) {
-  return To<T>(T::NewFromUnsigned(value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(int32_t value) {
-  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(uint32_t value) {
-  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
-}
-
-
-//=== Object ===================================================================
-
-Factory<v8::Object>::return_t
-Factory<v8::Object>::New() {
-  return v8::Object::New();
-}
-
-//=== Object Template ==========================================================
-
-Factory<v8::ObjectTemplate>::return_t
-Factory<v8::ObjectTemplate>::New() {
-  return v8::ObjectTemplate::New();
-}
-
-//=== RegExp ===================================================================
-
-Factory<v8::RegExp>::return_t
-Factory<v8::RegExp>::New(
-    v8::Handle<v8::String> pattern
-  , v8::RegExp::Flags flags) {
-  return v8::RegExp::New(pattern, flags);
-}
-
-//=== Script ===================================================================
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source) {
-  return v8::Script::New(source);
-}
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source
-                        , v8::ScriptOrigin const& origin) {
-  return v8::Script::New(source, const_cast<v8::ScriptOrigin*>(&origin));
-}
-
-//=== Signature ================================================================
-
-Factory<v8::Signature>::return_t
-Factory<v8::Signature>::New( Factory<v8::Signature>::FTH receiver
-                           , int argc
-                           , Factory<v8::Signature>::FTH argv[]) {
-  return v8::Signature::New(receiver, argc, argv);
-}
-
-//=== String ===================================================================
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New() {
-  return v8::String::Empty();
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const char * value, int length) {
-  return v8::String::New(value, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(std::string const& value) {
-  assert(value.size() <= INT_MAX && "string too long");
-  return v8::String::New( value.data(), static_cast<int>(value.size()));
-}
-
-inline
-void
-widenString(std::vector<uint16_t> *ws, const uint8_t *s, int l = -1) {
-  size_t len = static_cast<size_t>(l);
-  if (l < 0) {
-    len = strlen(reinterpret_cast<const char*>(s));
-  }
-  assert(len <= INT_MAX && "string too long");
-  ws->resize(len);
-  std::copy(s, s + len, ws->begin());
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint16_t * value, int length) {
-  return v8::String::New(value, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint8_t * value, int length) {
-  std::vector<uint16_t> wideString;
-  widenString(&wideString, value, length);
-  if (wideString.size() == 0) {
-    return v8::String::Empty();
-  } else {
-    return v8::String::New(&wideString.front()
-         , static_cast<int>(wideString.size()));
-  }
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
-  return v8::String::NewExternal(value);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalAsciiStringResource * value) {
-  return v8::String::NewExternal(value);
-}
-
-//=== String Object ============================================================
-
-Factory<v8::StringObject>::return_t
-Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
-  return v8::StringObject::New(value).As<v8::StringObject>();
-}
-
-}  // end of namespace NanIntern
-
-//=== Presistents and Handles ==================================================
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Handle<T> h) {
-  return v8::Local<T>::New(h);
-}
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
-  return v8::Local<T>::New(p);
-}
-
-#endif  // NAN_IMPLEMENTATION_PRE_12_INL_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_new.h b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_new.h
deleted file mode 100644
index 95b6b51e..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_new.h
+++ /dev/null
@@ -1,329 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_NEW_H_
-#define NAN_NEW_H_
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-namespace NanIntern {  // scnr
-
-// TODO(agnat): Generalize
-template <typename T> v8::Local<T> To(v8::Handle<v8::Integer> i);
-
-template <>
-inline
-v8::Local<v8::Integer>
-To<v8::Integer>(v8::Handle<v8::Integer> i) { return i->ToInteger(); }
-
-template <>
-inline
-v8::Local<v8::Int32>
-To<v8::Int32>(v8::Handle<v8::Integer> i)   { return i->ToInt32(); }
-
-template <>
-inline
-v8::Local<v8::Uint32>
-To<v8::Uint32>(v8::Handle<v8::Integer> i)  { return i->ToUint32(); }
-
-template <typename T> struct FactoryBase { typedef v8::Local<T> return_t; };
-
-template <typename T> struct Factory;
-
-template <>
-struct Factory<v8::Array> : FactoryBase<v8::Array> {
-  static inline return_t New();
-  static inline return_t New(int length);
-};
-
-template <>
-struct Factory<v8::Boolean> : FactoryBase<v8::Boolean> {
-  static inline return_t New(bool value);
-};
-
-template <>
-struct Factory<v8::BooleanObject> : FactoryBase<v8::BooleanObject> {
-  static inline return_t New(bool value);
-};
-
-template <>
-struct Factory<v8::Context> : FactoryBase<v8::Context> {
-  static inline
-  return_t
-  New( v8::ExtensionConfiguration* extensions = NULL
-     , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-     , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>());
-};
-
-template <>
-struct Factory<v8::Date> : FactoryBase<v8::Date> {
-  static inline return_t New(double value);
-};
-
-template <>
-struct Factory<v8::External> : FactoryBase<v8::External> {
-  static inline return_t New(void *value);
-};
-
-template <>
-struct Factory<v8::Function> : FactoryBase<v8::Function> {
-  static inline
-  return_t
-  New( NanFunctionCallback callback
-     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>());
-};
-
-template <>
-struct Factory<v8::FunctionTemplate> : FactoryBase<v8::FunctionTemplate> {
-  static inline
-  return_t
-  New( NanFunctionCallback callback = NULL
-     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-     , v8::Handle<v8::Signature> signature = v8::Handle<v8::Signature>());
-};
-
-template <>
-struct Factory<v8::Number> : FactoryBase<v8::Number> {
-  static inline return_t New(double value);
-};
-
-template <>
-struct Factory<v8::NumberObject> : FactoryBase<v8::NumberObject> {
-  static inline return_t New(double value);
-};
-
-template <typename T>
-struct IntegerFactory : FactoryBase<T> {
-  typedef typename FactoryBase<T>::return_t return_t;
-  static inline return_t New(int32_t value);
-  static inline return_t New(uint32_t value);
-};
-
-template <>
-struct Factory<v8::Integer> : IntegerFactory<v8::Integer> {};
-
-template <>
-struct Factory<v8::Int32> : IntegerFactory<v8::Int32> {};
-
-template <>
-struct Factory<v8::Uint32> : FactoryBase<v8::Uint32> {
-  static inline return_t New(int32_t value);
-  static inline return_t New(uint32_t value);
-};
-
-template <>
-struct Factory<v8::Object> : FactoryBase<v8::Object> {
-  static inline return_t New();
-};
-
-template <>
-struct Factory<v8::ObjectTemplate> : FactoryBase<v8::ObjectTemplate> {
-  static inline return_t New();
-};
-
-template <>
-struct Factory<v8::RegExp> : FactoryBase<v8::RegExp> {
-  static inline return_t New(
-      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags);
-};
-
-template <>
-struct Factory<v8::Script> : FactoryBase<v8::Script> {
-  static inline return_t New( v8::Local<v8::String> source);
-  static inline return_t New( v8::Local<v8::String> source
-                            , v8::ScriptOrigin const& origin);
-};
-
-template <>
-struct Factory<v8::Signature> : FactoryBase<v8::Signature> {
-  typedef v8::Handle<v8::FunctionTemplate> FTH;
-  static inline
-  return_t
-  New( FTH receiver = FTH(), int argc = 0, FTH argv[] = NULL );
-};
-
-template <>
-struct Factory<v8::String> : FactoryBase<v8::String> {
-  static inline return_t New();
-  static inline return_t New(const char *value, int length = -1);
-  static inline return_t New(const uint16_t *value, int length = -1);
-  static inline return_t New(std::string const& value);
-
-  static inline return_t New(v8::String::ExternalStringResource * value);
-  static inline return_t New(NanExternalOneByteStringResource * value);
-
-  // TODO(agnat): Deprecate.
-  static inline return_t New(const uint8_t * value, int length = -1);
-};
-
-template <>
-struct Factory<v8::StringObject> : FactoryBase<v8::StringObject> {
-  static inline return_t New(v8::Handle<v8::String> value);
-};
-
-}  // end of namespace NanIntern
-
-#if (NODE_MODULE_VERSION >= 12)
-
-namespace NanIntern {
-
-template <>
-struct Factory<v8::UnboundScript> : FactoryBase<v8::UnboundScript> {
-  static inline return_t New( v8::Local<v8::String> source);
-  static inline return_t New( v8::Local<v8::String> source
-                            , v8::ScriptOrigin const& origin);
-};
-
-}  // end of namespace NanIntern
-
-# include "nan_implementation_12_inl.h"
-
-#else  // NODE_MODULE_VERSION >= 12
-
-# include "nan_implementation_pre_12_inl.h"
-
-#endif
-
-//=== API ======================================================================
-
-template <typename T>
-typename NanIntern::Factory<T>::return_t
-NanNew() {
-  return NanIntern::Factory<T>::New();
-}
-
-template <typename T, typename A0>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0) {
-  return NanIntern::Factory<T>::New(arg0);
-}
-
-template <typename T, typename A0, typename A1>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1) {
-  return NanIntern::Factory<T>::New(arg0, arg1);
-}
-
-template <typename T, typename A0, typename A1, typename A2>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1, A2 arg2) {
-  return NanIntern::Factory<T>::New(arg0, arg1, arg2);
-}
-
-template <typename T, typename A0, typename A1, typename A2, typename A3>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1, A2 arg2, A3 arg3) {
-  return NanIntern::Factory<T>::New(arg0, arg1, arg2, arg3);
-}
-
-// Note(agnat): When passing overloaded function pointers to template functions
-// as generic arguments the compiler needs help in picking the right overload.
-// These two functions handle NanNew<Function> and NanNew<FunctionTemplate> with
-// all argument variations.
-
-// v8::Function and v8::FunctionTemplate with one or two arguments
-template <typename T>
-typename NanIntern::Factory<T>::return_t
-NanNew( NanFunctionCallback callback
-      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()) {
-    return NanIntern::Factory<T>::New(callback, data);
-}
-
-// v8::Function and v8::FunctionTemplate with three arguments
-template <typename T, typename A2>
-typename NanIntern::Factory<T>::return_t
-NanNew( NanFunctionCallback callback
-      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-      , A2 a2 = A2()) {
-    return NanIntern::Factory<T>::New(callback, data, a2);
-}
-
-// Convenience
-
-template <typename T> inline v8::Local<T> NanNew(v8::Handle<T> h);
-template <typename T> inline v8::Local<T> NanNew(v8::Persistent<T> const& p);
-
-inline
-NanIntern::Factory<v8::Boolean>::return_t
-NanNew(bool value) {
-  return NanNew<v8::Boolean>(value);
-}
-
-inline
-NanIntern::Factory<v8::Int32>::return_t
-NanNew(int32_t value) {
-  return NanNew<v8::Int32>(value);
-}
-
-inline
-NanIntern::Factory<v8::Uint32>::return_t
-NanNew(uint32_t value) {
-  return NanNew<v8::Uint32>(value);
-}
-
-inline
-NanIntern::Factory<v8::Number>::return_t
-NanNew(double value) {
-  return NanNew<v8::Number>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(std::string const& value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const char * value, int length) {
-  return NanNew<v8::String>(value, length);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const char * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const uint8_t * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const uint16_t * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(v8::String::ExternalStringResource * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(NanExternalOneByteStringResource * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::RegExp>::return_t
-NanNew(v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
-  return NanNew<v8::RegExp>(pattern, flags);
-}
-
-#endif  // NAN_NEW_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_string_bytes.h b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_string_bytes.h
deleted file mode 100644
index 9deecfbb..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/nan_string_bytes.h
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-#ifndef NAN_STRING_BYTES_H_
-#define NAN_STRING_BYTES_H_
-
-// Decodes a v8::Handle<v8::String> or Buffer to a raw char*
-
-#include <node.h>
-#include <node_buffer.h>
-#include <assert.h>
-#include <string.h>  // memcpy
-#include <limits.h>
-
-namespace NanIntern {
-
-using v8::Local;
-using v8::Handle;
-using v8::Object;
-using v8::String;
-using v8::Value;
-
-
-//// Base 64 ////
-
-#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
-
-
-
-//// Nan::HEX ////
-
-static bool contains_non_ascii_slow(const char* buf, size_t len) {
-  for (size_t i = 0; i < len; ++i) {
-    if (buf[i] & 0x80) return true;
-  }
-  return false;
-}
-
-
-static bool contains_non_ascii(const char* src, size_t len) {
-  if (len < 16) {
-    return contains_non_ascii_slow(src, len);
-  }
-
-  const unsigned bytes_per_word = sizeof(void*);
-  const unsigned align_mask = bytes_per_word - 1;
-  const unsigned unaligned = reinterpret_cast<uintptr_t>(src) & align_mask;
-
-  if (unaligned > 0) {
-    const unsigned n = bytes_per_word - unaligned;
-    if (contains_non_ascii_slow(src, n)) return true;
-    src += n;
-    len -= n;
-  }
-
-
-#if defined(__x86_64__) || defined(_WIN64)
-  const uintptr_t mask = 0x8080808080808080ll;
-#else
-  const uintptr_t mask = 0x80808080l;
-#endif
-
-  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
-
-  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
-    if (srcw[i] & mask) return true;
-  }
-
-  const unsigned remainder = len & align_mask;
-  if (remainder > 0) {
-    const size_t offset = len - remainder;
-    if (contains_non_ascii_slow(src + offset, remainder)) return true;
-  }
-
-  return false;
-}
-
-
-static void force_ascii_slow(const char* src, char* dst, size_t len) {
-  for (size_t i = 0; i < len; ++i) {
-    dst[i] = src[i] & 0x7f;
-  }
-}
-
-
-static void force_ascii(const char* src, char* dst, size_t len) {
-  if (len < 16) {
-    force_ascii_slow(src, dst, len);
-    return;
-  }
-
-  const unsigned bytes_per_word = sizeof(void*);
-  const unsigned align_mask = bytes_per_word - 1;
-  const unsigned src_unalign = reinterpret_cast<uintptr_t>(src) & align_mask;
-  const unsigned dst_unalign = reinterpret_cast<uintptr_t>(dst) & align_mask;
-
-  if (src_unalign > 0) {
-    if (src_unalign == dst_unalign) {
-      const unsigned unalign = bytes_per_word - src_unalign;
-      force_ascii_slow(src, dst, unalign);
-      src += unalign;
-      dst += unalign;
-      len -= src_unalign;
-    } else {
-      force_ascii_slow(src, dst, len);
-      return;
-    }
-  }
-
-#if defined(__x86_64__) || defined(_WIN64)
-  const uintptr_t mask = ~0x8080808080808080ll;
-#else
-  const uintptr_t mask = ~0x80808080l;
-#endif
-
-  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
-  uintptr_t* dstw = reinterpret_cast<uintptr_t*>(dst);
-
-  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
-    dstw[i] = srcw[i] & mask;
-  }
-
-  const unsigned remainder = len & align_mask;
-  if (remainder > 0) {
-    const size_t offset = len - remainder;
-    force_ascii_slow(src + offset, dst + offset, remainder);
-  }
-}
-
-
-static size_t base64_encode(const char* src,
-                            size_t slen,
-                            char* dst,
-                            size_t dlen) {
-  // We know how much we'll write, just make sure that there's space.
-  assert(dlen >= base64_encoded_size(slen) &&
-      "not enough space provided for base64 encode");
-
-  dlen = base64_encoded_size(slen);
-
-  unsigned a;
-  unsigned b;
-  unsigned c;
-  unsigned i;
-  unsigned k;
-  unsigned n;
-
-  static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                              "abcdefghijklmnopqrstuvwxyz"
-                              "0123456789+/";
-
-  i = 0;
-  k = 0;
-  n = slen / 3 * 3;
-
-  while (i < n) {
-    a = src[i + 0] & 0xff;
-    b = src[i + 1] & 0xff;
-    c = src[i + 2] & 0xff;
-
-    dst[k + 0] = table[a >> 2];
-    dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
-    dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
-    dst[k + 3] = table[c & 0x3f];
-
-    i += 3;
-    k += 4;
-  }
-
-  if (n != slen) {
-    switch (slen - n) {
-      case 1:
-        a = src[i + 0] & 0xff;
-        dst[k + 0] = table[a >> 2];
-        dst[k + 1] = table[(a & 3) << 4];
-        dst[k + 2] = '=';
-        dst[k + 3] = '=';
-        break;
-
-      case 2:
-        a = src[i + 0] & 0xff;
-        b = src[i + 1] & 0xff;
-        dst[k + 0] = table[a >> 2];
-        dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
-        dst[k + 2] = table[(b & 0x0f) << 2];
-        dst[k + 3] = '=';
-        break;
-    }
-  }
-
-  return dlen;
-}
-
-
-static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) {
-  // We know how much we'll write, just make sure that there's space.
-  assert(dlen >= slen * 2 &&
-      "not enough space provided for hex encode");
-
-  dlen = slen * 2;
-  for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {
-    static const char hex[] = "0123456789abcdef";
-    uint8_t val = static_cast<uint8_t>(src[i]);
-    dst[k + 0] = hex[val >> 4];
-    dst[k + 1] = hex[val & 15];
-  }
-
-  return dlen;
-}
-
-
-
-static Local<Value> Encode(const char* buf,
-                           size_t buflen,
-                           enum Nan::Encoding encoding) {
-  assert(buflen <= node::Buffer::kMaxLength);
-  if (!buflen && encoding != Nan::BUFFER)
-    return NanNew("");
-
-  Local<String> val;
-  switch (encoding) {
-    case Nan::BUFFER:
-      return NanNewBufferHandle(buf, buflen);
-
-    case Nan::ASCII:
-      if (contains_non_ascii(buf, buflen)) {
-        char* out = new char[buflen];
-        force_ascii(buf, out, buflen);
-        val = NanNew<String>(out, buflen);
-        delete[] out;
-      } else {
-        val = NanNew<String>(buf, buflen);
-      }
-      break;
-
-    case Nan::UTF8:
-      val = NanNew<String>(buf, buflen);
-      break;
-
-    case Nan::BINARY: {
-      // TODO(isaacs) use ExternalTwoByteString?
-      const unsigned char *cbuf = reinterpret_cast<const unsigned char*>(buf);
-      uint16_t * twobytebuf = new uint16_t[buflen];
-      for (size_t i = 0; i < buflen; i++) {
-        // XXX is the following line platform independent?
-        twobytebuf[i] = cbuf[i];
-      }
-      val = NanNew<String>(twobytebuf, buflen);
-      delete[] twobytebuf;
-      break;
-    }
-
-    case Nan::BASE64: {
-      size_t dlen = base64_encoded_size(buflen);
-      char* dst = new char[dlen];
-
-      size_t written = base64_encode(buf, buflen, dst, dlen);
-      assert(written == dlen);
-
-      val = NanNew<String>(dst, dlen);
-      delete[] dst;
-      break;
-    }
-
-    case Nan::UCS2: {
-      const uint16_t* data = reinterpret_cast<const uint16_t*>(buf);
-      val = NanNew<String>(data, buflen / 2);
-      break;
-    }
-
-    case Nan::HEX: {
-      size_t dlen = buflen * 2;
-      char* dst = new char[dlen];
-      size_t written = hex_encode(buf, buflen, dst, dlen);
-      assert(written == dlen);
-
-      val = NanNew<String>(dst, dlen);
-      delete[] dst;
-      break;
-    }
-
-    default:
-      assert(0 && "unknown encoding");
-      break;
-  }
-
-  return val;
-}
-
-#undef base64_encoded_size
-
-}  // namespace NanIntern
-
-#endif  // NAN_STRING_BYTES_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/package.json b/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/package.json
deleted file mode 100644
index ba489436..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/node_modules/nan/package.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
-  "name": "nan",
-  "version": "1.6.2",
-  "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility",
-  "main": "include_dirs.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/rvagg/nan.git"
-  },
-  "scripts": {
-    "test": "tap --gc test/js/*-test.js",
-    "rebuild-tests": "pangyp rebuild --directory test"
-  },
-  "contributors": [
-    {
-      "name": "Rod Vagg",
-      "email": "r@va.gg",
-      "url": "https://github.com/rvagg"
-    },
-    {
-      "name": "Benjamin Byholm",
-      "email": "bbyholm@abo.fi",
-      "url": "https://github.com/kkoopa/"
-    },
-    {
-      "name": "Trevor Norris",
-      "email": "trev.norris@gmail.com",
-      "url": "https://github.com/trevnorris"
-    },
-    {
-      "name": "Nathan Rajlich",
-      "email": "nathan@tootallnate.net",
-      "url": "https://github.com/TooTallNate"
-    },
-    {
-      "name": "Brett Lawson",
-      "email": "brett19@gmail.com",
-      "url": "https://github.com/brett19"
-    },
-    {
-      "name": "Ben Noordhuis",
-      "email": "info@bnoordhuis.nl",
-      "url": "https://github.com/bnoordhuis"
-    },
-    {
-      "name": "David Siegel",
-      "email": "david@artcom.de",
-      "url": "https://github.com/agnat"
-    }
-  ],
-  "devDependencies": {
-    "bindings": "~1.2.1",
-    "node-gyp": "~1.0.2",
-    "pangyp": "~2.0.1",
-    "tap": "~0.5.0",
-    "xtend": "~4.0.0"
-  },
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/rvagg/nan/issues"
-  },
-  "readme": "ERROR: No README data found!",
-  "_id": "nan@1.6.2",
-  "_from": "nan@1.6.x"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/package.json b/input_devices/mag/node_modules/ws/node_modules/bufferutil/package.json
deleted file mode 100644
index 8de1a020..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "bufferutil",
-  "version": "1.0.1",
-  "description": "WebSocket buffer utils",
-  "main": "index.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1",
-    "install": "node-gyp rebuild"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/websockets/bufferutil"
-  },
-  "keywords": [
-    "bufferutil"
-  ],
-  "author": {
-    "name": "Einar Otto Stangvik",
-    "email": "einaros@gmail.com",
-    "url": "http://2x.io"
-  },
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/websockets/bufferutil/issues"
-  },
-  "homepage": "https://github.com/websockets/bufferutil",
-  "dependencies": {
-    "bindings": "1.2.x",
-    "nan": "1.6.x"
-  },
-  "gypfile": true,
-  "readme": "ERROR: No README data found!",
-  "_id": "bufferutil@1.0.1",
-  "_from": "bufferutil@1.0.x"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/bufferutil/src/bufferutil.cc b/input_devices/mag/node_modules/ws/node_modules/bufferutil/src/bufferutil.cc
deleted file mode 100644
index bd6f368f..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/bufferutil/src/bufferutil.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*!
- * bufferutil: WebSocket buffer utils
- * Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-#include <v8.h>
-#include <node.h>
-#include <node_version.h>
-#include <node_buffer.h>
-#include <node_object_wrap.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-#include <stdio.h>
-#include "nan.h"
-
-using namespace v8;
-using namespace node;
-
-class BufferUtil : public ObjectWrap
-{
-public:
-
-  static void Initialize(v8::Handle<v8::Object> target)
-  {
-    NanScope();
-    Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
-    t->InstanceTemplate()->SetInternalFieldCount(1);
-    NODE_SET_METHOD(t, "unmask", BufferUtil::Unmask);
-    NODE_SET_METHOD(t, "mask", BufferUtil::Mask);
-    NODE_SET_METHOD(t, "merge", BufferUtil::Merge);
-    target->Set(NanNew<String>("BufferUtil"), t->GetFunction());
-  }
-
-protected:
-
-  static NAN_METHOD(New)
-  {
-    NanScope();
-    BufferUtil* bufferUtil = new BufferUtil();
-    bufferUtil->Wrap(args.This());
-    NanReturnValue(args.This());
-  }
-
-  static NAN_METHOD(Merge)
-  {
-    NanScope();
-    Local<Object> bufferObj = args[0]->ToObject();
-    char* buffer = Buffer::Data(bufferObj);
-    Local<Array> array = Local<Array>::Cast(args[1]);
-    unsigned int arrayLength = array->Length();
-    size_t offset = 0;
-    unsigned int i;
-    for (i = 0; i < arrayLength; ++i) {
-      Local<Object> src = array->Get(i)->ToObject();
-      size_t length = Buffer::Length(src);
-      memcpy(buffer + offset, Buffer::Data(src), length);
-      offset += length;
-    }
-    NanReturnValue(NanTrue());
-  }
-
-  static NAN_METHOD(Unmask)
-  {
-    NanScope();
-    Local<Object> buffer_obj = args[0]->ToObject();
-    size_t length = Buffer::Length(buffer_obj);
-    Local<Object> mask_obj = args[1]->ToObject();
-    unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj);
-    unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj);
-    size_t len32 = length / 4;
-    unsigned int i;
-    for (i = 0; i < len32; ++i) *(from + i) ^= *mask;
-    from += i;
-    switch (length % 4) {
-      case 3: *((unsigned char*)from+2) = *((unsigned char*)from+2) ^ ((unsigned char*)mask)[2];
-      case 2: *((unsigned char*)from+1) = *((unsigned char*)from+1) ^ ((unsigned char*)mask)[1];
-      case 1: *((unsigned char*)from  ) = *((unsigned char*)from  ) ^ ((unsigned char*)mask)[0];
-      case 0:;
-    }
-    NanReturnValue(NanTrue());
-  }
-
-  static NAN_METHOD(Mask)
-  {
-    NanScope();
-    Local<Object> buffer_obj = args[0]->ToObject();
-    Local<Object> mask_obj = args[1]->ToObject();
-    unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj);
-    Local<Object> output_obj = args[2]->ToObject();
-    unsigned int dataOffset = args[3]->Int32Value();
-    unsigned int length = args[4]->Int32Value();
-    unsigned int* to = (unsigned int*)(Buffer::Data(output_obj) + dataOffset);
-    unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj);
-    unsigned int len32 = length / 4;
-    unsigned int i;
-    for (i = 0; i < len32; ++i) *(to + i) = *(from + i) ^ *mask;
-    to += i;
-    from += i;
-    switch (length % 4) {
-      case 3: *((unsigned char*)to+2) = *((unsigned char*)from+2) ^ *((unsigned char*)mask+2);
-      case 2: *((unsigned char*)to+1) = *((unsigned char*)from+1) ^ *((unsigned char*)mask+1);
-      case 1: *((unsigned char*)to  ) = *((unsigned char*)from  ) ^ *((unsigned char*)mask);
-      case 0:;
-    }
-    NanReturnValue(NanTrue());
-  }
-};
-
-#if !NODE_VERSION_AT_LEAST(0,10,0)
-extern "C"
-#endif
-void init (Handle<Object> target)
-{
-  NanScope();
-  BufferUtil::Initialize(target);
-}
-
-NODE_MODULE(bufferutil, init)
-
diff --git a/input_devices/mag/node_modules/ws/node_modules/options/.npmignore b/input_devices/mag/node_modules/ws/node_modules/options/.npmignore
deleted file mode 100644
index 1b18fb39..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/options/.npmignore
+++ /dev/null
@@ -1,7 +0,0 @@
-npm-debug.log
-node_modules
-.*.swp
-.lock-*
-build/
-
-test
diff --git a/input_devices/mag/node_modules/ws/node_modules/options/Makefile b/input_devices/mag/node_modules/ws/node_modules/options/Makefile
deleted file mode 100644
index 7496b6fc..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/options/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-ALL_TESTS = $(shell find test/ -name '*.test.js')
-
-run-tests:
-	@./node_modules/.bin/mocha \
-		-t 2000 \
-		$(TESTFLAGS) \
-		$(TESTS)
-
-test:
-	@$(MAKE) NODE_PATH=lib TESTS="$(ALL_TESTS)" run-tests
-
-.PHONY: test
diff --git a/input_devices/mag/node_modules/ws/node_modules/options/README.md b/input_devices/mag/node_modules/ws/node_modules/options/README.md
deleted file mode 100644
index 0dabc755..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/options/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# options.js #
-
-A very light-weight in-code option parsers for node.js.
-
-## Usage ##
-
-``` js
-var Options = require("options");
-
-// Create an Options object
-function foo(options) {
-        var default_options = {
-                foo : "bar"
-        };
-        
-        // Create an option object with default value
-        var opts = new Options(default_options);
-        
-        // Merge options
-        opts = opts.merge(options);
-        
-        // Reset to default value
-        opts.reset();
-        
-        // Copy selected attributes out
-        var seled_att = opts.copy("foo");
-        
-        // Read json options from a file. 
-        opts.read("options.file"); // Sync
-        opts.read("options.file", function(err){ // Async
-                if(err){ // If error occurs
-                        console.log("File error.");
-                }else{
-                        // No error
-                }
-        });
-        
-        // Attributes defined or not
-        opts.isDefinedAndNonNull("foobar");
-        opts.isDefined("foobar");
-}
-
-```
-
-
-## License ##
-
-(The MIT License)
-
-Copyright (c) 2012 Einar Otto Stangvik &lt;einaros@gmail.com&gt;
-
-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/input_devices/mag/node_modules/ws/node_modules/options/lib/options.js b/input_devices/mag/node_modules/ws/node_modules/options/lib/options.js
deleted file mode 100644
index 4fc45e90..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/options/lib/options.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/*!
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-var fs = require('fs');
-
-function Options(defaults) {
-  var internalValues = {};
-  var values = this.value = {};
-  Object.keys(defaults).forEach(function(key) {
-    internalValues[key] = defaults[key];
-    Object.defineProperty(values, key, {
-      get: function() { return internalValues[key]; },
-      configurable: false,
-      enumerable: true
-    });
-  });
-  this.reset = function() {
-    Object.keys(defaults).forEach(function(key) {
-      internalValues[key] = defaults[key];
-    });
-    return this;
-  };
-  this.merge = function(options, required) {
-    options = options || {};
-    if (Object.prototype.toString.call(required) === '[object Array]') {
-      var missing = [];
-      for (var i = 0, l = required.length; i < l; ++i) {
-        var key = required[i];
-        if (!(key in options)) {
-          missing.push(key);
-        }
-      }
-      if (missing.length > 0) {
-        if (missing.length > 1) {
-          throw new Error('options ' +
-            missing.slice(0, missing.length - 1).join(', ') + ' and ' +
-            missing[missing.length - 1] + ' must be defined');
-        }
-        else throw new Error('option ' + missing[0] + ' must be defined');
-      }
-    }
-    Object.keys(options).forEach(function(key) {
-      if (key in internalValues) {
-        internalValues[key] = options[key];
-      }
-    });
-    return this;
-  };
-  this.copy = function(keys) {
-    var obj = {};
-    Object.keys(defaults).forEach(function(key) {
-      if (keys.indexOf(key) !== -1) {
-        obj[key] = values[key];
-      }
-    });
-    return obj;
-  };
-  this.read = function(filename, cb) {
-    if (typeof cb == 'function') {
-      var self = this;
-      fs.readFile(filename, function(error, data) {
-        if (error) return cb(error);
-        var conf = JSON.parse(data);
-        self.merge(conf);
-        cb();
-      });
-    }
-    else {
-      var conf = JSON.parse(fs.readFileSync(filename));
-      this.merge(conf);
-    }
-    return this;
-  };
-  this.isDefined = function(key) {
-    return typeof values[key] != 'undefined';
-  };
-  this.isDefinedAndNonNull = function(key) {
-    return typeof values[key] != 'undefined' && values[key] !== null;
-  };
-  Object.freeze(values);
-  Object.freeze(this);
-}
-
-module.exports = Options;
diff --git a/input_devices/mag/node_modules/ws/node_modules/options/package.json b/input_devices/mag/node_modules/ws/node_modules/options/package.json
deleted file mode 100644
index 376551d1..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/options/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "author": {
-    "name": "Einar Otto Stangvik",
-    "email": "einaros@gmail.com",
-    "url": "http://2x.io"
-  },
-  "name": "options",
-  "description": "A very light-weight in-code option parsers for node.js.",
-  "version": "0.0.6",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/einaros/options.js.git"
-  },
-  "main": "lib/options",
-  "scripts": {
-    "test": "make test"
-  },
-  "engines": {
-    "node": ">=0.4.0"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "mocha": "latest"
-  },
-  "readme": "# options.js #\n\nA very light-weight in-code option parsers for node.js.\n\n## Usage ##\n\n``` js\nvar Options = require(\"options\");\n\n// Create an Options object\nfunction foo(options) {\n        var default_options = {\n                foo : \"bar\"\n        };\n        \n        // Create an option object with default value\n        var opts = new Options(default_options);\n        \n        // Merge options\n        opts = opts.merge(options);\n        \n        // Reset to default value\n        opts.reset();\n        \n        // Copy selected attributes out\n        var seled_att = opts.copy(\"foo\");\n        \n        // Read json options from a file. \n        opts.read(\"options.file\"); // Sync\n        opts.read(\"options.file\", function(err){ // Async\n                if(err){ // If error occurs\n                        console.log(\"File error.\");\n                }else{\n                        // No error\n                }\n        });\n        \n        // Attributes defined or not\n        opts.isDefinedAndNonNull(\"foobar\");\n        opts.isDefined(\"foobar\");\n}\n\n```\n\n\n## License ##\n\n(The MIT License)\n\nCopyright (c) 2012 Einar Otto Stangvik &lt;einaros@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/einaros/options.js/issues"
-  },
-  "_id": "options@0.0.6",
-  "_from": "options@>=0.0.5"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/ultron/.npmignore b/input_devices/mag/node_modules/ws/node_modules/ultron/.npmignore
deleted file mode 100644
index 66210a2a..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/ultron/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules
-coverage
-.tern-port
diff --git a/input_devices/mag/node_modules/ws/node_modules/ultron/.travis.yml b/input_devices/mag/node_modules/ws/node_modules/ultron/.travis.yml
deleted file mode 100644
index a6e97419..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/ultron/.travis.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-language: node_js
-node_js:
-  - "0.8"
-  - "0.10"
-  - "0.11"
-before_install:
-  - "npm install -g npm@1.4.x"
-script:
-  - "npm run test-travis"
-after_script:
-  - "npm install coveralls@2.11.x && cat coverage/lcov.info | coveralls"
-notifications:
-  irc:
-    channels:
-      - "irc.freenode.org#unshift"
-    on_success: change
-    on_failure: change
diff --git a/input_devices/mag/node_modules/ws/node_modules/ultron/README.md b/input_devices/mag/node_modules/ws/node_modules/ultron/README.md
deleted file mode 100644
index 84fa3f23..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/ultron/README.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# Ultron
-
-[![Made by unshift](https://img.shields.io/badge/made%20by-unshift-00ffcc.svg?style=flat-square)](http://unshift.io)[![Version npm](http://img.shields.io/npm/v/ultron.svg?style=flat-square)](http://browsenpm.org/package/ultron)[![Build Status](http://img.shields.io/travis/unshiftio/ultron/master.svg?style=flat-square)](https://travis-ci.org/unshiftio/ultron)[![Dependencies](https://img.shields.io/david/unshiftio/ultron.svg?style=flat-square)](https://david-dm.org/unshiftio/ultron)[![Coverage Status](http://img.shields.io/coveralls/unshiftio/ultron/master.svg?style=flat-square)](https://coveralls.io/r/unshiftio/ultron?branch=master)[![IRC channel](http://img.shields.io/badge/IRC-irc.freenode.net%23unshift-00a8ff.svg?style=flat-square)](http://webchat.freenode.net/?channels=unshift)
-
-Ultron is a high-intelligence robot. It gathers intelligence so it can start
-improving upon his rudimentary design. It will learn your event emitting
-patterns and find ways to exterminate them. Allowing you to remove only the
-event emitters that **you** assigned and not the ones that your users or
-developers assigned. This can prevent race conditions, memory leaks and even file
-descriptor leaks from ever happening as you won't remove clean up processes.
-
-## Installation
-
-The module is designed to be used in browsers using browserify and in Node.js.
-You can install the module through the public npm registry by running the
-following command in CLI:
-
-```
-npm install --save ultron
-```
-
-## Usage
-
-In all examples we assume that you've required the library as following:
-
-```js
-'use strict';
-
-var Ultron = require('ultron');
-```
-
-Now that we've required the library we can construct our first `Ultron` instance.
-The constructor requires one argument which should be the `EventEmitter`
-instance that we need to operate upon. This can be the `EventEmitter` module
-that ships with Node.js or `EventEmitter3` or anything else as long as it
-follow the same API and internal structure as these 2. So with that in mind we
-can create the instance:
-
-```js
-//
-// For the sake of this example we're going to construct an empty EventEmitter
-//
-var EventEmitter = require('events').EventEmitter; // or require('eventmitter3');
-var events = new EventEmitter();
-
-var ultron = new Ultron(events);
-```
-
-You can now use the following API's from the Ultron instance:
-
-### Ultron.on
-
-Register a new event listener for the given event. It follows the exact same API
-as `EventEmitter.on` but it will return itself instead of returning the
-EventEmitter instance. If you are using EventEmitter3 it also supports the
-context param:
-
-```js
-ultron.on('event-name', handler, { custom: 'function context' });
-```
-
-### Ultron.once
-
-Exactly the same as the [Ultron.on](#ultronon) but it only allows the execution
-once.
-
-### Ultron.remove
-
-This is where all the magic happens and the safe removal starts. This function
-accepts different argument styles:
-
-- No arguments, assume that all events need to be removed so it will work as
-  `removeAllListeners()` API.
-- 1 argument, when it's a string it will be split on ` ` and `,` to create a
-  list of events that need to be cleared.
-- Multiple arguments, we assume that they are all names of events that need to
-  be cleared.
-
-```js
-ultron.remove('foo, bar baz');        // Removes foo, bar and baz.
-ultron.remove('foo', 'bar', 'baz');   // Removes foo, bar and baz.
-ultron.remove();                      // Removes everything.
-```
-
-If you just want to remove a single event listener using a function reference
-you can still use the EventEmitter's `removeListener(event, fn)` API:
-
-```js
-function foo() {}
-
-ulton.on('foo', foo);
-events.removeListener('foo', foo);
-```
-
-## License
-
-MIT
diff --git a/input_devices/mag/node_modules/ws/node_modules/ultron/index.js b/input_devices/mag/node_modules/ws/node_modules/ultron/index.js
deleted file mode 100644
index f0e8113e..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/ultron/index.js
+++ /dev/null
@@ -1,125 +0,0 @@
-'use strict';
-
-/**
- * An auto incrementing id which we can use to create "unique" Ultron instances
- * so we can track the event emitters that are added through the Ultron
- * interface.
- *
- * @type {Number}
- * @private
- */
-var id = 0;
-
-/**
- * Ultron is high-intelligence robot. It gathers intelligence so it can start improving
- * upon his rudimentary design. It will learn from your EventEmitting patterns
- * and exterminate them.
- *
- * @constructor
- * @param {EventEmitter} ee EventEmitter instance we need to wrap.
- * @api public
- */
-function Ultron(ee) {
-  if (!(this instanceof Ultron)) return new Ultron(ee);
-
-  this.id = id++;
-  this.ee = ee;
-}
-
-/**
- * Register a new EventListener for the given event.
- *
- * @param {String} event Name of the event.
- * @param {Functon} fn Callback function.
- * @param {Mixed} context The context of the function.
- * @returns {Ultron}
- * @api public
- */
-Ultron.prototype.on = function on(event, fn, context) {
-  fn.__ultron = this.id;
-  this.ee.on(event, fn, context);
-
-  return this;
-};
-/**
- * Add an EventListener that's only called once.
- *
- * @param {String} event Name of the event.
- * @param {Function} fn Callback function.
- * @param {Mixed} context The context of the function.
- * @returns {Ultron}
- * @api public
- */
-Ultron.prototype.once = function once(event, fn, context) {
-  fn.__ultron = this.id;
-  this.ee.once(event, fn, context);
-
-  return this;
-};
-
-/**
- * Remove the listeners we assigned for the given event.
- *
- * @returns {Ultron}
- * @api public
- */
-Ultron.prototype.remove = function remove() {
-  var args = arguments
-    , event;
-
-  //
-  // When no event names are provided we assume that we need to clear all the
-  // events that were assigned through us.
-  //
-  if (args.length === 1 && 'string' === typeof args[0]) {
-    args = args[0].split(/[, ]+/);
-  } else if (!args.length) {
-    args = [];
-
-    for (event in this.ee._events) {
-      if (this.ee._events.hasOwnProperty(event)) {
-        args.push(event);
-      }
-    }
-  }
-
-  for (var i = 0; i < args.length; i++) {
-    var listeners = this.ee.listeners(args[i]);
-
-    for (var j = 0; j < listeners.length; j++) {
-      event = listeners[j];
-
-      if (event.listener) {
-        if (event.listener.__ultron !== this.id) continue;
-        delete event.listener.__ultron;
-      } else {
-        if (event.__ultron !== this.id) continue;
-        delete event.__ultron;
-      }
-
-      this.ee.removeListener(args[i], event);
-    }
-  }
-
-  return this;
-};
-
-/**
- * Destroy the Ultron instance, remove all listeners and release all references.
- *
- * @returns {Boolean}
- * @api public
- */
-Ultron.prototype.destroy = function destroy() {
-  if (!this.ee) return false;
-
-  this.remove();
-  this.ee = null;
-
-  return true;
-};
-
-//
-// Expose the module.
-//
-module.exports = Ultron;
diff --git a/input_devices/mag/node_modules/ws/node_modules/ultron/package.json b/input_devices/mag/node_modules/ws/node_modules/ultron/package.json
deleted file mode 100644
index 48362377..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/ultron/package.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "name": "ultron",
-  "version": "1.0.1",
-  "description": "Ultron is high-intelligence robot. It gathers intel so it can start improving upon his rudimentary design",
-  "main": "index.js",
-  "scripts": {
-    "test": "mocha --reporter spec --ui bdd test.js",
-    "watch": "mocha --watch --reporter spec --ui bdd test.js",
-    "coverage": "istanbul cover ./node_modules/.bin/_mocha -- --reporter spec --ui bdd test.js",
-    "test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- --reporter spec --ui bdd test.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/unshiftio/ultron"
-  },
-  "keywords": [
-    "Ultron",
-    "robot",
-    "gather",
-    "intelligence",
-    "event",
-    "events",
-    "eventemitter",
-    "emitter",
-    "cleanup"
-  ],
-  "author": {
-    "name": "Arnout Kazemier"
-  },
-  "license": "MIT",
-  "devDependencies": {
-    "assume": "0.0.x",
-    "eventemitter3": "0.1.x",
-    "istanbul": "0.3.x",
-    "mocha": "2.0.x",
-    "pre-commit": "0.0.x"
-  },
-  "bugs": {
-    "url": "https://github.com/unshiftio/ultron/issues"
-  },
-  "homepage": "https://github.com/unshiftio/ultron",
-  "readme": "# Ultron\n\n[![Made by unshift](https://img.shields.io/badge/made%20by-unshift-00ffcc.svg?style=flat-square)](http://unshift.io)[![Version npm](http://img.shields.io/npm/v/ultron.svg?style=flat-square)](http://browsenpm.org/package/ultron)[![Build Status](http://img.shields.io/travis/unshiftio/ultron/master.svg?style=flat-square)](https://travis-ci.org/unshiftio/ultron)[![Dependencies](https://img.shields.io/david/unshiftio/ultron.svg?style=flat-square)](https://david-dm.org/unshiftio/ultron)[![Coverage Status](http://img.shields.io/coveralls/unshiftio/ultron/master.svg?style=flat-square)](https://coveralls.io/r/unshiftio/ultron?branch=master)[![IRC channel](http://img.shields.io/badge/IRC-irc.freenode.net%23unshift-00a8ff.svg?style=flat-square)](http://webchat.freenode.net/?channels=unshift)\n\nUltron is a high-intelligence robot. It gathers intelligence so it can start\nimproving upon his rudimentary design. It will learn your event emitting\npatterns and find ways to exterminate them. Allowing you to remove only the\nevent emitters that **you** assigned and not the ones that your users or\ndevelopers assigned. This can prevent race conditions, memory leaks and even file\ndescriptor leaks from ever happening as you won't remove clean up processes.\n\n## Installation\n\nThe module is designed to be used in browsers using browserify and in Node.js.\nYou can install the module through the public npm registry by running the\nfollowing command in CLI:\n\n```\nnpm install --save ultron\n```\n\n## Usage\n\nIn all examples we assume that you've required the library as following:\n\n```js\n'use strict';\n\nvar Ultron = require('ultron');\n```\n\nNow that we've required the library we can construct our first `Ultron` instance.\nThe constructor requires one argument which should be the `EventEmitter`\ninstance that we need to operate upon. This can be the `EventEmitter` module\nthat ships with Node.js or `EventEmitter3` or anything else as long as it\nfollow the same API and internal structure as these 2. So with that in mind we\ncan create the instance:\n\n```js\n//\n// For the sake of this example we're going to construct an empty EventEmitter\n//\nvar EventEmitter = require('events').EventEmitter; // or require('eventmitter3');\nvar events = new EventEmitter();\n\nvar ultron = new Ultron(events);\n```\n\nYou can now use the following API's from the Ultron instance:\n\n### Ultron.on\n\nRegister a new event listener for the given event. It follows the exact same API\nas `EventEmitter.on` but it will return itself instead of returning the\nEventEmitter instance. If you are using EventEmitter3 it also supports the\ncontext param:\n\n```js\nultron.on('event-name', handler, { custom: 'function context' });\n```\n\n### Ultron.once\n\nExactly the same as the [Ultron.on](#ultronon) but it only allows the execution\nonce.\n\n### Ultron.remove\n\nThis is where all the magic happens and the safe removal starts. This function\naccepts different argument styles:\n\n- No arguments, assume that all events need to be removed so it will work as\n  `removeAllListeners()` API.\n- 1 argument, when it's a string it will be split on ` ` and `,` to create a\n  list of events that need to be cleared.\n- Multiple arguments, we assume that they are all names of events that need to\n  be cleared.\n\n```js\nultron.remove('foo, bar baz');        // Removes foo, bar and baz.\nultron.remove('foo', 'bar', 'baz');   // Removes foo, bar and baz.\nultron.remove();                      // Removes everything.\n```\n\nIf you just want to remove a single event listener using a function reference\nyou can still use the EventEmitter's `removeListener(event, fn)` API:\n\n```js\nfunction foo() {}\n\nulton.on('foo', foo);\nevents.removeListener('foo', foo);\n```\n\n## License\n\nMIT\n",
-  "readmeFilename": "README.md",
-  "_id": "ultron@1.0.1",
-  "_from": "ultron@1.0.x"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/ultron/test.js b/input_devices/mag/node_modules/ws/node_modules/ultron/test.js
deleted file mode 100644
index 1fd4f1bb..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/ultron/test.js
+++ /dev/null
@@ -1,327 +0,0 @@
-/* istanbul ignore next */
-describe('Ultron', function () {
-  'use strict';
-
-  var EventEmitter = require('eventemitter3')
-    , EE = require('events').EventEmitter
-    , assume = require('assume')
-    , Ultron = require('./')
-    , ultron
-    , ee;
-
-  beforeEach(function () {
-    ee = new EventEmitter();
-    ultron = new Ultron(ee);
-  });
-
-  afterEach(function () {
-    ultron.destroy();
-    ee.removeAllListeners();
-  });
-
-  it('is exposed as a function', function () {
-    assume(Ultron).is.a('function');
-  });
-
-  it('can be initialized without the new keyword', function () {
-    assume(Ultron(ee)).is.instanceOf(Ultron);
-  });
-
-  it('assigns a unique id to every instance', function () {
-    for (var i = 0; i < 100; i++) {
-      assume(ultron.id).does.not.equal((new Ultron()).id);
-    }
-  });
-
-  it('allows removal through the event emitter', function () {
-    function foo() {}
-    function bar() {}
-
-    ultron.on('foo', foo);
-    ultron.once('foo', bar);
-
-    assume(foo.__ultron).equals(ultron.id);
-    assume(bar.__ultron).equals(ultron.id);
-    assume(ee.listeners('foo').length).equals(2);
-
-    ee.removeListener('foo', foo);
-    assume(ee.listeners('foo').length).equals(1);
-
-    ee.removeListener('foo', bar);
-    assume(ee.listeners('foo').length).equals(0);
-  });
-
-  describe('#on', function () {
-    it('assigns a listener', function () {
-      assume(ee.listeners('foo').length).equals(0);
-
-      function foo() {}
-
-      ultron.on('foo', foo);
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('foo')[0]).equals(foo);
-    });
-
-    it('tags the assigned function', function () {
-      assume(ee.listeners('foo').length).equals(0);
-
-      ultron.on('foo', function () {});
-      assume(ee.listeners('foo')[0].__ultron).equals(ultron.id);
-    });
-
-    it('also passes in the context', function (next) {
-      var context = 1313;
-
-      ultron.on('foo', function (a, b, c) {
-        assume(a).equals('a');
-        assume(b).equals('b');
-        assume(c).equals('c');
-
-        assume(this).equals(context);
-
-        next();
-      }, context);
-
-      ee.emit('foo', 'a', 'b', 'c');
-    });
-
-    it('works with regular eventemitters as well', function (next) {
-      var ee = new EE()
-        , ultron = new Ultron(ee);
-
-      ultron.on('foo', function (a, b, c) {
-        assume(a).equals('a');
-        assume(b).equals('b');
-        assume(c).equals('c');
-
-        next();
-      });
-
-      ee.emit('foo', 'a', 'b', 'c');
-    });
-  });
-
-  describe('#once', function () {
-    it('assigns a listener', function () {
-      assume(ee.listeners('foo').length).equals(0);
-
-      function foo() {}
-      ultron.once('foo', foo);
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('foo')[0]).equals(foo);
-    });
-
-    it('tags the assigned function', function () {
-      assume(ee.listeners('foo').length).equals(0);
-
-      ultron.once('foo', function () {});
-      assume(ee.listeners('foo')[0].__ultron).equals(ultron.id);
-    });
-
-    it('also passes in the context', function (next) {
-      var context = 1313;
-
-      ultron.once('foo', function (a, b, c) {
-        assume(a).equals('a');
-        assume(b).equals('b');
-        assume(c).equals('c');
-
-        assume(this).equals(context);
-
-        next();
-      }, context);
-
-      ee.emit('foo', 'a', 'b', 'c');
-      ee.emit('foo', 'a', 'b', 'c'); // Ensure that we don't double execute
-    });
-
-    it('works with regular eventemitters as well', function (next) {
-      var ee = new EE()
-        , ultron = new Ultron(ee);
-
-      ultron.once('foo', function (a, b, c) {
-        assume(a).equals('a');
-        assume(b).equals('b');
-        assume(c).equals('c');
-
-        next();
-      });
-
-      ee.emit('foo', 'a', 'b', 'c');
-      ee.emit('foo', 'a', 'b', 'c'); // Ensure that we don't double execute
-    });
-  });
-
-  describe('#remove', function () {
-    it('removes only our assigned `on` listeners', function () {
-      function foo() {}
-      function bar() {}
-
-      ee.on('foo', foo);
-      ultron.on('foo', bar);
-      assume(ee.listeners('foo').length).equals(2);
-
-      ultron.remove('foo');
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('foo')[0]).equals(foo);
-    });
-
-    it('removes our private __ultron references', function () {
-      function once() {}
-      function on() {}
-
-      assume('__ultron' in once).is.false();
-      assume('__ultron' in on).is.false();
-
-      ultron.on('foo', on);
-      ultron.once('bar', once);
-
-      assume('__ultron' in once).is.true();
-      assume('__ultron' in on).is.true();
-
-      ultron.remove('foo, bar');
-
-      assume('__ultron' in once).is.false();
-      assume('__ultron' in on).is.false();
-
-      ultron.destroy();
-
-      ee = new EE();
-      ultron = new Ultron(ee);
-
-      assume('__ultron' in once).is.false();
-      assume('__ultron' in on).is.false();
-
-      ultron.on('foo', on);
-      ultron.once('bar', once);
-
-      assume('__ultron' in once).is.true();
-      assume('__ultron' in on).is.true();
-
-      ultron.remove('foo, bar');
-
-      assume('__ultron' in once).is.false();
-      assume('__ultron' in on).is.false();
-    });
-
-    it('removes only our assigned `once` listeners', function () {
-      function foo() {}
-      function bar() {}
-
-      ee.once('foo', foo);
-      ultron.once('foo', bar);
-      assume(ee.listeners('foo').length).equals(2);
-
-      ultron.remove('foo');
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('foo')[0]).equals(foo);
-    });
-
-    it('removes only our assigned `once` listeners from regular EE', function () {
-      var ee = new EE()
-        , ultron = new Ultron(ee);
-
-      function foo() {}
-      function bar() {}
-
-      ee.once('foo', foo);
-      ultron.once('foo', bar);
-      assume(ee.listeners('foo').length).equals(2);
-
-      ultron.remove('foo');
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('foo')[0].listener).equals(foo);
-    });
-
-    it('removes all assigned events if called without args', function () {
-      function foo() {}
-      function bar() {}
-
-      ultron.on('foo', foo);
-      ultron.on('bar', bar);
-
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('bar').length).equals(1);
-
-      ultron.remove();
-
-      assume(ee.listeners('foo').length).equals(0);
-      assume(ee.listeners('bar').length).equals(0);
-    });
-
-    it('removes multiple listeners based on args', function () {
-      function foo() {}
-      function bar() {}
-      function baz() {}
-
-      ultron.on('foo', foo);
-      ultron.on('bar', bar);
-      ultron.on('baz', baz);
-
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('bar').length).equals(1);
-      assume(ee.listeners('baz').length).equals(1);
-
-      ultron.remove('foo', 'bar');
-
-      assume(ee.listeners('foo').length).equals(0);
-      assume(ee.listeners('bar').length).equals(0);
-      assume(ee.listeners('baz').length).equals(1);
-    });
-
-    it('removes multiple listeners if first arg is seperated string', function () {
-      function foo() {}
-      function bar() {}
-      function baz() {}
-
-      ultron.on('foo', foo);
-      ultron.on('bar', bar);
-      ultron.on('baz', baz);
-
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('bar').length).equals(1);
-      assume(ee.listeners('baz').length).equals(1);
-
-      ultron.remove('foo, bar');
-
-      assume(ee.listeners('foo').length).equals(0);
-      assume(ee.listeners('bar').length).equals(0);
-      assume(ee.listeners('baz').length).equals(1);
-    });
-  });
-
-  describe('#destroy', function () {
-    it('removes all listeners', function () {
-      function foo() {}
-      function bar() {}
-      function baz() {}
-
-      ultron.on('foo', foo);
-      ultron.on('bar', bar);
-      ultron.on('baz', baz);
-
-      assume(ee.listeners('foo').length).equals(1);
-      assume(ee.listeners('bar').length).equals(1);
-      assume(ee.listeners('baz').length).equals(1);
-
-      ultron.destroy();
-
-      assume(ee.listeners('foo').length).equals(0);
-      assume(ee.listeners('bar').length).equals(0);
-      assume(ee.listeners('baz').length).equals(0);
-    });
-
-    it('removes the .ee reference', function () {
-      assume(ultron.ee).equals(ee);
-      ultron.destroy();
-      assume(ultron.ee).equals(null);
-    });
-
-    it('returns booleans for state indication', function () {
-      assume(ultron.destroy()).is.true();
-      assume(ultron.destroy()).is.false();
-      assume(ultron.destroy()).is.false();
-      assume(ultron.destroy()).is.false();
-    });
-  });
-});
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/.npmignore b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/.npmignore
deleted file mode 100644
index 0c90f673..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-npm-debug.log
-node_modules
-build
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/binding.gyp b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/binding.gyp
deleted file mode 100644
index 2c5c8827..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/binding.gyp
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  'targets': [
-    {
-      'target_name': 'validation',
-      'include_dirs': ["<!(node -e \"require('nan')\")"],
-      'cflags': [ '-O3' ],
-      'sources': [ 'src/validation.cc' ]
-    }
-  ]
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Makefile b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Makefile
deleted file mode 100644
index 9eb43cea..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Makefile
+++ /dev/null
@@ -1,332 +0,0 @@
-# We borrow heavily from the kernel build setup, though we are simpler since
-# we don't have Kconfig tweaking settings on us.
-
-# The implicit make rules have it looking for RCS files, among other things.
-# We instead explicitly write all the rules we care about.
-# It's even quicker (saves ~200ms) to pass -r on the command line.
-MAKEFLAGS=-r
-
-# The source directory tree.
-srcdir := ..
-abs_srcdir := $(abspath $(srcdir))
-
-# The name of the builddir.
-builddir_name ?= .
-
-# The V=1 flag on command line makes us verbosely print command lines.
-ifdef V
-  quiet=
-else
-  quiet=quiet_
-endif
-
-# Specify BUILDTYPE=Release on the command line for a release build.
-BUILDTYPE ?= Release
-
-# Directory all our build output goes into.
-# Note that this must be two directories beneath src/ for unit tests to pass,
-# as they reach into the src/ directory for data with relative paths.
-builddir ?= $(builddir_name)/$(BUILDTYPE)
-abs_builddir := $(abspath $(builddir))
-depsdir := $(builddir)/.deps
-
-# Object output directory.
-obj := $(builddir)/obj
-abs_obj := $(abspath $(obj))
-
-# We build up a list of every single one of the targets so we can slurp in the
-# generated dependency rule Makefiles in one pass.
-all_deps :=
-
-
-
-CC.target ?= $(CC)
-CFLAGS.target ?= $(CFLAGS)
-CXX.target ?= $(CXX)
-CXXFLAGS.target ?= $(CXXFLAGS) $(CPPFLAGS)
-LINK.target ?= $(LINK)
-LDFLAGS.target ?= $(LDFLAGS)
-AR.target ?= $(AR)
-
-# C++ apps need to be linked with g++.
-#
-# Note: flock is used to seralize linking. Linking is a memory-intensive
-# process so running parallel links can often lead to thrashing.  To disable
-# the serialization, override LINK via an envrionment variable as follows:
-#
-#   export LINK=g++
-#
-# This will allow make to invoke N linker processes as specified in -jN.
-LINK ?= flock $(builddir)/linker.lock $(CXX.target)
-
-# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
-# to replicate this environment fallback in make as well.
-CC.host ?= gcc
-CFLAGS.host ?=
-CXX.host ?= g++
-CXXFLAGS.host ?=
-LINK.host ?= $(CXX.host)
-LDFLAGS.host ?=
-AR.host ?= ar
-
-# Define a dir function that can handle spaces.
-# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
-# "leading spaces cannot appear in the text of the first argument as written.
-# These characters can be put into the argument value by variable substitution."
-empty :=
-space := $(empty) $(empty)
-
-# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
-replace_spaces = $(subst $(space),?,$1)
-unreplace_spaces = $(subst ?,$(space),$1)
-dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
-
-# Flags to make gcc output dependency info.  Note that you need to be
-# careful here to use the flags that ccache and distcc can understand.
-# We write to a dep file on the side first and then rename at the end
-# so we can't end up with a broken dep file.
-depfile = $(depsdir)/$(call replace_spaces,$@).d
-DEPFLAGS = -MMD -MF $(depfile).raw
-
-# We have to fixup the deps output in a few ways.
-# (1) the file output should mention the proper .o file.
-# ccache or distcc lose the path to the target, so we convert a rule of
-# the form:
-#   foobar.o: DEP1 DEP2
-# into
-#   path/to/foobar.o: DEP1 DEP2
-# (2) we want missing files not to cause us to fail to build.
-# We want to rewrite
-#   foobar.o: DEP1 DEP2 \
-#               DEP3
-# to
-#   DEP1:
-#   DEP2:
-#   DEP3:
-# so if the files are missing, they're just considered phony rules.
-# We have to do some pretty insane escaping to get those backslashes
-# and dollar signs past make, the shell, and sed at the same time.
-# Doesn't work with spaces, but that's fine: .d files have spaces in
-# their names replaced with other characters.
-define fixup_dep
-# The depfile may not exist if the input file didn't have any #includes.
-touch $(depfile).raw
-# Fixup path as in (1).
-sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
-# Add extra rules as in (2).
-# We remove slashes and replace spaces with new lines;
-# remove blank lines;
-# delete the first line and append a colon to the remaining lines.
-sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
-  grep -v '^$$'                             |\
-  sed -e 1d -e 's|$$|:|'                     \
-    >> $(depfile)
-rm $(depfile).raw
-endef
-
-# Command definitions:
-# - cmd_foo is the actual command to run;
-# - quiet_cmd_foo is the brief-output summary of the command.
-
-quiet_cmd_cc = CC($(TOOLSET)) $@
-cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_cxx = CXX($(TOOLSET)) $@
-cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-
-quiet_cmd_touch = TOUCH $@
-cmd_touch = touch $@
-
-quiet_cmd_copy = COPY $@
-# send stderr to /dev/null to ignore messages when linking directories.
-cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
-
-quiet_cmd_alink = AR($(TOOLSET)) $@
-cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
-
-quiet_cmd_alink_thin = AR($(TOOLSET)) $@
-cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
-
-# Due to circular dependencies between libraries :(, we wrap the
-# special "figure out circular dependencies" flags around the entire
-# input list during linking.
-quiet_cmd_link = LINK($(TOOLSET)) $@
-cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
-
-# We support two kinds of shared objects (.so):
-# 1) shared_library, which is just bundling together many dependent libraries
-# into a link line.
-# 2) loadable_module, which is generating a module intended for dlopen().
-#
-# They differ only slightly:
-# In the former case, we want to package all dependent code into the .so.
-# In the latter case, we want to package just the API exposed by the
-# outermost module.
-# This means shared_library uses --whole-archive, while loadable_module doesn't.
-# (Note that --whole-archive is incompatible with the --start-group used in
-# normal linking.)
-
-# Other shared-object link notes:
-# - Set SONAME to the library filename so our binaries don't reference
-# the local, absolute paths used on the link command-line.
-quiet_cmd_solink = SOLINK($(TOOLSET)) $@
-cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
-
-quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
-cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
-
-
-# Define an escape_quotes function to escape single quotes.
-# This allows us to handle quotes properly as long as we always use
-# use single quotes and escape_quotes.
-escape_quotes = $(subst ','\'',$(1))
-# This comment is here just to include a ' to unconfuse syntax highlighting.
-# Define an escape_vars function to escape '$' variable syntax.
-# This allows us to read/write command lines with shell variables (e.g.
-# $LD_LIBRARY_PATH), without triggering make substitution.
-escape_vars = $(subst $$,$$$$,$(1))
-# Helper that expands to a shell command to echo a string exactly as it is in
-# make. This uses printf instead of echo because printf's behaviour with respect
-# to escape sequences is more portable than echo's across different shells
-# (e.g., dash, bash).
-exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
-
-# Helper to compare the command we're about to run against the command
-# we logged the last time we ran the command.  Produces an empty
-# string (false) when the commands match.
-# Tricky point: Make has no string-equality test function.
-# The kernel uses the following, but it seems like it would have false
-# positives, where one string reordered its arguments.
-#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
-#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
-# We instead substitute each for the empty string into the other, and
-# say they're equal if both substitutions produce the empty string.
-# .d files contain ? instead of spaces, take that into account.
-command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
-                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
-
-# Helper that is non-empty when a prerequisite changes.
-# Normally make does this implicitly, but we force rules to always run
-# so we can check their command lines.
-#   $? -- new prerequisites
-#   $| -- order-only dependencies
-prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
-
-# Helper that executes all postbuilds until one fails.
-define do_postbuilds
-  @E=0;\
-  for p in $(POSTBUILDS); do\
-    eval $$p;\
-    E=$$?;\
-    if [ $$E -ne 0 ]; then\
-      break;\
-    fi;\
-  done;\
-  if [ $$E -ne 0 ]; then\
-    rm -rf "$@";\
-    exit $$E;\
-  fi
-endef
-
-# do_cmd: run a command via the above cmd_foo names, if necessary.
-# Should always run for a given target to handle command-line changes.
-# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
-# Third argument, if non-zero, makes it do POSTBUILDS processing.
-# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
-# spaces already and dirx strips the ? characters.
-define do_cmd
-$(if $(or $(command_changed),$(prereq_changed)),
-  @$(call exact_echo,  $($(quiet)cmd_$(1)))
-  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
-  $(if $(findstring flock,$(word 1,$(cmd_$1))),
-    @$(cmd_$(1))
-    @echo "  $(quiet_cmd_$(1)): Finished",
-    @$(cmd_$(1))
-  )
-  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
-  @$(if $(2),$(fixup_dep))
-  $(if $(and $(3), $(POSTBUILDS)),
-    $(call do_postbuilds)
-  )
-)
-endef
-
-# Declare the "all" target first so it is the default,
-# even though we don't have the deps yet.
-.PHONY: all
-all:
-
-# make looks for ways to re-generate included makefiles, but in our case, we
-# don't have a direct way. Explicitly telling make that it has nothing to do
-# for them makes it go faster.
-%.d: ;
-
-# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
-# do_cmd.
-.PHONY: FORCE_DO_CMD
-FORCE_DO_CMD:
-
-TOOLSET := target
-# Suffix rules, putting all outputs into $(obj).
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
-	@$(call do_cmd,cc,1)
-
-
-ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
-    $(findstring $(join ^,$(prefix)),\
-                 $(join ^,validation.target.mk)))),)
-  include validation.target.mk
-endif
-
-quiet_cmd_regen_makefile = ACTION Regenerating $@
-cmd_regen_makefile = cd $(srcdir); /usr/share/node-gyp/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -I/home/neilg/hg/academy.classes/Web/classes/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/config.gypi -I/usr/share/node-gyp/addon.gypi -I/usr/include/nodejs/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/usr/include/nodejs" "-Dmodule_root_dir=/home/neilg/hg/academy.classes/Web/classes/input_devices/mag/node_modules/ws/node_modules/utf-8-validate" binding.gyp
-Makefile: $(srcdir)/../../../../../../../../../../../../usr/share/node-gyp/addon.gypi $(srcdir)/../../../../../../../../../../../../usr/include/nodejs/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp
-	$(call do_cmd,regen_makefile)
-
-# "all" is a concatenation of the "all" targets from all the included
-# sub-makefiles. This is just here to clarify.
-all:
-
-# Add in dependency-tracking rules.  $(all_deps) is the list of every single
-# target in our tree. Only consider the ones with .d (dependency) info:
-d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
-ifneq ($(d_files),)
-  include $(d_files)
-endif
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation.node.d b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation.node.d
deleted file mode 100644
index f39b7c98..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation.node.d
+++ /dev/null
@@ -1 +0,0 @@
-cmd_Release/obj.target/validation.node := flock ./Release/linker.lock g++ -shared -pthread -rdynamic -m64  -Wl,-soname=validation.node -o Release/obj.target/validation.node -Wl,--start-group Release/obj.target/validation/src/validation.o -Wl,--end-group 
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation/src/validation.o.d b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation/src/validation.o.d
deleted file mode 100644
index db61fd3d..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/obj.target/validation/src/validation.o.d
+++ /dev/null
@@ -1,30 +0,0 @@
-cmd_Release/obj.target/validation/src/validation.o := g++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -I../node_modules/nan  -fPIC -Wall -Wextra -Wno-unused-parameter -pthread -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-omit-frame-pointer -fno-rtti -fno-exceptions -MMD -MF ./Release/.deps/Release/obj.target/validation/src/validation.o.d.raw   -c -o Release/obj.target/validation/src/validation.o ../src/validation.cc
-Release/obj.target/validation/src/validation.o: ../src/validation.cc \
- /usr/include/nodejs/deps/v8/include/v8.h \
- /usr/include/nodejs/deps/v8/include/v8stdint.h \
- /usr/include/nodejs/src/node.h /usr/include/nodejs/deps/uv/include/uv.h \
- /usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h \
- /usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h \
- /usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h \
- /usr/include/nodejs/src/node_object_wrap.h \
- /usr/include/nodejs/src/node.h /usr/include/nodejs/src/node_version.h \
- /usr/include/nodejs/src/node_buffer.h \
- /usr/include/nodejs/src/node_object_wrap.h ../node_modules/nan/nan.h \
- ../node_modules/nan/nan_new.h \
- ../node_modules/nan/nan_implementation_pre_12_inl.h
-../src/validation.cc:
-/usr/include/nodejs/deps/v8/include/v8.h:
-/usr/include/nodejs/deps/v8/include/v8stdint.h:
-/usr/include/nodejs/src/node.h:
-/usr/include/nodejs/deps/uv/include/uv.h:
-/usr/include/nodejs/deps/uv/include/uv-private/uv-unix.h:
-/usr/include/nodejs/deps/uv/include/uv-private/ngx-queue.h:
-/usr/include/nodejs/deps/uv/include/uv-private/uv-linux.h:
-/usr/include/nodejs/src/node_object_wrap.h:
-/usr/include/nodejs/src/node.h:
-/usr/include/nodejs/src/node_version.h:
-/usr/include/nodejs/src/node_buffer.h:
-/usr/include/nodejs/src/node_object_wrap.h:
-../node_modules/nan/nan.h:
-../node_modules/nan/nan_new.h:
-../node_modules/nan/nan_implementation_pre_12_inl.h:
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/validation.node.d b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/validation.node.d
deleted file mode 100644
index e0ff2cfd..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/.deps/Release/validation.node.d
+++ /dev/null
@@ -1 +0,0 @@
-cmd_Release/validation.node := ln -f "Release/obj.target/validation.node" "Release/validation.node" 2>/dev/null || (rm -rf "Release/validation.node" && cp -af "Release/obj.target/validation.node" "Release/validation.node")
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/obj.target/validation.node b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/obj.target/validation.node
deleted file mode 100755
index d1fae0dd2c694cf83f280e070fd4af761ee15701..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 20472
zcmb<-^>JfjWMqH=W(GS35O0GdM8p9?F>Ek`G8h;b92hJZ*clucWErHuYFQCd7%Ukb
zh!BisU{C-Hfb3vnU|<l?1#=k$bRps}x`G8F-T<Xx`j{9P7(n_qK=o~a>VwfAKn61~
zFu-UIh%pQxV?g)>R34pHfvSViAhjT&fTtxXAhv@hh{wQyPM1K08DKO>El4QvX-Nvm
zogg+bSOBUh2x=d$aQOfV0FeKnG}Jp_|A{a#FfcPPFu41LGSr^$e6f6s_@$eDUYYS6
z`Kk~4H0FY=5M*Fr0C@$Zot=S!VFIIq)&eFe-VS!og<ZM<T_8Cv1_lOD@ai!zFc^R|
zL9rnN1A{RG1A_?z1A{381A`d@1A{qK&H_r?FfcH5<{X**>hgQON2LLkCku|u-r4(+
z??z#S%=eaeGj>0oRI}{ULltM&t8Xr!cenrgP2}qGNXw5eV=X^wCRu(IiA}cn;b$}J
z#Qp_O3~!}{&w4kh+CAgQY^d>ADP{&v1_N<aDPDF423VLP%g8cg7w=-jE?$E}eGd-v
zLGb}e$;h@cFeEa-QZTCcM^**~AygqSFOdnm_+v)w?tIRIU0eo-y%U(Qs|Up+HuncH
zFfb^AU4}~N;IKCWNBA7X5uVC8{H2H^UR-gQ{||?HQC#lCp}rf3`hz&sPr>1SP{PHQ
z4tL{l|0z(Jh#JITULg*9rCG7ZqbQE}1(hGz+~bKueIpL@-{ElQW(Mr(b_tGn_htp9
zD{ck{d9XJbQXmwA7}y*hh6-4L3>7b6fv9JIst2W4kkmG)IJ!9?zY1X~AGkR{;U>Y*
zVThXA0~jIZZ-AQr3}iS11A{nJ{RA}i=UEsS6d8mW9H8|Oth{6as~5*GpN9<;KHLl&
zq#*`}g9>5>28Nvs5OW&P%=rNeA86*whG=6r0u@hCgb2XGZ37PRlk5x(f(+se2~hWI
zK(sNGg7Y;ugMb`F;1PskNP(KO02(~|q2j*G(C~q}2Ud^fgUc&!h6_><g|{IT!wsl8
z7ohHhxt}3EK0P--FTS`Wv8W_Io*_OnFSCRpJ}omZlOf(S#5X=AwJ0?`v$!O+D8$z}
zCqFMWBrz!`6(WaSCO)|$5oADOPG(gqL%dg6d=S(G=bXgi;?!b>_$WU^gRsP$%#_5E
z%=|oKztnQqAa6gTG7C$`qV&?-)Vz{nSCA^BG7CdPkHox`oYdgt{DM?xL)S8f_^7<{
zT!#3lkT7IJpvuksld@8iOAIYM^GZ^S@)C30GE;L>obyZbO2Aq{mKcRu7+SdJ<R^h$
z7?hfpT9lfXoa!17;1?WkkqOlZH3{YpDA&j|IJG1oAFRkT55*GK%m9$%{7mxlQ&J5L
zAPxyHN-Qum3QtYUc23O6NlHx4b_F@X&>$eSs2CKic_p5H!G`gsVTn1VsjjZB5HpO*
zER4b|EPNBQQ$c!hI4z(oz^%+LI3CS3gkiy^@i6y;JZ<WmSd{IVmy%kLnwOHASAxS>
zXi%bryhTuAxpPi_F@aD*(c=P+t$0wJ7nQ`PC1&O@#7CKc5*R25%pmdV=@%Ri4O>@N
zm}3pi+)DG3L1`l-HMbxqu_P6oMgrVGiV^zYffnTL7aWh2c3gvv<3XVcGTbsaGd(Y{
zq_hYWx-hR{m~Uw2nO9trn3tRivk{(L3{4<W36n4~3{EXUiFru!$^;pXoFokmJ&VDq
zJT%130(Sz(bc>;TY6&a=;Lb1$E-A{)OSkk(Ef22DP0G)44e(9|+i6s0VF7cTad2vh
zD{3e~HM+XG!h*!aC9xzC%#SxT4=BnnNG&R<bSx<;%1kOPNrgoMR39Yd5mrGX3yVeY
z=m3X4PNOmMhjCD98r+*kVHTFoIjM<7c+x#6pfOBwF#?+r5{8)pVLk%o0dvn{NY?jD
zO)PRrO)Sa4p9?^Gj9oH|3-XIoAsX?h$8;1p3q)Z$$uu;t2-VkyMlhEV@Hui4gL)dJ
zIE7?8EOxpWfI}!H2U5nMm;;eAG|nuJF9Q|K@uekc7P$e*@SrwxDosmEEdpimVpvuI
z7iEZij8uw&w0RqqSwND6MMyp*3xVzTLz3_;MwT!tvw)>8b9Yc4OG&LrO@SuR%+zAn
z3P_pmSX7i)2~NY{0vDmp#F!{;KB;->B^eOMfE?+Tm{Xhz=YqTluW<~GoQqNuOHv_)
zjw`+z!ZI{3B{eNGFEs^jl%;D$a%usn9J36mEJ$@ND#|aynL9yY2CDE(LNbc-%i%iF
z)I&lPQB<0Q6qSP94vsZ&bsC?WpHiBW%8-+pR9uphtgWqAoUdmF;ue%-6s0DnfcOR=
zelmz<#t@&Hl30?+5FejZTnuRlFvO?kr7$3j)B{y%4DLRjPR{X0dPaJt5OzdFys;jr
z7Yc1;z$qqh{};vu^@U+<!ZfHM#>hYl`~_{pgPKUCQkk5f-nR~PzyV~=ZKyoR?h?&O
z91ILh3>Hv%*f<B2%P;}jZjyku|6t+)P;m!nyA37|;}@WbzfuL+#=y{kCjK8P9so5T
z)K3NV^&zSm7$T6wZDE283=9cK;@U{!3vh^MAc<Qcsb7IZd;*d<XgmR?Wd@QsXsiJy
zzCa%o+K@3I(0Bw)d<Bv?Xj}s(z5z)b7Iq-H9Z2H5AOR>ofF#Zj6$4Qxki<cK3Xm8G
zUqBMK1PMU#4J2{ol==WkTpy|yM7=-~w+0D7aRoFULGc9|TY(BQNEkrE0pwRu%7uw5
zAc-TVe+?vY*ccT^j{%Z6@;IIak~s1>mIIPF$Zn7sAnbu8&IuBL;s7LZE~prYia-+Q
z1_?lM0+KinR18FAAc^yV1faM8NgO#|Dv-nlp=v=?1CluMxJw6;xG+c|6i+}B2aSC}
zg&AfbiG#-7VB!mq#6@9(3=9k_ki<cKTbR@aByr>+tQ|<=5-`OK3=9X5#Gym9VA&H$
z;?N=kEPeq=9NOgsi{C&J2aOSd1sNC^9w3R!!UP!@7+xTWL%WJ#*$+tK&@MAr{0EXa
zB&C9d85p4H8I*RQT|%$~2a-6nYY7$?KoVC5i$DkoByr>+0tF;-Xpsljpn)W=1{Q%3
z21w%S5Fs#Wfg}#=D}y9Fn%{7EbhGA4C@^@m9w=db0qW3tG#}wO43cGF_;0#NLV@AG
z>J|wF27Y-5hX1M{eg;VL<%9qK|NmEAC85BO0m{xVFM#=rKzvXZet7`Qp9SKBvhK?b
zVE!Z!ACzTZE&%hpKzvYEeK`TlZvyc_S@dNCm|q3rgM#;E0hnI|;)9C5mkD5g7KjhZ
zqAvr${3H+`lr>*Efca4%J}67RGywC1KzvYEe5nBDdx7|%BJ-sHnC}GQgR<mH1~A_W
z#0M3fFF*VP`PT@<2W8Ed55Rma5FeB!UtR$7l|Xz@R(yE?%$EZ3L0RzS1~6X;#0O=u
zmkYprE)XA-wO&pD^O-<=P?mbx0OtP^S768hWu=z|VE!i%AC!e&CV=^`KzvZvc^Lra
zKLYVVS>~k!n12hz2W6F)24Mar5FeC9UMhh3r$BsA)_5rZ<{tv_L0RG@1DL-H#0O=C
zmmmIu{J#mr2W5em55W9YAU-JRzq|nEF9PvFN&e*lFn<<^4@&AUH-Pz*KzvXVf4SiA
z|No&Ly}TNH3=AH<rVqJ5l<gXB28Lars?ekJ>5IRA|Nl?Z<Ckv%B{&9tc?OSO))nFk
z3?99<Aag@KG=F$>KJ{q+!B@@{d)T9!b&Dt@A%BYf{{WO;J$hLSA?mZl6&PUZ5B^~G
z=se_c@Rhv>;{}h4KT5%xMeD(uFO__X_2@kI{}D)kgRP;s0s}*-x<|8Zx~KvJL#RjR
z(-Iz!Zre*@3Jfpi{{8>|MaKXC|6`A_a)>K1Fn&Iq1_E#=do<g22q`cyl&E=hv+{$@
zKTskS>d|XkB&5LL(fRcMh1i$j|NsBzmu~?1@ul~FWFJoeS?3t;80Oje&oR`eH+O?$
zh)-|ogkYb}=N`>(JYM|y`~SaB=ld65{{H{((QSKHM1jHZlHs=(U;h06@6mbOqx0|!
z%YXm>?*nB}kIv&Sd_dyewtHdf&Vcxx$6thi=w4e^E(QkA&g1()DgOm1J^6J0GCb+g
zdCa5p{)-17HJ$fgXn^Qm+ozli3?7|_A!=1X_IKU_tM%#p{$k1>h`Y{!-S_;(5s-ZI
z5szrc7{^%0ILG+d!~F6t3=AHv|M^?2nHU&CUHG^0d2~K?40Q}~<=^(uGx<ocN3U!S
z4+8`LHXdgFZ3jIpkC!?4^vYU--T2Ayk_-Q~gO0rpj6TUPd>LOg|6nR{<?ox!z`)S_
zgSkYj`3DQXJVPm;BmXw1|IG&)Z0yT~(k2)l0J{KWJ2<>On_n>^RFpq}^KJH*Uv_Nx
z`If(>k&%Iczs;GEfx)ri=Li0lL<s8(f2%tq1A|R}`D%W72Ezl64L`r|PdiXPzu_k<
ze|rfd1A}KWOScc>4NyX4X#T-i+U(ft*kI$x-&X$r|Nqx#!TxtOe8RttMXcA0(UI|p
z<H09v{M%UgdIK3<7#|#bz}D-<$iGcQjPU}99mvSPjfao%#K8w_ofjcYk6vDBZUzP?
zZI(vc|NjLT_}gXv|NpPcaD#!t_CGtw**yRM|8G9T=-7G5)AAR8^HBx{22aLMuKe4$
zpn(huTu4B&2zXc?=Wk#2@BjaoSO0-hqzeN>=S5e;Coj`Mi4yEy!vio5BujQ)G(7M!
z5s`ik54?<rD2B*`>^}H}?WH(ai32DIACwB&%;#@E_3!`xv<WY>!8S3p9N_N+m1i$+
zK=?NO{Ov11F7bx)=kvGC0P(FMd~hu80Hx~K!(i%g8q9sqK?cK$3~>H|<Q{O&IRMQ$
z3NH@*`u~4Fs2qI}@%#UOkK+!YI)&l51E^>RrE8CF)^<S!29M?g0v?^rp51O7KD`+n
zpuD!?*Z=>m2kO!d|NFMSE#U?Uv4V^MWw&Y$kIq|$-(Fn#3CfS6z9192L4x;QIQ{|&
zRdc+s`1$|8XLlI~I1eA=c+v3-lvkdE^6FfWn&u-49-TM9K6H$WJ?zoTo5l_*8cp}J
zf+*V;tPBjh+(C_)dq0p13s8CG(fPxpyPm_N^?wOxvx5NR%hf+2g={kiNUv!P#0V2M
z28LY`44@4B^u>%HpvZ>A7bv`fJvx6w+XcP?un=H}8Eg8Y<H!I1EeA@BJ-VwoUU-8&
zTFn72bwKU`iGr+WeX#%}b=(;ouAnAGbnM|5Jim}#oCYc1Kn2?Y#}LoXKR%uBgFQMw
zdo;h%c%k_7|9{`sCm!9-93>T?#!0nDH-o1oiwggg11$$ia=V=cS`YBIHZm|U__jVN
zG4<(u{^IR-u+ua>T5p$ddUP{;bl(3T0FE?gkYk#UXn=zil>H(8_2}h2$p#LYBo+{5
zn+git3Q*uSe*gb}f=BBC{wW7u_j~m6E`+GFf~W&cRP8DQsf+yn|G!5sZxcjX8X_$O
zGNv3PZS@`5$Ee{8jwt??c96PF;7~1%2Yai|viSvL>w!*Zff8P5&_U8SICQ&3zw&`9
zk9%PMf`yuoa74$xy!Q?4lyHbsCNP72w3CH_VOJ)|iuDj_3y5?fM7jec4QkN6m;jNM
zgh&TLq`5%S=^)*O-~Rsx#}`ui&;_{zoI{Y(N5(gBBtX)KHYjwuq3L5E$Oce$X#HQp
z`l10Og_b_vpoA7AeIVJlmlsQV{P7iRpA{$|UhIZi0Zxy8P!1$L3ZU8N(Rn{Q_GQ=C
z|Nmc<eg|a%7fAJvWS=iK`#O;A^M+ahw(s6oNEV0Kw*VxC<UfdgQXu<Sk?jLjd7hnr
zf<1a;7l0~tP+hC??f-wr?hqA$)=T_-=Ag=?yGDiMMK9QD{+6o@3=EFlE-IiL(6<9r
zsDq`~f$Z-*?%8?dg)lf0_*+~U85lr0Bl!!skn!w1`T`PO{4HD%DWBfd123k01xdg2
zNdEDH^Xvcr%|94@I-m2moCQVv43LYBzyAMk_zjc|xjniqUVQlsYF``!nS2tg^*P97
zkpF!;-+?@^`Ro7xo}EWP%o8A2H6QWt>3jgqeTXLAi_>2~1|0`C*7@ZbK#p-Wd<!yH
z5u~lxR*8{;0n)}e08#qF14?fIxuNwy3D`l&pF#E=_33=>+xg~2=-2=MUpMp1GrY)#
zD1LbmQg49mdvWax)HD38`v3p`e`)$3oNw%zKpDpL2B=)@we4nPVAvG~3V?EuMZLTU
z5NXiVrbn-B4oKPuBpm^g2KA#5-6jTHK)<xONIx?#Ij1xwRUb4Om{qJ_T$BuE#^;0Q
z+~UiN5)1S|Ig){aAp<;Vr)!5fPoklzV5b0^o@H>$EGjNhNQBP%DdeT5rW7lb<SQhl
zDkLf-m4b$x!A`<!KSUka>P*Cp3j=uW1w16mpa^kKyq;&VYi>bFrG_Tdg&-05On`<a
zXw0)TRl(L)AwMZg*AA+SK@rR=N=++{hp5o=EJoIaWISl_UPF@stQPFivcw!+J5T61
zw}vKzo*p>hkOo(ilR<_;Cqu!$#Uv8G|NkHG{r`W5@BjZBfC~6;|Nj?!|NkGRvMfI{
zMFA8qR#uP^b<o74l@*B8D6_D#f{b6=fS3?@JLFME28QC2#FETph2qSr)c6vpL68xD
zD=WxwIl3|62}`&sQ2ogniA7py+Cc;L_%$=Y?Z@Q}r1?{@QHa@7u$Lfi(NO?t*FyCe
zG=R!7i%LopbHFN~?t_E_D1@x6z_T$LSam`SAfP`eH4UF`1_qdZ%qXfuxC70I1_K6$
z1_eHb289#M4GJ8;8WcF1Ag&pHBqIU9ga(+QfQ5yHg_V_+l~J168npHgG$11I?*IP@
z3=9kfAO8QhU}RvJ@bUlu7a;zp|NkSH7#J>m`TrkO_Z;~8|GxyNDgN#M{|H6~hJtVZ
z|2Hr)Fo5#f21W)3g&+U_KLF|f@&7*uXk_T;|NjO|3=9Q7|NmbB;xjNXfCfZBvB6js
z#K2e~z$neb&M|?JfdMp702-{Qc>Di9sQhK%6L8~`@Z#q#=V)NCm$KF}RsoGQFo2e2
zx`5X3eEI($yynA^PoRy-nU~F}kJ-JKrH9q0nT=^B7Y{p!BWNrLtRCdg1t0$Z2e0jb
zsdwpT?qhN7Wp(Re^J!*h+ReibZoh)uu!MnuVZoRG|G{f?!a(N7@`47cK<);~9|5f|
zeE<JHXt09;Y#u@$<c}v%{ou7NV0mX=HpgaWrbtwG@h~zly!i6}KX|PUOr29Nvs({~
zdowFj3P`ml*cS|7f7mcGFs%6c|37$53rxLZGjj<@p*wdhh;oIh2e|`Ob6I@*{~w<_
zK<Yqiz#6{&{|_1xg!l*Q-WY_5Aa#2f85m9wPzS0gpMchsefa+$yhg|i6n^f!Y%aab
zJuDv0tW05Chn>ziopn6M!_MKs&AgKl%yk2CeR<dfnpxYJdRTfv1BsyU2F14t69dD6
zZ~y;;*X+Rj4K~lEnU(1!$dTSqZ-caqNDP~YgU!1Qwm<+C8z47<<`zLTjQ<KW;>*AQ
zUXKkD2hB}_Xg(0Zz`!5_&Xo)dpn+VF5Ny3HsN4eaVe9Nb1EU~5Y<?0n5DMZ$wKISQ
zN<n<sJS8X}gZMD{umAq%gZQxZ*PwxF5WfPd0G9t@<rrw-86@ulm4~H2&_Dx79F~3=
zpz{gP;*X&MDgi48q26Zz4g7-i?EsA+GcYi~#4A7}&I}9;P-_?*pay{k!a?d`_Wk=0
zalZvr{eLJQs+{2il)nc&?7_hB6UvAA6J*v<!mxGo=x$Df24oqOZiCX(p!6~*y$wnq
zgVNWa^fM^^4N9{?16T}7t3hcqDD4KN!=Q8;lrDqPZBTj|lwJm<w?XM+Q2H8_eg>t#
zL1{K<!WM(lYEaq?O1nYnFese{rOTjn8<d^~rI$fz*gQOX_`&$F^bF&}=I3F2*u1>E
zv$K_gMrcxLUP-BfiJpa?k*=X-DVS@h2@zmm&?~OYElEsb&?_z}g3uW-R$hKds$P0t
zsa{fPW=@K3W(otCmyuYU!JwB?nO9ty3!zJjATnj3b%6PKD4h5r2EC%xoJ5cYD61f+
zgh3CqbdEu<B(<W1K@Yq_Q?Do=ymUh^H6uQ)C^0uRJ|m@w0nUTyh))D9mx1Vjv9pqk
z81z6|LH6hs<%8Xnn46i*pqHLs0w(mpR)W+p=p_{wGw3Df=Ym#d!a|HP8dRQv$^=+`
z2G@lQ3=A+DR6irz0GfD1=7aV`eEa_&wA>Xe3@hhgG^l+Cl7JRZ@bU&E2Ew4W5GYN+
z?1z<uF!}<tAOYD6QUfcmpvjm4v>yj#Hb@R+9;{r2(Xet9BnQH<`T@iSVGjld&@>&~
z{jhQjM%RE8LHCh>m@s=_bSMJ@XqpSIA68DnXps9r`q14E5(8mS8ww@|;={^i7!50z
zL4E|uqx(OPfdRbN1?C=DIS->@^#VvgsBS^mUjeNnVf7HK9)!`b`VC|^2!q@TqG7lg
zO@9Eie1p;8HaAQ$sC^A(L#qphIyC(opyddRJ^^wxR1b)P=>xGr7&HnCic^^TVf8kQ
zhSg^vwIGb{{w}Efu<%;|P4I9UO#^7+5@ZexPeRj=Yd;iBJ(_V03()lMfcAZ1bPCL2
zPy=A`2jw!XVqjnZwP`@{3lf91Q(*h0(AA^!w=pm<fF`G5`eE%D3DAZor1k;GY!F7*
ze+cS+n0^K5Iwb`n^&dym58F530M%arvJ?rUhyNAm{x_KYu=*Re9}ZRy!NMKpepouX
zi)KG;J=Fr}Vx#~hyFpBtei#kvD}vG=%zjwA47O3s0VE012*ogcF#0u`{jmDe0W^aR
z8b^fcgHh=I{|JpEnEkN*8y!&nFneJ7(VWBZ4QfApAP}k$rXQLeprVNOG|U`Ovk+!C
zToD5U!y2gl@PRR?BupQa3vQpIC2_FS2k7Fl4bc1#YFC5S!@>LmEB`_H8=L(LK%IF8
z28IYw<pMSlLZI6Z5yeh2GcdyIL1Y!o3{3F-l&Ip&46u3&Rh)$ZRv)2?vogTy8B}pL
z23Y-pD$dRTs~1qkIT&E&J*qe-#y&uhJTn6q1FU=o@nM*mftvwV?!v@CG&2L{z9Wb@
zF9WQc1o2^*nSl?!FBB#QqL~@^8DQlah!4Ze3<B`|t}rnW&CDRk04t9`d>CeC5MqFp
zGcYj_&5X3~2*ihBW(E-kSh)Zb1JTS3q6`b5>kL7B7-k0Twu1JrU}7MenL(TZmOnv!
z7-nX`+&2Z1V`hL>W*`m}gVG-h!$<UN0WO0X8F(2Spo_6!Yb2w=`IDDn0dz4IYz<d0
z18DUuBEG<5MhpxLYoY2NK-I(6YC+05UIqrJxG&T_pm8~ny$MipD8&F8;{k~~zzhI6
zoPmL%jS*A^@G=NM#bNnyHdMR;>VDW-SJ3`UkU0mS;;{X(noOW}3uZWg#$*_=#IGY0
z#J>;Ff;0>&E`Zih$%Kldk6Y9;f!vRXFQ~T|`oQ9t>1`|29N0JrG}sspg4JWDTU`En
z09Mb>AORY9f*HcV!0-+%jy*kNODDg;>ctq~^$gT30cMcDF!$HVK*iD1ttMC;GhZ0t
z*q4}vLwptv@ryXbf8r3=z_D-80k)4(3F1-kSRw-hLkJ7@{lm#P#LHPg`wSswAd{ed
zt)Rtr$YLP&GO&8ga&HaPJ?Q%_kK@=M`x9&q<~~3v9Q#Q9Sh4#n3y1nsIMhD@?=uAX
z1P!x+_IaX-F)%Q=utD}QqVJ!Kz@feesvdoR=~5i(f8yBZ$%nKj0NGX6IK+!^h_~X{
z&pDkP;xF|5oO^MYa|Va_V;tgtaEPme_q!td2*OUmA-)-h_-U{>qP&8b!oYBy1L80A
z{it8S>S3x7G!rL8J^H>=X-@3v!5)Wr1P<{IsQKvWXATba7r^2Y4CwoZuY$!9?uN0L
zxUjoZ3WvBS7sS8l=`#t3`srYC%<^*{7xsO~>!IeO?~DG-g}t0%<A%6r1GF52jjxz;
zWA|4OH^>}L%=R1Ve06*jmi=WWpt)3xJz>xtU9PUKu7;NJ@c}`uAt90RZlQk8A)fwz
zpe@JP%!2F*#Hqs%bEln=Ynfg_Vo`~n83R_=fwslrG!Kh!NZhqciqWRv>1Nk5oO*nW
z3`&X;GjlTY(w!<xQj6X4i$Hrw8RDaS3{CUX(uz|{irtFxbD@Gz*F(4HnL+03F(LxK
za}1}osOCU+iK1@RMcU$r!<6KrlH!umv^2eBhWL0d=b(5W&)|^wcm~8i^7xY6_+-#d
z@?r+q267~!`1q9k_;m2*?D&+D{G#Ic#L^0e<ow)%oYa!k6g@Lbb0Y?<ia>kLGvmR7
zo$;x8B}J7CkRj2O(%jrihIr@zDVPV|<&L5>KHe?J(bqNJ)z1Z#B*89+vfX|Bog97Q
z{oUMxT|?qS9G!ez;~C=PLwud#s#A*d;~{HB7~)+b{TzKgongEAkhiasu$hpgO~;50
zkj5nLo5b8`ZHRUAu_5uB5^-+8#oTX-cJu(&lLA1yRUI6_TMwbz4dan_ltZPUyAr`k
z02J~V#RH@~0ZBo&)*BMP7oMmc>!5AI=CBRC@TEaGw+iDsSs@CP<uD@#vJaaIJK#Zf
z!!jP~nGPr?H=u<q*j3Q7ocz7tC}{w?HyU*81AMnDk^5vZ;ulo9Lt~fPd*QKfibmu)
zVvmG?7SEvV#YFC)289grreZ`L4BO*N%1IigsN0;eZSP0gnT@(-8<J^=+L(_B81i;w
zQ~BHrP;kR{b3@J#LEh&Kt@4nM>wwkH(BuT$U>%P|DRf6YD8oXt2JVALkir(W8W6ru
z98`J`eaHYx9)cWt0CE6|M+qO-0ovdl56;w>MGd~gFp%prq)Z3$0kH=dU}j!~FF@vy
rayAQe>v|OCVK5lBkl3JuoHGM01z}YW>cKU{9q<9oXcz}~fM;_7Gl`6&

diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/obj.target/validation/src/validation.o b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/obj.target/validation/src/validation.o
deleted file mode 100644
index 19d69f589e09b4a1955453f932f6ac4dd84d92d3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 17856
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
ADF6Tf

diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/validation.node b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/Release/validation.node
deleted file mode 100755
index d1fae0dd2c694cf83f280e070fd4af761ee15701..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 20472
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

diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/binding.Makefile b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/binding.Makefile
deleted file mode 100644
index 5e6f8326..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/binding.Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-export builddir_name ?= build/./.
-.PHONY: all
-all:
-	$(MAKE) validation
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/config.gypi b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/config.gypi
deleted file mode 100644
index 8515666f..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/config.gypi
+++ /dev/null
@@ -1,116 +0,0 @@
-# Do not edit. File was generated by node-gyp's "configure" step
-{
-  "target_defaults": {
-    "cflags": [],
-    "default_configuration": "Release",
-    "defines": [],
-    "include_dirs": [],
-    "libraries": []
-  },
-  "variables": {
-    "clang": 0,
-    "gcc_version": 48,
-    "host_arch": "x64",
-    "node_byteorder": "little",
-    "node_install_npm": "false",
-    "node_prefix": "/usr",
-    "node_shared_cares": "true",
-    "node_shared_http_parser": "false",
-    "node_shared_libuv": "false",
-    "node_shared_openssl": "true",
-    "node_shared_v8": "true",
-    "node_shared_zlib": "true",
-    "node_tag": "",
-    "node_unsafe_optimizations": 0,
-    "node_use_dtrace": "false",
-    "node_use_etw": "false",
-    "node_use_openssl": "true",
-    "node_use_perfctr": "false",
-    "node_use_systemtap": "false",
-    "python": "/usr/bin/python",
-    "target_arch": "x64",
-    "v8_enable_gdbjit": 0,
-    "v8_no_strict_aliasing": 1,
-    "v8_use_snapshot": "false",
-    "nodedir": "/usr/include/nodejs",
-    "copy_dev_lib": "true",
-    "standalone_static_library": 1,
-    "cache_lock_stale": "60000",
-    "pre": "",
-    "sign_git_tag": "",
-    "always_auth": "",
-    "user_agent": "node/v0.10.25 linux x64",
-    "bin_links": "true",
-    "description": "true",
-    "fetch_retries": "2",
-    "init_version": "0.0.0",
-    "user": "",
-    "force": "",
-    "ignore": "",
-    "cache_min": "10",
-    "editor": "emacs",
-    "rollback": "true",
-    "cache_max": "null",
-    "userconfig": "/home/neilg/.npmrc",
-    "coverage": "",
-    "engine_strict": "",
-    "init_author_name": "",
-    "init_author_url": "",
-    "tmp": "/home/neilg/tmp",
-    "userignorefile": "/home/neilg/.npmignore",
-    "yes": "",
-    "depth": "null",
-    "save_dev": "",
-    "usage": "",
-    "https_proxy": "",
-    "onload_script": "",
-    "rebuild_bundle": "true",
-    "save_bundle": "",
-    "shell": "/bin/bash",
-    "prefix": "/usr/local",
-    "registry": "http://registry.npmjs.org/",
-    "__DO_NOT_MODIFY_THIS_FILE___use__etc_npmrc_instead_": "true",
-    "browser": "",
-    "cache_lock_wait": "10000",
-    "save_optional": "",
-    "searchopts": "",
-    "versions": "",
-    "cache": "/home/neilg/.npm",
-    "npaturl": "http://npat.npmjs.org/",
-    "searchsort": "name",
-    "version": "",
-    "viewer": "man",
-    "color": "true",
-    "fetch_retry_mintimeout": "10000",
-    "umask": "18",
-    "fetch_retry_maxtimeout": "60000",
-    "message": "%s",
-    "global": "",
-    "link": "",
-    "save": "",
-    "unicode": "true",
-    "long": "",
-    "production": "",
-    "unsafe_perm": "true",
-    "node_version": "v0.10.25",
-    "tag": "latest",
-    "shrinkwrap": "true",
-    "fetch_retry_factor": "10",
-    "npat": "",
-    "proprietary_attribs": "true",
-    "strict_ssl": "true",
-    "username": "",
-    "globalconfig": "/etc/npmrc",
-    "dev": "",
-    "init_module": "/home/neilg/.npm-init.js",
-    "parseable": "",
-    "globalignorefile": "/etc/npmignore",
-    "cache_lock_retries": "10",
-    "group": "1000",
-    "init_author_email": "",
-    "searchexclude": "",
-    "git": "git",
-    "optional": "true",
-    "json": ""
-  }
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/validation.target.mk b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/validation.target.mk
deleted file mode 100644
index 6c71b1b3..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/build/validation.target.mk
+++ /dev/null
@@ -1,133 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := validation
-DEFS_Debug := \
-	'-D_LARGEFILE_SOURCE' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DBUILDING_NODE_EXTENSION' \
-	'-DDEBUG' \
-	'-D_DEBUG'
-
-# Flags passed to all source files.
-CFLAGS_Debug := \
-	-fPIC \
-	-Wall \
-	-Wextra \
-	-Wno-unused-parameter \
-	-pthread \
-	-m64 \
-	-O3 \
-	-g \
-	-O0
-
-# Flags passed to only C files.
-CFLAGS_C_Debug :=
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Debug := \
-	-fno-rtti \
-	-fno-exceptions
-
-INCS_Debug := \
-	-I/usr/include/nodejs/src \
-	-I/usr/include/nodejs/deps/uv/include \
-	-I/usr/include/nodejs/deps/v8/include \
-	-I$(srcdir)/node_modules/nan
-
-DEFS_Release := \
-	'-D_LARGEFILE_SOURCE' \
-	'-D_FILE_OFFSET_BITS=64' \
-	'-DBUILDING_NODE_EXTENSION'
-
-# Flags passed to all source files.
-CFLAGS_Release := \
-	-fPIC \
-	-Wall \
-	-Wextra \
-	-Wno-unused-parameter \
-	-pthread \
-	-m64 \
-	-O2 \
-	-fno-strict-aliasing \
-	-fno-tree-vrp \
-	-fno-omit-frame-pointer
-
-# Flags passed to only C files.
-CFLAGS_C_Release :=
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Release := \
-	-fno-rtti \
-	-fno-exceptions
-
-INCS_Release := \
-	-I/usr/include/nodejs/src \
-	-I/usr/include/nodejs/deps/uv/include \
-	-I/usr/include/nodejs/deps/v8/include \
-	-I$(srcdir)/node_modules/nan
-
-OBJS := \
-	$(obj).target/$(TARGET)/src/validation.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
-	@$(call do_cmd,cxx,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Debug := \
-	-pthread \
-	-rdynamic \
-	-m64
-
-LDFLAGS_Release := \
-	-pthread \
-	-rdynamic \
-	-m64
-
-LIBS :=
-
-$(obj).target/validation.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(obj).target/validation.node: LIBS := $(LIBS)
-$(obj).target/validation.node: TOOLSET := $(TOOLSET)
-$(obj).target/validation.node: $(OBJS) FORCE_DO_CMD
-	$(call do_cmd,solink_module)
-
-all_deps += $(obj).target/validation.node
-# Add target alias
-.PHONY: validation
-validation: $(builddir)/validation.node
-
-# Copy this to the executable output path.
-$(builddir)/validation.node: TOOLSET := $(TOOLSET)
-$(builddir)/validation.node: $(obj).target/validation.node FORCE_DO_CMD
-	$(call do_cmd,copy)
-
-all_deps += $(builddir)/validation.node
-# Short alias for building this executable.
-.PHONY: validation.node
-validation.node: $(obj).target/validation.node $(builddir)/validation.node
-
-# Add executable to "all" target.
-.PHONY: all
-all: $(builddir)/validation.node
-
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/fallback.js b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/fallback.js
deleted file mode 100644
index f929d77e..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/fallback.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict';
-
-/*!
- * UTF-8 validate: UTF-8 validation for WebSockets.
- * Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-module.exports.Validation = {
-  isValidUTF8: function(buffer) {
-    return true;
-  }
-};
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/index.js b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/index.js
deleted file mode 100644
index e7bfde8e..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-'use strict';
-
-try {
-  module.exports = require('bindings')('validation');
-} catch (e) {
-  module.exports = require('./fallback');
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/README.md b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/README.md
deleted file mode 100644
index 585cf512..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/README.md
+++ /dev/null
@@ -1,97 +0,0 @@
-node-bindings
-=============
-### Helper module for loading your native module's .node file
-
-This is a helper module for authors of Node.js native addon modules.
-It is basically the "swiss army knife" of `require()`ing your native module's
-`.node` file.
-
-Throughout the course of Node's native addon history, addons have ended up being
-compiled in a variety of different places, depending on which build tool and which
-version of node was used. To make matters worse, now the _gyp_ build tool can
-produce either a _Release_ or _Debug_ build, each being built into different
-locations.
-
-This module checks _all_ the possible locations that a native addon would be built
-at, and returns the first one that loads successfully.
-
-
-Installation
-------------
-
-Install with `npm`:
-
-``` bash
-$ npm install bindings
-```
-
-Or add it to the `"dependencies"` section of your _package.json_ file.
-
-
-Example
--------
-
-`require()`ing the proper bindings file for the current node version, platform
-and architecture is as simple as:
-
-``` js
-var bindings = require('bindings')('binding.node')
-
-// Use your bindings defined in your C files
-bindings.your_c_function()
-```
-
-
-Nice Error Output
------------------
-
-When the `.node` file could not be loaded, `node-bindings` throws an Error with
-a nice error message telling you exactly what was tried. You can also check the
-`err.tries` Array property.
-
-```
-Error: Could not load the bindings file. Tried:
- → /Users/nrajlich/ref/build/binding.node
- → /Users/nrajlich/ref/build/Debug/binding.node
- → /Users/nrajlich/ref/build/Release/binding.node
- → /Users/nrajlich/ref/out/Debug/binding.node
- → /Users/nrajlich/ref/Debug/binding.node
- → /Users/nrajlich/ref/out/Release/binding.node
- → /Users/nrajlich/ref/Release/binding.node
- → /Users/nrajlich/ref/build/default/binding.node
- → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node
-    at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)
-    at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)
-    at Module._compile (module.js:449:26)
-    at Object.Module._extensions..js (module.js:467:10)
-    at Module.load (module.js:356:32)
-    at Function.Module._load (module.js:312:12)
-    ...
-```
-
-
-License
--------
-
-(The MIT License)
-
-Copyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
-
-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/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/bindings.js b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/bindings.js
deleted file mode 100644
index 93dcf85a..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/bindings.js
+++ /dev/null
@@ -1,166 +0,0 @@
-
-/**
- * Module dependencies.
- */
-
-var fs = require('fs')
-  , path = require('path')
-  , join = path.join
-  , dirname = path.dirname
-  , exists = fs.existsSync || path.existsSync
-  , defaults = {
-        arrow: process.env.NODE_BINDINGS_ARROW || ' → '
-      , compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled'
-      , platform: process.platform
-      , arch: process.arch
-      , version: process.versions.node
-      , bindings: 'bindings.node'
-      , try: [
-          // node-gyp's linked version in the "build" dir
-          [ 'module_root', 'build', 'bindings' ]
-          // node-waf and gyp_addon (a.k.a node-gyp)
-        , [ 'module_root', 'build', 'Debug', 'bindings' ]
-        , [ 'module_root', 'build', 'Release', 'bindings' ]
-          // Debug files, for development (legacy behavior, remove for node v0.9)
-        , [ 'module_root', 'out', 'Debug', 'bindings' ]
-        , [ 'module_root', 'Debug', 'bindings' ]
-          // Release files, but manually compiled (legacy behavior, remove for node v0.9)
-        , [ 'module_root', 'out', 'Release', 'bindings' ]
-        , [ 'module_root', 'Release', 'bindings' ]
-          // Legacy from node-waf, node <= 0.4.x
-        , [ 'module_root', 'build', 'default', 'bindings' ]
-          // Production "Release" buildtype binary (meh...)
-        , [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ]
-        ]
-    }
-
-/**
- * The main `bindings()` function loads the compiled bindings for a given module.
- * It uses V8's Error API to determine the parent filename that this function is
- * being invoked from, which is then used to find the root directory.
- */
-
-function bindings (opts) {
-
-  // Argument surgery
-  if (typeof opts == 'string') {
-    opts = { bindings: opts }
-  } else if (!opts) {
-    opts = {}
-  }
-  opts.__proto__ = defaults
-
-  // Get the module root
-  if (!opts.module_root) {
-    opts.module_root = exports.getRoot(exports.getFileName())
-  }
-
-  // Ensure the given bindings name ends with .node
-  if (path.extname(opts.bindings) != '.node') {
-    opts.bindings += '.node'
-  }
-
-  var tries = []
-    , i = 0
-    , l = opts.try.length
-    , n
-    , b
-    , err
-
-  for (; i<l; i++) {
-    n = join.apply(null, opts.try[i].map(function (p) {
-      return opts[p] || p
-    }))
-    tries.push(n)
-    try {
-      b = opts.path ? require.resolve(n) : require(n)
-      if (!opts.path) {
-        b.path = n
-      }
-      return b
-    } catch (e) {
-      if (!/not find/i.test(e.message)) {
-        throw e
-      }
-    }
-  }
-
-  err = new Error('Could not locate the bindings file. Tried:\n'
-    + tries.map(function (a) { return opts.arrow + a }).join('\n'))
-  err.tries = tries
-  throw err
-}
-module.exports = exports = bindings
-
-
-/**
- * Gets the filename of the JavaScript file that invokes this function.
- * Used to help find the root directory of a module.
- * Optionally accepts an filename argument to skip when searching for the invoking filename
- */
-
-exports.getFileName = function getFileName (calling_file) {
-  var origPST = Error.prepareStackTrace
-    , origSTL = Error.stackTraceLimit
-    , dummy = {}
-    , fileName
-
-  Error.stackTraceLimit = 10
-
-  Error.prepareStackTrace = function (e, st) {
-    for (var i=0, l=st.length; i<l; i++) {
-      fileName = st[i].getFileName()
-      if (fileName !== __filename) {
-        if (calling_file) {
-            if (fileName !== calling_file) {
-              return
-            }
-        } else {
-          return
-        }
-      }
-    }
-  }
-
-  // run the 'prepareStackTrace' function above
-  Error.captureStackTrace(dummy)
-  dummy.stack
-
-  // cleanup
-  Error.prepareStackTrace = origPST
-  Error.stackTraceLimit = origSTL
-
-  return fileName
-}
-
-/**
- * Gets the root directory of a module, given an arbitrary filename
- * somewhere in the module tree. The "root directory" is the directory
- * containing the `package.json` file.
- *
- *   In:  /home/nate/node-native-module/lib/index.js
- *   Out: /home/nate/node-native-module
- */
-
-exports.getRoot = function getRoot (file) {
-  var dir = dirname(file)
-    , prev
-  while (true) {
-    if (dir === '.') {
-      // Avoids an infinite loop in rare cases, like the REPL
-      dir = process.cwd()
-    }
-    if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
-      // Found the 'package.json' file or 'node_modules' dir; we're done
-      return dir
-    }
-    if (prev === dir) {
-      // Got to the top
-      throw new Error('Could not find module root given file: "' + file
-                    + '". Do you have a `package.json` file? ')
-    }
-    // Try the parent dir next
-    prev = dir
-    dir = join(dir, '..')
-  }
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/package.json b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/package.json
deleted file mode 100644
index 6ecf3a43..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/bindings/package.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "name": "bindings",
-  "description": "Helper module for loading your native module's .node file",
-  "keywords": [
-    "native",
-    "addon",
-    "bindings",
-    "gyp",
-    "waf",
-    "c",
-    "c++"
-  ],
-  "version": "1.2.1",
-  "author": {
-    "name": "Nathan Rajlich",
-    "email": "nathan@tootallnate.net",
-    "url": "http://tootallnate.net"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/TooTallNate/node-bindings.git"
-  },
-  "main": "./bindings.js",
-  "bugs": {
-    "url": "https://github.com/TooTallNate/node-bindings/issues"
-  },
-  "homepage": "https://github.com/TooTallNate/node-bindings",
-  "license": "MIT",
-  "readme": "node-bindings\n=============\n### Helper module for loading your native module's .node file\n\nThis is a helper module for authors of Node.js native addon modules.\nIt is basically the \"swiss army knife\" of `require()`ing your native module's\n`.node` file.\n\nThroughout the course of Node's native addon history, addons have ended up being\ncompiled in a variety of different places, depending on which build tool and which\nversion of node was used. To make matters worse, now the _gyp_ build tool can\nproduce either a _Release_ or _Debug_ build, each being built into different\nlocations.\n\nThis module checks _all_ the possible locations that a native addon would be built\nat, and returns the first one that loads successfully.\n\n\nInstallation\n------------\n\nInstall with `npm`:\n\n``` bash\n$ npm install bindings\n```\n\nOr add it to the `\"dependencies\"` section of your _package.json_ file.\n\n\nExample\n-------\n\n`require()`ing the proper bindings file for the current node version, platform\nand architecture is as simple as:\n\n``` js\nvar bindings = require('bindings')('binding.node')\n\n// Use your bindings defined in your C files\nbindings.your_c_function()\n```\n\n\nNice Error Output\n-----------------\n\nWhen the `.node` file could not be loaded, `node-bindings` throws an Error with\na nice error message telling you exactly what was tried. You can also check the\n`err.tries` Array property.\n\n```\nError: Could not load the bindings file. Tried:\n → /Users/nrajlich/ref/build/binding.node\n → /Users/nrajlich/ref/build/Debug/binding.node\n → /Users/nrajlich/ref/build/Release/binding.node\n → /Users/nrajlich/ref/out/Debug/binding.node\n → /Users/nrajlich/ref/Debug/binding.node\n → /Users/nrajlich/ref/out/Release/binding.node\n → /Users/nrajlich/ref/Release/binding.node\n → /Users/nrajlich/ref/build/default/binding.node\n → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node\n    at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)\n    at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)\n    at Module._compile (module.js:449:26)\n    at Object.Module._extensions..js (module.js:467:10)\n    at Module.load (module.js:356:32)\n    at Function.Module._load (module.js:312:12)\n    ...\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
-  "readmeFilename": "README.md",
-  "_id": "bindings@1.2.1",
-  "_from": "bindings@1.2.x"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/.dntrc b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/.dntrc
deleted file mode 100644
index 47971da6..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/.dntrc
+++ /dev/null
@@ -1,30 +0,0 @@
-## DNT config file
-## see https://github.com/rvagg/dnt
-
-NODE_VERSIONS="\
-  master   \
-  v0.11.13 \
-  v0.10.30 \
-  v0.10.29 \
-  v0.10.28 \
-  v0.10.26 \
-  v0.10.25 \
-  v0.10.24 \
-  v0.10.23 \
-  v0.10.22 \
-  v0.10.21 \
-  v0.10.20 \
-  v0.10.19 \
-  v0.8.28  \
-  v0.8.27  \
-  v0.8.26  \
-  v0.8.24  \
-"
-OUTPUT_PREFIX="nan-"
-TEST_CMD="                                                                        \
-  cd /dnt/ &&                                                                     \
-  npm install &&                                                                  \
-  node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \
-  node_modules/.bin/tap --gc test/js/*-test.js                                    \
-"
-
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/CHANGELOG.md b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/CHANGELOG.md
deleted file mode 100644
index de0ac02a..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/CHANGELOG.md
+++ /dev/null
@@ -1,265 +0,0 @@
-# NAN ChangeLog
-
-**Version 1.6.2: current Node unstable: 0.11.16, Node stable: 0.10.36, io.js: 1.1.0**
-
-### 1.6.2 Feb 6 2015
-
-  - Bugfix: NanEncode: fix argument type for node::Encode on io.js 2be8639
-
-### 1.6.1 Jan 23 2015
-
-  - Build: version bump
-
-### 1.5.3 Jan 23 2015
-
-  - Build: repackage
-
-### 1.6.0 Jan 23 2015
-
- - Deprecated `NanNewContextHandle` in favor of `NanNew<Context>` 49259af
- - Support utility functions moved in newer v8 versions (Node 0.11.15, io.js 1.0) a0aa179
- - Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite` 75e6fb9
-
-### 1.5.2 Jan 23 2015
-
-  - Bugfix: Fix non-inline definition build error with clang++ 21d96a1, 60fadd4
-  - Bugfix: Readded missing String constructors 18d828f
-  - Bugfix: Add overload handling NanNew<FunctionTemplate>(..) 5ef813b
-  - Bugfix: Fix uv_work_cb versioning 997e4ae
-  - Bugfix: Add function factory and test 4eca89c
-  - Bugfix: Add object template factory and test cdcb951
-  - Correctness: Lifted an io.js related typedef c9490be
-  - Correctness: Make explicit downcasts of String lengths 00074e6
-  - Windows: Limit the scope of disabled warning C4530 83d7deb
-
-### 1.5.1 Jan 15 2015
-
-  - Build: version bump
-
-### 1.4.3 Jan 15 2015
-
-  - Build: version bump
-
-### 1.4.2 Jan 15 2015
-
-  - Feature: Support io.js 0dbc5e8
-
-### 1.5.0 Jan 14 2015
-
- - Feature: Support io.js b003843
- - Correctness: Improved NanNew internals 9cd4f6a
- - Feature: Implement progress to NanAsyncWorker 8d6a160
-
-### 1.4.1 Nov 8 2014
-
- - Bugfix: Handle DEBUG definition correctly
- - Bugfix: Accept int as Boolean
-
-### 1.4.0 Nov 1 2014
-
- - Feature: Added NAN_GC_CALLBACK 6a5c245
- - Performance: Removed unnecessary local handle creation 18a7243, 41fe2f8
- - Correctness: Added constness to references in NanHasInstance 02c61cd
- - Warnings: Fixed spurious warnings from -Wundef and -Wshadow, 541b122, 99d8cb6
- - Windoze: Shut Visual Studio up when compiling 8d558c1
- - License: Switch to plain MIT from custom hacked MIT license 11de983
- - Build: Added test target to Makefile e232e46
- - Performance: Removed superfluous scope in NanAsyncWorker f4b7821
- - Sugar/Feature: Added NanReturnThis() and NanReturnHolder() shorthands 237a5ff, d697208
- - Feature: Added suitable overload of NanNew for v8::Integer::NewFromUnsigned b27b450
-
-### 1.3.0 Aug 2 2014
-
- - Added NanNew<v8::String, std::string>(std::string)
- - Added NanNew<v8::String, std::string&>(std::string&)
- - Added NanAsciiString helper class
- - Added NanUtf8String helper class
- - Added NanUcs2String helper class
- - Deprecated NanRawString()
- - Deprecated NanCString()
- - Added NanGetIsolateData(v8::Isolate *isolate)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value>* argv)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::String> symbol, int argc, v8::Handle<v8::Value>* argv)
- - Added NanMakeCallback(v8::Handle<v8::Object> target, const char* method, int argc, v8::Handle<v8::Value>* argv)
- - Added NanSetTemplate(v8::Handle<v8::Template> templ, v8::Handle<v8::String> name , v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- - Added NanSetPrototypeTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, const char *name, v8::Handle<v8::Data> value)
- - Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
-
-### 1.2.0 Jun 5 2014
-
- - Add NanSetPrototypeTemplate
- - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class,
-     introduced _NanWeakCallbackDispatcher
- - Removed -Wno-unused-local-typedefs from test builds
- - Made test builds Windows compatible ('Sleep()')
-
-### 1.1.2 May 28 2014
-
- - Release to fix more stuff-ups in 1.1.1
-
-### 1.1.1 May 28 2014
-
- - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0
-
-### 1.1.0 May 25 2014
-
- - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead
- - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]),
-     (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*,
-     v8::String::ExternalAsciiStringResource*
- - Deprecate NanSymbol()
- - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker
-
-### 1.0.0 May 4 2014
-
- - Heavy API changes for V8 3.25 / Node 0.11.13
- - Use cpplint.py
- - Removed NanInitPersistent
- - Removed NanPersistentToLocal
- - Removed NanFromV8String
- - Removed NanMakeWeak
- - Removed NanNewLocal
- - Removed NAN_WEAK_CALLBACK_OBJECT
- - Removed NAN_WEAK_CALLBACK_DATA
- - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions
- - Introduce NanUndefined, NanNull, NanTrue and NanFalse
- - Introduce NanEscapableScope and NanEscapeScope
- - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node)
- - Introduce NanMakeCallback for node::MakeCallback
- - Introduce NanSetTemplate
- - Introduce NanGetCurrentContext
- - Introduce NanCompileScript and NanRunScript
- - Introduce NanAdjustExternalMemory
- - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback
- - Introduce NanGetHeapStatistics
- - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent()
-
-### 0.8.0 Jan 9 2014
-
- - NanDispose -> NanDisposePersistent, deprecate NanDispose
- - Extract _NAN_*_RETURN_TYPE, pull up NAN_*()
-
-### 0.7.1 Jan 9 2014
-
- - Fixes to work against debug builds of Node
- - Safer NanPersistentToLocal (avoid reinterpret_cast)
- - Speed up common NanRawString case by only extracting flattened string when necessary
-
-### 0.7.0 Dec 17 2013
-
- - New no-arg form of NanCallback() constructor.
- - NanCallback#Call takes Handle rather than Local
- - Removed deprecated NanCallback#Run method, use NanCallback#Call instead
- - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS
- - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call()
- - Introduce NanRawString() for char* (or appropriate void*) from v8::String
-     (replacement for NanFromV8String)
- - Introduce NanCString() for null-terminated char* from v8::String
-
-### 0.6.0 Nov 21 2013
-
- - Introduce NanNewLocal<T>(v8::Handle<T> value) for use in place of
-     v8::Local<T>::New(...) since v8 started requiring isolate in Node 0.11.9
-
-### 0.5.2 Nov 16 2013
-
- - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public
-
-### 0.5.1 Nov 12 2013
-
- - Use node::MakeCallback() instead of direct v8::Function::Call()
-
-### 0.5.0 Nov 11 2013
-
- - Added @TooTallNate as collaborator
- - New, much simpler, "include_dirs" for binding.gyp
- - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros
-
-### 0.4.4 Nov 2 2013
-
- - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+
-
-### 0.4.3 Nov 2 2013
-
- - Include node_object_wrap.h, removed from node.h for Node 0.11.8.
-
-### 0.4.2 Nov 2 2013
-
- - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for
-     Node 0.11.8 release.
-
-### 0.4.1 Sep 16 2013
-
- - Added explicit `#include <uv.h>` as it was removed from node.h for v0.11.8
-
-### 0.4.0 Sep 2 2013
-
- - Added NAN_INLINE and NAN_DEPRECATED and made use of them
- - Added NanError, NanTypeError and NanRangeError
- - Cleaned up code
-
-### 0.3.2 Aug 30 2013
-
- - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent
-     in NanAsyncWorker
-
-### 0.3.1 Aug 20 2013
-
- - fix "not all control paths return a value" compile warning on some platforms
-
-### 0.3.0 Aug 19 2013
-
- - Made NAN work with NPM
- - Lots of fixes to NanFromV8String, pulling in features from new Node core
- - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API
- - Added optional error number argument for NanThrowError()
- - Added NanInitPersistent()
- - Added NanReturnNull() and NanReturnEmptyString()
- - Added NanLocker and NanUnlocker
- - Added missing scopes
- - Made sure to clear disposed Persistent handles
- - Changed NanAsyncWorker to allocate error messages on the heap
- - Changed NanThrowError(Local<Value>) to NanThrowError(Handle<Value>)
- - Fixed leak in NanAsyncWorker when errmsg is used
-
-### 0.2.2 Aug 5 2013
-
- - Fixed usage of undefined variable with node::BASE64 in NanFromV8String()
-
-### 0.2.1 Aug 5 2013
-
- - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for
-     NanFromV8String()
-
-### 0.2.0 Aug 5 2013
-
- - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR,
-     NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY
- - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS,
-     _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS,
-     _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS,
-     _NAN_PROPERTY_QUERY_ARGS
- - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer
- - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT,
-     NAN_WEAK_CALLBACK_DATA, NanMakeWeak
- - Renamed THROW_ERROR to _NAN_THROW_ERROR
- - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*)
- - Added NanBufferUse(char*, uint32_t)
- - Added NanNewContextHandle(v8::ExtensionConfiguration*,
-       v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
- - Fixed broken NanCallback#GetFunction()
- - Added optional encoding and size arguments to NanFromV8String()
- - Added NanGetPointerSafe() and NanSetPointerSafe()
- - Added initial test suite (to be expanded)
- - Allow NanUInt32OptionValue to convert any Number object
-
-### 0.1.0 Jul 21 2013
-
- - Added `NAN_GETTER`, `NAN_SETTER`
- - Added `NanThrowError` with single Local<Value> argument
- - Added `NanNewBufferHandle` with single uint32_t argument
- - Added `NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)`
- - Added `Local<Function> NanCallback#GetFunction()`
- - Added `NanCallback#Call(int, Local<Value>[])`
- - Deprecated `NanCallback#Run(int, Local<Value>[])` in favour of Call
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/LICENSE.md b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/LICENSE.md
deleted file mode 100644
index 95c2eb5f..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/LICENSE.md
+++ /dev/null
@@ -1,13 +0,0 @@
-The MIT License (MIT)
-=====================
-
-Copyright (c) 2015 NAN contributors
------------------------------------
-
-*NAN contributors listed at <https://github.com/rvagg/nan#contributors>*
-
-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/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/appveyor.yml b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/appveyor.yml
deleted file mode 100644
index 17771078..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/appveyor.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-# http://www.appveyor.com/docs/appveyor-yml
-
-# Test against these versions of Io.js and Node.js.
-environment:
-  matrix:
-  # node.js
-    - nodejs_version: "0.8"
-    - nodejs_version: "0.10"
-    - nodejs_version: "0.11"
-  # io.js
-    - nodejs_version: "1"
-
-# Install scripts. (runs after repo cloning)
-install:
-  # Get the latest stable version of Node 0.STABLE.latest
-  - ps: if($env:nodejs_version -eq "0.8") {Install-Product node $env:nodejs_version}
-  - ps: if($env:nodejs_version -ne "0.8") {Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)}
-  - IF NOT %nodejs_version% == 1 npm -g install npm
-  - IF NOT %nodejs_version% == 1 set PATH=%APPDATA%\npm;%PATH%
-  # Typical npm stuff.
-  - npm install
-  - IF %nodejs_version% == 0.8 node node_modules\node-gyp\bin\node-gyp.js rebuild --directory test
-  - IF NOT %nodejs_version% == 0.8 npm run rebuild-tests
-
-# Post-install test scripts.
-test_script:
-  # Output useful info for debugging.
-  - node --version
-  - npm --version
-  # run tests
-  - npm test
-
-# Don't actually build.
-build: off
-
-# Set build version format here instead of in the admin panel.
-version: "{build}"
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/include_dirs.js b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/include_dirs.js
deleted file mode 100644
index 4f1dfb41..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/include_dirs.js
+++ /dev/null
@@ -1 +0,0 @@
-console.log(require('path').relative('.', __dirname));
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan.h b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan.h
deleted file mode 100644
index e95a3b3e..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan.h
+++ /dev/null
@@ -1,2174 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors:
- *   - Rod Vagg <https://github.com/rvagg>
- *   - Benjamin Byholm <https://github.com/kkoopa>
- *   - Trevor Norris <https://github.com/trevnorris>
- *   - Nathan Rajlich <https://github.com/TooTallNate>
- *   - Brett Lawson <https://github.com/brett19>
- *   - Ben Noordhuis <https://github.com/bnoordhuis>
- *   - David Siegel <https://github.com/agnat>
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- *
- * Version 1.6.2: current Node unstable: 0.11.16, Node stable: 0.10.36, io.js: 1.1.0
- *
- * See https://github.com/rvagg/nan for the latest update to this file
- **********************************************************************************/
-
-#ifndef NAN_H_
-#define NAN_H_
-
-#include <uv.h>
-#include <node.h>
-#include <node_buffer.h>
-#include <node_version.h>
-#include <node_object_wrap.h>
-#include <cstring>
-#include <climits>
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-#if defined(__GNUC__) && !(defined(DEBUG) && DEBUG)
-# define NAN_INLINE inline __attribute__((always_inline))
-#elif defined(_MSC_VER) && !(defined(DEBUG) && DEBUG)
-# define NAN_INLINE __forceinline
-#else
-# define NAN_INLINE inline
-#endif
-
-#if defined(__GNUC__) && \
-    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
-# define NAN_DEPRECATED __attribute__((deprecated))
-#elif defined(_MSC_VER) && \
-    !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS)
-# define NAN_DEPRECATED __declspec(deprecated)
-#else
-# define NAN_DEPRECATED
-#endif
-
-#if (NODE_MODULE_VERSION < 12)
-typedef v8::InvocationCallback NanFunctionCallback;
-typedef v8::Script             NanUnboundScript;
-typedef v8::Script             NanBoundScript;
-#else
-typedef v8::FunctionCallback   NanFunctionCallback;
-typedef v8::UnboundScript      NanUnboundScript;
-typedef v8::Script             NanBoundScript;
-#endif
-
-#if (NODE_MODULE_VERSION < 42)
-typedef v8::String::ExternalAsciiStringResource
-    NanExternalOneByteStringResource;
-#else  // io.js v1.0.0
-typedef v8::String::ExternalOneByteStringResource
-    NanExternalOneByteStringResource;
-#endif
-
-#include "nan_new.h"  // NOLINT(build/include)
-
-// uv helpers
-#ifdef UV_VERSION_MAJOR
-#ifndef UV_VERSION_PATCH
-#define UV_VERSION_PATCH 0
-#endif
-#define NAUV_UVVERSION  ((UV_VERSION_MAJOR << 16) | \
-                     (UV_VERSION_MINOR <<  8) | \
-                     (UV_VERSION_PATCH))
-#else
-#define NAUV_UVVERSION 0x000b00
-#endif
-
-
-#if NAUV_UVVERSION < 0x000b17
-#define NAUV_WORK_CB(func) \
-    void func(uv_async_t *async, int)
-#else
-#define NAUV_WORK_CB(func) \
-    void func(uv_async_t *async)
-#endif
-
-// some generic helpers
-
-template<typename T> NAN_INLINE bool NanSetPointerSafe(
-    T *var
-  , T val
-) {
-  if (var) {
-    *var = val;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-template<typename T> NAN_INLINE T NanGetPointerSafe(
-    T *var
-  , T fallback = reinterpret_cast<T>(0)
-) {
-  if (var) {
-    return *var;
-  } else {
-    return fallback;
-  }
-}
-
-NAN_INLINE bool NanBooleanOptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt, bool def
-) {
-  if (def) {
-    return optionsObj.IsEmpty()
-      || !optionsObj->Has(opt)
-      || optionsObj->Get(opt)->BooleanValue();
-  } else {
-    return !optionsObj.IsEmpty()
-      && optionsObj->Has(opt)
-      && optionsObj->Get(opt)->BooleanValue();
-  }
-}
-
-NAN_INLINE bool NanBooleanOptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt
-) {
-  return NanBooleanOptionValue(optionsObj, opt, false);
-}
-
-NAN_INLINE uint32_t NanUInt32OptionValue(
-    v8::Local<v8::Object> optionsObj
-  , v8::Handle<v8::String> opt
-  , uint32_t def
-) {
-  return !optionsObj.IsEmpty()
-    && optionsObj->Has(opt)
-    && optionsObj->Get(opt)->IsNumber()
-      ? optionsObj->Get(opt)->Uint32Value()
-      : def;
-}
-
-template<typename T>
-v8::Local<T> NanNew(v8::Handle<T>);
-
-template<typename T>
-NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Handle<T> val) {
-  return NanNew(val);
-}
-
-template<typename T>
-NAN_INLINE v8::Local<T> _NanEnsureLocal(v8::Local<T> val) {
-  return val;
-}
-
-/* io.js 1.0  */
-#if NODE_MODULE_VERSION >= 42 || NODE_VERSION_AT_LEAST(0, 11, 15)
-  NAN_INLINE
-  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
-    v8::Isolate::GetCurrent()->SetCounterFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
-    v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
-    v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb);
-  }
-
-  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
-    return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms);
-  }
-
-  NAN_INLINE void NanLowMemoryNotification() {
-    v8::Isolate::GetCurrent()->LowMemoryNotification();
-  }
-
-  NAN_INLINE void NanContextDisposedNotification() {
-    v8::Isolate::GetCurrent()->ContextDisposedNotification();
-  }
-#else
-  NAN_INLINE
-  void NanSetCounterFunction(v8::CounterLookupCallback cb) {
-    v8::V8::SetCounterFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetCreateHistogramFunction(v8::CreateHistogramCallback cb) {
-    v8::V8::SetCreateHistogramFunction(cb);
-  }
-
-  NAN_INLINE
-  void NanSetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) {
-    v8::V8::SetAddHistogramSampleFunction(cb);
-  }
-
-  NAN_INLINE bool NanIdleNotification(int idle_time_in_ms) {
-    return v8::V8::IdleNotification(idle_time_in_ms);
-  }
-
-  NAN_INLINE void NanLowMemoryNotification() {
-    v8::V8::LowMemoryNotification();
-  }
-
-  NAN_INLINE void NanContextDisposedNotification() {
-    v8::V8::ContextDisposedNotification();
-  }
-#endif
-
-#if (NODE_MODULE_VERSION > 0x000B)
-// Node 0.11+ (0.11.12 and below won't compile with these)
-
-# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo<v8::Value>&
-# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args
-# define _NAN_METHOD_RETURN_TYPE void
-
-# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args
-# define _NAN_GETTER_RETURN_TYPE void
-
-# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo<void>&
-# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args
-# define _NAN_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_GETTER_ARGS_TYPE                                        \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_GETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_SETTER_ARGS_TYPE                                        \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE                                    \
-    const v8::PropertyCallbackInfo<v8::Array>&
-# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args
-# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void
-
-# define _NAN_PROPERTY_DELETER_ARGS_TYPE                                       \
-    const v8::PropertyCallbackInfo<v8::Boolean>&
-# define _NAN_PROPERTY_DELETER_ARGS                                            \
-    _NAN_PROPERTY_DELETER_ARGS_TYPE args
-# define _NAN_PROPERTY_DELETER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_QUERY_ARGS_TYPE                                         \
-    const v8::PropertyCallbackInfo<v8::Integer>&
-# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args
-# define _NAN_PROPERTY_QUERY_RETURN_TYPE void
-
-# define _NAN_INDEX_GETTER_ARGS_TYPE                                           \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args
-# define _NAN_INDEX_GETTER_RETURN_TYPE void
-
-# define _NAN_INDEX_SETTER_ARGS_TYPE                                           \
-    const v8::PropertyCallbackInfo<v8::Value>&
-# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args
-# define _NAN_INDEX_SETTER_RETURN_TYPE void
-
-# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE                                       \
-    const v8::PropertyCallbackInfo<v8::Array>&
-# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args
-# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void
-
-# define _NAN_INDEX_DELETER_ARGS_TYPE                                          \
-    const v8::PropertyCallbackInfo<v8::Boolean>&
-# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args
-# define _NAN_INDEX_DELETER_RETURN_TYPE void
-
-# define _NAN_INDEX_QUERY_ARGS_TYPE                                            \
-    const v8::PropertyCallbackInfo<v8::Integer>&
-# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
-# define _NAN_INDEX_QUERY_RETURN_TYPE void
-
-# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent())
-# define NanEscapableScope()                                                   \
-  v8::EscapableHandleScope scope(v8::Isolate::GetCurrent())
-
-# define NanEscapeScope(val) scope.Escape(_NanEnsureLocal(val))
-# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent())
-# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent())
-# define NanReturnValue(value) return args.GetReturnValue().Set(value)
-# define NanReturnUndefined() return
-# define NanReturnHolder() NanReturnValue(args.Holder())
-# define NanReturnThis() NanReturnValue(args.This())
-# define NanReturnNull() return args.GetReturnValue().SetNull()
-# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString()
-
-# define NanObjectWrapHandle(obj) obj->handle()
-
-  NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Primitive> NanNull() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanTrue() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanFalse() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent())));
-  }
-
-  NAN_INLINE int NanAdjustExternalMemory(int bc) {
-    return static_cast<int>(
-        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc));
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , const char *name
-    , v8::Handle<v8::Data> value) {
-    templ->Set(v8::Isolate::GetCurrent(), name, value);
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , v8::Handle<v8::String> name
-    , v8::Handle<v8::Data> value
-    , v8::PropertyAttribute attributes) {
-    templ->Set(name, value, attributes);
-  }
-
-  NAN_INLINE v8::Local<v8::Context> NanGetCurrentContext() {
-    return v8::Isolate::GetCurrent()->GetCurrentContext();
-  }
-
-  NAN_INLINE void* NanGetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index) {
-    return object->GetAlignedPointerFromInternalField(index);
-  }
-
-  NAN_INLINE void NanSetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index
-    , void* value) {
-    object->SetAlignedPointerInInternalField(index, value);
-  }
-
-# define NAN_GC_CALLBACK(name)                                                 \
-    void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags)
-
-  NAN_INLINE void NanAddGCEpilogueCallback(
-      v8::Isolate::GCEpilogueCallback callback
-    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter);
-  }
-
-  NAN_INLINE void NanRemoveGCEpilogueCallback(
-      v8::Isolate::GCEpilogueCallback callback) {
-    v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback);
-  }
-
-  NAN_INLINE void NanAddGCPrologueCallback(
-      v8::Isolate::GCPrologueCallback callback
-    , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter);
-  }
-
-  NAN_INLINE void NanRemoveGCPrologueCallback(
-      v8::Isolate::GCPrologueCallback callback) {
-    v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback);
-  }
-
-  NAN_INLINE void NanGetHeapStatistics(
-      v8::HeapStatistics *heap_statistics) {
-    v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::String> NanSymbol(
-      const char* data, int length = -1) {
-    return NanNew<v8::String>(data, length);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , v8::Handle<T> obj) {
-      handle.Reset(v8::Isolate::GetCurrent(), obj);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , const v8::Persistent<T>& obj) {
-      handle.Reset(v8::Isolate::GetCurrent(), obj);
-  }
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData;
-
-  template<typename T, typename P>
-  struct _NanWeakCallbackInfo {
-    typedef void (*Callback)(const _NanWeakCallbackData<T, P>& data);
-    NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
-      : parameter(param), callback(cb) {
-       NanAssignPersistent(persistent, handle);
-    }
-
-    NAN_INLINE ~_NanWeakCallbackInfo() {
-      persistent.Reset();
-    }
-
-    P* const parameter;
-    Callback const callback;
-    v8::Persistent<T> persistent;
-  };
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData {
-   public:
-    NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
-      : info_(info) { }
-
-    NAN_INLINE v8::Local<T> GetValue() const {
-      return NanNew(info_->persistent);
-    }
-
-    NAN_INLINE P* GetParameter() const { return info_->parameter; }
-
-    NAN_INLINE bool IsNearDeath() const {
-      return info_->persistent.IsNearDeath();
-    }
-
-    NAN_INLINE void Revive() const;
-
-    NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
-      return info_;
-    }
-
-    NAN_DEPRECATED NAN_INLINE void Dispose() const {
-    }
-
-   private:
-    _NanWeakCallbackInfo<T, P>* info_;
-  };
-
-  template<typename T, typename P>
-  static void _NanWeakCallbackDispatcher(
-    const v8::WeakCallbackData<T, _NanWeakCallbackInfo<T, P> > &data) {
-      _NanWeakCallbackInfo<T, P> *info = data.GetParameter();
-      _NanWeakCallbackData<T, P> wcbd(info);
-      info->callback(wcbd);
-      if (wcbd.IsNearDeath()) {
-        delete wcbd.GetCallbackInfo();
-      }
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
-      info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher<T, P>);
-  }
-
-template<typename T, typename P>
-NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
-    v8::Handle<T> handle
-  , P* parameter
-  , typename _NanWeakCallbackInfo<T, P>::Callback callback) {
-    _NanWeakCallbackInfo<T, P> *cbinfo =
-     new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
-    cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher<T, P>);
-    return cbinfo;
-}
-
-# define NAN_WEAK_CALLBACK(name)                                               \
-    template<typename T, typename P>                                           \
-    static void name(const _NanWeakCallbackData<T, P> &data)
-
-# define _NAN_ERROR(fun, errmsg) fun(NanNew<v8::String>(errmsg))
-
-# define _NAN_THROW_ERROR(fun, errmsg)                                         \
-    do {                                                                       \
-      NanScope();                                                              \
-      v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg));      \
-    } while (0);
-
-  NAN_INLINE v8::Local<v8::Value> NanError(const char* errmsg) {
-    return  _NAN_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE void NanThrowError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE void NanThrowError(v8::Handle<v8::Value> error) {
-    NanScope();
-    v8::Isolate::GetCurrent()->ThrowException(error);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    v8::Local<v8::Value> err = v8::Exception::Error(NanNew<v8::String>(msg));
-    v8::Local<v8::Object> obj = err.As<v8::Object>();
-    obj->Set(NanNew<v8::String>("code"), NanNew<v8::Integer>(errorNumber));
-    return err;
-  }
-
-  NAN_INLINE void NanThrowError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    NanThrowError(NanError(msg, errorNumber));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanTypeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE void NanThrowTypeError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRangeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  NAN_INLINE void NanThrowRangeError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  template<typename T> NAN_INLINE void NanDisposePersistent(
-      v8::Persistent<T> &handle
-  ) {
-    handle.Reset();
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      char *data
-    , size_t length
-    , node::smalloc::FreeCallback callback
-    , void *hint
-  ) {
-    return node::Buffer::New(
-        v8::Isolate::GetCurrent(), data, length, callback, hint);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      const char *data
-    , uint32_t size
-  ) {
-    return node::Buffer::New(v8::Isolate::GetCurrent(), data, size);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
-    return node::Buffer::New(v8::Isolate::GetCurrent(), size);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanBufferUse(
-      char* data
-    , uint32_t size
-  ) {
-    return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size);
-  }
-
-  NAN_INLINE bool NanHasInstance(
-      const v8::Persistent<v8::FunctionTemplate>& function_template
-    , v8::Handle<v8::Value> value
-  ) {
-    return NanNew(function_template)->HasInstance(value);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
-      v8::ExtensionConfiguration* extensions = NULL
-    , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-    , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
-  ) {
-    v8::Isolate* isolate = v8::Isolate::GetCurrent();
-    return v8::Local<v8::Context>::New(
-        isolate
-      , v8::Context::New(isolate, extensions, tmpl, obj)
-    );
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-    , const v8::ScriptOrigin& origin
-  ) {
-    v8::ScriptCompiler::Source source(s, origin);
-    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-  ) {
-    v8::ScriptCompiler::Source source(s);
-    return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(
-      v8::Handle<NanUnboundScript> script
-  ) {
-    return script->BindToCurrentContext()->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(
-      v8::Handle<NanBoundScript> script
-  ) {
-    return script->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::Function> func
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, func, argc, argv));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::String> symbol
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, symbol, argc, argv));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , const char* method
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-    return NanNew(node::MakeCallback(
-        v8::Isolate::GetCurrent(), target, method, argc, argv));
-  }
-
-  template<typename T>
-  NAN_INLINE void NanSetIsolateData(
-      v8::Isolate *isolate
-    , T *data
-  ) {
-      isolate->SetData(0, data);
-  }
-
-  template<typename T>
-  NAN_INLINE T *NanGetIsolateData(
-      v8::Isolate *isolate
-  ) {
-      return static_cast<T*>(isolate->GetData(0));
-  }
-
-  class NanAsciiString {
-   public:
-    NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new char[size + 1];
-      size = toStr->WriteOneByte(reinterpret_cast<unsigned char*>(buf));
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanAsciiString() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanAsciiString(const NanAsciiString&);
-    void operator=(const NanAsciiString&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUtf8String {
-   public:
-    NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Utf8Length();
-      buf = new char[size + 1];
-      toStr->WriteUtf8(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUtf8String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUtf8String(const NanUtf8String&);
-    void operator=(const NanUtf8String&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUcs2String {
-   public:
-    NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new uint16_t[size + 1];
-      toStr->Write(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE uint16_t* operator*() { return buf; }
-    NAN_INLINE const uint16_t* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUcs2String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUcs2String(const NanUcs2String&);
-    void operator=(const NanUcs2String&);
-
-    uint16_t *buf;
-    int size;
-  };
-
-#else
-// Node 0.8 and 0.10
-
-# define _NAN_METHOD_ARGS_TYPE const v8::Arguments&
-# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args
-# define _NAN_METHOD_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo &
-# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args
-# define _NAN_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo &
-# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args
-# define _NAN_SETTER_RETURN_TYPE void
-
-# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args
-# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args
-# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle<v8::Array>
-
-# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args
-# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle<v8::Boolean>
-
-# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args
-# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle<v8::Integer>
-
-# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args
-# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args
-# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle<v8::Value>
-
-# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args
-# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle<v8::Array>
-
-# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args
-# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle<v8::Boolean>
-
-# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo&
-# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args
-# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle<v8::Integer>
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::String> NanSymbol(
-      const char* data, int length = -1) {
-    return v8::String::NewSymbol(data, length);
-  }
-
-# define NanScope() v8::HandleScope scope
-# define NanEscapableScope() v8::HandleScope scope
-# define NanEscapeScope(val) scope.Close(val)
-# define NanLocker() v8::Locker locker
-# define NanUnlocker() v8::Unlocker unlocker
-# define NanReturnValue(value) return scope.Close(value)
-# define NanReturnHolder() NanReturnValue(args.Holder())
-# define NanReturnThis() NanReturnValue(args.This())
-# define NanReturnUndefined() return v8::Undefined()
-# define NanReturnNull() return v8::Null()
-# define NanReturnEmptyString() return v8::String::Empty()
-# define NanObjectWrapHandle(obj) v8::Local<v8::Object>::New(obj->handle_)
-
-  NAN_INLINE v8::Local<v8::Primitive> NanUndefined() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Undefined()));
-  }
-
-  NAN_INLINE v8::Local<v8::Primitive> NanNull() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::Null()));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanTrue() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::True()));
-  }
-
-  NAN_INLINE v8::Local<v8::Boolean> NanFalse() {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(v8::False()));
-  }
-
-  NAN_INLINE int NanAdjustExternalMemory(int bc) {
-    return static_cast<int>(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc));
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , const char *name
-    , v8::Handle<v8::Data> value) {
-    templ->Set(name, value);
-  }
-
-  NAN_INLINE void NanSetTemplate(
-      v8::Handle<v8::Template> templ
-    , v8::Handle<v8::String> name
-    , v8::Handle<v8::Data> value
-    , v8::PropertyAttribute attributes) {
-    templ->Set(name, value, attributes);
-  }
-
-  NAN_INLINE v8::Local<v8::Context> NanGetCurrentContext() {
-    return v8::Context::GetCurrent();
-  }
-
-  NAN_INLINE void* NanGetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index) {
-    return object->GetPointerFromInternalField(index);
-  }
-
-  NAN_INLINE void NanSetInternalFieldPointer(
-      v8::Handle<v8::Object> object
-    , int index
-    , void* value) {
-    object->SetPointerInInternalField(index, value);
-  }
-
-# define NAN_GC_CALLBACK(name)                                                 \
-    void name(v8::GCType type, v8::GCCallbackFlags flags)
-
-  NAN_INLINE void NanAddGCEpilogueCallback(
-    v8::GCEpilogueCallback callback
-  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::V8::AddGCEpilogueCallback(callback, gc_type_filter);
-  }
-  NAN_INLINE void NanRemoveGCEpilogueCallback(
-    v8::GCEpilogueCallback callback) {
-    v8::V8::RemoveGCEpilogueCallback(callback);
-  }
-  NAN_INLINE void NanAddGCPrologueCallback(
-    v8::GCPrologueCallback callback
-  , v8::GCType gc_type_filter = v8::kGCTypeAll) {
-    v8::V8::AddGCPrologueCallback(callback, gc_type_filter);
-  }
-  NAN_INLINE void NanRemoveGCPrologueCallback(
-    v8::GCPrologueCallback callback) {
-    v8::V8::RemoveGCPrologueCallback(callback);
-  }
-  NAN_INLINE void NanGetHeapStatistics(
-    v8::HeapStatistics *heap_statistics) {
-    v8::V8::GetHeapStatistics(heap_statistics);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanAssignPersistent(
-      v8::Persistent<T>& handle
-    , v8::Handle<T> obj) {
-      handle.Dispose();
-      handle = v8::Persistent<T>::New(obj);
-  }
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData;
-
-  template<typename T, typename P>
-  struct _NanWeakCallbackInfo {
-    typedef void (*Callback)(const _NanWeakCallbackData<T, P> &data);
-    NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
-      : parameter(param)
-      , callback(cb)
-      , persistent(v8::Persistent<T>::New(handle)) { }
-
-    NAN_INLINE ~_NanWeakCallbackInfo() {
-      persistent.Dispose();
-      persistent.Clear();
-    }
-
-    P* const parameter;
-    Callback const callback;
-    v8::Persistent<T> persistent;
-  };
-
-  template<typename T, typename P>
-  class _NanWeakCallbackData {
-   public:
-    NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
-      : info_(info) { }
-
-    NAN_INLINE v8::Local<T> GetValue() const {
-      return NanNew(info_->persistent);
-    }
-
-    NAN_INLINE P* GetParameter() const { return info_->parameter; }
-
-    NAN_INLINE bool IsNearDeath() const {
-      return info_->persistent.IsNearDeath();
-    }
-
-    NAN_INLINE void Revive() const;
-
-    NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
-      return info_;
-    }
-
-    NAN_DEPRECATED NAN_INLINE void Dispose() const {
-    }
-
-   private:
-    _NanWeakCallbackInfo<T, P>* info_;
-  };
-
-  template<typename T, typename P>
-  static void _NanWeakPersistentDispatcher(
-      v8::Persistent<v8::Value> object, void *data) {
-    _NanWeakCallbackInfo<T, P>* info =
-        static_cast<_NanWeakCallbackInfo<T, P>*>(data);
-    _NanWeakCallbackData<T, P> wcbd(info);
-    info->callback(wcbd);
-    if (wcbd.IsNearDeath()) {
-      delete wcbd.GetCallbackInfo();
-    }
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
-      info_->persistent.MakeWeak(
-          info_
-        , &_NanWeakPersistentDispatcher<T, P>);
-  }
-
-  template<typename T, typename P>
-  NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
-    v8::Handle<T> handle
-  , P* parameter
-  , typename _NanWeakCallbackInfo<T, P>::Callback callback) {
-      _NanWeakCallbackInfo<T, P> *cbinfo =
-        new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
-      cbinfo->persistent.MakeWeak(
-          cbinfo
-        , &_NanWeakPersistentDispatcher<T, P>);
-      return cbinfo;
-  }
-
-# define NAN_WEAK_CALLBACK(name)                                               \
-    template<typename T, typename P>                                           \
-    static void name(const _NanWeakCallbackData<T, P> &data)
-
-# define _NAN_ERROR(fun, errmsg)                                               \
-    fun(v8::String::New(errmsg))
-
-# define _NAN_THROW_ERROR(fun, errmsg)                                         \
-    do {                                                                       \
-      NanScope();                                                              \
-      return v8::Local<v8::Value>::New(                                        \
-        v8::ThrowException(_NAN_ERROR(fun, errmsg)));                          \
-    } while (0);
-
-  NAN_INLINE v8::Local<v8::Value> NanError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(const char* errmsg) {
-    _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(
-      v8::Handle<v8::Value> error
-  ) {
-    NanScope();
-    return v8::Local<v8::Value>::New(v8::ThrowException(error));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    v8::Local<v8::Value> err = v8::Exception::Error(v8::String::New(msg));
-    v8::Local<v8::Object> obj = err.As<v8::Object>();
-    obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber));
-    return err;
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowError(
-      const char *msg
-    , const int errorNumber
-  ) {
-    return NanThrowError(NanError(msg, errorNumber));
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanTypeError(const char* errmsg) {
-    return _NAN_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowTypeError(
-      const char* errmsg
-  ) {
-    _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRangeError(
-      const char* errmsg
-  ) {
-    return _NAN_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanThrowRangeError(
-      const char* errmsg
-  ) {
-    _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
-  }
-
-  template<typename T>
-  NAN_INLINE void NanDisposePersistent(
-      v8::Persistent<T> &handle) {  // NOLINT(runtime/references)
-    handle.Dispose();
-    handle.Clear();
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      char *data
-    , size_t length
-    , node::Buffer::free_callback callback
-    , void *hint
-  ) {
-    return NanNew(
-        node::Buffer::New(data, length, callback, hint)->handle_);
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
-      const char *data
-    , uint32_t size
-  ) {
-#if NODE_MODULE_VERSION >= 0x000B
-    return NanNew(node::Buffer::New(data, size)->handle_);
-#else
-    return NanNew(
-      node::Buffer::New(const_cast<char*>(data), size)->handle_);
-#endif
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
-    return NanNew(node::Buffer::New(size)->handle_);
-  }
-
-  NAN_INLINE void FreeData(char *data, void *hint) {
-    delete[] data;
-  }
-
-  NAN_INLINE v8::Local<v8::Object> NanBufferUse(
-      char* data
-    , uint32_t size
-  ) {
-    return NanNew(
-        node::Buffer::New(data, size, FreeData, NULL)->handle_);
-  }
-
-  NAN_INLINE bool NanHasInstance(
-      const v8::Persistent<v8::FunctionTemplate>& function_template
-    , v8::Handle<v8::Value> value
-  ) {
-    return function_template->HasInstance(value);
-  }
-
-  NAN_DEPRECATED NAN_INLINE v8::Local<v8::Context> NanNewContextHandle(
-      v8::ExtensionConfiguration* extensions = NULL
-    , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-    , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
-  ) {
-    v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
-    v8::Local<v8::Context> lctx = NanNew(ctx);
-    ctx.Dispose();
-    return lctx;
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-      v8::Local<v8::String> s
-    , const v8::ScriptOrigin& origin
-  ) {
-    return v8::Script::Compile(s, const_cast<v8::ScriptOrigin *>(&origin));
-  }
-
-  NAN_INLINE v8::Local<NanBoundScript> NanCompileScript(
-    v8::Local<v8::String> s
-  ) {
-    return v8::Script::Compile(s);
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanRunScript(v8::Handle<v8::Script> script) {
-    return script->Run();
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::Function> func
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, func, argc, argv));
-# else
-    v8::TryCatch try_catch;
-    v8::Local<v8::Value> result = func->Call(target, argc, argv);
-    if (try_catch.HasCaught()) {
-        node::FatalException(try_catch);
-    }
-    return result;
-# endif
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , v8::Handle<v8::String> symbol
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, symbol, argc, argv));
-# else
-    v8::Local<v8::Function> callback = target->Get(symbol).As<v8::Function>();
-    return NanMakeCallback(target, callback, argc, argv);
-# endif
-  }
-
-  NAN_INLINE v8::Local<v8::Value> NanMakeCallback(
-      v8::Handle<v8::Object> target
-    , const char* method
-    , int argc
-    , v8::Handle<v8::Value>* argv) {
-# if NODE_VERSION_AT_LEAST(0, 8, 0)
-    return NanNew(node::MakeCallback(target, method, argc, argv));
-# else
-    return NanMakeCallback(target, NanNew(method), argc, argv);
-# endif
-  }
-
-  template<typename T>
-  NAN_INLINE void NanSetIsolateData(
-      v8::Isolate *isolate
-    , T *data
-  ) {
-      isolate->SetData(data);
-  }
-
-  template<typename T>
-  NAN_INLINE T *NanGetIsolateData(
-      v8::Isolate *isolate
-  ) {
-      return static_cast<T*>(isolate->GetData());
-  }
-
-  class NanAsciiString {
-   public:
-    NAN_INLINE explicit NanAsciiString(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new char[size + 1];
-      size = toStr->WriteAscii(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanAsciiString() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanAsciiString(const NanAsciiString&);
-    void operator=(const NanAsciiString&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUtf8String {
-   public:
-    NAN_INLINE explicit NanUtf8String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Utf8Length();
-      buf = new char[size + 1];
-      toStr->WriteUtf8(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE char* operator*() { return buf; }
-    NAN_INLINE const char* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUtf8String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUtf8String(const NanUtf8String&);
-    void operator=(const NanUtf8String&);
-
-    char *buf;
-    int size;
-  };
-
-  class NanUcs2String {
-   public:
-    NAN_INLINE explicit NanUcs2String(v8::Handle<v8::Value> from) {
-      v8::Local<v8::String> toStr = from->ToString();
-      size = toStr->Length();
-      buf = new uint16_t[size + 1];
-      toStr->Write(buf);
-    }
-
-    NAN_DEPRECATED NAN_INLINE int Size() const {
-      return size;
-    }
-
-    NAN_INLINE int length() const {
-      return size;
-    }
-
-    NAN_INLINE uint16_t* operator*() { return buf; }
-    NAN_INLINE const uint16_t* operator*() const { return buf; }
-
-    NAN_INLINE ~NanUcs2String() {
-      delete[] buf;
-    }
-
-   private:
-    // disallow copying and assigning
-    NanUcs2String(const NanUcs2String&);
-    void operator=(const NanUcs2String&);
-
-    uint16_t *buf;
-    int size;
-  };
-
-#endif  // NODE_MODULE_VERSION
-
-typedef void (*NanFreeCallback)(char *data, void *hint);
-
-#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS)
-#define NAN_GETTER(name)                                                       \
-    _NAN_GETTER_RETURN_TYPE name(                                              \
-        v8::Local<v8::String> property                                         \
-      , _NAN_GETTER_ARGS)
-#define NAN_SETTER(name)                                                       \
-    _NAN_SETTER_RETURN_TYPE name(                                              \
-        v8::Local<v8::String> property                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_SETTER_ARGS)
-#define NAN_PROPERTY_GETTER(name)                                              \
-    _NAN_PROPERTY_GETTER_RETURN_TYPE name(                                     \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_GETTER_ARGS)
-#define NAN_PROPERTY_SETTER(name)                                              \
-    _NAN_PROPERTY_SETTER_RETURN_TYPE name(                                     \
-        v8::Local<v8::String> property                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_PROPERTY_SETTER_ARGS)
-#define NAN_PROPERTY_ENUMERATOR(name)                                          \
-    _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS)
-#define NAN_PROPERTY_DELETER(name)                                             \
-    _NAN_PROPERTY_DELETER_RETURN_TYPE name(                                    \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_DELETER_ARGS)
-#define NAN_PROPERTY_QUERY(name)                                               \
-    _NAN_PROPERTY_QUERY_RETURN_TYPE name(                                      \
-        v8::Local<v8::String> property                                         \
-      , _NAN_PROPERTY_QUERY_ARGS)
-# define NAN_INDEX_GETTER(name)                                                \
-    _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS)
-#define NAN_INDEX_SETTER(name)                                                 \
-    _NAN_INDEX_SETTER_RETURN_TYPE name(                                        \
-        uint32_t index                                                         \
-      , v8::Local<v8::Value> value                                             \
-      , _NAN_INDEX_SETTER_ARGS)
-#define NAN_INDEX_ENUMERATOR(name)                                             \
-    _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS)
-#define NAN_INDEX_DELETER(name)                                                \
-    _NAN_INDEX_DELETER_RETURN_TYPE name(                                       \
-        uint32_t index                                                         \
-      , _NAN_INDEX_DELETER_ARGS)
-#define NAN_INDEX_QUERY(name)                                                  \
-    _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS)
-
-class NanCallback {
- public:
-  NanCallback() {
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(handle, obj);
-  }
-
-  explicit NanCallback(const v8::Handle<v8::Function> &fn) {
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(handle, obj);
-    SetFunction(fn);
-  }
-
-  ~NanCallback() {
-    if (handle.IsEmpty()) return;
-    NanDisposePersistent(handle);
-  }
-
-  NAN_INLINE void SetFunction(const v8::Handle<v8::Function> &fn) {
-    NanScope();
-    NanNew(handle)->Set(kCallbackIndex, fn);
-  }
-
-  NAN_INLINE v8::Local<v8::Function> GetFunction() const {
-    NanEscapableScope();
-    return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex)
-        .As<v8::Function>());
-  }
-
-  NAN_INLINE bool IsEmpty() const {
-    NanScope();
-    return NanNew(handle)->Get(kCallbackIndex)->IsUndefined();
-  }
-
-  v8::Handle<v8::Value> Call(int argc, v8::Handle<v8::Value> argv[]) const {
-    NanEscapableScope();
-#if (NODE_MODULE_VERSION > 0x000B)  // 0.11.12+
-    v8::Isolate* isolate = v8::Isolate::GetCurrent();
-    v8::Local<v8::Function> callback = NanNew(handle)->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(node::MakeCallback(
-        isolate
-      , isolate->GetCurrentContext()->Global()
-      , callback
-      , argc
-      , argv
-    ));
-#else
-#if NODE_VERSION_AT_LEAST(0, 8, 0)
-    v8::Local<v8::Function> callback = handle->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(node::MakeCallback(
-        v8::Context::GetCurrent()->Global()
-      , callback
-      , argc
-      , argv
-    ));
-#else
-    v8::Local<v8::Function> callback = handle->
-        Get(kCallbackIndex).As<v8::Function>();
-    return NanEscapeScope(NanMakeCallback(
-        v8::Context::GetCurrent()->Global(), callback, argc, argv));
-#endif
-#endif
-  }
-
- private:
-  v8::Persistent<v8::Object> handle;
-  static const uint32_t kCallbackIndex = 0;
-};
-
-/* abstract */ class NanAsyncWorker {
- public:
-  explicit NanAsyncWorker(NanCallback *callback_)
-      : callback(callback_), errmsg_(NULL) {
-    request.data = this;
-
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(persistentHandle, obj);
-  }
-
-  virtual ~NanAsyncWorker() {
-    NanScope();
-
-    if (!persistentHandle.IsEmpty())
-      NanDisposePersistent(persistentHandle);
-    if (callback)
-      delete callback;
-    if (errmsg_)
-      delete[] errmsg_;
-  }
-
-  virtual void WorkComplete() {
-    NanScope();
-
-    if (errmsg_ == NULL)
-      HandleOKCallback();
-    else
-      HandleErrorCallback();
-    delete callback;
-    callback = NULL;
-  }
-
-  NAN_INLINE void SaveToPersistent(
-      const char *key, const v8::Local<v8::Object> &obj) {
-    v8::Local<v8::Object> handle = NanNew(persistentHandle);
-    handle->Set(NanNew<v8::String>(key), obj);
-  }
-
-  v8::Local<v8::Object> GetFromPersistent(const char *key) const {
-    NanEscapableScope();
-    v8::Local<v8::Object> handle = NanNew(persistentHandle);
-    return NanEscapeScope(handle->Get(NanNew(key)).As<v8::Object>());
-  }
-
-  virtual void Execute() = 0;
-
-  uv_work_t request;
-
-  virtual void Destroy() {
-      delete this;
-  }
-
- protected:
-  v8::Persistent<v8::Object> persistentHandle;
-  NanCallback *callback;
-
-  virtual void HandleOKCallback() {
-    callback->Call(0, NULL);
-  }
-
-  virtual void HandleErrorCallback() {
-    NanScope();
-
-    v8::Local<v8::Value> argv[] = {
-        v8::Exception::Error(NanNew<v8::String>(ErrorMessage()))
-    };
-    callback->Call(1, argv);
-  }
-
-  void SetErrorMessage(const char *msg) {
-    if (errmsg_) {
-      delete[] errmsg_;
-    }
-
-    size_t size = strlen(msg) + 1;
-    errmsg_ = new char[size];
-    memcpy(errmsg_, msg, size);
-  }
-
-  const char* ErrorMessage() const {
-    return errmsg_;
-  }
-
- private:
-  char *errmsg_;
-};
-
-/* abstract */ class NanAsyncProgressWorker : public NanAsyncWorker {
- public:
-  explicit NanAsyncProgressWorker(NanCallback *callback_)
-      : NanAsyncWorker(callback_), asyncdata_(NULL), asyncsize_(0) {
-    async = new uv_async_t;
-    uv_async_init(
-        uv_default_loop()
-      , async
-      , AsyncProgress_
-    );
-    async->data = this;
-
-    uv_mutex_init(&async_lock);
-  }
-
-  virtual ~NanAsyncProgressWorker() {
-    uv_mutex_destroy(&async_lock);
-
-    if (asyncdata_) {
-      delete[] asyncdata_;
-    }
-  }
-
-  void WorkProgress() {
-    uv_mutex_lock(&async_lock);
-    char *data = asyncdata_;
-    size_t size = asyncsize_;
-    asyncdata_ = NULL;
-    uv_mutex_unlock(&async_lock);
-
-    // Dont send progress events after we've already completed.
-    if (callback) {
-        HandleProgressCallback(data, size);
-    }
-    delete[] data;
-  }
-
-  class ExecutionProgress {
-    friend class NanAsyncProgressWorker;
-   public:
-    // You could do fancy generics with templates here.
-    void Send(const char* data, size_t size) const {
-        that_->SendProgress_(data, size);
-    }
-
-   private:
-    explicit ExecutionProgress(NanAsyncProgressWorker* that) : that_(that) {}
-    // Prohibit copying and assignment.
-    ExecutionProgress(const ExecutionProgress&);
-    void operator=(const ExecutionProgress&);
-  #if __cplusplus >= 201103L
-    // Prohibit C++11 move semantics.
-    ExecutionProgress(ExecutionProgress&&) = delete;
-    void operator=(ExecutionProgress&&) = delete;
-  #endif
-    NanAsyncProgressWorker* const that_;
-  };
-
-  virtual void Execute(const ExecutionProgress& progress) = 0;
-  virtual void HandleProgressCallback(const char *data, size_t size) = 0;
-
-  virtual void Destroy() {
-      uv_close(reinterpret_cast<uv_handle_t*>(async), AsyncClose_);
-  }
-
- private:
-  void Execute() /*final override*/ {
-      ExecutionProgress progress(this);
-      Execute(progress);
-  }
-
-  void SendProgress_(const char *data, size_t size) {
-    char *new_data = new char[size];
-    memcpy(new_data, data, size);
-
-    uv_mutex_lock(&async_lock);
-    char *old_data = asyncdata_;
-    asyncdata_ = new_data;
-    asyncsize_ = size;
-    uv_mutex_unlock(&async_lock);
-
-    if (old_data) {
-      delete[] old_data;
-    }
-    uv_async_send(async);
-  }
-
-  NAN_INLINE static NAUV_WORK_CB(AsyncProgress_) {
-    NanAsyncProgressWorker *worker =
-            static_cast<NanAsyncProgressWorker*>(async->data);
-    worker->WorkProgress();
-  }
-
-  NAN_INLINE static void AsyncClose_(uv_handle_t* handle) {
-    NanAsyncProgressWorker *worker =
-            static_cast<NanAsyncProgressWorker*>(handle->data);
-    delete reinterpret_cast<uv_async_t*>(handle);
-    delete worker;
-  }
-
-  uv_async_t *async;
-  uv_mutex_t async_lock;
-  char *asyncdata_;
-  size_t asyncsize_;
-};
-
-NAN_INLINE void NanAsyncExecute (uv_work_t* req) {
-  NanAsyncWorker *worker = static_cast<NanAsyncWorker*>(req->data);
-  worker->Execute();
-}
-
-NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) {
-  NanAsyncWorker* worker = static_cast<NanAsyncWorker*>(req->data);
-  worker->WorkComplete();
-  worker->Destroy();
-}
-
-NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) {
-  uv_queue_work(
-      uv_default_loop()
-    , &worker->request
-    , NanAsyncExecute
-    , (uv_after_work_cb)NanAsyncExecuteComplete
-  );
-}
-
-//// Base 64 ////
-
-#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
-
-// Doesn't check for padding at the end.  Can be 1-2 bytes over.
-NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) {
-  size_t remainder = size % 4;
-
-  size = (size / 4) * 3;
-  if (remainder) {
-    if (size == 0 && remainder == 1) {
-      // special case: 1-byte input cannot be decoded
-      size = 0;
-    } else {
-      // non-padded input, add 1 or 2 extra bytes
-      size += 1 + (remainder == 3);
-    }
-  }
-
-  return size;
-}
-
-template<typename T>
-NAN_INLINE size_t _nan_base64_decoded_size(
-    const T* src
-  , size_t size
-) {
-  if (size == 0)
-    return 0;
-
-  if (src[size - 1] == '=')
-    size--;
-  if (size > 0 && src[size - 1] == '=')
-    size--;
-
-  return _nan_base64_decoded_size_fast(size);
-}
-
-// supports regular and URL-safe base64
-static const int _nan_unbase64_table[] = {
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63
-  , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1
-  , -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14
-  , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63
-  , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
-  , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)]
-
-template<typename T> static size_t _nan_base64_decode(
-    char* buf
-  , size_t len
-  , const T* src
-  , const size_t srcLen
-) {
-  char* dst = buf;
-  char* dstEnd = buf + len;
-  const T* srcEnd = src + srcLen;
-
-  while (src < srcEnd && dst < dstEnd) {
-    ptrdiff_t remaining = srcEnd - src;
-    char a, b, c, d;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining == 0 || *src == '=') break;
-    a = _nan_unbase64(*src++);
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 1 || *src == '=') break;
-    b = _nan_unbase64(*src++);
-
-    *dst++ = (a << 2) | ((b & 0x30) >> 4);
-    if (dst == dstEnd) break;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 2 || *src == '=') break;
-    c = _nan_unbase64(*src++);
-
-    *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
-    if (dst == dstEnd) break;
-
-    while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
-    if (remaining <= 3 || *src == '=') break;
-    d = _nan_unbase64(*src++);
-
-    *dst++ = ((c & 0x03) << 6) | (d & 0x3F);
-  }
-
-  return dst - buf;
-}
-
-//// HEX ////
-
-template<typename T> unsigned _nan_hex2bin(T c) {
-  if (c >= '0' && c <= '9') return c - '0';
-  if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
-  if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
-  return static_cast<unsigned>(-1);
-}
-
-template<typename T> static size_t _nan_hex_decode(
-    char* buf
-  , size_t len
-  , const T* src
-  , const size_t srcLen
-) {
-  size_t i;
-  for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
-    unsigned a = _nan_hex2bin(src[i * 2 + 0]);
-    unsigned b = _nan_hex2bin(src[i * 2 + 1]);
-    if (!~a || !~b) return i;
-    buf[i] = a * 16 + b;
-  }
-
-  return i;
-}
-
-namespace NanIntern {
-
-inline
-NanExternalOneByteStringResource const*
-GetExternalResource(v8::Local<v8::String> str) {
-#if NODE_MODULE_VERSION < 42
-    return str->GetExternalAsciiStringResource();
-#else  // io.js v1.0.0
-    return str->GetExternalOneByteStringResource();
-#endif
-}
-
-inline
-bool
-IsExternal(v8::Local<v8::String> str) {
-#if NODE_MODULE_VERSION < 42
-    return str->IsExternalAscii();
-#else  // io.js v1.0.0
-    return str->IsExternalOneByte();
-#endif
-}
-
-}  // end of namespace NanIntern
-
-static bool _NanGetExternalParts(
-    v8::Handle<v8::Value> val
-  , const char** data
-  , size_t* len
-) {
-  if (node::Buffer::HasInstance(val)) {
-    *data = node::Buffer::Data(val.As<v8::Object>());
-    *len = node::Buffer::Length(val.As<v8::Object>());
-    return true;
-  }
-
-  assert(val->IsString());
-  v8::Local<v8::String> str = NanNew(val.As<v8::String>());
-
-  if (NanIntern::IsExternal(str)) {
-    const NanExternalOneByteStringResource* ext;
-    ext = NanIntern::GetExternalResource(str);
-    *data = ext->data();
-    *len = ext->length();
-    return true;
-  }
-
-  if (str->IsExternal()) {
-    const v8::String::ExternalStringResource* ext;
-    ext = str->GetExternalStringResource();
-    *data = reinterpret_cast<const char*>(ext->data());
-    *len = ext->length();
-    return true;
-  }
-
-  return false;
-}
-
-namespace Nan {
-  enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
-}
-
-#if !NODE_VERSION_AT_LEAST(0, 10, 0)
-# include "nan_string_bytes.h"  // NOLINT(build/include)
-#endif
-
-NAN_INLINE v8::Local<v8::Value> NanEncode(
-    const void *buf, size_t len, enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION >= 42)
-  v8::Isolate* isolate = v8::Isolate::GetCurrent();
-  node::encoding node_enc = static_cast<node::encoding>(encoding);
-
-  if (encoding == Nan::UCS2) {
-    return node::Encode(
-        isolate
-      , reinterpret_cast<const uint16_t *>(buf)
-      , len / 2);
-  } else {
-    return node::Encode(
-        isolate
-      , reinterpret_cast<const char *>(buf)
-      , len
-      , node_enc);
-  }
-#elif (NODE_MODULE_VERSION > 0x000B)
-  return node::Encode(
-      v8::Isolate::GetCurrent()
-    , buf, len
-    , static_cast<node::encoding>(encoding));
-#else
-# if NODE_VERSION_AT_LEAST(0, 10, 0)
-  return node::Encode(buf, len, static_cast<node::encoding>(encoding));
-# else
-  return NanIntern::Encode(reinterpret_cast<const char*>(buf), len, encoding);
-# endif
-#endif
-}
-
-NAN_INLINE ssize_t NanDecodeBytes(
-    v8::Handle<v8::Value> val, enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION > 0x000B)
-  return node::DecodeBytes(
-      v8::Isolate::GetCurrent()
-    , val
-    , static_cast<node::encoding>(encoding));
-#else
-# if (NODE_MODULE_VERSION < 0x000B)
-  if (encoding == Nan::BUFFER) {
-    return node::DecodeBytes(val, node::BINARY);
-  }
-# endif
-  return node::DecodeBytes(val, static_cast<node::encoding>(encoding));
-#endif
-}
-
-NAN_INLINE ssize_t NanDecodeWrite(
-    char *buf
-  , size_t len
-  , v8::Handle<v8::Value> val
-  , enum Nan::Encoding encoding = Nan::BINARY) {
-#if (NODE_MODULE_VERSION > 0x000B)
-  return node::DecodeWrite(
-      v8::Isolate::GetCurrent()
-    , buf
-    , len
-    , val
-    , static_cast<node::encoding>(encoding));
-#else
-# if (NODE_MODULE_VERSION < 0x000B)
-  if (encoding == Nan::BUFFER) {
-    return node::DecodeWrite(buf, len, val, node::BINARY);
-  }
-# endif
-  return node::DecodeWrite(
-      buf
-    , len
-    , val
-    , static_cast<node::encoding>(encoding));
-#endif
-}
-
-/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString(
-    v8::Handle<v8::Value> from
-  , enum Nan::Encoding encoding
-  , size_t *datalen
-  , void *buf
-  , size_t buflen
-  , int flags
-) {
-  NanScope();
-
-  size_t sz_;
-  size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION);
-  char *data = NULL;
-  size_t len;
-  bool is_extern = _NanGetExternalParts(
-      from
-    , const_cast<const char**>(&data)
-    , &len);
-
-  if (is_extern && !term_len) {
-    NanSetPointerSafe(datalen, len);
-    return data;
-  }
-
-  v8::Local<v8::String> toStr = from->ToString();
-
-  char *to = static_cast<char *>(buf);
-
-  switch (encoding) {
-    case Nan::ASCII:
-#if NODE_MODULE_VERSION < 0x000C
-      sz_ = toStr->Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-      NanSetPointerSafe<size_t>(
-          datalen
-        , toStr->WriteAscii(to, 0, static_cast<int>(sz_ + term_len), flags));
-      return to;
-#endif
-    case Nan::BINARY:
-    case Nan::BUFFER:
-      sz_ = toStr->Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-#if NODE_MODULE_VERSION < 0x000C
-      {
-        uint16_t* twobytebuf = new uint16_t[sz_ + term_len];
-
-        size_t somelen = toStr->Write(twobytebuf, 0,
-          static_cast<int>(sz_ + term_len), flags);
-
-        for (size_t i = 0; i < sz_ + term_len && i < somelen + term_len; i++) {
-          unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
-          to[i] = *b;
-        }
-
-        NanSetPointerSafe<size_t>(datalen, somelen);
-
-        delete[] twobytebuf;
-        return to;
-      }
-#else
-      NanSetPointerSafe<size_t>(
-        datalen,
-        toStr->WriteOneByte(
-            reinterpret_cast<uint8_t *>(to)
-          , 0
-          , static_cast<int>(sz_ + term_len)
-          , flags));
-      return to;
-#endif
-    case Nan::UTF8:
-      sz_ = toStr->Utf8Length();
-      if (to == NULL) {
-        to = new char[sz_ + term_len];
-      } else {
-        assert(buflen >= sz_ + term_len && "too small buffer");
-      }
-      NanSetPointerSafe<size_t>(
-          datalen
-        , toStr->WriteUtf8(to, static_cast<int>(sz_ + term_len)
-            , NULL, flags)
-          - term_len);
-      return to;
-    case Nan::BASE64:
-      {
-        v8::String::Value value(toStr);
-        sz_ = _nan_base64_decoded_size(*value, value.length());
-        if (to == NULL) {
-          to = new char[sz_ + term_len];
-        } else {
-          assert(buflen >= sz_ + term_len);
-        }
-        NanSetPointerSafe<size_t>(
-            datalen
-          , _nan_base64_decode(to, sz_, *value, value.length()));
-        if (term_len) {
-          to[sz_] = '\0';
-        }
-        return to;
-      }
-    case Nan::UCS2:
-      {
-        sz_ = toStr->Length();
-        if (to == NULL) {
-          to = new char[(sz_ + term_len) * 2];
-        } else {
-          assert(buflen >= (sz_ + term_len) * 2 && "too small buffer");
-        }
-
-        int bc = 2 * toStr->Write(
-            reinterpret_cast<uint16_t *>(to)
-          , 0
-          , static_cast<int>(sz_ + term_len)
-          , flags);
-        NanSetPointerSafe<size_t>(datalen, bc);
-        return to;
-      }
-    case Nan::HEX:
-      {
-        v8::String::Value value(toStr);
-        sz_ = value.length();
-        assert(!(sz_ & 1) && "bad hex data");
-        if (to == NULL) {
-          to = new char[sz_ / 2 + term_len];
-        } else {
-          assert(buflen >= sz_ / 2 + term_len && "too small buffer");
-        }
-        NanSetPointerSafe<size_t>(
-            datalen
-          , _nan_hex_decode(to, sz_ / 2, *value, value.length()));
-      }
-      if (term_len) {
-        to[sz_ / 2] = '\0';
-      }
-      return to;
-    default:
-      assert(0 && "unknown encoding");
-  }
-  return to;
-}
-
-NAN_DEPRECATED NAN_INLINE void* NanRawString(
-    v8::Handle<v8::Value> from
-  , enum Nan::Encoding encoding
-  , size_t *datalen
-  , void *buf
-  , size_t buflen
-  , int flags
-) {
-  return _NanRawString(from, encoding, datalen, buf, buflen, flags);
-}
-
-
-NAN_DEPRECATED NAN_INLINE char* NanCString(
-    v8::Handle<v8::Value> from
-  , size_t *datalen
-  , char *buf = NULL
-  , size_t buflen = 0
-  , int flags = v8::String::NO_OPTIONS
-) {
-    return static_cast<char *>(
-      _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags)
-    );
-}
-
-NAN_INLINE void NanSetPrototypeTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , const char *name
-  , v8::Handle<v8::Data> value
-) {
-  NanSetTemplate(templ->PrototypeTemplate(), name, value);
-}
-
-NAN_INLINE void NanSetPrototypeTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , v8::Handle<v8::String> name
-  , v8::Handle<v8::Data> value
-  , v8::PropertyAttribute attributes
-) {
-  NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes);
-}
-
-NAN_INLINE void NanSetInstanceTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , const char *name
-  , v8::Handle<v8::Data> value
-) {
-  NanSetTemplate(templ->InstanceTemplate(), name, value);
-}
-
-NAN_INLINE void NanSetInstanceTemplate(
-    v8::Local<v8::FunctionTemplate> templ
-  , v8::Handle<v8::String> name
-  , v8::Handle<v8::Data> value
-  , v8::PropertyAttribute attributes
-) {
-  NanSetTemplate(templ->InstanceTemplate(), name, value, attributes);
-}
-
-//=== Export ==================================================================
-
-inline
-void
-NanExport(v8::Handle<v8::Object> target, const char * name,
-    NanFunctionCallback f) {
-  target->Set(NanNew<v8::String>(name),
-      NanNew<v8::FunctionTemplate>(f)->GetFunction());
-}
-
-//=== Tap Reverse Binding =====================================================
-
-struct NanTap {
-  explicit NanTap(v8::Handle<v8::Value> t) : t_() {
-    NanAssignPersistent(t_, t->ToObject());
-  }
-
-  ~NanTap() { NanDisposePersistent(t_); }  // not sure if neccessary
-
-  inline void plan(int i) {
-    v8::Handle<v8::Value> arg = NanNew(i);
-    NanMakeCallback(NanNew(t_), "plan", 1, &arg);
-  }
-
-  inline void ok(bool isOk, const char * msg = NULL) {
-    v8::Handle<v8::Value> args[2];
-    args[0] = NanNew(isOk);
-    if (msg) args[1] = NanNew(msg);
-    NanMakeCallback(NanNew(t_), "ok", msg ? 2 : 1, args);
-  }
-
- private:
-  v8::Persistent<v8::Object> t_;
-};
-
-#define NAN_STRINGIZE2(x) #x
-#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x)
-#define NAN_TEST_EXPRESSION(expression) \
-  ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression
-
-#define return_NanValue(v) NanReturnValue(v)
-#define return_NanUndefined() NanReturnUndefined()
-#define NAN_EXPORT(target, function) NanExport(target, #function, function)
-
-#endif  // NAN_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_12_inl.h b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_12_inl.h
deleted file mode 100644
index ff63ec0c..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_12_inl.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_IMPLEMENTATION_12_INL_H_
-#define NAN_IMPLEMENTATION_12_INL_H_
-//==============================================================================
-// node v0.11 implementation
-//==============================================================================
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-namespace NanIntern {
-
-//=== Array ====================================================================
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New() {
-  return v8::Array::New(v8::Isolate::GetCurrent());
-}
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New(int length) {
-  return v8::Array::New(v8::Isolate::GetCurrent(), length);
-}
-
-//=== Boolean ==================================================================
-
-Factory<v8::Boolean>::return_t
-Factory<v8::Boolean>::New(bool value) {
-  return v8::Boolean::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Boolean Object ===========================================================
-
-Factory<v8::BooleanObject>::return_t
-Factory<v8::BooleanObject>::New(bool value) {
-  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-}
-
-//=== Context ==================================================================
-
-Factory<v8::Context>::return_t
-Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
-                         , v8::Handle<v8::ObjectTemplate> tmpl
-                         , v8::Handle<v8::Value> obj) {
-  return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj);
-}
-
-//=== Date =====================================================================
-
-Factory<v8::Date>::return_t
-Factory<v8::Date>::New(double value) {
-  return v8::Date::New(v8::Isolate::GetCurrent(), value).As<v8::Date>();
-}
-
-//=== External =================================================================
-
-Factory<v8::External>::return_t
-Factory<v8::External>::New(void * value) {
-  return v8::External::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Function =================================================================
-
-Factory<v8::Function>::return_t
-Factory<v8::Function>::New( NanFunctionCallback callback
-                          , v8::Handle<v8::Value> data) {
-  return v8::Function::New( v8::Isolate::GetCurrent()
-                          , callback
-                          , data);
-}
-
-//=== Function Template ========================================================
-
-Factory<v8::FunctionTemplate>::return_t
-Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
-                                  , v8::Handle<v8::Value> data
-                                  , v8::Handle<v8::Signature> signature) {
-  return v8::FunctionTemplate::New( v8::Isolate::GetCurrent()
-                                  , callback
-                                  , data
-                                  , signature);
-}
-
-//=== Number ===================================================================
-
-Factory<v8::Number>::return_t
-Factory<v8::Number>::New(double value) {
-  return v8::Number::New(v8::Isolate::GetCurrent(), value);
-}
-
-//=== Number Object ============================================================
-
-Factory<v8::NumberObject>::return_t
-Factory<v8::NumberObject>::New(double value) {
-  return v8::NumberObject::New( v8::Isolate::GetCurrent()
-                              , value).As<v8::NumberObject>();
-}
-
-//=== Integer, Int32 and Uint32 ================================================
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(int32_t value) {
-  return To<T>(T::New(v8::Isolate::GetCurrent(), value));
-}
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(uint32_t value) {
-  return To<T>(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(int32_t value) {
-  return To<v8::Uint32>(
-      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(uint32_t value) {
-  return To<v8::Uint32>(
-      v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value));
-}
-
-//=== Object ===================================================================
-
-Factory<v8::Object>::return_t
-Factory<v8::Object>::New() {
-  return v8::Object::New(v8::Isolate::GetCurrent());
-}
-
-//=== Object Template ==========================================================
-
-Factory<v8::ObjectTemplate>::return_t
-Factory<v8::ObjectTemplate>::New() {
-  return v8::ObjectTemplate::New(v8::Isolate::GetCurrent());
-}
-
-//=== RegExp ===================================================================
-
-Factory<v8::RegExp>::return_t
-Factory<v8::RegExp>::New(
-    v8::Handle<v8::String> pattern
-  , v8::RegExp::Flags flags) {
-  return v8::RegExp::New(pattern, flags);
-}
-
-//=== Script ===================================================================
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source) {
-  v8::ScriptCompiler::Source src(source);
-  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
-}
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source
-                        , v8::ScriptOrigin const& origin) {
-  v8::ScriptCompiler::Source src(source, origin);
-  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src);
-}
-
-//=== Signature ================================================================
-
-Factory<v8::Signature>::return_t
-Factory<v8::Signature>::New( Factory<v8::Signature>::FTH receiver
-                           , int argc
-                           , Factory<v8::Signature>::FTH argv[]) {
-  return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv);
-}
-
-//=== String ===================================================================
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New() {
-  return v8::String::Empty(v8::Isolate::GetCurrent());
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const char * value, int length) {
-  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value,
-      v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(std::string const& value) {
-  assert(value.size() <= INT_MAX && "string too long");
-  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(),
-      value.data(), v8::String::kNormalString, static_cast<int>(value.size()));
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint8_t * value, int length) {
-  return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value,
-        v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint16_t * value, int length) {
-  return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value,
-        v8::String::kNormalString, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
-  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(NanExternalOneByteStringResource * value) {
-  return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
-}
-
-//=== String Object ============================================================
-
-Factory<v8::StringObject>::return_t
-Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
-  return v8::StringObject::New(value).As<v8::StringObject>();
-}
-
-//=== Unbound Script ===========================================================
-
-Factory<v8::UnboundScript>::return_t
-Factory<v8::UnboundScript>::New(v8::Local<v8::String> source) {
-  v8::ScriptCompiler::Source src(source);
-  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
-}
-
-Factory<v8::UnboundScript>::return_t
-Factory<v8::UnboundScript>::New( v8::Local<v8::String> source
-                               , v8::ScriptOrigin const& origin) {
-  v8::ScriptCompiler::Source src(source, origin);
-  return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src);
-}
-
-}  // end of namespace NanIntern
-
-//=== Presistents and Handles ==================================================
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Handle<T> h) {
-  return v8::Local<T>::New(v8::Isolate::GetCurrent(), h);
-}
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
-  return v8::Local<T>::New(v8::Isolate::GetCurrent(), p);
-}
-
-#endif  // NAN_IMPLEMENTATION_12_INL_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_pre_12_inl.h b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_pre_12_inl.h
deleted file mode 100644
index 85dd2754..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_implementation_pre_12_inl.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_
-#define NAN_IMPLEMENTATION_PRE_12_INL_H_
-
-#include <algorithm>
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# include <vector>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-# include <vector>
-#endif
-
-//==============================================================================
-// node v0.10 implementation
-//==============================================================================
-
-namespace NanIntern {
-
-//=== Array ====================================================================
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New() {
-  return v8::Array::New();
-}
-
-Factory<v8::Array>::return_t
-Factory<v8::Array>::New(int length) {
-  return v8::Array::New(length);
-}
-
-//=== Boolean ==================================================================
-
-Factory<v8::Boolean>::return_t
-Factory<v8::Boolean>::New(bool value) {
-  return v8::Boolean::New(value)->ToBoolean();
-}
-
-//=== Boolean Object ===========================================================
-
-Factory<v8::BooleanObject>::return_t
-Factory<v8::BooleanObject>::New(bool value) {
-  return v8::BooleanObject::New(value).As<v8::BooleanObject>();
-}
-
-//=== Context ==================================================================
-
-Factory<v8::Context>::return_t
-Factory<v8::Context>::New( v8::ExtensionConfiguration* extensions
-                         , v8::Handle<v8::ObjectTemplate> tmpl
-                         , v8::Handle<v8::Value> obj) {
-  v8::Persistent<v8::Context> ctx = v8::Context::New(extensions, tmpl, obj);
-  v8::Local<v8::Context> lctx = v8::Local<v8::Context>::New(ctx);
-  ctx.Dispose();
-  return lctx;
-}
-
-//=== Date =====================================================================
-
-Factory<v8::Date>::return_t
-Factory<v8::Date>::New(double value) {
-  return v8::Date::New(value).As<v8::Date>();
-}
-
-//=== External =================================================================
-
-Factory<v8::External>::return_t
-Factory<v8::External>::New(void * value) {
-  return v8::External::New(value);
-}
-
-//=== Function =================================================================
-
-Factory<v8::Function>::return_t
-Factory<v8::Function>::New( NanFunctionCallback callback
-                          , v8::Handle<v8::Value> data) {
-  return Factory<v8::FunctionTemplate>::New( callback
-                                           , data
-                                           , v8::Handle<v8::Signature>()
-                                           )->GetFunction();
-}
-
-
-//=== FunctionTemplate =========================================================
-
-Factory<v8::FunctionTemplate>::return_t
-Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
-                                  , v8::Handle<v8::Value> data
-                                  , v8::Handle<v8::Signature> signature) {
-  // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find
-  // a way. Have at it though...
-  return v8::FunctionTemplate::New( callback
-                                  , data
-                                  , signature);
-}
-
-//=== Number ===================================================================
-
-Factory<v8::Number>::return_t
-Factory<v8::Number>::New(double value) {
-  return v8::Number::New(value);
-}
-
-//=== Number Object ============================================================
-
-Factory<v8::NumberObject>::return_t
-Factory<v8::NumberObject>::New(double value) {
-  return v8::NumberObject::New(value).As<v8::NumberObject>();
-}
-
-//=== Integer, Int32 and Uint32 ================================================
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(int32_t value) {
-  return To<T>(T::New(value));
-}
-
-template <typename T>
-typename IntegerFactory<T>::return_t
-IntegerFactory<T>::New(uint32_t value) {
-  return To<T>(T::NewFromUnsigned(value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(int32_t value) {
-  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
-}
-
-Factory<v8::Uint32>::return_t
-Factory<v8::Uint32>::New(uint32_t value) {
-  return To<v8::Uint32>(v8::Uint32::NewFromUnsigned(value));
-}
-
-
-//=== Object ===================================================================
-
-Factory<v8::Object>::return_t
-Factory<v8::Object>::New() {
-  return v8::Object::New();
-}
-
-//=== Object Template ==========================================================
-
-Factory<v8::ObjectTemplate>::return_t
-Factory<v8::ObjectTemplate>::New() {
-  return v8::ObjectTemplate::New();
-}
-
-//=== RegExp ===================================================================
-
-Factory<v8::RegExp>::return_t
-Factory<v8::RegExp>::New(
-    v8::Handle<v8::String> pattern
-  , v8::RegExp::Flags flags) {
-  return v8::RegExp::New(pattern, flags);
-}
-
-//=== Script ===================================================================
-
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source) {
-  return v8::Script::New(source);
-}
-Factory<v8::Script>::return_t
-Factory<v8::Script>::New( v8::Local<v8::String> source
-                        , v8::ScriptOrigin const& origin) {
-  return v8::Script::New(source, const_cast<v8::ScriptOrigin*>(&origin));
-}
-
-//=== Signature ================================================================
-
-Factory<v8::Signature>::return_t
-Factory<v8::Signature>::New( Factory<v8::Signature>::FTH receiver
-                           , int argc
-                           , Factory<v8::Signature>::FTH argv[]) {
-  return v8::Signature::New(receiver, argc, argv);
-}
-
-//=== String ===================================================================
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New() {
-  return v8::String::Empty();
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const char * value, int length) {
-  return v8::String::New(value, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(std::string const& value) {
-  assert(value.size() <= INT_MAX && "string too long");
-  return v8::String::New( value.data(), static_cast<int>(value.size()));
-}
-
-inline
-void
-widenString(std::vector<uint16_t> *ws, const uint8_t *s, int l = -1) {
-  size_t len = static_cast<size_t>(l);
-  if (l < 0) {
-    len = strlen(reinterpret_cast<const char*>(s));
-  }
-  assert(len <= INT_MAX && "string too long");
-  ws->resize(len);
-  std::copy(s, s + len, ws->begin());
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint16_t * value, int length) {
-  return v8::String::New(value, length);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(const uint8_t * value, int length) {
-  std::vector<uint16_t> wideString;
-  widenString(&wideString, value, length);
-  if (wideString.size() == 0) {
-    return v8::String::Empty();
-  } else {
-    return v8::String::New(&wideString.front()
-         , static_cast<int>(wideString.size()));
-  }
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
-  return v8::String::NewExternal(value);
-}
-
-Factory<v8::String>::return_t
-Factory<v8::String>::New(v8::String::ExternalAsciiStringResource * value) {
-  return v8::String::NewExternal(value);
-}
-
-//=== String Object ============================================================
-
-Factory<v8::StringObject>::return_t
-Factory<v8::StringObject>::New(v8::Handle<v8::String> value) {
-  return v8::StringObject::New(value).As<v8::StringObject>();
-}
-
-}  // end of namespace NanIntern
-
-//=== Presistents and Handles ==================================================
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Handle<T> h) {
-  return v8::Local<T>::New(h);
-}
-
-template <typename T>
-inline v8::Local<T> NanNew(v8::Persistent<T> const& p) {
-  return v8::Local<T>::New(p);
-}
-
-#endif  // NAN_IMPLEMENTATION_PRE_12_INL_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_new.h b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_new.h
deleted file mode 100644
index 95b6b51e..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_new.h
+++ /dev/null
@@ -1,329 +0,0 @@
-/*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2015 NAN contributors
- *
- * MIT License <https://github.com/rvagg/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
-#ifndef NAN_NEW_H_
-#define NAN_NEW_H_
-
-#if defined(_MSC_VER)
-# pragma warning( disable : 4530 )
-# include <string>
-# pragma warning( default : 4530 )
-#else
-# include <string>
-#endif
-
-namespace NanIntern {  // scnr
-
-// TODO(agnat): Generalize
-template <typename T> v8::Local<T> To(v8::Handle<v8::Integer> i);
-
-template <>
-inline
-v8::Local<v8::Integer>
-To<v8::Integer>(v8::Handle<v8::Integer> i) { return i->ToInteger(); }
-
-template <>
-inline
-v8::Local<v8::Int32>
-To<v8::Int32>(v8::Handle<v8::Integer> i)   { return i->ToInt32(); }
-
-template <>
-inline
-v8::Local<v8::Uint32>
-To<v8::Uint32>(v8::Handle<v8::Integer> i)  { return i->ToUint32(); }
-
-template <typename T> struct FactoryBase { typedef v8::Local<T> return_t; };
-
-template <typename T> struct Factory;
-
-template <>
-struct Factory<v8::Array> : FactoryBase<v8::Array> {
-  static inline return_t New();
-  static inline return_t New(int length);
-};
-
-template <>
-struct Factory<v8::Boolean> : FactoryBase<v8::Boolean> {
-  static inline return_t New(bool value);
-};
-
-template <>
-struct Factory<v8::BooleanObject> : FactoryBase<v8::BooleanObject> {
-  static inline return_t New(bool value);
-};
-
-template <>
-struct Factory<v8::Context> : FactoryBase<v8::Context> {
-  static inline
-  return_t
-  New( v8::ExtensionConfiguration* extensions = NULL
-     , v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>()
-     , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>());
-};
-
-template <>
-struct Factory<v8::Date> : FactoryBase<v8::Date> {
-  static inline return_t New(double value);
-};
-
-template <>
-struct Factory<v8::External> : FactoryBase<v8::External> {
-  static inline return_t New(void *value);
-};
-
-template <>
-struct Factory<v8::Function> : FactoryBase<v8::Function> {
-  static inline
-  return_t
-  New( NanFunctionCallback callback
-     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>());
-};
-
-template <>
-struct Factory<v8::FunctionTemplate> : FactoryBase<v8::FunctionTemplate> {
-  static inline
-  return_t
-  New( NanFunctionCallback callback = NULL
-     , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-     , v8::Handle<v8::Signature> signature = v8::Handle<v8::Signature>());
-};
-
-template <>
-struct Factory<v8::Number> : FactoryBase<v8::Number> {
-  static inline return_t New(double value);
-};
-
-template <>
-struct Factory<v8::NumberObject> : FactoryBase<v8::NumberObject> {
-  static inline return_t New(double value);
-};
-
-template <typename T>
-struct IntegerFactory : FactoryBase<T> {
-  typedef typename FactoryBase<T>::return_t return_t;
-  static inline return_t New(int32_t value);
-  static inline return_t New(uint32_t value);
-};
-
-template <>
-struct Factory<v8::Integer> : IntegerFactory<v8::Integer> {};
-
-template <>
-struct Factory<v8::Int32> : IntegerFactory<v8::Int32> {};
-
-template <>
-struct Factory<v8::Uint32> : FactoryBase<v8::Uint32> {
-  static inline return_t New(int32_t value);
-  static inline return_t New(uint32_t value);
-};
-
-template <>
-struct Factory<v8::Object> : FactoryBase<v8::Object> {
-  static inline return_t New();
-};
-
-template <>
-struct Factory<v8::ObjectTemplate> : FactoryBase<v8::ObjectTemplate> {
-  static inline return_t New();
-};
-
-template <>
-struct Factory<v8::RegExp> : FactoryBase<v8::RegExp> {
-  static inline return_t New(
-      v8::Handle<v8::String> pattern, v8::RegExp::Flags flags);
-};
-
-template <>
-struct Factory<v8::Script> : FactoryBase<v8::Script> {
-  static inline return_t New( v8::Local<v8::String> source);
-  static inline return_t New( v8::Local<v8::String> source
-                            , v8::ScriptOrigin const& origin);
-};
-
-template <>
-struct Factory<v8::Signature> : FactoryBase<v8::Signature> {
-  typedef v8::Handle<v8::FunctionTemplate> FTH;
-  static inline
-  return_t
-  New( FTH receiver = FTH(), int argc = 0, FTH argv[] = NULL );
-};
-
-template <>
-struct Factory<v8::String> : FactoryBase<v8::String> {
-  static inline return_t New();
-  static inline return_t New(const char *value, int length = -1);
-  static inline return_t New(const uint16_t *value, int length = -1);
-  static inline return_t New(std::string const& value);
-
-  static inline return_t New(v8::String::ExternalStringResource * value);
-  static inline return_t New(NanExternalOneByteStringResource * value);
-
-  // TODO(agnat): Deprecate.
-  static inline return_t New(const uint8_t * value, int length = -1);
-};
-
-template <>
-struct Factory<v8::StringObject> : FactoryBase<v8::StringObject> {
-  static inline return_t New(v8::Handle<v8::String> value);
-};
-
-}  // end of namespace NanIntern
-
-#if (NODE_MODULE_VERSION >= 12)
-
-namespace NanIntern {
-
-template <>
-struct Factory<v8::UnboundScript> : FactoryBase<v8::UnboundScript> {
-  static inline return_t New( v8::Local<v8::String> source);
-  static inline return_t New( v8::Local<v8::String> source
-                            , v8::ScriptOrigin const& origin);
-};
-
-}  // end of namespace NanIntern
-
-# include "nan_implementation_12_inl.h"
-
-#else  // NODE_MODULE_VERSION >= 12
-
-# include "nan_implementation_pre_12_inl.h"
-
-#endif
-
-//=== API ======================================================================
-
-template <typename T>
-typename NanIntern::Factory<T>::return_t
-NanNew() {
-  return NanIntern::Factory<T>::New();
-}
-
-template <typename T, typename A0>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0) {
-  return NanIntern::Factory<T>::New(arg0);
-}
-
-template <typename T, typename A0, typename A1>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1) {
-  return NanIntern::Factory<T>::New(arg0, arg1);
-}
-
-template <typename T, typename A0, typename A1, typename A2>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1, A2 arg2) {
-  return NanIntern::Factory<T>::New(arg0, arg1, arg2);
-}
-
-template <typename T, typename A0, typename A1, typename A2, typename A3>
-typename NanIntern::Factory<T>::return_t
-NanNew(A0 arg0, A1 arg1, A2 arg2, A3 arg3) {
-  return NanIntern::Factory<T>::New(arg0, arg1, arg2, arg3);
-}
-
-// Note(agnat): When passing overloaded function pointers to template functions
-// as generic arguments the compiler needs help in picking the right overload.
-// These two functions handle NanNew<Function> and NanNew<FunctionTemplate> with
-// all argument variations.
-
-// v8::Function and v8::FunctionTemplate with one or two arguments
-template <typename T>
-typename NanIntern::Factory<T>::return_t
-NanNew( NanFunctionCallback callback
-      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()) {
-    return NanIntern::Factory<T>::New(callback, data);
-}
-
-// v8::Function and v8::FunctionTemplate with three arguments
-template <typename T, typename A2>
-typename NanIntern::Factory<T>::return_t
-NanNew( NanFunctionCallback callback
-      , v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
-      , A2 a2 = A2()) {
-    return NanIntern::Factory<T>::New(callback, data, a2);
-}
-
-// Convenience
-
-template <typename T> inline v8::Local<T> NanNew(v8::Handle<T> h);
-template <typename T> inline v8::Local<T> NanNew(v8::Persistent<T> const& p);
-
-inline
-NanIntern::Factory<v8::Boolean>::return_t
-NanNew(bool value) {
-  return NanNew<v8::Boolean>(value);
-}
-
-inline
-NanIntern::Factory<v8::Int32>::return_t
-NanNew(int32_t value) {
-  return NanNew<v8::Int32>(value);
-}
-
-inline
-NanIntern::Factory<v8::Uint32>::return_t
-NanNew(uint32_t value) {
-  return NanNew<v8::Uint32>(value);
-}
-
-inline
-NanIntern::Factory<v8::Number>::return_t
-NanNew(double value) {
-  return NanNew<v8::Number>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(std::string const& value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const char * value, int length) {
-  return NanNew<v8::String>(value, length);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const char * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const uint8_t * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(const uint16_t * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(v8::String::ExternalStringResource * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::String>::return_t
-NanNew(NanExternalOneByteStringResource * value) {
-  return NanNew<v8::String>(value);
-}
-
-inline
-NanIntern::Factory<v8::RegExp>::return_t
-NanNew(v8::Handle<v8::String> pattern, v8::RegExp::Flags flags) {
-  return NanNew<v8::RegExp>(pattern, flags);
-}
-
-#endif  // NAN_NEW_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_string_bytes.h b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_string_bytes.h
deleted file mode 100644
index 9deecfbb..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/nan_string_bytes.h
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-#ifndef NAN_STRING_BYTES_H_
-#define NAN_STRING_BYTES_H_
-
-// Decodes a v8::Handle<v8::String> or Buffer to a raw char*
-
-#include <node.h>
-#include <node_buffer.h>
-#include <assert.h>
-#include <string.h>  // memcpy
-#include <limits.h>
-
-namespace NanIntern {
-
-using v8::Local;
-using v8::Handle;
-using v8::Object;
-using v8::String;
-using v8::Value;
-
-
-//// Base 64 ////
-
-#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
-
-
-
-//// Nan::HEX ////
-
-static bool contains_non_ascii_slow(const char* buf, size_t len) {
-  for (size_t i = 0; i < len; ++i) {
-    if (buf[i] & 0x80) return true;
-  }
-  return false;
-}
-
-
-static bool contains_non_ascii(const char* src, size_t len) {
-  if (len < 16) {
-    return contains_non_ascii_slow(src, len);
-  }
-
-  const unsigned bytes_per_word = sizeof(void*);
-  const unsigned align_mask = bytes_per_word - 1;
-  const unsigned unaligned = reinterpret_cast<uintptr_t>(src) & align_mask;
-
-  if (unaligned > 0) {
-    const unsigned n = bytes_per_word - unaligned;
-    if (contains_non_ascii_slow(src, n)) return true;
-    src += n;
-    len -= n;
-  }
-
-
-#if defined(__x86_64__) || defined(_WIN64)
-  const uintptr_t mask = 0x8080808080808080ll;
-#else
-  const uintptr_t mask = 0x80808080l;
-#endif
-
-  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
-
-  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
-    if (srcw[i] & mask) return true;
-  }
-
-  const unsigned remainder = len & align_mask;
-  if (remainder > 0) {
-    const size_t offset = len - remainder;
-    if (contains_non_ascii_slow(src + offset, remainder)) return true;
-  }
-
-  return false;
-}
-
-
-static void force_ascii_slow(const char* src, char* dst, size_t len) {
-  for (size_t i = 0; i < len; ++i) {
-    dst[i] = src[i] & 0x7f;
-  }
-}
-
-
-static void force_ascii(const char* src, char* dst, size_t len) {
-  if (len < 16) {
-    force_ascii_slow(src, dst, len);
-    return;
-  }
-
-  const unsigned bytes_per_word = sizeof(void*);
-  const unsigned align_mask = bytes_per_word - 1;
-  const unsigned src_unalign = reinterpret_cast<uintptr_t>(src) & align_mask;
-  const unsigned dst_unalign = reinterpret_cast<uintptr_t>(dst) & align_mask;
-
-  if (src_unalign > 0) {
-    if (src_unalign == dst_unalign) {
-      const unsigned unalign = bytes_per_word - src_unalign;
-      force_ascii_slow(src, dst, unalign);
-      src += unalign;
-      dst += unalign;
-      len -= src_unalign;
-    } else {
-      force_ascii_slow(src, dst, len);
-      return;
-    }
-  }
-
-#if defined(__x86_64__) || defined(_WIN64)
-  const uintptr_t mask = ~0x8080808080808080ll;
-#else
-  const uintptr_t mask = ~0x80808080l;
-#endif
-
-  const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
-  uintptr_t* dstw = reinterpret_cast<uintptr_t*>(dst);
-
-  for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
-    dstw[i] = srcw[i] & mask;
-  }
-
-  const unsigned remainder = len & align_mask;
-  if (remainder > 0) {
-    const size_t offset = len - remainder;
-    force_ascii_slow(src + offset, dst + offset, remainder);
-  }
-}
-
-
-static size_t base64_encode(const char* src,
-                            size_t slen,
-                            char* dst,
-                            size_t dlen) {
-  // We know how much we'll write, just make sure that there's space.
-  assert(dlen >= base64_encoded_size(slen) &&
-      "not enough space provided for base64 encode");
-
-  dlen = base64_encoded_size(slen);
-
-  unsigned a;
-  unsigned b;
-  unsigned c;
-  unsigned i;
-  unsigned k;
-  unsigned n;
-
-  static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                              "abcdefghijklmnopqrstuvwxyz"
-                              "0123456789+/";
-
-  i = 0;
-  k = 0;
-  n = slen / 3 * 3;
-
-  while (i < n) {
-    a = src[i + 0] & 0xff;
-    b = src[i + 1] & 0xff;
-    c = src[i + 2] & 0xff;
-
-    dst[k + 0] = table[a >> 2];
-    dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
-    dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
-    dst[k + 3] = table[c & 0x3f];
-
-    i += 3;
-    k += 4;
-  }
-
-  if (n != slen) {
-    switch (slen - n) {
-      case 1:
-        a = src[i + 0] & 0xff;
-        dst[k + 0] = table[a >> 2];
-        dst[k + 1] = table[(a & 3) << 4];
-        dst[k + 2] = '=';
-        dst[k + 3] = '=';
-        break;
-
-      case 2:
-        a = src[i + 0] & 0xff;
-        b = src[i + 1] & 0xff;
-        dst[k + 0] = table[a >> 2];
-        dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
-        dst[k + 2] = table[(b & 0x0f) << 2];
-        dst[k + 3] = '=';
-        break;
-    }
-  }
-
-  return dlen;
-}
-
-
-static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) {
-  // We know how much we'll write, just make sure that there's space.
-  assert(dlen >= slen * 2 &&
-      "not enough space provided for hex encode");
-
-  dlen = slen * 2;
-  for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {
-    static const char hex[] = "0123456789abcdef";
-    uint8_t val = static_cast<uint8_t>(src[i]);
-    dst[k + 0] = hex[val >> 4];
-    dst[k + 1] = hex[val & 15];
-  }
-
-  return dlen;
-}
-
-
-
-static Local<Value> Encode(const char* buf,
-                           size_t buflen,
-                           enum Nan::Encoding encoding) {
-  assert(buflen <= node::Buffer::kMaxLength);
-  if (!buflen && encoding != Nan::BUFFER)
-    return NanNew("");
-
-  Local<String> val;
-  switch (encoding) {
-    case Nan::BUFFER:
-      return NanNewBufferHandle(buf, buflen);
-
-    case Nan::ASCII:
-      if (contains_non_ascii(buf, buflen)) {
-        char* out = new char[buflen];
-        force_ascii(buf, out, buflen);
-        val = NanNew<String>(out, buflen);
-        delete[] out;
-      } else {
-        val = NanNew<String>(buf, buflen);
-      }
-      break;
-
-    case Nan::UTF8:
-      val = NanNew<String>(buf, buflen);
-      break;
-
-    case Nan::BINARY: {
-      // TODO(isaacs) use ExternalTwoByteString?
-      const unsigned char *cbuf = reinterpret_cast<const unsigned char*>(buf);
-      uint16_t * twobytebuf = new uint16_t[buflen];
-      for (size_t i = 0; i < buflen; i++) {
-        // XXX is the following line platform independent?
-        twobytebuf[i] = cbuf[i];
-      }
-      val = NanNew<String>(twobytebuf, buflen);
-      delete[] twobytebuf;
-      break;
-    }
-
-    case Nan::BASE64: {
-      size_t dlen = base64_encoded_size(buflen);
-      char* dst = new char[dlen];
-
-      size_t written = base64_encode(buf, buflen, dst, dlen);
-      assert(written == dlen);
-
-      val = NanNew<String>(dst, dlen);
-      delete[] dst;
-      break;
-    }
-
-    case Nan::UCS2: {
-      const uint16_t* data = reinterpret_cast<const uint16_t*>(buf);
-      val = NanNew<String>(data, buflen / 2);
-      break;
-    }
-
-    case Nan::HEX: {
-      size_t dlen = buflen * 2;
-      char* dst = new char[dlen];
-      size_t written = hex_encode(buf, buflen, dst, dlen);
-      assert(written == dlen);
-
-      val = NanNew<String>(dst, dlen);
-      delete[] dst;
-      break;
-    }
-
-    default:
-      assert(0 && "unknown encoding");
-      break;
-  }
-
-  return val;
-}
-
-#undef base64_encoded_size
-
-}  // namespace NanIntern
-
-#endif  // NAN_STRING_BYTES_H_
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/package.json b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/package.json
deleted file mode 100644
index ba489436..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/node_modules/nan/package.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
-  "name": "nan",
-  "version": "1.6.2",
-  "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility",
-  "main": "include_dirs.js",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/rvagg/nan.git"
-  },
-  "scripts": {
-    "test": "tap --gc test/js/*-test.js",
-    "rebuild-tests": "pangyp rebuild --directory test"
-  },
-  "contributors": [
-    {
-      "name": "Rod Vagg",
-      "email": "r@va.gg",
-      "url": "https://github.com/rvagg"
-    },
-    {
-      "name": "Benjamin Byholm",
-      "email": "bbyholm@abo.fi",
-      "url": "https://github.com/kkoopa/"
-    },
-    {
-      "name": "Trevor Norris",
-      "email": "trev.norris@gmail.com",
-      "url": "https://github.com/trevnorris"
-    },
-    {
-      "name": "Nathan Rajlich",
-      "email": "nathan@tootallnate.net",
-      "url": "https://github.com/TooTallNate"
-    },
-    {
-      "name": "Brett Lawson",
-      "email": "brett19@gmail.com",
-      "url": "https://github.com/brett19"
-    },
-    {
-      "name": "Ben Noordhuis",
-      "email": "info@bnoordhuis.nl",
-      "url": "https://github.com/bnoordhuis"
-    },
-    {
-      "name": "David Siegel",
-      "email": "david@artcom.de",
-      "url": "https://github.com/agnat"
-    }
-  ],
-  "devDependencies": {
-    "bindings": "~1.2.1",
-    "node-gyp": "~1.0.2",
-    "pangyp": "~2.0.1",
-    "tap": "~0.5.0",
-    "xtend": "~4.0.0"
-  },
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/rvagg/nan/issues"
-  },
-  "readme": "ERROR: No README data found!",
-  "_id": "nan@1.6.2",
-  "_from": "nan@1.6.x"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/package.json b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/package.json
deleted file mode 100644
index 853d9835..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-  "name": "utf-8-validate",
-  "version": "1.0.1",
-  "description": "Validate UTF-8 for Web",
-  "main": "index.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1",
-    "install": "node-gyp rebuild"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/websockets/utf-8-validate"
-  },
-  "keywords": [
-    "utf-8-validate"
-  ],
-  "author": {
-    "name": "Einar Otto Stangvik",
-    "email": "einaros@gmail.com",
-    "url": "http://2x.io"
-  },
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/websockets/utf-8-validate/issues"
-  },
-  "homepage": "https://github.com/websockets/utf-8-validate",
-  "dependencies": {
-    "bindings": "1.2.x",
-    "nan": "1.6.x"
-  },
-  "gypfile": true,
-  "readme": "ERROR: No README data found!",
-  "_id": "utf-8-validate@1.0.1",
-  "_from": "utf-8-validate@1.0.x"
-}
diff --git a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/src/validation.cc b/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/src/validation.cc
deleted file mode 100644
index 264edcd7..00000000
--- a/input_devices/mag/node_modules/ws/node_modules/utf-8-validate/src/validation.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-/*!
- * UTF-8 validate: UTF-8 validation for WebSockets.
- * Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
- * MIT Licensed
- */
-
-#include <v8.h>
-#include <node.h>
-#include <node_version.h>
-#include <node_buffer.h>
-#include <node_object_wrap.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <stdio.h>
-#include "nan.h"
-
-using namespace v8;
-using namespace node;
-
-#define UNI_SUR_HIGH_START   (uint32_t) 0xD800
-#define UNI_SUR_LOW_END    (uint32_t) 0xDFFF
-#define UNI_REPLACEMENT_CHAR (uint32_t) 0x0000FFFD
-#define UNI_MAX_LEGAL_UTF32  (uint32_t) 0x0010FFFF
-
-static const uint8_t trailingBytesForUTF8[256] = {
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
-};
-
-static const uint32_t offsetsFromUTF8[6] = {
-  0x00000000, 0x00003080, 0x000E2080,
-  0x03C82080, 0xFA082080, 0x82082080
-};
-
-static int isLegalUTF8(const uint8_t *source, const int length)
-{
-  uint8_t a;
-  const uint8_t *srcptr = source+length;
-  switch (length) {
-  default: return 0;
-  /* Everything else falls through when "true"... */
-  /* RFC3629 makes 5 & 6 bytes UTF-8 illegal
-  case 6: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
-  case 5: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; */
-  case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
-  case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
-  case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
-    switch (*source) {
-      /* no fall-through in this inner switch */
-      case 0xE0: if (a < 0xA0) return 0; break;
-      case 0xED: if (a > 0x9F) return 0; break;
-      case 0xF0: if (a < 0x90) return 0; break;
-      case 0xF4: if (a > 0x8F) return 0; break;
-      default:   if (a < 0x80) return 0;
-    }
-
-  case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
-  }
-  if (*source > 0xF4) return 0;
-  return 1;
-}
-
-int is_valid_utf8 (size_t len, char *value)
-{
-  /* is the string valid UTF-8? */
-  for (unsigned int i = 0; i < len; i++) {
-    uint32_t ch = 0;
-    uint8_t  extrabytes = trailingBytesForUTF8[(uint8_t) value[i]];
-
-    if (extrabytes + i >= len)
-      return 0;
-
-    if (isLegalUTF8 ((uint8_t *) (value + i), extrabytes + 1) == 0) return 0;
-
-    switch (extrabytes) {
-      case 5 : ch += (uint8_t) value[i++]; ch <<= 6;
-      case 4 : ch += (uint8_t) value[i++]; ch <<= 6;
-      case 3 : ch += (uint8_t) value[i++]; ch <<= 6;
-      case 2 : ch += (uint8_t) value[i++]; ch <<= 6;
-      case 1 : ch += (uint8_t) value[i++]; ch <<= 6;
-      case 0 : ch += (uint8_t) value[i];
-    }
-
-    ch -= offsetsFromUTF8[extrabytes];
-
-    if (ch <= UNI_MAX_LEGAL_UTF32) {
-      if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
-        return 0;
-    } else {
-      return 0;
-    }
-  }
-
-  return 1;
-}
-
-class Validation : public ObjectWrap
-{
-public:
-
-  static void Initialize(v8::Handle<v8::Object> target)
-  {
-    NanScope();
-    Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);
-    t->InstanceTemplate()->SetInternalFieldCount(1);
-    NODE_SET_METHOD(t, "isValidUTF8", Validation::IsValidUTF8);
-    target->Set(NanNew<String>("Validation"), t->GetFunction());
-  }
-
-protected:
-
-  static NAN_METHOD(New)
-  {
-    NanScope();
-    Validation* validation = new Validation();
-    validation->Wrap(args.This());
-    NanReturnValue(args.This());
-  }
-
-  static NAN_METHOD(IsValidUTF8)
-  {
-    NanScope();
-    if (!Buffer::HasInstance(args[0])) {
-      return NanThrowTypeError("First argument needs to be a buffer");
-    }
-    Local<Object> buffer_obj = args[0]->ToObject();
-    char *buffer_data = Buffer::Data(buffer_obj);
-    size_t buffer_length = Buffer::Length(buffer_obj);
-    NanReturnValue(is_valid_utf8(buffer_length, buffer_data) == 1 ? NanTrue() : NanFalse());
-  }
-};
-#if !NODE_VERSION_AT_LEAST(0,10,0)
-extern "C"
-#endif
-void init (Handle<Object> target)
-{
-  NanScope();
-  Validation::Initialize(target);
-}
-
-NODE_MODULE(validation, init)
-
diff --git a/input_devices/mag/node_modules/ws/package.json b/input_devices/mag/node_modules/ws/package.json
index 9452ba41..5efd115c 100644
--- a/input_devices/mag/node_modules/ws/package.json
+++ b/input_devices/mag/node_modules/ws/package.json
@@ -1,15 +1,80 @@
 {
+  "_args": [
+    [
+      "ws",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag"
+    ]
+  ],
+  "_from": "ws@latest",
+  "_hasShrinkwrap": false,
+  "_id": "ws@6.1.0",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/ws",
+  "_nodeVersion": "10.11.0",
+  "_npmOperationalInternal": {
+    "host": "s3://npm-registry-packages",
+    "tmp": "tmp/ws_6.1.0_1538722328829_0.473546842393884"
+  },
+  "_npmUser": {
+    "email": "luigipinca@gmail.com",
+    "name": "lpinca"
+  },
+  "_npmVersion": "6.4.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "ws",
+    "raw": "ws",
+    "rawSpec": "",
+    "scope": null,
+    "spec": "latest",
+    "type": "tag"
+  },
+  "_requiredBy": [
+    "#USER"
+  ],
+  "_resolved": "https://registry.npmjs.org/ws/-/ws-6.1.0.tgz",
+  "_shasum": "119a9dbf92c54e190ec18d10e871d55c95cf9373",
+  "_shrinkwrap": null,
+  "_spec": "ws",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag",
   "author": {
-    "name": "Einar Otto Stangvik",
     "email": "einaros@gmail.com",
+    "name": "Einar Otto Stangvik",
     "url": "http://2x.io"
   },
-  "name": "ws",
-  "description": "simple to use, blazing fast and thoroughly tested websocket client, server and console for node.js, up-to-date against RFC-6455",
-  "version": "0.7.1",
-  "license": "MIT",
+  "browser": "browser.js",
+  "bugs": {
+    "url": "https://github.com/websockets/ws/issues"
+  },
+  "dependencies": {
+    "async-limiter": "~1.0.0"
+  },
+  "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
+  "devDependencies": {
+    "benchmark": "~2.1.2",
+    "bufferutil": "~4.0.0",
+    "eslint": "~5.6.1",
+    "eslint-config-standard": "~12.0.0",
+    "eslint-plugin-import": "~2.14.0",
+    "eslint-plugin-node": "~7.0.0",
+    "eslint-plugin-promise": "~4.0.0",
+    "eslint-plugin-standard": "~4.0.0",
+    "mocha": "~5.2.0",
+    "nyc": "~13.0.1",
+    "utf-8-validate": "~5.0.0"
+  },
+  "directories": {},
+  "dist": {
+    "fileCount": 15,
+    "integrity": "sha512-H3dGVdGvW2H8bnYpIDc3u3LH8Wue3Qh+Zto6aXXFzvESkTVT6rAfKR6tR/+coaUvxs8yHtmNV0uioBF62ZGSTg==",
+    "shasum": "119a9dbf92c54e190ec18d10e871d55c95cf9373",
+    "tarball": "https://registry.npmjs.org/ws/-/ws-6.1.0.tgz",
+    "unpackedSize": 99539
+  },
+  "gitHead": "b9ce38d80f847a843c05edfe1a907278bcffde0c",
+  "homepage": "https://github.com/websockets/ws",
   "keywords": [
-    "Hixie",
     "HyBi",
     "Push",
     "RFC-6455",
@@ -17,43 +82,37 @@
     "WebSockets",
     "real-time"
   ],
+  "license": "MIT",
+  "main": "index.js",
+  "maintainers": [
+    {
+      "name": "3rdeden",
+      "email": "npm@3rd-Eden.com"
+    },
+    {
+      "name": "einaros",
+      "email": "einaros@gmail.com"
+    },
+    {
+      "name": "lpinca",
+      "email": "luigipinca@gmail.com"
+    },
+    {
+      "name": "v1",
+      "email": "npm@3rd-Eden.com"
+    }
+  ],
+  "name": "ws",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
   "repository": {
     "type": "git",
-    "url": "git://github.com/websockets/ws.git"
+    "url": "git+https://github.com/websockets/ws.git"
   },
   "scripts": {
-    "test": "make test"
-  },
-  "dependencies": {
-    "options": ">=0.0.5",
-    "ultron": "1.0.x",
-    "bufferutil": "1.0.x",
-    "utf-8-validate": "1.0.x"
-  },
-  "optionalDependencies": {
-    "bufferutil": "1.0.x",
-    "utf-8-validate": "1.0.x"
-  },
-  "devDependencies": {
-    "ansi": "0.3.x",
-    "benchmark": "0.3.x",
-    "expect.js": "0.3.x",
-    "mocha": "2.0.x",
-    "should": "4.3.x",
-    "tinycolor": "0.0.x"
-  },
-  "browser": "./lib/browser.js",
-  "component": {
-    "scripts": {
-      "ws/index.js": "./lib/browser.js"
-    }
-  },
-  "gypfile": true,
-  "readme": "# ws: a node.js websocket library\n\n[![Build Status](https://travis-ci.org/einaros/ws.svg?branch=master)](https://travis-ci.org/einaros/ws)\n\n`ws` is a simple to use WebSocket implementation, up-to-date against RFC-6455,\nand [probably the fastest WebSocket library for node.js][archive].\n\nPasses the quite extensive Autobahn test suite. See http://einaros.github.com/ws\nfor the full reports.\n\n## Protocol support\n\n* **Hixie draft 76** (Old and deprecated, but still in use by Safari and Opera.\n  Added to ws version 0.4.2, but server only. Can be disabled by setting the\n  `disableHixie` option to true.)\n* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)\n* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`)\n\n### Installing\n\n```\nnpm install --save ws\n```\n\n### Sending and receiving text data\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://www.host.com/path');\n\nws.on('open', function open() {\n  ws.send('something');\n});\n\nws.on('message', function(data, flags) {\n  // flags.binary will be set if a binary data is received.\n  // flags.masked will be set if the data was masked.\n});\n```\n\n### Sending binary data\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://www.host.com/path');\n\nws.on('open', function open() {\n  var array = new Float32Array(5);\n\n  for (var i = 0; i < array.length; ++i) {\n    array[i] = i / 2;\n  }\n\n  ws.send(array, { binary: true, mask: true });\n});\n```\n\nSetting `mask`, as done for the send options above, will cause the data to be\nmasked according to the WebSocket protocol. The same option applies for text\ndata.\n\n### Server example\n\n```js\nvar WebSocketServer = require('ws').Server\n  , wss = new WebSocketServer({ port: 8080 });\n\nwss.on('connection', function connection(ws) {\n  ws.on('message', function incoming(message) {\n    console.log('received: %s', message);\n  });\n\n  ws.send('something');\n});\n```\n\n### Server sending broadcast data\n\n```js\nvar WebSocketServer = require('ws').Server\n  , wss = new WebSocketServer({ port: 8080 });\n\nwss.broadcast = function broadcast(data) {\n  wss.clients.forEach(function each(client) {\n    client.send(data);\n  });\n};\n```\n\n### Error handling best practices\n\n```js\n// If the WebSocket is closed before the following send is attempted\nws.send('something');\n\n// Errors (both immediate and async write errors) can be detected in an optional\n// callback. The callback is also the only way of being notified that data has\n// actually been sent.\nws.send('something', function ack(error) {\n  // if error is not defined, the send has been completed,\n  // otherwise the error object will indicate what failed.\n});\n\n// Immediate errors can also be handled with try/catch-blocks, but **note** that\n// since sends are inherently asynchronous, socket write failures will *not* be\n// captured when this technique is used.\ntry { ws.send('something'); }\ncatch (e) { /* handle error */ }\n```\n\n### echo.websocket.org demo\n\n```js\nvar WebSocket = require('ws');\nvar ws = new WebSocket('ws://echo.websocket.org/', {\n  protocolVersion: 8, \n  origin: 'http://websocket.org'\n});\n\nws.on('open', function open() {\n  console.log('connected');\n  ws.send(Date.now().toString(), {mask: true});\n});\n\nws.on('close', function close() {\n  console.log('disconnected');\n});\n\nws.on('message', function message(data, flags) {\n  console.log('Roundtrip time: ' + (Date.now() - parseInt(data)) + 'ms', flags);\n\n  setTimeout(function timeout() {\n    ws.send(Date.now().toString(), {mask: true});\n  }, 500);\n});\n```\n\n### Other examples\n\nFor a full example with a browser client communicating with a ws server, see the\nexamples folder.\n\nNote that the usage together with Express 3.0 is quite different from Express\n2.x. The difference is expressed in the two different serverstats-examples.\n\nOtherwise, see the test cases.\n\n### Running the tests\n\n```\nmake test\n```\n\n## API Docs\n\nSee the doc/ directory for Node.js-like docs for the ws classes.\n\n## Changelog\n\nWe're using the GitHub `releases` for changelog entries.\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2011 Einar Otto Stangvik &lt;einaros@gmail.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n[archive]: http://web.archive.org/web/20130314230536/http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/websockets/ws/issues"
+    "integration": "eslint . && mocha test/*.integration.js",
+    "lint": "eslint .",
+    "test": "eslint . && nyc --reporter=html --reporter=text mocha test/*.test.js"
   },
-  "_id": "ws@0.7.1",
-  "_from": "ws@"
+  "version": "6.1.0"
 }
diff --git a/input_devices/mag/node_modules/xtend/.jshintrc b/input_devices/mag/node_modules/xtend/.jshintrc
new file mode 100644
index 00000000..77887b5f
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/.jshintrc
@@ -0,0 +1,30 @@
+{
+    "maxdepth": 4,
+    "maxstatements": 200,
+    "maxcomplexity": 12,
+    "maxlen": 80,
+    "maxparams": 5,
+
+    "curly": true,
+    "eqeqeq": true,
+    "immed": true,
+    "latedef": false,
+    "noarg": true,
+    "noempty": true,
+    "nonew": true,
+    "undef": true,
+    "unused": "vars",
+    "trailing": true,
+
+    "quotmark": true,
+    "expr": true,
+    "asi": true,
+
+    "browser": false,
+    "esnext": true,
+    "devel": false,
+    "node": false,
+    "nonstandard": false,
+
+    "predef": ["require", "module", "__dirname", "__filename"]
+}
diff --git a/input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/.npmignore b/input_devices/mag/node_modules/xtend/.npmignore
similarity index 100%
rename from input_devices/mag/node_modules/serialport/node_modules/node-pre-gyp/node_modules/npmlog/node_modules/ansi/.npmignore
rename to input_devices/mag/node_modules/xtend/.npmignore
diff --git a/input_devices/mag/node_modules/xtend/LICENCE b/input_devices/mag/node_modules/xtend/LICENCE
new file mode 100644
index 00000000..1a14b437
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/LICENCE
@@ -0,0 +1,19 @@
+Copyright (c) 2012-2014 Raynos.
+
+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/input_devices/mag/node_modules/xtend/Makefile b/input_devices/mag/node_modules/xtend/Makefile
new file mode 100644
index 00000000..d583fcf4
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/Makefile
@@ -0,0 +1,4 @@
+browser:
+	node ./support/compile
+
+.PHONY: browser
\ No newline at end of file
diff --git a/input_devices/mag/node_modules/xtend/README.md b/input_devices/mag/node_modules/xtend/README.md
new file mode 100644
index 00000000..093cb297
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/README.md
@@ -0,0 +1,32 @@
+# xtend
+
+[![browser support][3]][4]
+
+[![locked](http://badges.github.io/stability-badges/dist/locked.svg)](http://github.com/badges/stability-badges)
+
+Extend like a boss
+
+xtend is a basic utility library which allows you to extend an object by appending all of the properties from each object in a list. When there are identical properties, the right-most property takes precedence.
+
+## Examples
+
+```js
+var extend = require("xtend")
+
+// extend returns a new object. Does not mutate arguments
+var combination = extend({
+    a: "a",
+    b: 'c'
+}, {
+    b: "b"
+})
+// { a: "a", b: "b" }
+```
+
+## Stability status: Locked
+
+## MIT Licenced
+
+
+  [3]: http://ci.testling.com/Raynos/xtend.png
+  [4]: http://ci.testling.com/Raynos/xtend
diff --git a/input_devices/mag/node_modules/xtend/immutable.js b/input_devices/mag/node_modules/xtend/immutable.js
new file mode 100644
index 00000000..94889c9d
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/immutable.js
@@ -0,0 +1,19 @@
+module.exports = extend
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function extend() {
+    var target = {}
+
+    for (var i = 0; i < arguments.length; i++) {
+        var source = arguments[i]
+
+        for (var key in source) {
+            if (hasOwnProperty.call(source, key)) {
+                target[key] = source[key]
+            }
+        }
+    }
+
+    return target
+}
diff --git a/input_devices/mag/node_modules/xtend/mutable.js b/input_devices/mag/node_modules/xtend/mutable.js
new file mode 100644
index 00000000..72debede
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/mutable.js
@@ -0,0 +1,17 @@
+module.exports = extend
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function extend(target) {
+    for (var i = 1; i < arguments.length; i++) {
+        var source = arguments[i]
+
+        for (var key in source) {
+            if (hasOwnProperty.call(source, key)) {
+                target[key] = source[key]
+            }
+        }
+    }
+
+    return target
+}
diff --git a/input_devices/mag/node_modules/xtend/package.json b/input_devices/mag/node_modules/xtend/package.json
new file mode 100644
index 00000000..b35806f1
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/package.json
@@ -0,0 +1,109 @@
+{
+  "_args": [
+    [
+      "xtend@^4.0.0",
+      "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream"
+    ]
+  ],
+  "_from": "xtend@>=4.0.0 <5.0.0",
+  "_id": "xtend@4.0.1",
+  "_inCache": true,
+  "_installable": true,
+  "_location": "/xtend",
+  "_nodeVersion": "0.10.32",
+  "_npmUser": {
+    "email": "raynos2@gmail.com",
+    "name": "raynos"
+  },
+  "_npmVersion": "2.14.1",
+  "_phantomChildren": {},
+  "_requested": {
+    "name": "xtend",
+    "raw": "xtend@^4.0.0",
+    "rawSpec": "^4.0.0",
+    "scope": null,
+    "spec": ">=4.0.0 <5.0.0",
+    "type": "range"
+  },
+  "_requiredBy": [
+    "/tar-stream"
+  ],
+  "_resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+  "_shasum": "a5c6d532be656e23db820efb943a1f04998d63af",
+  "_shrinkwrap": null,
+  "_spec": "xtend@^4.0.0",
+  "_where": "/media/neilg/SSD2T/git/fab2/academy/classes/input_devices/mag/node_modules/tar-stream",
+  "author": {
+    "email": "raynos2@gmail.com",
+    "name": "Raynos"
+  },
+  "bugs": {
+    "email": "raynos2@gmail.com",
+    "url": "https://github.com/Raynos/xtend/issues"
+  },
+  "contributors": [
+    {
+      "name": "Jake Verbaten"
+    },
+    {
+      "name": "Matt Esch"
+    }
+  ],
+  "dependencies": {},
+  "description": "extend like a boss",
+  "devDependencies": {
+    "tape": "~1.1.0"
+  },
+  "directories": {},
+  "dist": {
+    "shasum": "a5c6d532be656e23db820efb943a1f04998d63af",
+    "tarball": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
+  },
+  "engines": {
+    "node": ">=0.4"
+  },
+  "gitHead": "23dc302a89756da89c1897bc732a752317e35390",
+  "homepage": "https://github.com/Raynos/xtend",
+  "keywords": [
+    "array",
+    "extend",
+    "merge",
+    "object",
+    "options",
+    "opts"
+  ],
+  "license": "MIT",
+  "main": "immutable",
+  "maintainers": [
+    {
+      "name": "raynos",
+      "email": "raynos2@gmail.com"
+    }
+  ],
+  "name": "xtend",
+  "optionalDependencies": {},
+  "readme": "ERROR: No README data found!",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/Raynos/xtend.git"
+  },
+  "scripts": {
+    "test": "node test"
+  },
+  "testling": {
+    "browsers": [
+      "chrome/22..latest",
+      "chrome/canary",
+      "firefox/16..latest",
+      "firefox/nightly",
+      "ie/7..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest",
+      "opera/12..latest",
+      "opera/next",
+      "safari/5.1..latest"
+    ],
+    "files": "test.js"
+  },
+  "version": "4.0.1"
+}
diff --git a/input_devices/mag/node_modules/xtend/test.js b/input_devices/mag/node_modules/xtend/test.js
new file mode 100644
index 00000000..093a2b06
--- /dev/null
+++ b/input_devices/mag/node_modules/xtend/test.js
@@ -0,0 +1,83 @@
+var test = require("tape")
+var extend = require("./")
+var mutableExtend = require("./mutable")
+
+test("merge", function(assert) {
+    var a = { a: "foo" }
+    var b = { b: "bar" }
+
+    assert.deepEqual(extend(a, b), { a: "foo", b: "bar" })
+    assert.end()
+})
+
+test("replace", function(assert) {
+    var a = { a: "foo" }
+    var b = { a: "bar" }
+
+    assert.deepEqual(extend(a, b), { a: "bar" })
+    assert.end()
+})
+
+test("undefined", function(assert) {
+    var a = { a: undefined }
+    var b = { b: "foo" }
+
+    assert.deepEqual(extend(a, b), { a: undefined, b: "foo" })
+    assert.deepEqual(extend(b, a), { a: undefined, b: "foo" })
+    assert.end()
+})
+
+test("handle 0", function(assert) {
+    var a = { a: "default" }
+    var b = { a: 0 }
+
+    assert.deepEqual(extend(a, b), { a: 0 })
+    assert.deepEqual(extend(b, a), { a: "default" })
+    assert.end()
+})
+
+test("is immutable", function (assert) {
+    var record = {}
+
+    extend(record, { foo: "bar" })
+    assert.equal(record.foo, undefined)
+    assert.end()
+})
+
+test("null as argument", function (assert) {
+    var a = { foo: "bar" }
+    var b = null
+    var c = void 0
+
+    assert.deepEqual(extend(b, a, c), { foo: "bar" })
+    assert.end()
+})
+
+test("mutable", function (assert) {
+    var a = { foo: "bar" }
+
+    mutableExtend(a, { bar: "baz" })
+
+    assert.equal(a.bar, "baz")
+    assert.end()
+})
+
+test("null prototype", function(assert) {
+    var a = { a: "foo" }
+    var b = Object.create(null)
+    b.b = "bar";
+
+    assert.deepEqual(extend(a, b), { a: "foo", b: "bar" })
+    assert.end()
+})
+
+test("null prototype mutable", function (assert) {
+    var a = { foo: "bar" }
+    var b = Object.create(null)
+    b.bar = "baz";
+
+    mutableExtend(a, b)
+
+    assert.equal(a.bar, "baz")
+    assert.end()
+})
-- 
GitLab